OpenCV frame capture from AVI - c++

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.

Related

Can't cat image from the videostream opencv

Other questions did't help me, so i ask mine
Can't get any image from my videocam using the latest opencv library.
void ShowCam(int CameraToBeOpened)
{
int i = 0;
cv::Mat frame;
cv::VideoCapture cap(CameraToBeOpened);
cvNamedWindow("Camera", CV_WINDOW_NORMAL);
while (true) {
if (cap.read(frame))
imshow("Camera", frame);
char c = cvWaitKey(50);
if (c == 27)
break;
if (c == 32) {
char filename[200];
sprintf_s(filename, "\Test pictures\test_%d.jpg", i);
i++;
cv::imwrite(filename, frame);
std::cout << "Image has been captured" << std::endl;
}
}
It doesn't generate mistakes, just can't find images in the folder.

How can I know if a image is RGB in OpenCV?

I've made a program in c++ using OpenCV library. The program record video from webcam and then split it in frames. I want to know if the frames are in RGB beacuse i want to access the RGB properties of every pixel. The codec for capture is CV_FOURCC('M','J','P','G'). How can i get the frames in RGB colorspace?
int main() {
Mat image;
VideoCapture cap(0);
cap.set(CV_CAP_PROP_FPS, 10);
if ( !cap.isOpened() ) {
cout << "ERROR : Cannot open the video file"<<endl;
return -1;
}
namedWindow("MyWindow", 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 oVideoWriter("E:/myVideo.avi", CV_FOURCC('M', 'J', 'P', 'G'), 10, frameSize, true);
if (!oVideoWriter.isOpened()) {
cout << "ERROR : Failed to write the video"<<endl;
return - 1;
}
while (1) {
Mat image;
bool bSuccess = cap.read(image);
if (!bSuccess) {
cout << "ERROR : Cannot read a frame from video file" << endl;
break;
}
oVideoWriter.write(image);
imshow("MyWindow", image);
if (waitKey(10) == 27) {
saveImages();
cout << "ESC key is pressed by user" << endl;
break
}
}
return 0;
}
int saveImages() {
CvCapture *capture = cvCaptureFromFile("E:/myVideo.avi");
if(!capture)
{
cout<<"!!! cvCaptureFromAVI failed (file not found?)"<<endl;
return -1;
}
int fps = (int) cvGetCaptureProperty(capture, CV_CAP_PROP_FPS);
IplImage* frame = NULL;
int frame_number = 0;
char key = 0;
while (key != 'q')
{
frame = cvQueryFrame(capture);
if (!frame)
{
cout<<"!!! cvQueryFrame failed: no frame"<<endl;
break;
}
char filename[100];
strcpy(filename, "frame_");
char frame_id[30];
_itoa(frame_number, frame_id, 10);
strcat(filename, frame_id);
strcat(filename, ".jpg");
printf("* Saving: %s\n", filename);
if (!cvSaveImage(filename, frame))
{
cout<<"!!! cvSaveImage failed"<<endl;
break;
}
frame_number++;
key = cvWaitKey(1000 / fps);
}
cvReleaseCapture(&capture);
return 0;
}
When OpenCV loads colored images (i.e. 3 channel) from the disk, camera, or a video file, the image data will be stored in the BGR format. This is a simple test that you can do:
/* Code using the C++ API */
cv::VideoCapture cap(0);
if (!cap.isOpened()) {
std::cout << "!!! Failed to open webcam" << std::endl;
return -1;
}
if (!cap.read(frame)) {
std::cout << "!!! Failed to read a frame from the camera" << std::endl;
return -1;
}
bool is_colored = false;
if (frame.channels() == 3) {
is_colored = true;
}
// Do something with is_colored
// ...
Unless you have a weird camera, the frames will always be colored (and as result, stored as BGR).
When cv::imwrite() (C++ API) or cvSaveImage() (C API) are called, OpenCV does the proper magic tricks to ensure the data is saved in a compatible way with requested output format (JPG, PNG, AVI, etc) and during this process it automatically converts the data to RGB if it needs to.
Nevertheless, if for some reason you need to convert the image to RGB you can call:
cv::Mat img_rgb;
cv::cvtColor(frame, img_rgb, CV_BGR2RGB);
Please note that OpenCV has a C API and also a C++ API, and they shouldn't be mixed:
If you use IplImage then stick with the rest of the C API.
If you decide to go with cv::Mat, then keep using the C++ API.
There are different ways to access the pixels of a cv::Mat, here is one of them:
unsigned char* pixels = (unsigned char*)(frame.data);
for (int i = 0; i < frame.rows; i++)
{
for (int j = 0; j < frame.cols; j++)
{
char b = pixels[frame.step * j + i] ;
char g = pixels[frame.step * j + i + 1];
char r = pixels[frame.step * j + i + 2];
}
}

OpenCV does not free camera

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.

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);
}