OpenCV with pthreads and mutexes - c++

I've written a fairly basic C++ program which uses OpenCV library to show an video steam for a IP camera I have.
Since I want to add image processing code in the future, I thought it would be a good idea to use threads to do it. One thread captures the most recent frame and the other thread reads this frame and displays it on screen. I used a pthread_mutex_t to lock the frame variable.
My problem is that the code actually compiles, but when I execute the program nothing happens, it just exists after couple of seconds. I've verified this is not a problem with the VideoCapture object, but I don't have any other idea why this does not work.
This is my code:
#include <stdio.h>
#include <opencv2/opencv.hpp>
#include <iostream>
#include <pthread.h>
using namespace cv;
using namespace std;
//GLOBALS
VideoCapture vcap;
Mat frame;
pthread_mutex_t *frameLocker;
const string videoStreamAddress = "http://10.0.0.6/mjpg/video.mjpg";
void *Proc(void *arg)
{
for(;;)
{
pthread_mutex_lock(frameLocker);
vcap.read(frame);
pthread_mutex_unlock(frameLocker);
}
}
int main(int, char**) {
frameLocker = new pthread_mutex_t();
vcap.open(videoStreamAddress);
pthread_mutex_init(frameLocker,NULL);
pthread_t *ProcThread;
pthread_create(ProcThread, NULL, Proc, NULL);
for(;;)
{
pthread_mutex_lock(frameLocker);
imshow("Output Window", frame);
pthread_mutex_unlock(frameLocker);
}
delete frameLocker;
}
I'd be glad if you could help me solve this issue.
Thanks,
Matan

I was able to solve this using the following code:
#include <stdio.h>
#include <opencv2/opencv.hpp>
#include <iostream>
#include <pthread.h>
using namespace cv;
using namespace std;
//GLOBALS
VideoCapture vcap;
Mat frame;
pthread_mutex_t frameLocker;
const string videoStreamAddress = "http://IP/mjpg/video.mjpg";
void *UpdateFrame(void *arg)
{
for(;;)
{
Mat tempFrame;
vcap >> tempFrame;
pthread_mutex_lock(&frameLocker);
frame = tempFrame;
pthread_mutex_unlock(&frameLocker);
}
}
int main(int, char**) {
vcap.open(videoStreamAddress);
pthread_mutex_init(&frameLocker,NULL);
pthread_t UpdThread;
pthread_create(&UpdThread, NULL, UpdateFrame, NULL);
for(;;)
{
Mat currentFrame;
pthread_mutex_lock(&frameLocker);
currentFrame = frame;
pthread_mutex_unlock(&frameLocker);
if(currentFrame.empty()){
printf("recieved empty frame\n");
continue;
}
imshow("Output Window", currentFrame);
waitKey(1);
}
}

Related

VideoFrames are only coming when esc,spacebar or enter keys are pressed OpenCV c++

I am kind of an intermediate in Computer Vison and fairly proficient in opencv python however coming to c++ i am facing problems in just selecting ROI from Video feed and displaying the cropped feed .My code looks like this.
#include "opencv2/highgui.hpp"
#include "opencv2/imgproc.hpp"
#include "opencv2/objdetect/objdetect.hpp"
#include "opencv2/tracking.hpp"
#include "iostream"
using namespace cv;
using namespace std;
int main() {
Mat frame1;
VideoCapture cap;
cap.open(0);
cap.read(frame1);
Rect2d roi = selectROI(frame1, true);
Mat Crop = frame1(roi);
while (1) {
cap.read(frame1);
Crop = frame1(roi);
if (Crop.empty()) {
cerr << "ERROR! blank frame grabbed\n";
break;
}
imshow("roi", Crop);
int key=waitkey(0);
}
}
The code is compiling ,and the cropped window is seen however I am always in need to click enter,spacebar or esc to get the video feed.Weird?
So the correct version of the corrected code will look somewhat like this.Thanks for the help.
#include "opencv2/highgui.hpp"
#include "opencv2/imgproc.hpp"
#include "opencv2/objdetect/objdetect.hpp"
#include "opencv2/tracking.hpp"
#include "iostream"
using namespace cv;
using namespace std;
int main() {
Mat frame1;
VideoCapture cap;
cap.open(0);
cap.read(frame1);
Rect2d roi = selectROI(frame1, true);
Mat Crop = frame1(roi);
while (1) {
cap.read(frame1);
Crop = frame1(roi);
if (Crop.empty()) {
cerr << "ERROR! blank frame grabbed\n";
break;
}
imshow("roi", Crop);
*int key=waitkey(1)*;
}
}

Initialising OpenCV-VideoCapture-class in another multithreading class

