gpt4 book ai didi

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

转载 作者:行者123 更新时间:2023-12-02 10:33:45 29 4
gpt4 key购买 nike

我想不出一个更好的更具描述性的标题,因为它涉及 3 种语言,我现在将对其进行解释。
我写了一个C++ Python 模块的包装器,顺便说一下,它在 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 端的主循环是一个阻塞方法,它们仅在阻塞方法结束时才开始执行(就像一个递归函数,直到输出不会被返回最后)。

然后我注意到 cv2.imshow()创建一个短暂的停顿,在此期间,C#客户端有机会更新输出及其发送到的内容。我首先尝试在 Python 中暂停当前正在运行的线程,它实际上有点工作,输出开始在 C# 端弹出,但应用程序仍然没有响应。

我注意到我实际上可以通过简单地使用 cv2.waitkey(1) 使回调输出显示在 C# 中。或 cv2.imread('')在 else 子句中当 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() 控制事件来打印输出并保持应用程序响应不起作用,创建新线程似乎也不起作用。似乎不能这样使用编码(marshal)回调(我很高兴听到我错了)。

当我找到比 C# 明智的(在线程上运行回调)或 Python 端更好的解决方案时,我会更新这个答案,制作一个可见的窗口或完全解决这个问题。

更新

我删除了 Python 端的更改并在 C# 部分实现了线程。初始线程不起作用的原因是,所有互操作必须在同一个线程中调用,这意味着所有导入的方法,例如 Initialize , StartAddCallback必须在同一个线程中设置和运行。

关于c# - 为什么只有在 python 模块使用 cv.imshow() 时才执行 C# 回调?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61183964/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com