OpenCV does not free camera - c++

I'm trying to release the camera in OpenCV and reinitialize it another time, but the problem is, I cannot properly release the camera. Asking OpenCV, the cv::VideoCapture, whether the camer is open or not, it says closed, but the little LED is still glowing and I cannot create another VideoCapture object around the same camera.
This is the include I use:
#include <opencv2/opencv.hpp>
This is a little sample of code showing the problem:
cv::VideoCapture cap(0);
for(int i = 0; i < 20; i++) {
cv::Mat frame;
cap >> frame;
cv::imshow("Test", frame);
if (cv::waitKey(30) >= 0) { break; }
}
cap.release();
std::cout << "Camera is closed is : " << !cap.isOpened() << std::endl;
while(true) {
if (cv::waitKey(30) >= 0) { break; }
}
As already mentioned, the output says the camera is closed, but the LED is glowing. When I try to create a new VideoCapture around the camera it fails and says the camera is busy.
Any ideas?

This might be a bug of OpenCV 2.4.8 with some devices, you should check their bug tracker and post this issue there.
A fix for this problem might could be accomplished by putting the variable cap inside another scope:
{
cv::VideoCapture cap(0);
for(int i = 0; i < 20; i++) {
cv::Mat frame;
cap >> frame;
cv::imshow("Test", frame);
if (cv::waitKey(30) >= 0)
break;
}
}
/* At this point, cap was destroyed and your camera should be operational again */
{
cv::VideoCapture cap(0);
for(int i = 0; i < 20; i++) {
cv::Mat frame;
cap >> frame;
cv::imshow("AnotherTest", frame);
if (cv::waitKey(30) >= 0)
break;
}
}
The documentation says that the camera will be deinitialized automatically in VideoCapture destructor.
The code should be enough to fix the problem. But as you noticed, the problem remains, so could be 1 of 2 things:
This is really an issue inside OpenCV;
There's a bug in driver of the camera, so updating it might solve the problem.

Related

OpenCV - Capture frames in a separatethread

I'm trying to use OpenCV 2.4.8 to capture frames in my android application. I write a .SO library for it and link OpenCV libraries to it.
From this link: http://docs.opencv.org/modules/core/doc/intro.html, I wrote a sample code as below.
int main() {
VideoCapture cap(0);
if(!cap.isOpened()) return -1;
capture(cap);
}
void capture(VideoCapture cap) {
for(int i = 0; i<= 3; i++)
{
cap >> frame;
}
}
This code works just fine as long as I run it from main thread. If I try to run it in a separate thread e.g.
std::thread t(capture, cap);
It can't capture the frames. It gives me some fatal error at the code line
cap>> frame;
in the above code. However, in the above OpenCV documentation, it clearly says "The current OpenCV implementation is fully re-enterable. That is, the same function, the same constant method of a class instance, or the same non-constant method of different class instances can be called from different threads. Also, the same cv::Mat can be used in different threads because the reference-counting operations use the architecture-specific atomic instructions."
Any idea what I'm missing here?
EDIT:
I tried opening camera within the thread and modified capture() as below:
void capture() {
VideoCapture cap(0); // fails here
if(!cap.isOpened()) return -1;
for(int i=0; i <= 3; i++) {
cap >> frame;
}
}
It fails while opening the camera itself which is quite strange. Any suggestions?
As far as I know the thread cant return results, so you need to pass cap by reference or it is better if you use future, using future with threads help you return results from a function.
Instead of using threads use async which is a better fit with threads.
Can you try the following:
#include <iostream>
#include <thread>
using namespace cv;
void capture(VideoCapture &cap)
{
Mat frame;
for(int i = 0; i<= 3; i++)
{
cap >> frame;
// do something with frame e.g. imshow("image", frame);
}
}
int main(int argc, char *argv[])
{
VideoCapture cap(0);
if(!cap.isOpened()) return -1;
std::thread t(capture, std::ref(cap));
// in the meantime do something else here
t.join(); // wait for the thread to be finalized
return 0;
}
Here I'm passing the cv::VideoCapture object by reference. It should solve your problem.

OpenCV - getting pixel data from camera device

