Why can't I get 3 webcam to run in parallel with pthreads?
Hey all, I need some help with OpenCV with threading using C++. I am using a raspberry pi 3B. Which is a quad core. There are 4 USB 2.0 devices, 3 USB 2.0 webcam and USB 2.0 Arduino. The webcam’s cable has been spliced out to provide voltage on its own, so only data wires are going into the pi. The Arduino is being powered by the pi. Now to the issue. I have 4 threads going, 3 for the webcams and 1 for the Arduino. The webcams wait for the Arduino to send a signal to the webcams in parallel. The issue is, I cannot get the 3 cameras to work simultaneously. I can get any combination of 2 cameras to work but not 3. When I try 3 webcams, I get an error of empty frames.
Error:
[ WARN:2] global /home/pi/opencv/modules/videoio/src/cap_v4l.cpp (1004) tryIoctl VIDEOIO(V4L2:/dev/video0): select() timeout.
Empty Frame
terminate called after throwing an instance of 'cv::Exception'
what(): OpenCV(4.3.0) /home/pi/opencv/modules/imgcodecs/src/loadsave.cpp:738: error: (-215:Assertion failed) !_img.empty() in function 'imwrite'
Aborted
Code:
#include<stdio.h>
#include<stdlib.h>
#include<thread>
#include<iostream>
#include<fstream>
#include<opencv2/highgui/highgui.hpp>
#include<opencv2/imgproc/imgproc.hpp>
#include<opencv2/core/core.hpp>
#include"pthread.h"
#include<stdlib.h>
#include<string>
#include<boost/date_time/posix_time/posix_time.hpp>
#include<mutex>
#include<condition_variable>
#include<atomic>
std::mutex m;
std::condition_variable suspend_cv;
std::atomic<bool> enabled (false);
struct args {
int camNum;
char* camName;
int x;
int y;
};
void* camSetup(void *inputs){
cv::VideoCapture stream(((struct args*)inputs)->camNum);
cv::Mat Frame;
//cv::Mat resizeFrame;
if(!stream.isOpened()){
std::cout << "Cannot Open Camera: " + ((struct args*) inputs)->camNum + '\n';
}
else{
std::cout << "Camera Open: " << ((struct args*) inputs)->camNum + '\n';
}
std::unique_lock<std::mutex> lock(m);
while (true){
stream >> Frame;
//cv::resize(Frame, resizeFrame, cv::Size(25, 25));
while (enabled){
// Get current time from the clock, using microseconds resolution
const boost::posix_time::ptime now =
boost::posix_time::microsec_clock::local_time();
// Get the time offset in current day
const boost::posix_time::time_duration td = now.time_of_day();
const long year = now.date().year();
const long month = now.date().month();
const long day = now.date().day();
const long hours = td.hours();
const long minutes = td.minutes();
const long seconds = td.seconds();
const long milliseconds = td.total_milliseconds() -
((hours * 3600 + minutes * 60 + seconds) * 1000);
char buf[80];
sprintf(buf, "%02ld%02ld%02ld_%02ld%02ld%02ld__%03ld",
year, month, day, hours, minutes, seconds, milliseconds);
std::string sBuf = buf;
std::string PATH = std::string("/home/pi/Desktop/") +
((struct args*)inputs)->camName +
'/' +
std::string(((struct args*)inputs)->camName) +
'_' +
sBuf +
".jpeg";
if (Frame.empty())
{
std::cout << "Empty Frame" <<std::endl;
stream >> Frame;
//cv::resize(Frame, resizeFrame, cv::Size(25, 25));
}
cv::imwrite(PATH, Frame);
if (cv::waitKey(30) >= 0){
break;
}
suspend_cv.wait(lock);
}
}
return NULL;
}
void* ardReader(void*){
ARDUINO STUFF HAPPENS…
}
int main(){
struct args *cameraA = (struct args *)malloc(sizeof(struct args));
struct args *cameraB = (struct args *)malloc(sizeof(struct ...
are those usb cams ? you're probably saturating the bus. can you try with smaller resolution ?
also, please keep all gui code (imshow, waitKey, etc) on the main thread
Hey @berak, I tried using
cap.set(CV_CAP_PROP_FRAME_WIDTH,640); cap.set(CV_CAP_PROP_FRAME_HEIGHT,480);
but this did not work.Also I am not sure what gui parts would need to be in the main thread. I don't really display anything. the only reason I have waitKey, is because I thought I would need it.
Yes, these are usb cams.
Didn't you install Arduino on Raspberry Pi?
Yes, but I don't think there is anything inherently wrong with that. Its getting opencv to save 3 usb webcams to save at the same time.