OpenCV - 如果从线程调用两次,imshow 就会挂起

2024-04-14

大家。

我试图有一个单独的线程来显示和处理来自网络摄像头的图像。 这些操作不能在主线程中,因为它专用于其他任务。 我需要做的是停止并最终重新启动线程。

发生的情况是,线程第一次运行,但在第二次运行时,imshow 调用永远冻结。

我用一个偏离另一个SO问题的简单例子重现了这个问题(在不同线程上时,cv::imshow 不显示 cv::mat 颜色 https://stackoverflow.com/questions/35189841/cvimshow-does-not-display-cvmat-color-when-on-different-thread)

不工作的多线程代码

#include <opencv2/opencv.hpp>
#include <thread>
#include <string>

using namespace std;
using namespace cv;

class Capture {
private:
    bool running;

    std::thread thread;
    cv::Mat background;
    void loop() {

        while (running) {
            cv::imshow(windowName, background);  // at the second time the thread is started this instruction will hang
            cv::waitKey(500);
            Scalar color(rand()&255, rand()&255, rand()&255);
            background.setTo(color);
        }
     cv::destroyWindow(windowName);
    cv::waitKey(1);
    }
public:
    char windowName[128];
    Capture() :
    windowName{"test"},
    running{ false },
        thread{},
        background{ 800, 800, CV_8UC3, cv::Scalar{ 255, 0, 255 } } {
    }
    inline ~Capture() {
        if (running) stop(); // stop and join the thread
    }
    void run() {
        if (!running) {
            running = true;
            thread = std::thread{ &Capture::loop, this };
        }
    }
    inline void join() { if (thread.joinable()) thread.join(); };
    inline void stop() {
        running = false;
        if (thread.joinable()) {
            thread.join();
        }
    }
};

int main()
{
    Capture cap;
    // run the thread one time
    cap.run();
    std::this_thread::sleep_for(std::chrono::milliseconds(2500));
    cap.stop();
    // wait
    std::this_thread::sleep_for(std::chrono::milliseconds(500));
    // run again
    cap.run(); //stuck!!!
    std::this_thread::sleep_for(std::chrono::milliseconds(2500));
    cap.stop();

    return 0;
}

工作单线程代码

#include <opencv2/opencv.hpp>
#include <thread>
#include <string>

using namespace std;
using namespace cv;

int main()
{
    Scalar color(rand()&255, rand()&255, rand()&255);
    cv::Mat background(800, 800, CV_8UC3, cv::Scalar{ 255, 0, 255 }) ;
    background.setTo(color);
    // try the first time to display an image
    for (int i=0; i<5; i++)
    {
    cv::imshow("test", background);
        cv::waitKey(500);
        color=(rand()&255, rand()&255, rand()&255);
        background.setTo(color);
    }
    // destroy the image
    cv::destroyWindow("test");

    // repeat the same as before
    for (int i=0; i<5; i++)
    {
    cv::imshow("test", background);
        cv::waitKey(500);
        color=(rand()&255, rand()&255, rand()&255);
        background.setTo(color);
    }
    cv::destroyWindow("test");
    // it worked !
    return 0;
}

片段 #1 不应该工作有什么原因吗?

Thanks,

Marco

edit

看来这两个片段都使用存储库中的 opencv3.x 来工作。 在 Xubuntu 19.04 上从头编译 opencv4.x 失败。


所有 UI 内容都应该保留在主线程上!这就是导致该问题的问题。你can not在另一个线程上使用 UI 东西,例如waitKey(), imshow() etc.

此外,您还试图从另一个线程停止计时器,这也是另一个问题。

以下是提到同一问题的主题:

Post1 https://github.com/opencv/opencv/issues/8407

Post2 https://answers.opencv.org/question/175795/using-multithreading-in-opencv/

Post3 https://answers.opencv.org/question/202790/run-opencv-application-concurrently-to-main-program/

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

OpenCV - 如果从线程调用两次,imshow 就会挂起 的相关文章

  • C# 和 Javascript SHA256 哈希的代码示例

    我有一个在服务器端运行的 C 算法 它对 Base64 编码的字符串进行哈希处理 byte salt Convert FromBase64String serverSalt Step 1 SHA256Managed sha256 new S
  • ASP.NET Core Serilog 未将属性推送到其自定义列

    我有这个设置appsettings json对于我的 Serilog 安装 Serilog MinimumLevel Information Enrich LogUserName Override Microsoft Critical Wr
  • Qt-Qlist 检查包含自定义类

    有没有办法覆盖加载自定义类的 Qt QList 的比较机制 即在 java 中你只需要重写一个比较方法 我有一个带有我的自定义类模型的 QList QList
  • 获取按下的按钮的返回值

    我有一个在特定事件中弹出的表单 它从数组中提取按钮并将标签值设置为特定值 因此 如果您要按下或单击此按钮 该函数应返回标签值 我怎样才能做到这一点 我如何知道点击了哪个按钮 此时代码返回 DialogResult 但我想从函数返回 Tag
  • 将数组向左或向右旋转一定数量的位置,复杂度为 o(n)

    我想编写一个程序 根据用户的输入 正 gt 负 include
  • UML类图:抽象方法和属性是这样写的吗?

    当我第一次为一个小型 C 项目创建 uml 类图时 我在属性方面遇到了一些麻烦 最后我只是将属性添加为变量 lt
  • Meteor.setTimeout 和 Meteor.methods 之间的并发

    在我的 Meteor 应用程序中实现回合制多人游戏服务器 客户端通过发布 订阅接收游戏状态 并且可以调用 Meteor 方法sendTurn将回合数据发送到服务器 他们无法直接更新游戏状态集合 var endRound function g
  • 使闭包捕获的变量变得易失性

    闭包捕获的变量如何与不同线程交互 在下面的示例代码中 我想将totalEvents 声明为易失性的 但C 不允许这样做 是的 我知道这是错误的代码 这只是一个例子 private void WaitFor10Events volatile
  • 当 contains() 工作正常时,xpath 函数ends-with() 工作时出现问题

    我正在尝试获取具有以特定 id 结尾的属性的标签 like span 我想获取 id 以 国家 地区 结尾的跨度我尝试以下xpath span ends with id Country 但我得到以下异常 需要命名空间管理器或 XsltCon
  • 指针问题(仅在发布版本中)

    不确定如何描述这一点 但我在这里 由于某种原因 当尝试创建我的游戏的发布版本进行测试时 它的敌人创建方面不起作用 Enemies e level1 3 e level1 0 Enemies sdlLib 500 2 3 128 250 32
  • C - 找到极限之间的所有友好数字

    首先是定义 一对友好的数字由两个不同的整数组成 其中 第一个整数的除数之和等于第二个整数 并且 第二个整数的除数之和等于第一个整数 完美数是等于其自身约数之和的数 我想做的是制作一个程序 询问用户一个下限和一个上限 然后向他 她提供这两个限
  • WPF TabControl,用C#代码更改TabItem的背景颜色

    嗨 我认为这是一个初学者的问题 我搜索了所有相关问题 但所有这些都由 xaml 回答 但是 我需要的是后台代码 我有一个 TabControl 我需要设置其项目的背景颜色 我需要在选择 取消选择和悬停时为项目设置不同的颜色 非常感谢你的帮助
  • 在 ASP.NET Core 3.1 中使用包含“System.Web.HttpContext”的旧项目

    我们有一些用 Net Framework编写的遗留项目 应该由由ASP NET Core3 1编写的API项目使用 问题是这些遗留项目正在使用 System Web HttpContext 您知道它不再存在于 net core 中 现在我们
  • Github Action 在运行可执行文件时卡住

    我正在尝试设置运行google tests on a C repository using Github Actions正在运行的Windows Latest 构建过程完成 但是当运行测试时 它被卡住并且不执行从生成的可执行文件Visual
  • 当操作繁忙时,表单不执行任何操作(冻结)

    我有一个使用 C 的 WinForms 应用程序 我尝试从文件中读取一些数据并将其插入数据表中 当此操作很忙时 我的表单冻结并且无法移动它 有谁知道我该如何解决这个问题 这可能是因为您在 UI 线程上执行了操作 将文件和数据库操作移至另一个
  • 将文本叠加在图像背景上并转换为 PDF

    使用 NET 我想以编程方式创建一个 PDF 它仅包含一个背景图像 其上有两个具有不同字体和位置的标签 我已阅读过有关现有 PDF 库的信息 但不知道 如果适用 哪一个对于如此简单的任务来说最简单 有人愿意指导我吗 P D 我不想使用生成的
  • Process.Start 阻塞

    我正在调用 Process Start 但它会阻止当前线程 pInfo new ProcessStartInfo C Windows notepad exe Start process mProcess new Process mProce
  • 如何使用 std::string 将所有出现的一个字符替换为两个字符?

    有没有一种简单的方法来替换所有出现的 in a std string with 转义 a 中的所有斜杠std string 完成此操作的最简单方法可能是boost字符串算法库 http www boost org doc libs 1 46
  • 防止索引超出范围错误

    我想编写对某些条件的检查 而不必使用 try catch 并且我想避免出现 Index Out of Range 错误的可能性 if array Element 0 Object Length gt 0 array Element 1 Ob
  • 使用按位运算符相乘

    我想知道如何使用按位运算符将一系列二进制位相乘 但是 我有兴趣这样做来查找二进制值的十进制小数值 这是我正在尝试做的一个例子 假设 1010010 我想使用每个单独的位 以便将其计算为 1 2 1 0 2 2 1 2 3 0 2 4 虽然我

随机推荐