我试图用Python,OpenCV和Tkinter创建一个多线程程序。 我的计划有一些普遍意义。
然而,我的剧本似乎表现得很奇怪。有时它可以完成播放视频直到结束,但有时它也会在视频的某个时刻崩溃。这是我到目前为止所做的。
from Tkinter import Tk, Text
from Tkinter import PhotoImage
from ttk import Frame, Scrollbar, Button, Label
from PIL import Image, ImageTk
import cv
import time
import Queue
import threading
def writeToLog(log, msg):
numlines = log.index('end - 1 line').split('.')[0]
if log.index('end-1c')!='1.0': log.insert('end', '\n')
log.insert('end', msg)
log.see('end')
def GetIplImageMode(img):
orientation = 1 if img.origin == 0 else -1
mode_list = {(1, cv.IPL_DEPTH_8U) : ("L", "L", 1),\
(3, cv.IPL_DEPTH_8U) : ("BGR", "RGB", 3),\
(1, cv.IPL_DEPTH_32F) : ("F", "F", 4)}
key = (img.nChannels, img.depth)
modes = mode_list[key]
return [modes[0], modes[1], orientation]
def IplImage2PIL(img, mode):
return Image.fromstring(mode[1], (img.width, img.height),\
img.tostring(), "raw", mode[0],\
img.width * img.channels,\
mode[2])
def ResizePILImage(pil, width = 260, height = 180):
return pil.resize((width, height), Image.ANTIALIAS)
def PIL2TkImage(pil):
return ImageTk.PhotoImage(pil)
def setImageLabelFromIplImage(label, img_ipl):
mode = GetIplImageMode(img_ipl)
img_pil = IplImage2PIL(img_ipl, mode)
img_resized = ResizePILImage(img_pil)
img_tk = PIL2TkImage(img_resized)
label.configure(image = img_tk)
label.image = img_tk
def setImageLabelFromFile(label, szFileName):
img_ipl = cv.LoadImage(szFileName)
setImageLabelFromIplImage(label, img_ipl)
def mat_from_ipl(ipl):
return cv.GetMat(ipl)
def ipl_from_mat(mat):
ipl = cv.CreateImageHeader((mat.width, mat.height),\
cv.IPL_DEPTH_8U, mat.channels)
cv.SetData(ipl, mat.tostring())
return ipl
class asdf(Frame):
def __init__(self, parent):
Frame.__init__(self, parent)
self.pack(fill='both', expand=True)
self.parent = parent
self.variables()
self.ui()
def variables(self):
self.ctr = 0
self.fps = 0
self.video = None
self.image = None
self.putProc = None
self.getProc = None
self.isRunning = False
self.queue = Queue.Queue()
def ui(self):
f1 = Frame(self)
frm1 = Frame(f1)
self.lbl1 = Label(frm1, image=None)
setImageLabelFromFile(self.lbl1, '../image.bmp')
self.txt1 = Text(frm1, width=30, height=8)
sb1 = Scrollbar(frm1, orient='vertical', command=self.txt1.yview)
self.txt1.configure(yscrollcommand = sb1.set)
self.lbl1.pack()
self.txt1.pack(side='left')
sb1.pack(side='left', fill='y')
frm1.pack(side='left')
frm2 = Frame(f1)
self.lbl2 = Label(frm2, image=None)
setImageLabelFromFile(self.lbl2, '../image.bmp')
self.txt2 = Text(frm2, width=30, height=8)
sb2 = Scrollbar(frm2, orient='vertical', command=self.txt2.yview)
self.txt2.configure(yscrollcommand = sb2.set)
self.lbl2.pack()
self.txt2.pack(side='left')
sb2.pack(side='left', fill='y')
frm2.pack(side='left')
f1.pack()
f2 = Frame(self)
Button(f2, text='Run', command=self.run).pack(side='left')
Button(f2, text='Stop', command=self.stop).pack(side='left')
f2.pack()
def put_to_queue(self):
while self.isRunning:
self.ctr = self.ctr + 1
self.image = cv.QueryFrame(self.video)
time.sleep(1 / self.fps)
try:
writeToLog(self.txt1, '\nPut to queue .. %d' % (self.ctr))
temp1 = cv.CloneImage(self.image)
setImageLabelFromIplImage(self.lbl1, temp1)
temp2 = mat_from_ipl(temp1)
self.queue.put([self.ctr, temp2])
except:
writeToLog(self.txt1, '\nReach end of video ..')
break
def get_from_queue(self):
while self.isRunning:
from_queue = self.queue.get()
self.ctr_fr = from_queue[0]
if self.ctr_fr == self.ctr: time.sleep(30 / self.fps)
temp1 = ipl_from_mat(from_queue[1])
setImageLabelFromIplImage(self.lbl2, temp1)
writeToLog(self.txt2, '\nGet from queue .. %d' % (self.ctr_fr))
time.sleep(1 / self.fps)
def run(self):
self.isRunning = True
self.video = cv.CreateFileCapture('../video.avi')
self.fps = cv.GetCaptureProperty(self.video, cv.CV_CAP_PROP_FPS)
writeToLog(self.txt1, '\nStart put_queue ..')
self.putProc = threading.Thread(target=self.put_to_queue)
self.putProc.start()
time.sleep(1)
writeToLog(self.txt2, '\nStart get_queue ..')
self.getProc = threading.Thread(target=self.get_from_queue)
self.getProc.start()
def stop(self):
self.isRunning = False
if self.putProc.isAlive():
self.putProc._Thread__stop()
writeToLog(self.txt1, '\nputProc still alive, stopping ..')
self.putProc = None
if self.getProc.isAlive():
self.getProc._Thread__stop()
writeToLog(self.txt2, '\ngetProc still alive, stopping ..')
self.getProc = None
self.ctr_fr = 0
self.ctr = 0
if __name__ == '__main__':
root = Tk()
c = asdf(root)
root.mainloop()
我做错了吗?
任何想法都将非常感激。
由于