Отправить объект словаря в класс потока, используя сигнал - PullRequest
0 голосов
/ 14 ноября 2018

Я использую PyQt5 и Python2.7

У меня есть класс UIWidget, класс PlayStreaming и класс Thread.

После нажатия кнопки из UIWidget и отправки объекта словаря из PlayStreaming в Threadкласс.

Если я удалю 'QVariantMap', я получу сигнал нажатия кнопки, но не могу отправить данные.

Как мне решить проблему?

МойВесь код выглядит следующим образом.

from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtWidgets import QApplication, QMainWindow, QInputDialog
import cv2
import time
import face_recognition.api as face_recognition

class Thread(QtCore.QThread):    
    changePixmap = QtCore.pyqtSignal(QtGui.QImage)
    updateStatus = QtCore.pyqtSignal(str)
    scaled_size = QtCore.QSize(640, 480)          
    curScale=1.0
    facearray=[]
    dim=(640,480) 
    processedImage=[]
    def run(self):
        cap = cv2.VideoCapture(-1)
        cap.set(3,1280);
        cap.set(4,1024);
        time.sleep(2)
        self.maxHeight=cap.get(cv2.CAP_PROP_FRAME_HEIGHT)
        self.maxScale=self.maxHeight/480.0        
        while True:
            ret, frame = cap.read()                  
            if ret:
                r=1                
                rescaleSize=int(480*self.curScale)                              
                if(frame.shape[0] > 480 and frame.shape[1] > 640):
                    r = rescaleSize / float(frame.shape[0])
                    self.dim = (int(frame.shape[1] * r), rescaleSize)
                    processedImage=cv2.resize(frame, self.dim, fx=0.0, fy=0.0)
                    face_locations = face_recognition.face_locations(processedImage)
                    if(len(face_locations) > 0):
                        encodefaces(facelocs)
                else:
                    processedImage=frame.copy()
                    face_locations = face_recognition.face_locations(processedImage)
                    if(len(face_locations) > 0):
                        encodefaces(facelocs)
                for face_location in face_locations:  
                    top, right, bottom, left = face_location
                    cv2.rectangle(frame,(int(right/r),int(top/r)),(int(left/r),int(bottom/r)),(0,255,0),2)
                rgbImage = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
                convertToQtFormat = QtGui.QImage(rgbImage.data, rgbImage.shape[1], rgbImage.shape[0], QtGui.QImage.Format_RGB888)                
                p = convertToQtFormat.scaled(self.scaled_size, QtCore.Qt.KeepAspectRatio)
                self.changePixmap.emit(p)

    @QtCore.pyqtSlot(QtCore.QSize)
    def scaled(self, scaled_size):
        self.scaled_size = scaled_size 

    @QtCore.pyqtSlot()
    def scaleup(self):
        self.curScale = self.curScale + 0.1
        if self.curScale > self.maxScale:
            self.curScale = self.maxScale
        self.updateStatus.emit('Cur scale:'+str(self.dim))

    @QtCore.pyqtSlot()
    def scaledown(self):
        self.curScale = self.curScale - 0.1
        if self.curScale < 1.0:
            self.curScale = 1.0
        self.updateStatus.emit('Cur scale:'+str(self.dim))

    @QtCore.pyqtSlot('QVariantMap')
    def getfacestorecognize(self, clickedInfos):
        facearray.append(clickedInfos)
        print(clickedInfos['x']+' '+clickedInfos['y']+' '+clickedInfos['name'])

    def encodefaces(self, facelocs):
        if(len(self.facearray) > 0):
            for face in facearray:
               r=(self.scaled_size[0]/self.dim[0])
               x=int(face['x'])*r
               y=int(face['y'])*r
               #for loc in facelocs:


class PlayStreaming(QtWidgets.QLabel):
    reSize = QtCore.pyqtSignal(QtCore.QSize)
    scaleupSignal = QtCore.pyqtSignal()
    scaledownSignal = QtCore.pyqtSignal()
    transferFaceInfosSignal = QtCore.pyqtSignal()#'QVariantMap'    

    def __init__(self):
        super(PlayStreaming, self).__init__()
        self.initUI()
        self.mousePressEvent = self.showDialog

    @QtCore.pyqtSlot(QtGui.QImage)
    def setImage(self, image):
        self.label.setPixmap(QtGui.QPixmap.fromImage(image))

    def initUI(self):
        # create a label
        self.label = QtWidgets.QLabel(self)        
        th = Thread(self)
        th.changePixmap.connect(self.setImage)
        th.updateStatus.connect(self.handle_status_message)
        self.scaleupSignal.connect(th.scaleup)
        self.scaledownSignal.connect(th.scaledown)
        self.transferFaceInfosSignal.connect(th.getfacestorecognize)
        self.reSize.connect(th.scaled)
        th.start()
        lay = QtWidgets.QVBoxLayout(self)
        lay.addWidget(self.label, alignment=QtCore.Qt.AlignCenter)

    def resizeEvent(self, event):
        self.reSize.emit(self.size())

    def showDialog(self, event): 
        x = event.pos().x()
        y = event.pos().y()
        facedata={"x": str(x),  "y": str(y),  "name": ''}
        text, ok = QInputDialog.getText(self, 'Name input dialog', 
            'Enter name:')        
        if (ok and str(text)!=''):
            facedata['name']=str(text)
            self.transferFaceInfosSignal.emit(facedata)

    def handle_status_message(self, message):
        self.window().set_status_message(message)    