Im trying to initialise VideoCapture capturedevice once in my multithreading program. Once initialised it should serve in the acquireImage-thread as the image-buffer, which is filled by a webcam.
The following code shows me a "OpenCV Error: Assertion failed (func != 0) in cv::imshow"-error during runtime, which means VideoCapture capturedevice is never really initialised and therefore imshow doesnt have necessary data, but why?
The code was constructed based on this question: Correctly using mutex in OpenCL-OpenCV-Realtime-Threads? Basically it uses two threads, one processes images originating from a usb-webcam and the second will find faces on those images...but does nothing at the moment for code-simplicity.
#include <memory>
#include <thread>
#include <mutex>
#include <condition_variable>
#include <vector>
#include <cmath>
#include <opencv2/objdetect/objdetect.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include "opencv2/ocl/ocl.hpp"
#include "opencv2/opencv.hpp"
#include <functional>
using namespace std;
using namespace cv;
typedef unsigned char uchar;
typedef unsigned int uint;
class FaceDetector
{
mutex imageLock, facesLock;
condition_variable imageAqcuired;
bool newImageAvailable;
Mat _img;
Mat _imgToWorkOn;
Mat _faceImages;
bool quit;
VideoCapture captureDevice;
int device_id;
FaceDetector (int _device_id);
void acquireImage()
{
while (!quit)
{
unique_lock<mutex> ulock(imageLock);
imageAqcuired.wait(ulock,[&](){return !newImageAvailable;}); //only take new image after current one was consumed
Mat captureFrame;
captureDevice>>captureFrame;
transpose(captureFrame,captureFrame);
flip(captureFrame,captureFrame,1);
_img = captureFrame.clone();
ulock.unlock();
newImageAvailable = true;
imageAqcuired.notify_one(); //notify that a new image is available
}
}
void processImage()
{
while (!quit)
{
unique_lock<mutex> ulock(imageLock);
imageAqcuired.wait(ulock,[&](){return newImageAvailable;}); //wait untill a new image is available
_imgToWorkOn = _img.clone();
ulock.unlock();
newImageAvailable = false;
imageAqcuired.notify_one(); //notify the current image can be replaced by a newer one
unique_lock<mutex> lockFace(facesLock);
//arbeit
lockFace.unlock();
}
}
public:
FaceDetector() : newImageAvailable(false) {}
void start() {
quit = false;
thread t1(&FaceDetector::acquireImage,this);
t1.detach();
thread t2(&FaceDetector::processImage,this);
t2.detach();
}
void stop() {
quit = true;
}
Mat getImage() {
if (quit)
return Mat();
lock_guard<mutex> lock(imageLock);
return _img;
}
Mat getProcessedImage() {
if (quit)
return Mat();
lock_guard<mutex> lock(facesLock);
return _faceImages;
}
};
FaceDetector::FaceDetector(int _device_id)
{
device_id = _device_id;
captureDevice.open(device_id);
captureDevice.set(CV_CAP_PROP_FRAME_WIDTH,620); //erst jetzt cam.set weil sonst system-pause nicht funzt
captureDevice.set(CV_CAP_PROP_FRAME_HEIGHT,480);
}
int main()
{
bool quit(false);
FaceDetector faceDet;
faceDet.start();
thread input([](bool &quitFlag) { getchar(); quitFlag = true; },ref(quit)); //stop on user press Enter
input.detach();
while (!quit) {
Mat img = faceDet.getImage();
Mat imgc = img.clone();
imshow("links", imgc);
/*
imgs = faceDet.getProcessedImage();
Mat imgsc = imgs.clone();
imshow("gsichter", imgsc);
*/
waitKey(30);
this_thread::sleep_for(chrono::milliseconds(33)); //no need to show more than 30 fps...
}
faceDet.stop();
return 0;
}
Edit: I tried to include your answer, still getting "Opencv Assertion Error in imshow".
#include <memory>
#include <thread>
#include <mutex>
#include <condition_variable>
#include <vector>
#include <cmath>
#include <opencv2/objdetect/objdetect.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include "opencv2/ocl/ocl.hpp"
#include "opencv2/opencv.hpp"
#include <functional>
using namespace std;
using namespace cv;
typedef unsigned char uchar;
typedef unsigned int uint;
class FaceDetector
{
mutex imageLock, facesLock;
condition_variable imageAqcuired;
bool newImageAvailable;
Mat _img;
Mat _imgToWorkOn;
Mat _faceImages;
bool quit;
VideoCapture captureDevice;
int device_id;
void acquireImage()
{
while (!quit)
{
unique_lock<mutex> ulock(imageLock);
imageAqcuired.wait(ulock,[&](){return !newImageAvailable;}); //only take new image after current one was consumed
Mat captureFrame;
captureDevice>>captureFrame;
//transpose(captureFrame,captureFrame);
//flip(captureFrame,captureFrame,1);
_img = captureFrame.clone();
ulock.unlock();
newImageAvailable = true;
imageAqcuired.notify_one(); //notify that a new image is available
}
}
void processImage()
{
while (!quit)
{
unique_lock<mutex> ulock(imageLock);
imageAqcuired.wait(ulock,[&](){return newImageAvailable;}); //wait untill a new image is available
_imgToWorkOn = _img.clone();
ulock.unlock();
newImageAvailable = false;
imageAqcuired.notify_one(); //notify the current image can be replaced by a newer one
unique_lock<mutex> lockFace(facesLock);
//arbeit
lockFace.unlock();
}
}
public:
FaceDetector() : newImageAvailable(false) {}
void start() {
quit = false;
thread t1(&FaceDetector::acquireImage,this);
t1.detach();
thread t2(&FaceDetector::processImage,this);
t2.detach();
}
void stop() {
quit = true;
}
Mat getImage() {
if (quit)
return Mat();
lock_guard<mutex> lock(imageLock);
return _img;
}
Mat getProcessedImage() {
if (quit)
return Mat();
lock_guard<mutex> lock(facesLock);
return _faceImages;
}
FaceDetector::FaceDetector(int _device_id)
{
VideoCapture captureDevice;
device_id = _device_id;
captureDevice.open(device_id);
captureDevice.set(CV_CAP_PROP_FRAME_WIDTH,620); //erst jetzt cam.set weil sonst system-pause nicht funzt
captureDevice.set(CV_CAP_PROP_FRAME_HEIGHT,480);
}
};
int main()
{
bool quit(false);
FaceDetector faceDet(0);
faceDet.start();
thread input([](bool &quitFlag) { getchar(); quitFlag = true; },ref(quit)); //stop on user press Enter
input.detach();
while (!quit) {
Mat img = faceDet.getImage();
Mat imgc = img.clone();
imshow("links", imgc);
/*
imgs = faceDet.getProcessedImage();
Mat imgsc = imgs.clone();
imshow("gsichter", imgsc);
*/
waitKey(30);
this_thread::sleep_for(chrono::milliseconds(33)); //no need to show more than 30 fps...
}
faceDet.stop();
return 0;
}
I also tried following code, but still getting said Assertion Error.
public:
FaceDetector(int device_id) : newImageAvailable(false) {}
....
void init() {
VideoCapture captureDevice;
captureDevice.open(device_id);
captureDevice.set(CV_CAP_PROP_FRAME_WIDTH,620); //erst jetzt cam.set weil sonst system-pause nicht funzt
captureDevice.set(CV_CAP_PROP_FRAME_HEIGHT,480);
}
int main()
{
FaceDetector faceDet(0);
faceDet.init();
faceDet.start();
}
In main() function You are not creating object faceDet using constructor FaceDetector::FaceDetector(int _device_id) but you are using default constructor. This means you are not opening captureDevice at all.
Edit for correction
In the declaration, make FaceDetector::FaceDetector(int _device_id) public.
Now in main(), create object faceDet using this constructor, you need to call like this:
FaceDetector faceDet(0); // I have taken 0 as as default camera ID, you can add other value like 1 or 2 etc depending the choice of camera too.
This should be be working now, please let me know of any problem should you face.

