I have two tasks (Threads) each task runs on a different processor(core), the first capture an image repeatedly using OpenCV videocapture()
.
I only used these two lines for the capture :
cv::Mat frame;
capture.read(frame);
Now I want to display the captured image using the second task. After executing the imshow
function within the second task's code :
cv::imshow("Display window", frame);
I got the following output error :
OpenCV Error: Assertion failed (size.width>0 && size.height>0) in imshow, file /build/opencv-L2vuMj/opencv-3.2.0+dfsg/modules/highgui/src/window.cpp, line 304
terminate called after throwing an instance of 'cv::Exception'
what(): /build/opencv-L2vuMj/opencv-3.2.0+dfsg/modules/highgui/src/window.cpp:304: error: (-215) size.width>0 && size.height>0 in function imshow
So, how can I avoid this error?
The complete code is hosted at Github
cv::VideoCapture::read()
returns bool
indicating if the read was successful or not.
You are passing an empty frame
to cv::imshow()
. Try checking if the read was successful before trying to show it.
cv::Mat frame;
if(capture.read(frame))
{
cv::imshow(frame);
}
OP posted a link to the code. In his program frame
is declared as a global variable. In line 120
capture.read(frame)
writing into the frame and in line 140
imshow(frame)
reads from the frame
without using a mutex - that's a data race. Correct code should be along the lines of:
#include <mutex>
#include <opencv2/opencv.hpp>
std::mutex mutex;
cv::Mat frame;
{
mutex.lock();
capture.read(frame);
mutex.unlock();
}
{
mutex.lock();
cv::imshow(frame);
mutex.unlock();
}
The problem with your code is that there is a data race.. Imagine the display thread goes first lock the frame & try to display it before it is read so as you can see the problem If you want a synchronized solution you can use the pthread condition & wait till an image is read to signal your display function otherwise you are gonna have an active wait!!
// in the declaration part
// Declaration of thread condition variable
pthread_cond_t cond1 = PTHREAD_COND_INITIALIZER;
//in the display function
ptask DisplyingImageTask()
{
int task_job = 0;
while (1)
{
std::cout << "The job " << task_job << " of Task T" << ptask_get_index()
<< " is running on core " << sched_getcpu() << " at time : "
<< ptask_gettime(MILLI) << std::endl;
cv::namedWindow("Display window", cv::WINDOW_AUTOSIZE);
pthread_mutex_lock(&frame_rw);
//wait for the read function to send a signal
pthread_cond_wait(&cond1, &frame_rw);
cv::imshow("Display window", frame);
cv::waitKey(1);
pthread_mutex_unlock(&frame_rw);
ptask_wait_for_period();
task_job++;
}
}
// in the Read function
ptask CapturingImageTask()
{
int task_job = 0;
while (1)
{
std::cout << "The job " << task_job << " of Task T" << ptask_get_index()
<< " is running on core " << sched_getcpu() << " at time : "
<< ptask_gettime(MILLI) << std::endl;
pthread_mutex_lock(&frame_rw);
capture.read(frame);
//after capturing the frame signal the display function & everything should be synchronize as you want
pthread_cond_signal(&cond1);
pthread_mutex_unlock(&frame_rw);
ptask_wait_for_period();
task_job++;
}
}
int main()
{
VideoCapture cap;
while(1){
Mat frame;
cap >> frame;
imshow("frame",frame);
waitKey();}
}
You can try this. İf you write waitKey(); Code want to press any key for get frame and show frame.
As others have mentioned try using a mutex.
You can also have a condition on the cv::Mat before trying to display it:
if (frame.data())
imshow("window", frame);
This will check that the frame to be displayed has data and thus avoiding the error.
Again this condition is only to avoid the imshow error and not to solve the original problem which, as mentioned in other answers, is a data race between the 2 threads.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.