I'm trying to make a live stereovision setup using OpenCV in C++ and two webcams. It is possible to seperately get frames from the two webcams. However, when I try to access them simultaneously in threads, I get a runtime error:
VIDIOC_STREAMON: Cannot allocate memory
OpenCV Error: Assertion failed (size.width>0 && size.height>0) in imshow, file /home/lorre851/Downloads/opencv-3.1.0/modules/highgui/src/window.cpp, line 281
terminate called after throwing an instance of 'cv::Exception'
what(): /home/lorre851/Downloads/opencv-3.1.0/modules/highgui/src/window.cpp:281: error: (-215) size.width>0 && size.height>0 in function imshow
My code is as follows:
#include <iostream>
#include <thread>
#include "opencv2/opencv.hpp"
using namespace std;
using namespace cv;
void stream(int camera) {
VideoCapture cap(camera); // open the default camera
if(cap.isOpened()) { // check if we succeeded
while(true) {
Mat frame;
cap >> frame; // get a new frame from camera
imshow("Stream " + to_string(camera), frame);
if (waitKey(30) >= 0) break;
}
}
}
int main() {
thread cam1 (stream, 1);
thread cam2 (stream, 2);
cam1.join();
cam2.join();
return 0;
}
Anybody got any idea what could be causing this? I'm using CLion on Ubuntu 15.10 LTE.
UPDATE 1: I'm using index 1 and 2 for the camera's because I have a built-in camera in my laptop (0) and two USB camera's (1 and 2) plugged in. The USB camera's are the target hardware here.
UPDATE 2: Putting both camera feeds in one thread (see code below) works just fine (assuming your USB ports use separate busses, otherwise you'll get a 'NO SPACE LEFT ON DEVICE' error), but the delay between the two frames is noticeable, which is not ideal for a stereovision setup.
cv::VideoCapture camera0(0);
cv::VideoCapture camera1(1);
if( !camera0.isOpened() ) return 1;
if( !camera1.isOpened() ) return 1;
cv::Mat3b frame0;
cv::Mat3b frame1;
while(true) {
camera0 >> frame0;
camera1 >> frame1;
if(mat_is_empty(frame0)) cout << "SKIPPED FRAME IN 0";
else cv::imshow("Stream 0", frame0);
if(mat_is_empty(frame1)) cout << "SKIPPED FRAME IN 1";
else cv::imshow("Stream 1", frame1);
int c = cvWaitKey(40);
//exit the loop if user press "Esc" key (ASCII value of "Esc" is 27)
if(27 == char(c)) break;
}
Maybe, I have stupid answer. Your code works fine..
Count cameras from zero.
thread cam1 (stream, 0); THIS works
// thread cam2 (stream, 1); I dont have second camera
First of all, I am on windows machine. My cameras are count from 0,1,2
I do not have second web camera.
In the picture i just use your code and paste cam(0) my web camera
and for the second camera i use testing rtsp stream.
#include <iostream>
#include <thread>
#include "opencv2/opencv.hpp"
using namespace std;
using namespace cv;
void stream(int camera) {
VideoCapture cap;
if (camera == 0) {
cap.open(0); // open the default camera
}
if (camera == 1) {
cap.open("rtsp://mpv.cdn3.bigCDN.com:554/bigCDN/definst/mp4:bigbuckbunnyiphone_400.mp4"); // open the default camera
}
if (cap.isOpened()) { // check if we succeeded
while (true) {
Mat frame;
cap >> frame; // get a new frame from camera
imshow("Stream " + to_string(camera), frame);
if (waitKey(30) >= 0) break;
}
}
}
int main() {
thread cam1(stream, 0);
thread cam2(stream, 1);
cam1.join();
cam2.join();
return 0;
}
Related
I'm trying to use the OpenCV Stitcher class to stitch frames from two cameras. I would just like to do this in the most simple way to start with and then get into the details of the Stitcher class.
The code is really simple and not so many line of code.
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include "opencv2/imgcodecs.hpp"
#include "opencv2/highgui.hpp"
#include "opencv2/stitching.hpp"
#include <opencv2/opencv.hpp>
#include <opencv2/imgcodecs.hpp>
#include<iostream>
#include <fstream>
#include<conio.h> // may have to modify this line if not using Windows
using namespace std;
using namespace cv;
//using namespace cv::detail;
bool try_use_gpu = true;
Stitcher::Mode mode = Stitcher::PANORAMA; //Stitcher::SCANS;
vector<Mat> imgs;
int main()
{
//initialize and allocate memory to load the video stream from camera
cv::VideoCapture camera0(2);
cv::VideoCapture camera1(3);
if (!camera0.isOpened()) return 1;
if (!camera1.isOpened()) return 1;
//Mat output_frame;
cv::Mat3b output_frame;
cv::Stitcher stitcher = cv::Stitcher::createDefault(true);
//Ptr<Stitcher> stitcher = Stitcher::create(mode, try_use_gpu);
Mat camera0_frame_resized;
Mat camera1_frame_resized;
while (true) {
//grab and retrieve each frames of the video sequentially
cv::Mat3b camera0_frame;
cv::Mat3b camera1_frame;
camera0 >> camera0_frame;
camera1 >> camera1_frame;
resize(camera0_frame, camera0_frame_resized, Size(640, 480));
resize(camera1_frame, camera1_frame_resized, Size(640, 480));
imgs.push_back(camera0_frame_resized);
imgs.push_back(camera1_frame_resized);
Stitcher::Status status = stitcher.stitch(imgs, output_frame);
output_frame.empty();
if (status != Stitcher::OK) {
cout << "Can't stitch images, error code = " << int(status) << endl;
return -1;
}
cv::imshow("Camera0", camera0_frame);
cv::imshow("Camera1", camera1_frame);
cv::imshow("Stitch", output_frame);
//wait for 40 milliseconds
int c = cvWaitKey(5);
//exit the loop if user press "Esc" key (ASCII value of "Esc" is 27)
if (27 == char(c)) break;
}
return 0;
}
I am using OpenCV 3.2 and Visual Studio Community Edition 2017 running on windows 10.
The issue is that it is extremely slow, It seems to stitch the first frame and then it kind of gets stuck and nothing else happens, after seconds/minute maybe next frames appear.
I am running on a extremely fast CPU and top of the line GPU.
I was not expecting fast stitching but this is just way to slow and gets me thinking that I am doing something wrong.
Any ideas on why it stitches only the first frame and then gets stuck?
I am trying to create a dual camera array utilising ELP USB OV7725 based webcams: ELP 480P Mini Webcam USB2.0 OmniVision OV7725 Color CMOS Sensor VGA USB Camera Module (https://www.amazon.co.uk/gp/product/B01DK0FPYC/ref=oh_aui_detailpage_o02_s00?ie=UTF8&psc=1). Unfortunatelly I am not able to stream a video from more than a single ELP camera.
The source code is as follows:
#include <opencv2/opencv.hpp>
#include "opencv2/calib3d.hpp"
#include "opencv2/imgproc.hpp"
#include "opencv2/imgcodecs.hpp"
#include "opencv2/highgui.hpp"
#include "opencv2/core/utility.hpp"
#include "opencv2/ximgproc/disparity_filter.hpp"
#include <iostream>
#include <string>
using namespace cv;
using namespace cv::ximgproc;
using namespace std;
int main()
{
//initialize and allocate memory to load the video stream from camera
cv::VideoCapture camera0(0);
cv::VideoCapture camera1(1);
if( !camera0.isOpened() ) return 1;
if( !camera1.isOpened() ) return 1;
camera0.set(CV_CAP_PROP_FRAME_WIDTH, 640);
camera0.set(CV_CAP_PROP_FRAME_HEIGHT, 480);
camera1.set(CV_CAP_PROP_FRAME_WIDTH, 640);
camera1.set(CV_CAP_PROP_FRAME_HEIGHT, 480);
while(true) {
//grab and retrieve each frames of the video sequentially
cv::Mat3b frame0;
cv::Mat3b frame1;
camera0 >> frame0;
camera1 >> frame1;
// display results
cv::imshow("Video0", frame0);
cv::imshow("Video1", frame1);
int c = cv::waitKey(20);
//exit the loop if user press "Esc" key (ASCII value of "Esc" is 27)
if(27 == char(c)) break;
}
return 0;
}
The output is as follows:
VIDIOC_STREAMON: No space left on device
init done
opengl support available
OpenCV Error: Assertion failed (size.width>0 && size.height>0) in imshow, file /home/User/Data/Install/DevLibs/OpenCV/opencv/modules/highgui/src/window.cpp, line 289
terminate called after throwing an instance of 'cv::Exception'
what(): /home/User/Data/Install/DevLibs/OpenCV/opencv/modules/highgui/src/window.cpp:289: error: (-215) size.width>0 && size.height>0 in function imshow
Aborted (core dumped)
Using slightly modified source code I am able to simultaneously stream video from two Logitech C920 webcams + one of those OV7725.
#include <opencv2/opencv.hpp>
#include "opencv2/calib3d.hpp"
#include "opencv2/imgproc.hpp"
#include "opencv2/imgcodecs.hpp"
#include "opencv2/highgui.hpp"
#include "opencv2/core/utility.hpp"
#include "opencv2/ximgproc/disparity_filter.hpp"
#include <iostream>
#include <string>
using namespace cv;
using namespace cv::ximgproc;
using namespace std;
int main()
{
//initialize and allocate memory to load the video stream from camera
cv::VideoCapture camera0(4);
cv::VideoCapture camera1(5);
cv::VideoCapture camera2(0);
if( !camera0.isOpened() ) return 1;
if( !camera1.isOpened() ) return 1;
if( !camera2.isOpened() ) return 1;
camera0.set(CV_CAP_PROP_FRAME_WIDTH, 640);
camera0.set(CV_CAP_PROP_FRAME_HEIGHT, 480);
camera1.set(CV_CAP_PROP_FRAME_WIDTH, 640);
camera1.set(CV_CAP_PROP_FRAME_HEIGHT, 480);
camera2.set(CV_CAP_PROP_FRAME_WIDTH, 640);
camera2.set(CV_CAP_PROP_FRAME_HEIGHT, 480);
while(true) {
//grab and retrieve each frames of the video sequentially
cv::Mat3b frame0;
cv::Mat3b frame1;
cv::Mat3b frame2;
camera0 >> frame0;
camera1 >> frame1;
camera2 >> frame2;
// display results
cv::imshow("Video0", frame0);
cv::imshow("Video1", frame1);
cv::imshow("Video2", frame2);
//wait for 40 milliseconds
int c = cv::waitKey(20);
//exit the loop if user press "Esc" key (ASCII value of "Esc" is 27)
if(27 == char(c)) break;
}
return 0;
}
Therefore I anticipate that it might be a driver problem of some sort. I tried to lower the resolution
camera0.set(CV_CAP_PROP_FRAME_WIDTH, 240);
camera0.set(CV_CAP_PROP_FRAME_HEIGHT, 240);
or decrease the FPS:
camera0.set(CV_CAP_PROP_FPS, 15);
camera1.set(CV_CAP_PROP_FPS, 15);
However it did not help.
The camera seems to support the compressed mode (Motion-JPEG):
$ v4l2-ctl -d /dev/video0 --list-formats
ioctl: VIDIOC_ENUM_FMT
Index : 0
Type : Video Capture
Pixel Format: 'YUYV'
Name : YUYV 4:2:2
Index : 1
Type : Video Capture
Pixel Format: 'MJPG' (compressed)
Name : Motion-JPEG
the webcam seems to work in MJPG mode:
codecCode = cap.get(CV_CAP_PROP_FOURCC);
Any suggestions how to solve this issue?
I'm using OpenCV 3.1, I try to run a simple code as the following one (main function):
cv::VideoCapture cam;
cv::Mat matTestingNumbers;
cam.open(0);
if (!cam.isOpened()) { printf("--(!)Error opening video capture\n"); return -1; }
while (cam.read(matTestingNumbers))
{
cv::imshow("matTestingNumbers", matTestingNumbers);
cv::waitKey(5000);
}
When I move the camera it seems that the code does not capture and show the current frame but shows all the captured frames from the previous position and only then from the new one.
So when I capture the wall it shows the correct frames (the wall itself) in the correct delay, but, when I twist the camera to my computer, I first see about 3 frames of the wall and only then the computer, it seems that the frames are stuck.
I've tried to use videoCapture.set() functions and set the FPS to 1, and I tried to switch the method of capturing to cam >> matTestingNumbers (and the rest of the main function according to this change) but nothing helped, I still got "stuck" frames.
BTW, These are the solutions I found on web.
What can I do to fix this problem?
Thank you, Dan.
EDIT:
I tried to retrieve frames as the following:
#include "opencv2/opencv.hpp"
using namespace cv;
int main(int, char**)
{
VideoCapture cap(0); // open the default camera
if(!cap.isOpened()) // check if we succeeded
return -1;
Mat frame;
namedWindow("edges",1);
for(;;)
{
cap.grab();
if (waitKey(11) >= 0)
{
cap.retrieve(frame);
imshow("edges", frame);
}
}
return 0;
}
But, it gave the result (when I pointed the camera on one spot and pressed a key it showed one more of the previous frames that were captured of the other point).
It is just like you're trying to picture one person then another but when you picture the second you get the photo of the first person what doesn't make sense.
Then, I tried the following:
#include "opencv2/opencv.hpp"
using namespace cv;
int main(int, char**)
{
VideoCapture cap(0); // open the default camera
if(!cap.isOpened()) // check if we succeeded
return -1;
Mat frame;
namedWindow("edges",1);
for(;;)
{
cap >> frame;
if (waitKey(33) >= 0)
imshow("edges", frame);
}
return 0;
}
And it worked as expected.
One of the problems is that you are not calling cv::waitKey(X) to properly freeze the window for X amount of milliseconds. Get rid of usleep()!
I am working on a university project where we have a table with glass surface, a webcam, and IR spots underneath.
We want to detect certain gestures such as:
1, 2, 3 fingers
3 fingertips
This is how a hand looks through the camera:
When the camera initialise it learns the background and subtracts it, going from
to this:
The hand, however, is also "learned" and disappears rather quickly.
We want to the program to learn the background, but will not store the hand as part of the background as it will be static.
Any suggestions on how to do this?
What we have tried: playing with the learning rate, blurring, morphology.
Code included below.
#include <opencv2/core/core.hpp>
#include "opencv2/opencv.hpp"
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/video/background_segm.hpp>
#include <opencv\cv.h>
#include <iostream>
#include <sstream>
using namespace cv;
using namespace std;
int main(int, char)
{
Mat frame; //current frame
Mat fgMaskMOG; //fg mask generated by MOG method
int frameNum = 0;
Ptr<BackgroundSubtractor> pMOG2; //MOG2 Background subtractor
//pMOG = new BackgroundSubtractorMOG(); //MOG approach
pMOG2 = createBackgroundSubtractorMOG2(20, 16, false); //MOG2 approach
VideoCapture cap(1); // open the default camera
if (!cap.isOpened()) // check if we succeeded
return -1;
for (;;)
{
cap >> frame; // get a new frame from camera
if (!cap.read(frame)) {
cerr << "Unable to read next frame." << endl;
continue;
}
imshow("orig", frame);
++frameNum;
pMOG2->apply(frame, fgMaskMOG, -1);
imshow("frame", fgMaskMOG);
if (waitKey(30) >= 0)
break;
}
// the camera will be deinitialized automatically in VideoCapture destructor
return 0;
}
I have been trying to get openCV to read an image from my computer's webcam. The code below successfully opens the webcam (green light turns on). However, attempts to grab a frame and hence read a frame fail. I am at a loss here. Can anyone help?
Many Thanks,
Hillary
P.S. I am running Mac OS X 10.9 on a MacBook Pro. And my opencv version is 2.4.6.1
And here is the code:
#include "opencv.hpp"
using namespace cv;
int main(int, char**) {
VideoCapture cap = VideoCapture(0);
if(!cap.isOpened()){
printf("failed to open camera\n");
return -1;
}
namedWindow("edges",1);
for(;;){
if(waitKey(50) >= 0 ) break;
if(!cap.grab()){
printf("failed to grab from camera\n");
}
}
return 0;
}
You forgot to read new frames in your loop and show them! There:
for(;;){
if(waitKey(50) >= 0 ) break;
Mat frame;
if(!cap.grab()){
printf("failed to grab from camera\n");
break;
}
cap >> frame;
if(frame.empty()){
printf("failed to grab from camera\n");
break;
}
imshow("edges", frame);
}