Which OpenCV's function support the analog camera for live streaming?

Which OpenCV's function support the analog camera for live streaming?
Please give me the answer.
I tried CvCapture and VideoCapture functions of OpenCV.
It works for USB camera but did not work for Analog camera.
I tried VideoInput function.It works well with analog camera but i want opencv inbuilt function.
So please help me.
Thanks for your time.
This is the code for cvcapture function which I have used.
#include "stdafx.h"
#include "cv.h"
#include "cxcore.h"
#include "highgui.h"
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <iostream>
#include "videoInput.h"
#include <opencv2/imgproc/imgproc.hpp>
using namespace cv;
using namespace std;
char key;
int main()
{
cvNamedWindow("Camera_Output", 1); //Create window
CvCapture* capture = cvCaptureFromCAM(CV_CAP_ANY); //Capture using any camera connected to your system
while(1){ //Create infinte loop for live streaming
IplImage* frame = cvQueryFrame(capture); //Create image frames from capture
cvShowImage("Camera_Output", frame); //Show image frames on created window
key = cvWaitKey(10); //Capture Keyboard stroke
if (char(key) == 27){
break; //If you hit ESC key loop will break.
}
}
cvReleaseCapture(&capture); //Release capture.
cvDestroyWindow("Camera_Output"); //Destroy Window
return 0;
}
end of code
Next code is using VideoInput function.
The code is
#include "stdafx.h"
#include "cv.h"
#include "cxcore.h"
#include "highgui.h"
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <iostream>
#include "videoInput.h"
#include <opencv2/imgproc/imgproc.hpp>
using namespace cv;
using namespace std;
int main(int, char**)
{
videoInput VI;
int numDevices = VI.listDevices();
//int device1= 0;
VI.setup(0);
unsigned char* yourBuffer = new unsigned char[VI.getSize(0)];
IplImage* colourImage = cvCreateImage(cvSize(320,240),8,3);
while(1)
{
VI.grabFrame(0, yourBuffer);
colourImage->imageData = (char*)yourBuffer;
cvConvertImage(colourImage, colourImage, 3);
cvShowImage("test",colourImage);
if( cvWaitKey(10) == 27)
break;
}
return 0;
}
end of code
and last code is using videocapture function
the code is
#include "stdafx.h"
#include "cv.h"
#include "cxcore.h"
#include "highgui.h"
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <iostream>
#include "videoInput.h"
#include <opencv2/imgproc/imgproc.hpp>
using namespace cv;
using namespace std;
int main() {
VideoCapture stream1(-1); //0 is the id of video device.0 if you have only one camera.
if (!stream1.isOpened()) { //check if video device has been initialised
cout << "cannot open camera";
return 0;
}
//unconditional loop
while (true) {
Mat cameraFrame;
stream1.read(cameraFrame);
imshow("cam", cameraFrame);
if (waitKey(30) >= 0)
break;
}
return 0;
}
End of code
Please help me.

