OpenCVでWebカメラ画像を取り込み, PySide2のQGraphicsViewに表示した際に, 少しハマったのでメモしておく.
[開発環境]
CPU : Intel Core i7 - 7700
OS : Ubuntu 20.04
Python : 3.7.11
opencv-python-headless : 4.5.5.62
PySide2 : 5.15.2.1
1. 不具合症状
まず, 発生した不具合症状について説明する.
以下のようなコードで, Webカメラ画像を読み込み, 表示するようなものである.
class MainDialog(QMainWindow): def __init__(self): super(MainDialog, self).__init__() self.ui = QUiLoader().load('./resource/dlgMain.ui') self.setWindowTitle(self.ui.windowTitle()) self.setCentralWidget(self.ui) # Setup Camera self.cap = cv2.VideoCapture(0) if not self.cap.isOpened(): raise 'Camera open error!' width = self.cap.get(cv2.CAP_PROP_FRAME_WIDTH) height = self.cap.get(cv2.CAP_PROP_FRAME_HEIGHT) fps = self.cap.get(cv2.CAP_PROP_FPS) # Setup Timer self.timer = QTimer() self.timer.timeout.connect(self.displayFrame) self.timer.start(1000/fps) # Setup View self.scene = QGraphicsScene(0, 0, width, height, self.ui.viewImage) self.ui.viewImage.setScene(self.scene) self.ui.viewImage.setCacheMode(QGraphicsView.CacheBackground) def displayFrame(self): ret, frame = self.cap.read() if ret == False: return # View frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB) h, w, c = frame.shape image = QImage(frame.flatten(), w, h, QImage.Format_RGB888) self.pixmap = QPixmap.fromImage(image) self.scene.clear() self.scene.addPixmap(self.pixmap) self.ui.viewImage.fitInView(self.scene.sceneRect(), Qt.KeepAspectRatio)
カメラ画像のビューへの表示は, QImage→QPixmap→QGraphicsSceneに追加→QGraphicsViewにセットって感じで行う.
この場合, 一応画像が表示されたが, カメラを動かしたりすると, 一部フレームで白っぽい画像となりチラついた動画となる時があった.
また, Webカメラ画像の読み込みを別スレッドで動作させた場合, 以下のような少しノイズのある 白っぽい画像となってカメラ画像が表示されません.
2. 対応策
少し調べて, あれこれ試してみたところ, 原因はいまだ不明なのだが, 対応策は見えてきた.
OpenCVで読み込んだ画像をQImageにする際, よく以下のようなコードを見かける. [1][2]
image = QImage(frame.flatten(), w, h, QImage.Format_RGB888)
ここの所を, 以下のように記述することで安定して画像表示できることが分かった. [3]
image = QImage(frame.data, w, h, w*c, QImage.Format_RGB888)
OpenCVやPySide2のバージョンに依存する不具合かもしれませんが, ご参考まで.
----
参照URL :
[1] OpenCV+pySide2でWebカメラ画像表示
[2] PyQtとOpenCVでwebカメラの映像表示 - 坂推しNIerの雑記帳
[3] OpenCV Face Detection Example - Qt for Python