【发布时间】: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,您需要编写一些Tkinter、Qt或wxwidgets。
标签: c++ multithreading opencv