всех.
Я пытаюсь создать отдельный поток для отображения и обработки изображений, поступающих с веб-камеры. Эти операции не могут быть в главном потоке, так как он предназначен для других задач. Что мне нужно сделать, это остановить и перезапустить поток.
Что происходит, когда поток работает в первый раз, но при втором запуске вызов imshow останавливается навсегда.
I воспроизвел проблему с простым примером, отклоненным от другого вопроса SO ( cv :: imshow не отображает цвет cv :: mat при работе в другом потоке )
нерабочий многопоточный код
#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 не должен работать?
Спасибо,
Marco
edit
Кажется, что оба фрагмента работают с использованием opencv3.x из репозитория. Сбой с opencv4.x, скомпилированной с нуля на Xubuntu 19.04.