opencv saving image captured from webcam - c++

I receive an error "SIGABRT ERROR" when the code is trying to save the image on the HD.
I'm working with a MacBook Pro Mountain Lion on last XCODE and the libraries are well reconfigured.
Someone has a solution or some ideas?
#include "cv.h"
#include "highgui.h"
#include <stdio.h>
using namespace cv;
// A Simple Camera Capture Framework
int main() {
CvCapture* capture = cvCaptureFromCAM( CV_CAP_ANY );
if ( !capture ) {
fprintf( stderr, "ERROR: capture is NULL \n" );
getchar();
return -1;
}
// Create a window in which the captured images will be presented
cvNamedWindow( "mywindow", CV_WINDOW_AUTOSIZE );
// Show the image captured from the camera in the window and repeat
while ( 1 ) {
// Get one frame
IplImage* frame = cvQueryFrame( capture );
if ( !frame ) {
fprintf( stderr, "ERROR: frame is null...\n" );
getchar();
break;
}
cvShowImage( "mywindow", frame );
// Do not release the frame!
if ( (cvWaitKey(10) & 255) == 's' ) {
CvSize size = cvGetSize(frame);
IplImage* img= cvCreateImage(size, IPL_DEPTH_16S, 1);
img = frame;
cvSaveImage("matteo.jpg",&img);
}
if ( (cvWaitKey(10) & 255) == 27 ) break;
}
// Release the capture device housekeeping
cvReleaseCapture( &capture );
cvDestroyWindow( "mywindow" );
return 0;
}

The problem is that you are mixing your pointer syntax. You are creating a new IplImage with IplImage* img= cvCreateImage(size, IPL_DEPTH_16S, 1); but on the following line, you lose this structure as you overwrite the pointer img with frame.
The code causing your sigabrt is where you're sending a pointer to a pointer in
cvSaveImage("matteo.jpg",&img);. You should not do &img as img already is a pointer. The following is correct:
cvSaveImage("matteo.jpg",img);
There is actually no reason for you to create a new IplImage unless you want to do some preprocessing before saving it to file.
I modified your if-clause to the following which works fine on my computer:
if ( cvWaitKey(10) < 0 ) {
cvSaveImage("matteo.jpg",frame);
}

I have spent several days searching the internet for the right solution with simple keyboard input. There was always some lag / delay while using cv::waitKey.
The solution I have found is with adding Sleep(5) just after capturing the frame from webcam.
The below example is a combination of different forum threads.
It works without any lag / delay. Windows OS.
Press "q" to capture and save the frame.
There is a webcam feed always present. You can change the sequence to show the captured frame / image.
PS "tipka" - means "key" on the keyboard.
Regards, Andrej
#include <opencv2/opencv.hpp>
#include <iostream>
#include <stdio.h>
#include <windows.h> // For Sleep
using namespace cv;
using namespace std;
int ct = 0;
char tipka;
char filename[100]; // For filename
int c = 1; // For filename
int main(int, char**)
{
Mat frame;
//--- INITIALIZE VIDEOCAPTURE
VideoCapture cap;
// open the default camera using default API
cap.open(0);
// OR advance usage: select any API backend
int deviceID = 0; // 0 = open default camera
int apiID = cv::CAP_ANY; // 0 = autodetect default API
// open selected camera using selected API
cap.open(deviceID + apiID);
// check if we succeeded
if (!cap.isOpened()) {
cerr << "ERROR! Unable to open camera\n";
return -1;
}
//--- GRAB AND WRITE LOOP
cout << "Start grabbing" << endl
<< "Press a to terminate" << endl;
for (;;)
{
// wait for a new frame from camera and store it into 'frame'
cap.read(frame);
if (frame.empty()) {
cerr << "ERROR! blank frame grabbed\n";
break;
}
Sleep(5); // Sleep is mandatory - for no leg!
// show live and wait for a key with timeout long enough to show images
imshow("CAMERA 1", frame); // Window name
tipka = cv::waitKey(30);
if (tipka == 'q') {
sprintf_s(filename, "C:/Images/Frame_%d.jpg", c); // select your folder - filename is "Frame_n"
cv::waitKey(10);
imshow("CAMERA 1", frame);
imwrite(filename, frame);
cout << "Frame_" << c << endl;
c++;
}
if (tipka == 'a') {
cout << "Terminating..." << endl;
Sleep(2000);
break;
}
}
// the camera will be deinitialized automatically in VideoCapture destructor
return 0;
}

Related

OpenCV SuperResolution OutputArray frame

