ということで、表題通り、OpenCV/numpyなどで扱ってる画像データをQt(pyqt5)のウィジェット上に表示する方法。
そんなに難しくもないのだけど、メモとして投稿してみる。
ここでは、Pythonから使えるQtラッパーであるPyQt5を使った例。
C++とかでも記述方法が変わるだけで要点は同じである。
まずは、イメージの配列(メモリ上に展開されている)を、QPixmap
に変換。
下記ソースを見てもらえれば分かるように、ARGB形式のデータである必要がある。なので、もしGrayscaleやRGB形式のデータであれば、OpenCVのcvtColor()
などで、事前にARGB形態に変換しておく必要がある。
import PyQt5.QtCore as QtCore
import PyQt5.QtGui as QtGui
import PyQt5.QtWidgets as QtWidgets
def create_QPixmap(image):
qimage = QtGui.QImage(image.data, image.shape[1], image.shape[0], image.shape[1] * 4, QtGui.QImage.Format_ARGB32_Premultiplied)
pixmap = QtGui.QPixmap.fromImage(image)
return pixmap
で、表示するためには、何らかのQWidget
上に、このQPixmap
を描画する必要がある。
なので、QWidget
を拡張して1つ、クラスを作っておくと便利である。
このクラスでは、ウィジェットが描画されるタイミングで呼び出されるpaintEvent()
を拡張して、その中でイメージを描画するようにしてみた。さらなる高速描画が必要なら、OpenGLなどの利用も検討かな。
QtGui.QPainter
を利用するところがポイント。
class ImageWidget(QtWidgets.QWidget):
def __init__(self, image):
super(ImageWidget, self).__init__()
self.image = image
def paintEvent(self, event):
painter = QtGui.QPainter(self)
if self.image is None:
painter.setPen(QtCore.Qt.black)
painter.setBrush(QtCore.Qt.black)
painter.drawRect(0, 0, self.width(), self.height())
return
pixmap = create_QPixmap(self.image)
painter.drawPixmap(0, 0, self.image.shape[1], self.image.shape[0], pixmap)
def set_image(self, image):
self.image = image
self.update()
ということで、以上!
matplotlib
使うよりスピードはダンチだし、OpenCVのimshow()
みたいな簡易的な感じでもないし、pygame
使うよりはちゃんとしたGUI形態に出来る。用途に応じて使い分けましょう。