Created
January 12, 2015 01:22
-
-
Save ExpandOcean/58f60113a7f61f549e40 to your computer and use it in GitHub Desktop.
Operate a camera using opencv and pyqt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# coding=utf-8 | |
import sys | |
from PyQt4 import QtGui | |
import cv | |
from PyQt4 import QtCore | |
class CameraDevice(QtCore.QObject): | |
_DEFAULT_FPS = 30 | |
newFrame = QtCore.pyqtSignal(cv.iplimage) | |
def __init__(self, cameraId=0, mirrored=False, parent=None, | |
size=(640, 480)): | |
super(CameraDevice, self).__init__(parent) | |
self.mirrored = mirrored | |
self._cameraDevice = cv.CaptureFromCAM(cameraId) | |
cv.SetCaptureProperty(self._cameraDevice, cv.CV_CAP_PROP_FRAME_WIDTH, | |
size[0]) | |
cv.SetCaptureProperty(self._cameraDevice, cv.CV_CAP_PROP_FRAME_HEIGHT, | |
size[1]) | |
self._timer = QtCore.QTimer(self) | |
self._timer.timeout.connect(self._queryFrame) | |
self._timer.setInterval(1000 / self.fps) | |
self.paused = False | |
@QtCore.pyqtSlot() | |
def _queryFrame(self): | |
frame = cv.QueryFrame(self._cameraDevice) | |
if self.mirrored: | |
mirroredFrame = cv.CreateImage(cv.GetSize(frame), frame.depth, | |
frame.nChannels) | |
cv.Flip(frame, mirroredFrame, 1) | |
frame = mirroredFrame | |
self.newFrame.emit(frame) | |
@property | |
def paused(self): | |
return not self._timer.isActive() | |
@paused.setter | |
def paused(self, p): | |
if p: | |
self._timer.stop() | |
else: | |
self._timer.start() | |
@property | |
def frameSize(self): | |
w = cv.GetCaptureProperty(self._cameraDevice, | |
cv.CV_CAP_PROP_FRAME_WIDTH) | |
h = cv.GetCaptureProperty(self._cameraDevice, | |
cv.CV_CAP_PROP_FRAME_HEIGHT) | |
return int(w), int(h) | |
@property | |
def fps(self): | |
fps = int(cv.GetCaptureProperty(self._cameraDevice, cv.CV_CAP_PROP_FPS)) | |
if not fps > 0: | |
fps = self._DEFAULT_FPS | |
return fps | |
class CameraWidget(QtGui.QWidget): | |
newFrame = QtCore.pyqtSignal(cv.iplimage) | |
def __init__(self, cameraDevice, parent=None): | |
super(CameraWidget, self).__init__(parent) | |
self._frame = None | |
self._cameraDevice = cameraDevice | |
self._cameraDevice.newFrame.connect(self._on_new_frame) | |
w, h = self._cameraDevice.frameSize | |
self.setMinimumSize(w, h) | |
self.setMaximumSize(w, h) | |
@QtCore.pyqtSlot(cv.iplimage) | |
def _on_new_frame(self, frame): | |
self._frame = cv.CloneImage(frame) | |
self.newFrame.emit(self._frame) | |
self.update() | |
def changeEvent(self, e): | |
if e.type() == QtCore.QEvent.EnabledChange: | |
if self.isEnabled(): | |
self._cameraDevice.newFrame.connect(self._on_new_frame) | |
else: | |
self._cameraDevice.newFrame.disconnect(self._on_new_frame) | |
def paintEvent(self, e): | |
if self._frame is None: | |
return | |
painter = QtGui.QPainter(self) | |
painter.drawImage(QtCore.QPoint(0, 0), OpenCVQImage(self._frame)) | |
def get_curr_frame(self): | |
return QtGui.QPixmap.fromImage(OpenCVQImage(self._frame)) | |
class OpenCVQImage(QtGui.QImage): | |
def __init__(self, opencv_bgr_img): | |
depth, n_channels = opencv_bgr_img.depth, opencv_bgr_img.nChannels | |
if depth != cv.IPL_DEPTH_8U or n_channels != 3: | |
raise ValueError("the input image must be 8-bit, 3-channel") | |
w, h = cv.GetSize(opencv_bgr_img) | |
opencv_rgb_img = cv.CreateImage((w, h), depth, n_channels) | |
# it's assumed the image is in BGR format | |
cv.CvtColor(opencv_bgr_img, opencv_rgb_img, cv.CV_BGR2RGB) | |
self._imgData = opencv_rgb_img.tostring() | |
super(OpenCVQImage, self).__init__(self._imgData, w, h, | |
QtGui.QImage.Format_RGB888) | |
class Example(QtGui.QWidget): | |
def __init__(self): | |
super(Example, self).__init__() | |
self.initUI() | |
def initUI(self): | |
cameraDevice = CameraDevice(cameraId=1, mirrored=True, size=(640, 480)) | |
cameraWidget1 = CameraWidget(cameraDevice) | |
cameraWidget2 = CameraWidget(cameraDevice) | |
cameraWidget2.newFrame.connect(self.onNewFrame) | |
hbox = QtGui.QHBoxLayout() | |
hbox.addWidget(cameraWidget1) | |
hbox.addWidget(cameraWidget2) | |
self.setLayout(hbox) | |
self.setWindowTitle('Buttons') | |
self.show() | |
@QtCore.pyqtSlot(cv.iplimage) | |
def onNewFrame(self, frame): | |
cv.CvtColor(frame, frame, cv.CV_RGB2BGR) | |
msg = "processed frame" | |
font = cv.InitFont(cv.CV_FONT_HERSHEY_DUPLEX, 1.0, 1.0) | |
tsize, baseline = cv.GetTextSize(msg, font) | |
w, h = cv.GetSize(frame) | |
tpt = (w - tsize[0]) / 2, (h - tsize[1]) / 2 | |
cv.PutText(frame, msg, tpt, font, cv.RGB(255, 255, 0)) | |
def main(): | |
app = QtGui.QApplication(sys.argv) | |
ex = Example() | |
sys.exit(app.exec_()) | |
if __name__ == "__main__": | |
main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment