【问题标题】:OpenCV - imshow hangs if called two times from a threadOpenCV - 如果从一个线程调用两次,imshow 挂起
【发布时间】:2020-06-29 10:44:13
【问题描述】:

大家。

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

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

我用一个偏离另一个 SO 问题 (cv::imshow does not display cv::mat 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;
}

sn-p #1 不工作有什么原因吗?

谢谢,

马可

编辑

似乎这两个 sn-ps 都使用存储库中的 opencv3.x 工作。 在 Xubuntu 19.04 上从头开始编译的 opencv4.x 失败。

【问题讨论】:

  • 多线程版本没有任何问题,除了 'winon working multithread codendowName' :)。它似乎工作正常。但是,我会在更新状态时添加一些同步,尽管在您的特定示例中应该没有问题。你在什么操作系统上尝试这个例子?
  • 天啊!!我的手指滑了...除了我在 Xubuntu 19.04 上测试过的形式之外,我自己编译了 opencv 库(版本 4)。我可能会尝试链接存储库中的那些,感谢您的帮助!
  • AFAIK, imshow() 只是在调试期间显示图像的一种快速“n”简单的方法。它不是生产质量代码。如果您想要一个复杂的多线程 GUI,您需要编写一些 TkinterQtwxwidgets

标签: c++ multithreading opencv


【解决方案1】:

所有 UI 的东西都应该保留在主线程上!这就是导致该问题的问题。您不能在另一个线程(如 waitKey()imshow() 等)上使用 UI 内容。

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

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

Post1

Post2

Post3

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-08-04
    • 2014-11-29
    • 1970-01-01
    • 2013-11-03
    • 1970-01-01
    • 2013-12-01
    • 1970-01-01
    • 2016-02-03
    相关资源
    最近更新 更多