I am using OpenCV 2.4.6. I have found over the Internet some example of getting frame from a camera. It works well (it displays my ugly face onto the screen). However, I absolutely cannot get pixel data from the frames. I've found some topic here: http://answers.opencv.org/question/1934/reading-pixel-values-from-a-frame-of-a-video/ but it doesn't work for me.
Here is the code - in the commented parts I pointed out what is wrong.
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
using namespace cv;
int main() {
int c;
IplImage* img;
CvCapture* capture = cvCaptureFromCAM(1);
cvNamedWindow("mainWin", CV_WINDOW_AUTOSIZE);
while(1) {
img = cvQueryFrame(capture);
uchar* data = (uchar*)img->imageData; // access violation
// this does not work either
//Mat m(img);
//uchar a = m.data[0]; // access violation
cvShowImage("mainWin", img);
c = cvWaitKey(10);
if(c == 27)
break;
}
}
Could you give me some suggestions, please?
I suggest using the newer Mat structure instead of IplImage since your question is tagged with C++ tag. For your task you can use a data member of Mat - it points to internal Mat storage. For example Mat img; uchar* data = img.data;. Here's a full example
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
using namespace cv;
int main() {
int c;
Mat img;
VideoCapture capture(0);
namedWindow("mainWin", CV_WINDOW_AUTOSIZE);
bool readOk = true;
while(capture.isOpened()) {
readOk = capture.read(img);
// make sure we grabbed the frame successfully
if (!readOk) {
std::cout << "No frame" << std::endl;
break;
}
uchar* data = img.data; // this should work
imshow("mainWin", img);
c = waitKey(10);
if(c == 27)
break;
}
}

Write/save videostream if detection true

I want to write a videostream after detection is found true.
I use this link as Videowrite example
My code implementation looks like that:
int main(int argc, const char** argv) {
bool detection = false;
VideoCapture cap(-1);
if (!cap.isOpened())
{
printf("ERROR: Cannot open the video file");
}
namedWindow("MyVideo", CV_WINDOW_AUTOSIZE);
double dWidth = cap.get(CV_CAP_PROP_FRAME_WIDTH);
double dHeight = cap.get(CV_CAP_PROP_FRAME_HEIGHT);
cout << "Frame Size = " << dWidth << "x" << dHeight << endl;
Size frameSize (static_cast<int>(dWidth), static_cast<int>(dHeight));
VideoWriter record ("/home/hacker/MyVideo.avi", CV_FOURCC('P','I','M','1'),
30, frameSize, true);
if (!record.isOpened())
{
printf("Error: Failed to write the video");
return -1;
}
while (true)
{
Mat frame;
if (!frame.empty())
{
detectAndDisplay(frame);
}
else
{
printf(" --(!) No captured frame -- Break!"); break;
}
if (detection == true)
{
record.write(frame);
}
char c = cvWaitKey(33);
if (c == 27) { break; }
}
return 0;
}
In my home directory I can see the Myvideo.avi but it's empty.
I got the following errors on command line:
VIDIOC_QUERMENU: Invalid argument
VIDIOC_QUERMENU: Invalid argument
Frame size: 640x480 Output #0, avi, to '/home/hacker/MyVideo.avi":
Stream #0.0: Video: mpeg1video (hq), yvu420p, 640x480, q=2-31, 19660
kb/s, 9ok tbn, 23,98 tbc
--(!) No captured frame -- Break! Process returned 0 (0x0) execution time: 0,75 s
You should release videowriter ( record.Release(); ). It closes file.
I try to solve it like this:
But i have 2 problems:
I want to save the MyVideo.avi if detecAndDisplay(frame) == true. But he saves it anyway(with an empty video record). And if that save the video recording is running faster.
int main( int argc, const char** argv ) {
Mat frame;
VideoCapture capture(-1); // open the default camera
if( !capture.isOpened() )
{
printf("Camera failed to open!\n");
return -1;
}
capture >> frame; // get first frame for size
for(;;)
{
// get a new frame from camera
capture >> frame;
//-- 3. Apply the classifier to the frame
if( !frame.empty() )
{
detectAndDisplay( frame );
}
if(detectAndDisplay(frame)==true)
{
// record video
VideoWriter record("MyVideo.avi", CV_FOURCC('D','I','V','X'), 30, frame.size(), true);
if( !record.isOpened() )
{
printf("VideoWriter failed to open!\n");
return -1;
}
// add frame to recorded
record << frame;
}
if(waitKey(30) >= 0) break;
}
return 0;
}
/** #function detectAndDisplay */
/** this function detect face draw a rectangle around and detect eye & mouth and draw a circle around */
bool detectAndDisplay( Mat frame ) {
...
...
return true;
}
This might be why your video file was empty.
bool detection = false;
...
if (detection == true)
{
record.write(frame);
}

