2
Python腳本從套接字中讀取png圖像,然後試圖用OpenCV顯示,就像慢速視頻一樣。 有2個類server.py和Worker.py。 Server.py從套接字接收一個原始png並將其放在隊列中。在其自己的線程中,工作人員將png出列並顯示出來。只有第一張圖像正確顯示。其他圖像不可見(即第一個圖像保留),但ShowImage和WaitKey被調用。Python OpenCV線程
線程模型是否正確?看起來服務器套接字線程阻止OpenCV線程顯示。有沒有辦法把服務器套接字放在後臺線程上?從後臺線程調用ShowWIndow和WaitKey是否正確?我對Mac上的Python或OpenCV線程知之甚少。任何意見和建議將不勝感激。
server.py:
#! /usr/bin/env python
import sys
import SocketServer
import socket
import subprocess
import time
import cv
import Worker
import ShowImage
HOST = 'andrew-rosenblums-macbook-pro.local'
PORT = 3001
FRAME_SIZE = 144*192
data = ''
worker = Worker.Worker()
class SingleTCPHandler(SocketServer.BaseRequestHandler):
imagesSaved = 0
"One instance per connection. Override handle(self) to customize action."
def handle(self):
# self.request is the client connection
print "connection received.."
while True:
#print "calling rcv"
messageLength = self.request.recv(6) # Read 6 ascii char image size
cv.WaitKey(30)
if (len(messageLength) > 0):
print "messageLength=" + messageLength
iLength = int(messageLength)
message = ''
while (iLength > 0):
if (iLength > 1024):
chunk = self.request.recv(1024)
else:
chunk = self.request.recv(iLength)
iLength -= len(chunk)
message += chunk
print "rcvd imsg of len=" + str(len(message))
worker.write(message)
if (SingleTCPHandler.imagesSaved == 0):
SingleTCPHandler.imagesSaved += 1
print "closing stream"
self.request.close()
print "done receiving"
def finish(self):
print "finish called"
class SimpleServer(SocketServer.ThreadingMixIn, SocketServer.TCPServer):
# Ctrl-C will cleanly kill all spawned threads
daemon_threads = True
# much faster rebinding
allow_reuse_address = True
def __init__(self, server_address, RequestHandlerClass):
SocketServer.TCPServer.__init__(self, server_address, RequestHandlerClass)
if __name__ == "__main__":
server = SimpleServer((HOST, PORT), SingleTCPHandler)
# terminate with Ctrl-C
try:
print "waiting for connections..."
server.serve_forever()
except KeyboardInterrupt:
sys.exit(0)
Worker.py
#! /usr/bin/env python
import time
from threading import Thread
from Queue import Queue
import sys
import cv
import cv2
import numpy as np
import Image
from cStringIO import StringIO
class Worker(Thread):
count = 0
def __init__(self):
Thread.__init__(self)
self.cvImage = None
cv.NamedWindow('display')
cv.MoveWindow('display', 10, 10)
self.queue = Queue()
self.writer = None
# Daemon threads won't prevent process from exiting
self.setDaemon(True)
# Start ourselves automatically
self.start()
print "Worker started"
def run(self):
writer = None
while 1:
frame = None
try:
#frame = self.queue.get(block=False)
frame = self.queue.get()
print "display izeof rawImage=" + str(len(frame))
#convert to mat
pilImage = Image.open(StringIO(frame));#.convert("RGB");
bgrImage = np.array(pilImage)
cvBgrImage = cv.fromarray(bgrImage)
self.cvImage = cv.CreateImage(cv.GetSize(cvBgrImage),8,3)
cv.CvtColor(cvBgrImage, self.cvImage, cv.CV_BGR2RGB)
#show it
cv.ShowImage('display', self.cvImage)
cv.WaitKey(30)
self.cvImage = None
except:
frame = None
print "done with thread"
# Requests from main thread
def write(self, frame):
self.queue.put(frame)
def stop(self):
self.queue.put(None)
其實,他們不必從主線程運行。我發現我可以使用'cv2.imshow'和'cv2.waitKey'(其中'delay'既爲零又非零)來自其他線程。儘管在最後(如果顯示一個圖像循環)'cv2.waitKey'後必須調用'cv2.destroyAllWindows',以防止最後一個圖像掛起。我也在線程中創建了命名窗口(隱式地通過'cv2.imshow')。 – 101 2015-07-13 01:40:28
這很奇怪。我在嘗試從非主線程使用cv2.waitKey和cv2.imshow時出現錯誤「QObject :: startTimer:定時器不能從另一個線程啓動」。顯示圖像,但waitKey似乎無法測量延遲並阻止,直到按下該鍵。 – ogurets 2017-02-06 17:36:59