最近忙完了年前的事情了,顿感空虚。所以准备这一两个月看看以前的书,另外学习下视频方面的东西(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