In the documentation for SuperResolution
The code required to output the nextframe is :
void superres::SuperResolution::nextFrame(OutputArray frame)
The input frame source has to be set with :
void superres::SuperResolution::setInput(const Ptr<FrameSource>& frameSource)
I have a code that takes frames from a video :
#include "opencv2/opencv.hpp"
#include "iostream"
using namespace cv;
using namespace std;
int main(int, char**)
{
VideoCapture cap ( "video1.mp4" ); // open the default camera
if( ! cap.isOpened () ) // check if we succeeded
return -1;
/* Mat edges; */
namedWindow ( "Video" , 1 );
double frnb ( cap.get ( CV_CAP_PROP_FRAME_COUNT ) );
std::cout << "frame count = " << frnb << endl;
for(;;)
{
Mat frame;
double fIdx;
std::cout << "frame index ? ";
std::cin >> fIdx;
if ( fIdx < 0 || fIdx >= frnb ) break;
cap.set ( CV_CAP_PROP_POS_FRAMES , fIdx );
bool success = cap.read(frame);
if ( ! success )
{
cout << "Cannot read frame " << endl;
break;
}
/* cap >> frame; // get a new frame from camera */
imshow("Video", frame);
if ( waitKey (0) == 27 ) break;
}
// the camera will be deinitialized automatically in VideoCapture destructor
return 0;
}
Given this I can use the frame variable as the parameter for the setInput method, but how can I initialize the OutputArray frame needed to generate the output ?
I think you cannot use frame as the parameter for the setInput and you don't need to initalize the OutputArray frame.
Check this example out:
FrameSource is created like this:
121. frameSource = createFrameSource_Video(inputVideoName);
And then the outputArray frame is used like this:
142. Mat result; // no intialization, just declaration
144. MEASURE_TIME(superRes->nextFrame(result));

detect object from video using LatentSVMDetector

I am using Hog+SVM in opencv for detecting cars in Video avi file. I am using car.xml model file.
I am not getting good results when I used LatentSvmDetetction for detecting cars
A Large number of false detections in frame.
It is very slow. It takes about 5 seconds to detect objects from a frame.
Please suggest me how to improve object detection time.
My code is below:
#include <iostream>
#include "opencv2/objdetect/objdetect.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/contrib/contrib.hpp"
#if defined(WIN32) || defined(_WIN32)
#include <io.h>
#else
#include <dirent.h>
#endif
#ifdef HAVE_CVCONFIG_H
#include <cvconfig.h>
#endif
#ifdef HAVE_TBB
#include "tbb/task_scheduler_init.h"
#endif
using namespace std;
using namespace cv;
static void detectAndDrawObjects( Mat& frame, LatentSvmDetector& detector, const vector<Scalar>& colors, float overlapThreshold, int numThreads )
{
vector<LatentSvmDetector::ObjectDetection> detections;
TickMeter tm;
tm.start();
detector.detect( frame, detections, overlapThreshold, numThreads);
tm.stop();
cout << "Detection time = " << tm.getTimeSec() << " sec" << endl;
const vector<string> classNames = detector.getClassNames();
CV_Assert( colors.size() == classNames.size() );
for( size_t i = 0; i < detections.size(); i++ )
{
const LatentSvmDetector::ObjectDetection& od = detections[i];
rectangle( frame, od.rect, colors[od.classID], 3 );
putText( frame, classNames[od.classID], Point(od.rect.x+4,od.rect.y+13), FONT_HERSHEY_SIMPLEX, 0.55, colors[od.classID], 2 );
}
}
static void readDirectory( const string& directoryName, vector<string>& filenames, bool addDirectoryName=true )
{
filenames.clear();
#if defined(WIN32) | defined(_WIN32)
struct _finddata_t s_file;
string str = directoryName + "\\*.*";
intptr_t h_file = _findfirst( str.c_str(), &s_file );
if( h_file != static_cast<intptr_t>(-1.0) )
{
do
{
if( addDirectoryName )
filenames.push_back(directoryName + "\\" + s_file.name);
else
filenames.push_back((string)s_file.name);
}
while( _findnext( h_file, &s_file ) == 0 );
}
_findclose( h_file );
#else
DIR* dir = opendir( directoryName.c_str() );
if( dir != NULL )
{
struct dirent* dent;
while( (dent = readdir(dir)) != NULL )
{
if( addDirectoryName )
filenames.push_back( directoryName + "/" + string(dent->d_name) );
else
filenames.push_back( string(dent->d_name) );
}
closedir( dir );
}
#endif
sort( filenames.begin(), filenames.end() );
}
int main()
{
string frames_folder, models_folder;
float overlapThreshold = 0.2f;
int numThreads = -1;
models_folder = "D:\\Downloads\\models_VOC2007";
VideoCapture cap("D:\\images\\videos\\vid2.AVI"); // open the video file for reading
cvNamedWindow("MyVideo", CV_WINDOW_AUTOSIZE);
if ( !cap.isOpened() ) // if not success, exit program
{
cout << "Cannot open the video file" << endl;
return -1;
}
LatentSvmDetector detector( models_filenames );
if( detector.empty() )
{
cout << "Models cann't be loaded" << endl;
exit(-1);
}
vector<Scalar> colors;
generateColors( colors, detector.getClassNames().size() );
Mat frame;
while(1)
{
bool bSuccess = cap.read(frame);
if (!bSuccess) //if not success, break loop
{
cout << "Cannot read the frame from video file" << endl;
break;
}
detectAndDrawObjects( frame, detector, colors, overlapThreshold, numThreads );
imshow( "MyVideo", frame );
//imshow("video", frame); //show the frame in "MyVideo" window
if(waitKey(30) == 27) //wait for 'esc' key press for 30 ms. If 'esc' key is pressed, break loop
{
cout << "esc key is pressed by user" << endl;
break;
}
}
return 0;
}
I suggest you
to resize the frame to a size that 10x5 pixel is the smallest possible car in the frame;
to do a blur first; it is possible to get lots of false-positives because there is noise that generate edges that can be similar to the car;
I suppose that the detector is for side cars (I have not tested it) ant it will not detect cars rotated with more than 60 degrees and it is trained on some database that was not similar to your environment; so maybe it is better to train your own detector (car.xml).
HOG is based on edges and edges are very sensible to light and shadows. Try to preprocess (contrast enhancement) the frame before detecting the cars.

