如果要用Python播放视频,或者打开摄像头获取视频流,我们可以用OpenCV Python。但是在视频帧获取的时候同时做一些图像识别和处理,可能会因为耗时多而导致卡顿。一般来说,我们首先会想到把这些工作放入到线程中处理。但是由于Python GIL的存在,用不用线程几乎没有区别。所以要解决这个问题,必须通过多进程。这里分享下使用Dynamsoft Barcode Reader开发Python条形码扫码的例子。
安装Dynamsoft Barcode Reader:
pip install dbr
安装OpenCV Python
pip install opencv-python
在主程序中创建一个新的扫码进程和共享内存:
from multiprocessing import Process, Queue
frame_queue = Queue(4)
finish_queue = Queue(1)
dbr_proc = Process(target=dbr_run, args=(
frame_queue, finish_queue))
dbr_proc.start()
通过OpenCV不断获取视频帧插入到队列中:
vc = cv2.VideoCapture(0)
if vc.isOpened(): # try to get the first frame
rval, frame = vc.read()
else:
return
windowName = "Barcode Reader"
base = 2
count = 0
while True:
cv2.imshow(windowName, frame)
rval, frame = vc.read()
count %= base
if count == 0:
try:
frame_queue.put_nowait(frame)
except:
try:
while True:
frame_queue.get_nowait()
except:
pass
count += 1
条形码读取进程不断从队列中拿出数据进行解码:
def dbr_run(frame_queue, finish_queue):
dbr.initLicense(config.license)
while finish_queue.qsize() == 0:
try:
inputframe = frame_queue.get_nowait()
results = dbr.decodeBuffer(inputframe, config.barcodeTypes)
if (len(results) > 0):
print(get_time())
print("Total count: " + str(len(results)))
for result in results:
print("Type: " + result[0])
print("Value: " + result[1] + "\n")
except:
pass
dbr.destroy()
这样基本完成。不过在app退出的时候会看到一些错误信息:
Traceback (most recent call last):
File "E:\Programs\Python\Python36\lib\multiprocessing\queues.py", line 236, in _feed
send_bytes(obj)
File "E:\Programs\Python\Python36\lib\multiprocessing\connection.py", line 200, in send_bytes
self._send_bytes(m[offset:offset + size])
File "E:\Programs\Python\Python36\lib\multiprocessing\connection.py", line 290, in _send_bytes
nwritten, err = ov.GetOverlappedResult(True)
BrokenPipeError: [WinError 109] The pipe has been ended
记得在结束应用之前要清空队列中的数据:
def clear_queue(queue):
try:
while True:
queue.get_nowait()
except:
pass
queue.close()
queue.join_thread()
程序运行效果:
https://github.com/dynamsoft-dbr/python/blob/master/examples/camera/camera_multiprocessing.py