为什么仅在python模块使用cv.imshow()时才执行C#回调?

问题描述 投票:1回答:1

我无法提供更好的更具描述性的标题,因为它涉及3种语言,我现在将对其进行解释。我围绕Python模块编写了一个C++包装器,顺便说一下,它在C ++中工作得很好。我用这个包装器制作了一个DLL,并将某些功能公开为C,并在C#应用程序中使用了它们。

问题是,如果我不显示网络摄像头,则C#应用程序将挂起。即在Python模块中存在这种情况:

if self.debug_show_feed:
    cv2.imshow('service core face Capture', frame)

并且设置为True时,将显示网络摄像头。这主要是我调试的东西,在实际生产中需要禁用它。在C ++上很好我可以将其设置为false(通过构造函数),一切都很好。但是,在C#上,如果我尝试使用该模块而不将摄像头提要设置为true,则不会发生此行为,C#应用会挂起,这是因为Start()调用了主操作成为阻塞调用,并且不返回任何回调。我的DllImport如下:

[DllImport(@"Core_DLL.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern int Initialize(bool showFeed);

[DllImport(@"Core_DLL.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern void Start(bool async);

[DllImport(@"Core_DLL.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern void Stop();

[DllImport(@"Core_DLL.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern void SetCpuAffinity(int mask);



public delegate void CallbackDelegate(bool status, string message);
[MethodImplAttribute(MethodImplOptions.InternalCall)]

[DllImport(@"Core_DLL.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern void AddCallback(IntPtr fn);

[DllImport(@"Core_DLL.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern void RemoveCallback(IntPtr fn);

这是我的C#回调:

private CallbackDelegate del;
public void SetUpCallback()
{
    txtLog.Text += "Registering C# callback...\r\n";
    del = new CallbackDelegate(callback01);
    AddCallback(Marshal.GetFunctionPointerForDelegate(del));
    txtLog.Text += "Calling passed C++ callback...\r\n";
}

bool status;
string id;
public void callback01(bool status, string id)
{
     this.status = status;
     this.id = id;
}

这是执行的主要python模块:

def start(self):
    try:
        self.is_running = True
        self._main_loop()

    except Exception as ex:
        path='exceptions-servicecore.log'
        track = traceback.format_exc()
        exception_time = datetime.now().strftime("%d/%m/%Y %H:%M:%S")
        with open(path, 'a') as f:
            f.writelines(f'\n{exception_time} : exception occured {ex.args} \n{track}')

def start_async(self):
    st = threading.Thread(target=self.start) 
    st.start()

def _main_loop(self):

    name = None
    is_valid = False
    while self.is_running and self.cap.isOpened():
        is_success, frame = self.cap.read()
        if is_success:
            name="sth"
            is_valid=True

            self._execute_callbacks(is_valid, name, frame)
            self._execute_c_callbacks(is_valid, name)

            if self.debug_show_feed:
                cv2.imshow('service core face Capture', frame)

        if self.save:
            self.video_writer.write(frame)

        if (cv2.waitKey(1)&0xFF == ord('q')) or (not self.is_running):
            break

    self.cap.release()
    if self.save:
        self.video_writer.release()
    cv2.destroyAllWindows()    

[知道这仅在C#中发生,而不在C++中发生,在这种情况下,我的封送处理或尝试使用C#回调的方式可能会出现问题。

这里是一个Visual Studio,其中包含一个最小的示例来演示此:https://workupload.com/file/epsgzmMMVMY

这里是什么问题?为什么cv.imshow()会导致这种现象?

c# python c++ unmanaged pybind11
1个回答
0
投票

我发现了C#端的回调未输出任何内容的原因。回调都按照应有的方式执行,但是由于python端的主循环是一个阻塞方法,因此它们仅在阻塞方法结束时才开始执行。直到最后)。然后,我注意到cv2.imshow()创建了一个短暂的暂停,在这段时间内,C#客户端有机会更新输出及其发送到的内容。我首先尝试在Python中暂停当前正在运行的线程,但实际上它确实有效,输出开始在C#侧弹出,但该应用仍然没有响应。我注意到我实际上可以通过简单地使用C#使回调输出显示出来cv2.waitkey(1)为False时,else子句中的cv2.imread('')showFeed

while (self.is_running):
...
    if self.showFeed:
        cv2.imshow("image", frame)
    else:
        #cv2.imread('')
        # or 
        cv2.waitkey(1)
    ...

并且通过写:

while (self.is_running):
...
    if self.showFeed:
        cv2.imshow("image", frame)
    else:
        cv2.namedWindow('image', cv2.WINDOW_OPENGL)
        cv2.waitKey(1)
        cv2.destroyAllWindows()
    ...

输出显示一切正常,应用程序再次响应,但是

,不断创建和销毁一个空的opencv窗口并不是一种解决方案,因为它会闪烁并且非常糟糕。

我需要补充一点,在c#上使用timer()控制事件来打印输出并保持应用程序响应不起作用,创建新线程似乎也不起作用。似乎无法像这样使用经过编组的回调(如果我错了,如果您能解释怎么做,我将不胜感激)

当我找到比C#明智的解决方案(在线程上运行回调)或Python端更好的解决方案时,我将更新此答案,从而使可见的窗口或完全解决此问题。

© www.soinside.com 2019 - 2024. All rights reserved.