Video Grabbing doesn't work OpenCV

I am using this piece of code to grab frames off a video :
#include <stdio.h>
#include <stdlib.h>
#include <opencv/cv.h>
#include <opencv/highgui.h>
#include <iostream>
using namespace cv;
using namespace std;
int main (int argc, char** argv)
{
//initializing capture from file
CvCapture * capture = cvCaptureFromAVI ("/home/<some_file>.avi");
//Capturing a frame
IplImage* img = 0;
if(!cvGrabFrame(capture)) //capture a frame
{
cout << Could not grab a frame\n\7";
exit(0);
}
img=cvRetrieveFrame(capture); //retrieve the captured frame
//free resources
cvReleaseCapture(&capture);
}
Which is returning :
Could not grab a frame
Additional details :
I had used code to save webcam video feed to the file from which i want to grab frames .
I used this code :
#include <opencv2/opencv.hpp>
#include <opencv2/highgui/highgui.hpp>
int main( int argc, char** argv ) {
CvCapture* capture;
capture = cvCreateCameraCapture(0);
assert( capture != NULL );
IplImage* bgr_frame = cvQueryFrame( capture );
CvSize size = cvSize(
(int)cvGetCaptureProperty( capture,
CV_CAP_PROP_FRAME_WIDTH),
(int)cvGetCaptureProperty( capture,
CV_CAP_PROP_FRAME_HEIGHT)
);
cvNamedWindow( "Webcam", CV_WINDOW_AUTOSIZE );
CvVideoWriter *writer = cvCreateVideoWriter( "/Users/user/Desktop/OpenCV_trial/OpenCV_trial/vidtry.AVI",
CV_FOURCC('D','I','V','X'),
30,
size
);
while( (bgr_frame = cvQueryFrame( capture )) != NULL )
{
cvWriteFrame(writer, bgr_frame );
cvShowImage( "Webcam", bgr_frame );
char c = cvWaitKey( 33 );
if( c == 27 ) break;
}
cvReleaseVideoWriter( &writer );
cvReleaseCapture( &capture );
cvDestroyWindow( "Webcam" );
return( 0 );
}
Does anyone know where I might be going wrong ? I am running OpenCV-2.4.3 on a Beagleboard -xM with Ubuntu Quantal.
I am not quite sure what your exactly question is, but if you want to grab frames from a video, you should at least have a loop.
A reason for your error could be, that your video file is not available. Have you tried another one? The full path of the file? Or put the file directly into your working directory and check it.
Another reason could be a problem with the first frame (this sometimes happens). So try to remove your exit and enclose your code with a loop over all frames.
Here is an example that shows the given video file (Consider to use the C++-interface):
#include <opencv/cv.h>
#include <opencv/highgui.h>
#include <iostream>
using namespace cv;
using namespace std;
int main (int argc, char** argv)
{
//initializing capture from file
Mat img;
VideoCapture capture("a.avi");
if(!capture.isOpened())
{
cout<<"Could not open video!\n";
return 1;
}
while(true)
{
//Capturing a frame
capture >> img;
if(!img.empty())
{
imshow("Video",img);
}
else
{
cout <<"Could not grab a frame\n";
break;
}
if(waitKey(5) >= 0)
break;
}
return 0;
}
This program runs on my PC if the file "a.avi" is in the current working directory of the program.

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

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
...
}