Python OpenCV和自定义多处理
我尝试构建一个网络摄像头软件,它使用网络摄像头输入并更改图像,然后将其输出到虚拟网络摄像头。所以我让它运行得很好,但现在我想添加一个系统托盘图标来控制它。由于这是一个GUI,我需要我的软件在另一个线程上运行 因此,我的(削减)类看起来如下:Python OpenCV和自定义多处理,python,multithreading,opencv,Python,Multithreading,Opencv,我尝试构建一个网络摄像头软件,它使用网络摄像头输入并更改图像,然后将其输出到虚拟网络摄像头。所以我让它运行得很好,但现在我想添加一个系统托盘图标来控制它。由于这是一个GUI,我需要我的软件在另一个线程上运行 因此,我的(削减)类看起来如下: import pyvirtualcam import cv2 import effects import numpy as np class VirtualCam: def __init__(self): self.stoppe
import pyvirtualcam
import cv2
import effects
import numpy as np
class VirtualCam:
def __init__(self):
self.stopped = False
self.paused = False
[...]
def run(self):
with pyvirtualcam.Camera(width=1280, height=720, fps=self.FPS, fmt=pyvirtualcam.PixelFormat.BGR) as cam:
while not self.stopped:
if not self.paused: # only copy image if NOT paused!
success, img = self.cap.read()
else:
img = self.EMPTY_IMAGE
cam.send(effects.zoom(img, self.zoom))
cam.sleep_until_next_frame()
所以这应该是直截了当的。
现在,在基于代码的gui线程上,我添加了菜单点,其中一个启动一个线程,而其他线程可以暂停、停止等(再次减少):
好吧,这应该行得通,不是吗?当我点击托盘菜单中的“开始”时,我得到一个错误:
Python WNDPROC handler failed
Traceback (most recent call last):
File "I:/Entwicklung/webcamZoomer/tray_gui.py", line 207, in command
self.execute_menu_option(id)
File "I:/Entwicklung/webcamZoomer/tray_gui.py", line 214, in execute_menu_option
menu_action(self)
File "I:/Entwicklung/webcamZoomer/tray_gui.py", line 256, in start
cam_thread.start()
File "H:\Programme\Python3\lib\multiprocessing\process.py", line 112, in start
self._popen = self._Popen(self)
File "H:\Programme\Python3\lib\multiprocessing\context.py", line 223, in _Popen
return _default_context.get_context().Process._Popen(process_obj)
File "H:\Programme\Python3\lib\multiprocessing\context.py", line 322, in _Popen
return Popen(process_obj)
File "H:\Programme\Python3\lib\multiprocessing\popen_spawn_win32.py", line 65, in __init__
reduction.dump(process_obj, to_child)
File "H:\Programme\Python3\lib\multiprocessing\reduction.py", line 60, in dump
ForkingPickler(file, protocol).dump(obj)
TypeError: can't pickle cv2.VideoCapture objects
Traceback (most recent call last):
File "<string>", line 1, in <module>
File "H:\Programme\Python3\lib\multiprocessing\spawn.py", line 105, in spawn_main
exitcode = _main(fd)
File "H:\Programme\Python3\lib\multiprocessing\spawn.py", line 115, in _main
self = reduction.pickle.load(from_parent)
EOFError: Ran out of input
Python WNDPROC处理程序失败
回溯(最近一次呼叫最后一次):
命令中第207行的文件“I:/Entwicklung/webcamZoomer/tray_gui.py”
self.execute\u菜单\u选项(id)
文件“I:/Entwicklung/webcamZoomer/tray\u gui.py”,第214行,在执行菜单选项中
菜单动作(自我)
文件“I:/Entwicklung/webcamZoomer/tray_gui.py”,第256行,开头
cam_thread.start()
文件“H:\Program\Python3\lib\multiprocessing\process.py”,第112行,在开始处
self.\u popen=self.\u popen(self)
文件“H:\program\Python3\lib\multiprocessing\context.py”,第223行,在\u Popen中
返回_default_context.get_context().Process._Popen(Process_obj)
文件“H:\program\Python3\lib\multiprocessing\context.py”,第322行,在\u Popen中
返回Popen(过程对象)
文件“H:\program\Python3\lib\multiprocessing\popen\u spawn\u win32.py”,第65行,在\uuu init中__
减少.转储(进程对象,到子进程)
文件“H:\Program\Python3\lib\multiprocessing\reduce.py”,第60行,在转储中
ForkingPickler(文件、协议).dump(obj)
TypeError:无法pickle cv2.VideoCapture对象
回溯(最近一次呼叫最后一次):
文件“”,第1行,在
文件“H:\Program\Python3\lib\multiprocessing\spawn.py”,第105行,在spawn\u main中
出口代码=_主(fd)
文件“H:\Program\Python3\lib\multiprocessing\spawn.py”,第115行,在_main中
self=reduce.pickle.load(从父级)
EOFError:输入不足
当然,我使用了搜索功能,但我只能找到一些我并不真正理解的东西:似乎OpenCV已经使用了多处理。但为什么它会干扰我的代码?此外,我不做任何手工酸洗;我实际上只需要网络摄像头的输入 有人能帮我解决这个问题吗?谢谢大家!
编辑:顺便说一句,我在Windows 10上,我只需要在Windows系统上使用此软件。“我不做任何手动酸洗”--不,但您启动一个新进程,并希望它运行您在原始进程中实例化的对象的方法。为了能够做到这一点,Python必须将该对象实例转移到第二个进程。要做到这一点,它必须通过队列发送,而要做到这一点,它需要对其进行酸洗您没有显示它,但我看到一个
self.cap.read()
,因此VirtualCam
确实有一个VideoCapture
成员(很可能已经打开)。即使可以通过某种方式对其进行腌制和传输,您也会有两个进程试图访问同一个网络摄像头(这是行不通的)@DanMašek谢谢,我现在明白了问题所在。现在我不应该在gui线程中创建实例了吗?如果没有,我如何访问实例来操作我想在virtualcam上使用的设置?您必须确保VideoCapture
(以及可能的其他对象)仅在第二个过程中实例化,并且您需要设置一些IPC机制(例如队列)将图像数据传输到主进程,并将命令传输到捕获进程IMHO多处理是一个不必要的复杂问题。OpenCV和许多numpy函数释放了GIL,因此在许多情况下,您只需使用线程
。例如,查看(有一条注释带有指向pastebin的链接,其中包含最终代码)。
Python WNDPROC handler failed
Traceback (most recent call last):
File "I:/Entwicklung/webcamZoomer/tray_gui.py", line 207, in command
self.execute_menu_option(id)
File "I:/Entwicklung/webcamZoomer/tray_gui.py", line 214, in execute_menu_option
menu_action(self)
File "I:/Entwicklung/webcamZoomer/tray_gui.py", line 256, in start
cam_thread.start()
File "H:\Programme\Python3\lib\multiprocessing\process.py", line 112, in start
self._popen = self._Popen(self)
File "H:\Programme\Python3\lib\multiprocessing\context.py", line 223, in _Popen
return _default_context.get_context().Process._Popen(process_obj)
File "H:\Programme\Python3\lib\multiprocessing\context.py", line 322, in _Popen
return Popen(process_obj)
File "H:\Programme\Python3\lib\multiprocessing\popen_spawn_win32.py", line 65, in __init__
reduction.dump(process_obj, to_child)
File "H:\Programme\Python3\lib\multiprocessing\reduction.py", line 60, in dump
ForkingPickler(file, protocol).dump(obj)
TypeError: can't pickle cv2.VideoCapture objects
Traceback (most recent call last):
File "<string>", line 1, in <module>
File "H:\Programme\Python3\lib\multiprocessing\spawn.py", line 105, in spawn_main
exitcode = _main(fd)
File "H:\Programme\Python3\lib\multiprocessing\spawn.py", line 115, in _main
self = reduction.pickle.load(from_parent)
EOFError: Ran out of input