class UIWidget(QtWidgets.QWidget):    
    def __init__(self, parent=None):
        super(UIWidget, self).__init__(parent)        
        # Initialize tab screen
        self.tabs = QtWidgets.QTabWidget()
        self.tab1 = QtWidgets.QWidget()
        self.tab2 = QtWidgets.QWidget()
        self.tab3 = QtWidgets.QWidget()

        # Add tabs
        self.tabs.addTab(self.tab1, "Face")
        self.tabs.addTab(self.tab2, "Human")
        self.tabs.addTab(self.tab3, "Vehicle")

        self.display = PlayStreaming()
        # Create first tab
        self.createGridLayout()
        self.tab1.layout = QtWidgets.QVBoxLayout()
        self.tab1.layout.addWidget(self.display, stretch=1)
        self.tab1.layout.addWidget(self.horizontalGroupBox)
        self.tab1.setLayout(self.tab1.layout)

        # Add tabs to widget
        layout = QtWidgets.QVBoxLayout(self)
        layout.addWidget(self.tabs)

    def createGridLayout(self):
        self.horizontalGroupBox = QtWidgets.QGroupBox("")
        self.horizontalGroupBox.setStyleSheet("QGroupBox{ background-color: red; border: none;}")  
        hlay1 = QtWidgets.QHBoxLayout()
        self.TestButton=QtWidgets.QPushButton('Test')
        hlay1.addWidget(self.TestButton) 
        self.RunButton=QtWidgets.QPushButton('Run')
        hlay1.addWidget(self.RunButton) 
        self.ScaleUpButton=QtWidgets.QPushButton('ScaleUp')
        self.ScaleUpButton.clicked.connect(self.display.scaleupSignal)
        hlay1.addWidget(self.ScaleUpButton) 
        self.ScaleDownButton=QtWidgets.QPushButton('ScaleDown')
        self.ScaleDownButton.clicked.connect(self.display.scaledownSignal)
        hlay1.addWidget(self.ScaleDownButton) 
        hlay1.addWidget(QtWidgets.QPushButton('Reset'))

        hlay2 = QtWidgets.QHBoxLayout()
        hlay2.addWidget(QtWidgets.QPushButton('Set Faces')) 
        hlay2.addWidget(QtWidgets.QPushButton('FacePose'))
        hlay2.addWidget(QtWidgets.QPushButton('Gender')) 
        hlay2.addWidget(QtWidgets.QPushButton('Age'))
        self.RecognizeButton=QtWidgets.QPushButton('Recognize')
        self.RecognizeButton.clicked.connect(self.display.transferFaceInfosSignal)
        hlay2.addWidget(self.RecognizeButton)

        layout = QtWidgets.QVBoxLayout()        
        layout.addLayout(hlay1)
        layout.addLayout(hlay2)
        self.horizontalGroupBox.setLayout(layout)

class App(QMainWindow): 
    def __init__(self):
        super(App,self).__init__()
        self.title = 'FaceHumanVehicle'
        self.left = 10
        self.top = 10
        self.width = 1000
        self.height = 800   
        self.initUI()

    def initUI(self):
        self.setWindowTitle(self.title)
        self.setGeometry(self.left, self.top, self.width, self.height)
        self.form_widget = UIWidget(self) 
        self.statusBar().showMessage('') 
        self.setCentralWidget(self.form_widget) 
        self.show()

    def set_status_message(self, message):
        return self.statusBar().showMessage(message) 

if __name__ == '__main__':
    import sys
    app = QApplication(sys.argv)
    ex = App()
    sys.exit(app.exec_())

1 Ответ

0 голосов
/ 15 ноября 2018

Из того, что я понимаю, вы хотите отправлять данные при нажатии кнопки, поэтому слот, соединяющий кнопку, должен излучать сигнал, а не подключаться к сигналу. Для этого данные, которые я вижу, заполнены mousePressEvent, должны быть членами класса, в этом случае логика заключается в том, чтобы сохранить позицию при нажатии изображения, а при нажатии кнопки откроется диалоговое окно, имя будет установлено, и данные будут отправлены.

class PlayStreaming(QtWidgets.QLabel):
    reSize = QtCore.pyqtSignal(QtCore.QSize)
    scaleupSignal = QtCore.pyqtSignal()
    scaledownSignal = QtCore.pyqtSignal()
    transferFaceInfosSignal = QtCore.pyqtSignal('QVariantMap') # <--- +++

    def __init__(self):
        super(PlayStreaming, self).__init__()
        self.facedata = {"x": "", "y": "", "name": ""} # <--- +++
        self.initUI()
        # self.mousePressEvent = self.showDialog <--- ---

    # ...

    def mousePressEvent(self, event):
        self.facedata["x"] = str(event.pos().x())
        self.facedata["y"] = str(event.pos().y())
        self.showDialog()
        super(PlayStreaming, self).mousePressEvent(event)

    def showDialog(self): 
        text, ok = QtWidgets.QInputDialog.getText(self, 'Name input dialog', 'Enter name:')        
        if ok and text:
            self.facedata['name']= text

    @QtCore.pyqtSlot()
    def send_signal(self)
        if self.facedata["name"]:
            self.transferFaceInfosSignal.emit(self.facedata)

class UIWidget(QtWidgets.QWidget): 
    # ...
    def createGridLayout(self):
        # ...
        self.RecognizeButton.clicked.connect(self.display.send_signal)
        # ...

С другой стороны, сигналы и слот поддерживают все собственные типы питонов, такие как dict, поэтому вы можете заменить 'QVariantMap' на dict.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...