如何在我的代码中正确使用带有树莓派相机模块的openCV?

时间:2019-01-05 10:14:24

标签: python opencv raspberry-pi3

我有一些检测情绪和面部表情的代码。我在笔记本电脑上开发了它,并且运行良好。 我放在树莓派上,现在代码没有显示视频,面部识别或情绪数据。

我从此链接为树莓派运行了命令,以查看打开的CV中的相机模块:VideoCapture.open(0) won't recognize pi cam

以及此链接:I am trying make the raspberry pi camera work with opencv

这是我的代码:

# -*- coding: utf-8 -*-
import os

import cv2
import numpy as np
from PyQt4 import QtCore, QtGui, uic
from keras.engine.saving import load_model
from keras_preprocessing.image import img_to_array
from picamera.array import PiRGBArray
from picamera import PiCamera

# parameters for loading data and images
dir_path = os.path.dirname(os.path.realpath(__file__))
detection_model_path = os.path.join("xxxx")
emotion_model_path = os.path.join("xxxx")

# hyper-parameters for bounding boxes shape
# loading models
face_detection = cv2.CascadeClassifier(detection_model_path)
emotion_classifier = load_model(emotion_model_path, compile=False)
EMOTIONS = ["angry", "disgust", "scared", "happy", "sad", "surprised", "neutral"]

emotion_classifier._make_predict_function()
running = False
capture_thread = None
form_class, _ = uic.loadUiType("simple2.ui")


def NumpyToQImage(img):
    rgb = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
    qimg = QtGui.QImage(rgb.data, rgb.shape[1], rgb.shape[0], QtGui.QImage.Format_RGB888)
    return qimg


class CaptureWorker(QtCore.QObject):
    imageChanged = QtCore.pyqtSignal(np.ndarray)

    def __init__(self, properties, parent=None):
        super(CaptureWorker, self).__init__(parent)
        self._running = False
        self._capture = None
        self._properties = properties

    @QtCore.pyqtSlot()
    def start(self):
        if self._capture is None:
            self._capture = cv2.VideoCapture(self._properties["index"])
            self._capture.set(cv2.cv.CV_CAP_PROP_FRAME_WIDTH, self._properties["width"])
            self._capture.set(cv2.cv.CV_CAP_PROP_FRAME_HEIGHT, self._properties["height"])
            self._capture.set(cv2.cv.CV_CAP_PROP_FPS, self._properties["fps"])
        self._running = True
        self.doWork()

    @QtCore.pyqtSlot()
    def stop(self):
        self._running = False

    def doWork(self):
        while self._running:
            self._capture.grab()
            ret, img = self._capture.retrieve(0)
            if ret:
                self.imageChanged.emit(img)
        self._capture.release()
        self._capture = None


class ProcessWorker(QtCore.QObject):
    resultsChanged = QtCore.pyqtSignal(np.ndarray)
    imageChanged = QtCore.pyqtSignal(np.ndarray)


    @QtCore.pyqtSlot(np.ndarray)
    def process_image(self, img):
        gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
        faces = face_detection.detectMultiScale(gray, scaleFactor=1.1, minNeighbors=5, minSize=(30, 30),
                                                flags=cv2.CASCADE_SCALE_IMAGE)
        canvas = np.zeros((250, 300, 3), dtype="uint8")
        if len(faces) > 0:
            face = sorted(faces, reverse=True, key=lambda x: (x[2] - x[0]) * (x[3] - x[1]))[0]
            (fX, fY, fW, fH) = face
            roi = gray[fY:fY + fH, fX:fX + fW]
            roi = cv2.resize(roi, (64, 64))
            roi = roi.astype("float") / 255.0
            roi = img_to_array(roi)
            roi = np.expand_dims(roi, axis=0)
            preds = emotion_classifier.predict(roi)[0]
            label = EMOTIONS[preds.argmax()]
            cv2.putText(img, label, (fX, fY - 10), cv2.FONT_HERSHEY_SIMPLEX, 0.45, (0, 0, 255), 2)
            cv2.rectangle(img, (fX, fY), (fX+fW, fY+fH), (255, 0, 0), 2)
            self.imageChanged.emit(img)

            for i, (emotion, prob) in enumerate(zip(EMOTIONS, preds)):
                text = "{}: {:.2f}%".format(emotion, prob * 100)
                w = int(prob * 300)
                cv2.rectangle(canvas, (7, (i * 35) + 5),
                              (w, (i * 35) + 35), (0, 0, 255), -1)
                cv2.putText(canvas, text, (10, (i * 35) + 23),
                            cv2.FONT_HERSHEY_SIMPLEX, 0.45,
                            (255, 255, 255), 2)
                cv2.putText(img, label, (fX, fY - 10),
                            cv2.FONT_HERSHEY_SIMPLEX, 0.45, (0, 0, 255), 2)
                cv2.rectangle(img, (fX, fY), (fX + fW, fY + fH),
                              (0, 0, 255), 2)
                self.resultsChanged.emit(canvas)


class MyWindowClass(QtGui.QMainWindow, form_class):
    def __init__(self, parent=None):
        super(MyWindowClass, self).__init__(parent)
        self.setupUi(self)
        self._thread = QtCore.QThread(self)
        self._thread.start()
        self._capture_obj = CaptureWorker({"index": 0, "width": 640, "height": 480, "fps": 30})
        self._process_obj = ProcessWorker()
        self._capture_obj.moveToThread(self._thread)
        self._process_obj.moveToThread(self._thread)
        self._capture_obj.imageChanged.connect(self._process_obj.process_image) 
        self._process_obj.imageChanged.connect(self.on_video_changed)
        self._process_obj.resultsChanged.connect(self.on_emotional_changed)
        self.startButton.clicked.connect(self.start_clicked)

    @QtCore.pyqtSlot()
    def start_clicked(self):
        QtCore.QMetaObject.invokeMethod(self._capture_obj, "start", QtCore.Qt.QueuedConnection)
        self.startButton.setEnabled(False)
        self.startButton.setText('Starting...')

    @QtCore.pyqtSlot(np.ndarray)
    def on_emotional_changed(self, im):
        img = NumpyToQImage(im)
        pix = QtGui.QPixmap.fromImage(img)
        self.emotional_label.setFixedSize(pix.size())
        self.emotional_label.setPixmap(pix)

    @QtCore.pyqtSlot(np.ndarray)
    def on_video_changed(self, im):
        img = NumpyToQImage(im)
        pix = QtGui.QPixmap.fromImage(img)
        self.video_label.setPixmap(pix.scaled(self.video_label.size()))

    def closeEvent(self, event):
        self._capture_obj.stop()
        self._thread.quit()
        self._thread.wait()
        super(MyWindowClass, self).closeEvent(event)


if __name__ == '__main__':
    import sys

    app = QtGui.QApplication(sys.argv)
    w = MyWindowClass()
    w.show()
    sys.exit(app.exec_())

当我启动我的应用程序并单击“启动相机”按钮时,相机的电源确实打开了(我看到树莓派上连接的相机模块上的红色LED)。

如何更改代码以使视频流和统计窗口显示在GUI中?

我的系统: python 2.7 最新版本的Rasbian OS 连接到Raspbery Pi 3B +的串行摄像机 使用pyqt4开发的GUI

0 个答案:

没有答案