PyQt+OpenCV 錄製儲存、播放視訊
準備這一兩個月看看以前的書,另外學習下視訊方面的東西(CV方面)。
之前學過幾天QT/PyQt,於是用PyQt結合OpenCV,做了一個小程式。具有播放並儲存攝像頭捕獲組成的視訊,以及播放本地視訊檔案兩個小功能。
介面很簡單,沒圖沒真相 。
程式碼就100多行,很容易看懂。最後感嘆下OpenCV和python的強大,噢,還有QT/PyQt。。
#! /usr/bin/env python
#coding=utf-8
from PyQt4.QtCore import *
from PyQt4.QtGui import *
import sys
import opencv
from PIL import Image
#this is important for capturing/displaying images
from opencv import highgui
from opencv import cv
import time
MPEG1VIDEO = 0x314D4950
camera = highgui.cvCreateCameraCapture(0)#找攝像頭,一般填0-99都可以
class MainWindow(QWidget):
def __init__(self, parent = None):
QWidget.__init__(self)
self.resize(550, 550)
self.setWindowTitle('vedio control')
self.status = 0 #0 is init status;1 is play video; 2 is capture video
self.image = QImage()
#錄製的視訊儲存位置、格式等引數設定
self.videowriter = highgui.cvCreateVideoWriter("test.mpg", highgui.CV_FOURCC('m','p','g','1'), 25, cv.cvSize(200,200), 1)
#播放的視訊位置
self.playcapture = highgui.cvCreateFileCapture("test.avi")
#初始化按鈕
self.capturebtn = QPushButton('capture')
self.playbtn = QPushButton('play')
exitbtn = QPushButton('exit')
# 介面佈局
vbox = QVBoxLayout()
vbox.addWidget(self.capturebtn)
vbox.addWidget(self.playbtn)
vbox.addWidget(exitbtn)
self.piclabel = QLabel('pic')
hbox = QHBoxLayout()
hbox.addLayout(vbox)
hbox.addStretch(1)
hbox.addWidget(self.piclabel)
self.setLayout(hbox)
#載入初始頁面
if self.image.load("1.jpg"):
self.piclabel.setPixmap(QPixmap.fromImage(self.image))
#設定定時器
self.timer = Timer() #錄製視訊
self.playtimer = Timer("updatePlay()")#播放視訊
#訊號--槽
self.connect(self.timer, SIGNAL("updateTime()"),
self.CaptureVGA)
self.connect(self.capturebtn, SIGNAL("clicked()"),
self.PauseBegin)
self.connect(self.playtimer, SIGNAL("updatePlay()"),
self.PlayVideo)
self.connect(self.playbtn, SIGNAL("clicked()"),
self.VideoPlayPause)
self.connect(exitbtn, SIGNAL("clicked()"),
app, SLOT("quit()"))
def PlayVideo(self):
im = highgui.cvQueryFrame(self.playcapture)
im = opencv.adaptors.Ipl2PIL(im)
im = im.convert('RGB').tostring('jpeg', 'RGB')
self.image.loadFromData(QByteArray(im))
self.piclabel.setPixmap(QPixmap.fromImage(self.image))
def VideoPlayPause(self):
self.status, playstr, capturestr = ((1, 'pause', 'capture'), (0, 'play', 'capture'), (1, 'pause', 'capture'))[self.status]#三種狀態分別對應的顯示、處理
self.playbtn.setText(playstr)
self.capturebtn.setText(capturestr)
if self.status is 1:#狀態1,播放視訊
self.timer.stop()
self.playtimer.start()
else:
self.playtimer.stop()
def PauseBegin(self):
self.status, playstr, capturestr = ((2, 'play', 'pause'), (2, 'play', 'pause'), (0, 'play', 'capture'))[self.status]
self.capturebtn.setText(capturestr)
self.playbtn.setText(playstr)
print self.status, playstr, capturestr
if self.status is 2:#狀態2,錄製並顯示視訊
self.timer.start()
self.playtimer.stop()
else:
self.timer.stop()
def CaptureVGA(self):
im = highgui.cvQueryFrame(camera)
highgui.cvWriteFrame(self.videowriter, im)#錄製視訊,寫入檔案
#convert Ipl image to PIL image
im = opencv.adaptors.Ipl2PIL(im)
im = im.convert('RGB').tostring('jpeg', 'RGB')# 轉換格式,jpeg
self.image.loadFromData(QByteArray(im))#格式支援QT,直接載入
#im.save('3.jpg')#opencv 返回的是Ipl 格式,QT無法直接顯示。不知道如何轉換格式,採用儲存、讀取的方式。
#pic.load('3.jpg')
self.piclabel.setPixmap(QPixmap.fromImage(self.image)) #一幀一幀的顯示
class Timer(QThread):
def __init__(self, signal = "updateTime()", parent=None):
super(Timer, self).__init__(parent)
self.stoped = False
self.signal = signal
self.mutex = QMutex()
def run(self):
with QMutexLocker(self.mutex):
self.stoped = False
while True:
if self.stoped:
return
self.emit(SIGNAL(self.signal))
time.sleep(0.04) #40毫秒傳送一次訊號,每秒25幀
def stop(self):
with QMutexLocker(self.mutex):
self.stoped = True
def isStoped(self):
with QMutexLocker(sellf.mutex):
return self.stoped
if __name__ == "__main__" :
app = QApplication(sys.argv)
main = MainWindow()
main.show()
sys.exit(app.exec_())