OpenCV frame capture from AVI

I am working on a project with openCV 2.2. I need to do processing on each frame of an AVI file but when I run my code it only grabs the first frame of the file. The CV_CAP_PROP_POS_FRAMES does not seem to be working. Any ideas why not?
CvCapture* capture = cvCaptureFromAVI("test1.avi");
IplImage *img = 0;
if (!cvGrabFrame(capture)) {
printf("Error: Couldn't open the image file.\n");
return 1;
}
int numFrames = (int) cvGetCaptureProperty(capture, CV_CAP_PROP_FRAME_COUNT);
int posFrame = 1;
for(int i =0; i <= numFrames; i++){
cvSetCaptureProperty(capture, CV_CAP_PROP_POS_FRAMES, i);
posFrame = cvGetCaptureProperty(capture, CV_CAP_PROP_POS_FRAMES);
img = cvGrabFrame(capture);
cvNamedWindow("Image:", CV_WINDOW_AUTOSIZE);
cvShowImage("Image:", img);
printf("%i\n",posFrame);
cvWaitKey(0);
cvDestroyWindow("Image:");
}
Why don't you try this way using OpenCV 2.3? I think it is more direct and efficient, and more clear to your eyes:
VideoCapture _videoSource;
if(!_videoSource.open("test1.avi"))
{
exit(1); // Exit if fail
}
_videoSource.set(CV_CAP_PROP_CONVERT_RGB, 1);
Mat frame;
namedWindow("Image");
int posFrame;
while(1)
{
_videoSource >> frame;
posFrame=_videoSource.get(CV_CAP_PROP_POS_FRAMES);
imshow("output", frame);
return 0;
}
Something like this should work.

Why does OpenCV emit "Bad flag in unknown function" for this code?

I have been trying to get a real basic video player working using the Open CV API. Everything seems to run smoothly until the end of a video clip, then i get this error:
OpenCV Error: Bad flag in unknown function, file ........\ocv\opencv\modules\core\src\array.cpp
This creates a break in the code at imshow("video", frame), i find this wierd as this is the part that effectively plays the video so why does it only kick up a fuss at the end of the clip?? I found that it seems to give me this error in the last 90% of every video i play so at the moment im working around it by telling it to stop once 90% of the clip has played but this isnt very good programming so can anyone send some suggestions/help?
I have looked at other peoples post on this matter and none of the solution suggested have worked for me as of yet.
Heres my code...its only an experimentation piece so im sorry if its a bit messy:
Thanks for any help in advance
#include <cv.h>
#include <cxcore.h>
#include <highgui.h>
#include <direct.h>
#include <iostream>
using namespace cv;
void onTrackBarSlide(int);
double the_next_play_frame;
VideoCapture video("test.MOV"); // open the video file
int main(int, char**)
{
if(!video.isOpened()) // check if we succeeded
{
return -1;
}
int no_of_frames = video.get(CV_CAP_PROP_FRAME_COUNT); //total number of frames in video
std::cout << no_of_frames << std::endl;
std::cout << video.get(CV_CAP_PROP_FPS) << std::endl;
namedWindow("Video", 1);
cvCreateTrackbar("trackbar", "Video", 0, 40, onTrackBarSlide);
double stop_at = no_of_frames * 0.999;
for(;;){
if(the_next_play_frame >= double(stop_at))
{
break;
}
Mat frame;
video >> frame; // get a new frame from camera
imshow("Video", frame); // <---------- place where break/error occurs
if(waitKey(30) >= 0)
{
break;
}
}
return 0;
}
void onTrackBarSlide(int pos)
{
std::cout << getTrackbarPos("trackbar", "Video") << std::endl;
double frameratio = video.get(CV_CAP_PROP_FRAME_COUNT)/40; //10005 is the maximum value the slider can actual hold
double next_play_frame = frameratio * getTrackbarPos("trackbar", "Video");
video.set(CV_CAP_PROP_POS_FRAMES,next_play_frame);
the_next_play_frame = next_play_frame;
}
VideoCapture video("test.MOV"); // open the video file
int main(int, char**)
{
if(!video.isOpened()) // check if we succeeded
{
return -1;
}
}
Try put the VideoCapture instantiation inside main.
int main(){
VideoCapture video("test.MOV"); // open the video file
...
}