how to get a single frame from a video clip using opencv and eclipse

#include <iostream>
#include<opencv2/highgui/highgui.hpp>
#include<opencv2/core/core.hpp>
using namespace std;
using namespace cv;
int main(int argc, const char* argv[]) {
VideoCapture cap(0);
if(!cap.isOpened())
{
cout<<"can't open video file"<<endl;
return -1;
}
namedWindow("Myvideo",CV_WINDOW_AUTOSIZE);
while(1)
{
Mat frame;
bool bsuccess=cap.read(frame);
if(!bsuccess)
{
cout<<"can't read a frame"<<endl;
break;
}
imshow("Myvideo",frame);
if(waitKey(30)==27)
{
cout<<"Esc key is pressed by the user"<<endl;
break;
}
}
return 0;
}
the above code is just to capture a video from camera.
But I want to get a image(ie only one frame) from this video. Can someone please tell me how to do this. I actually tried to remove the while loop, so that I can get just one loop instead of getting one after the other(ie video). And also removed the "break" statement.
#include <iostream>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/core/core.hpp>`
using namespace std;
using namespace cv;
int main(int argc, const char* argv[]) {
VideoCapture cap(0);
if(!cap.isOpened())
{
cout<<"can't open video file"<<endl;
return -1;
}
namedWindow("Myvideo",CV_WINDOW_AUTOSIZE);
Mat frame;
cap.read(frame);
imshow("Myvideo",frame);
if(waitKey(30)==27)
{
cout<<"Esc key is pressed by the user"<<endl;
}
return 0;
}
but unfortunately, it is just showing a blank window.
Can anybody help me out... Thanks in advance
First readed frame is usually(always?) black/gray, try to display next frame - replace this code
cap.read(frame);
imshow("Myvideo",frame);
with this:
cap.read(frame);
cap.read(frame);
imshow("Myvideo",frame);

OpenCV 2.4.3 camera capture not working on Ubuntu 12.04

I am trying to execute the following program using openCV 2.4.3 on Ubuntu 12.04 LTS.
But I get "camera not initialized as the output" Can anybody help me.
here is the code:
include <iostream>
include "opencv2/imgproc/imgproc.hpp"
include "opencv2/highgui/highgui.hpp"
using namespace cv;
using namespace std;
int main()
{
VideoCapture cap(1);
if (!cap.isOpened())
{
cout <<"Failed to initialize camera\n";
return 1;
}
namedWindow("CameraCapture");
Mat frame;
while (1)
{
cap>> frame;
imshow("cameraCapture",frame);
if (waitKey(30)>0)break;
}
destroyAllWindows();
return 0;
}
Please help me!
Thanks,
Kushal
try the following...
#include "iostream"
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
using namespace std;
using namespace cv;
int main()
{
CvCapture *webcam = cvCaptureFromCAM(-1);
IplImage *img = NULL;
while(true)
{
img = cvQueryFrame(webcam);
cvShowImage("TEST",img);
cvWaitKey(20);
}
return 0;
}
did u check the default capture device? by default it is 0
VideoCapture cap(0);