最近忙完了年前的事情了,顿感空虚。所以准备这一两个月看看以前的书,另外学习下视频方面的东西(CV方面)。
之前学过几天QT/PyQt,于是用PyQt结合OpenCV,做了一个小程序。具有播放并保存摄像头捕获组成的视频,以及播放本地视频文件两个小功能。
界面很简单,没图没真相 。
代码就100多行,很容易看懂。最后感叹下OpenCV和python的强大,噢,还有QT/PyQt。。
001 | #! /usr/bin/env python |
002 | #coding=utf-8 |
003 | from PyQt4.QtCore import * |
004 | from PyQt4.QtGui import * |
005 | import sys |
006 | import opencv |
007 | from PIL import Image |
008 | #this is important for capturing/displaying images |
009 | from opencv import highgui |
010 | from opencv import cv |
011 | import time |
012 |
013 |
014 | MPEG1VIDEO = 0x314D4950 |
015 | camera = highgui.cvCreateCameraCapture(0)#找摄像头,一般填0-99都可以 |
016 |
017 |
018 | class MainWindow(QWidget): |
019 | def __init__(self, parent = None): |
020 | QWidget.__init__(self) |
021 | self.resize(550, 550) |
022 | self.setWindowTitle('vedio control') |
023 | self.status = 0 #0 is init status;1 is play video; 2 is capture video |
024 | self.image = QImage() |
025 | |
026 | #录制的视频保存位置、格式等参数设定 |
027 | self.videowriter = highgui.cvCreateVideoWriter("test.mpg", highgui.CV_FOURCC('m','p','g','1'), 25, cv.cvSize(200,200), 1) |
028 | #播放的视频位置 |
029 | self.playcapture = highgui.cvCreateFileCapture("test.avi") |
030 | |
031 | #初始化按钮 |
032 | self.capturebtn = QPushButton('capture') |
033 | self.playbtn = QPushButton('play') |
034 | exitbtn = QPushButton('exit') |
035 | |
036 | # 界面布局 |
037 | vbox = QVBoxLayout() |
038 | vbox.addWidget(self.capturebtn) |
039 | vbox.addWidget(self.playbtn) |
040 | vbox.addWidget(exitbtn) |
041 | |
042 | self.piclabel = QLabel('pic') |
043 | hbox = QHBoxLayout() |
044 | hbox.addLayout(vbox) |
045 | hbox.addStretch(1) |
046 | hbox.addWidget(self.piclabel) |
047 | |
048 | self.setLayout(hbox) |
049 | |
050 | #加载初始页面 |
051 | if self.image.load("1.jpg"): |
052 | self.piclabel.setPixmap(QPixmap.fromImage(self.image)) |
053 | |
054 | #设定定时器 |
055 | self.timer = Timer() #录制视频 |
056 | self.playtimer = Timer("updatePlay()")#播放视频 |
057 | |
058 | #信号--槽 |
059 | self.connect(self.timer, SIGNAL("updateTime()"), |
060 | self.CaptureVGA) |
061 | self.connect(self.capturebtn, SIGNAL("clicked()"), |
062 | self.PauseBegin) |
063 | self.connect(self.playtimer, SIGNAL("updatePlay()"), |
064 | self.PlayVideo) |
065 | self.connect(self.playbtn, SIGNAL("clicked()"), |
066 | self.VideoPlayPause) |
067 | self.connect(exitbtn, SIGNAL("clicked()"), |
068 | app, SLOT("quit()")) |
069 |
070 |
071 | |
072 | def PlayVideo(self): |
073 | im = highgui.cvQueryFrame(self.playcapture) |
074 | im = opencv.adaptors.Ipl2PIL(im) |
075 | im = im.convert('RGB').tostring('jpeg', 'RGB') |
076 | self.image.loadFromData(QByteArray(im)) |
077 | self.piclabel.setPixmap(QPixmap.fromImage(self.image)) |
078 | |
079 | def VideoPlayPause(self): |
080 | self.status, playstr, capturestr =((1, 'pause', 'capture'), (0, 'play', 'capture'), (1, 'pause', 'capture'))[self.status]#三种状态分别对应的显示、处理 |
081 | self.playbtn.setText(playstr) |
082 | self.capturebtn.setText(capturestr) |
083 | if self.status is 1:#状态1,播放视频 |
084 | self.timer.stop() |
085 | self.playtimer.start() |
086 | else: |
087 | self.playtimer.stop() |
088 | |
089 | def PauseBegin(self): |
090 | self.status, playstr, capturestr =((2, 'play', 'pause'), (2, 'play', 'pause'), (0, 'play', 'capture'))[self.status] |
091 | self.capturebtn.setText(capturestr) |
092 | self.playbtn.setText(playstr) |
093 | print self.status, playstr, capturestr |
094 | if self.status is 2:#状态2,录制并显示视频 |
095 | self.timer.start() |
096 | self.playtimer.stop() |
097 | else: |
098 | self.timer.stop() |
099 | |
100 | |
101 | def CaptureVGA(self): |
102 | im = highgui.cvQueryFrame(camera) |
103 | highgui.cvWriteFrame(self.videowriter, im)#录制视频,写入文件 |
104 | #convert Ipl image to PIL image |
105 | im = opencv.adaptors.Ipl2PIL(im) |
106 | im = im.convert('RGB').tostring('jpeg', 'RGB')# 转换格式,jpeg |
107 | self.image.loadFromData(QByteArray(im))#格式支持QT,直接加载 |
108 | #im.save('3.jpg')#opencv 返回的是Ipl 格式,QT无法直接显示。不知道如何转换格式,采用保存、读取的方式。 |
109 | #pic.load('3.jpg') |
110 | self.piclabel.setPixmap(QPixmap.fromImage(self.image)) #一帧一帧的显示 |
111 | |
112 | |
113 | class Timer(QThread): |
114 | |
115 | def __init__(self, signal = "updateTime()", parent=None): |
116 | super(Timer, self).__init__(parent) |
117 | self.stoped = False |
118 | self.signal = signal |
119 | self.mutex = QMutex() |
120 |
121 |
122 | def run(self): |
123 | with QMutexLocker(self.mutex): |
124 | self.stoped = False |
125 | while True: |
126 | if self.stoped: |
127 | return |
128 |
129 |
130 | self.emit(SIGNAL(self.signal)) |
131 | time.sleep(0.04) #40毫秒发送一次信号,每秒25帧 |
132 | |
133 | def stop(self): |
134 | with QMutexLocker(self.mutex): |
135 | self.stoped = True |
136 | |
137 | def isStoped(self): |
138 | with QMutexLocker(sellf.mutex): |
139 | return self.stoped |
140 | |
141 | if __name__ == "__main__" : |
142 | app = QApplication(sys.argv) |
143 | main = MainWindow() |
144 | main.show() |
145 | sys.exit(app.exec_()) |
146 |
147 | |
148 | |
149 | <div> |
150 |
151 |
152 | |
153 | |
154 | </div> |
来源:http://my.oschina.net/hebianxizao/blog/99418?from=20130103

作者分享了一段经历,利用Python的PyQt和OpenCV库,构建了一个具备摄像头实时视频播放、保存功能的小程序。代码简洁易懂,展示了OpenCV与Python的强大能力,同时涉及到了QT/PyQt的使用。


5242

被折叠的 条评论
为什么被折叠?



