Sujay Ghosh
Sujay Ghosh

Reputation: 2868

Saving an image in OpenCV

I am new to OpenCV, and trying to capture an image, and then save it to a file. I am posting the code for your reference, below.

The jpg file is being saved, but it is black.

// Capture the Image from the webcam
CvCapture *pCapturedImage = cvCreateCameraCapture(0);

// Get the frame
IplImage *pSaveImg = cvQueryFrame(pCapturedImage);

// Save the frame into a file
cvSaveImage("test.jpg". ,pSaveImg); // A JPG FILE IS BEING SAVED
                                    // OF 6KB , BUT IT IS BLACK

All of the functions are succesful. I have tried the above code in both XP and Vista - the result is a black image on both. Please let me know what I am missing out.

Upvotes: 35

Views: 151474

Answers (15)

Haris Hussain
Haris Hussain

Reputation: 11

hopefully this will save images form your webcam

#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <iostream>

using namespace std;
using namespace cv;

int main()
{
   VideoCapture cap(0);

   Mat save_img;

   cap >> save_img;

   char Esc = 0;

   while (Esc != 27 && cap.isOpened()) {        
    bool Frame = cap.read(save_img);        
    if (!Frame || save_img.empty()) {       
        cout << "error: frame not read from webcam\n";      
        break;                                              
    }
    namedWindow("save_img", CV_WINDOW_NORMAL);  
    imshow("imgOriginal", save_img);            
    Esc = waitKey(1);
}
imwrite("test.jpg",save_img); 
}

Upvotes: 1

Dhanish_Elementz
Dhanish_Elementz

Reputation: 118

I had similar problem with my Microsoft WebCam. I looked in the image aquisition toolbox in Matlab and found that the maximum supported resolution is 640*480.

I just changed the code in openCV and added

cvSetCaptureProperty(capture, CV_CAP_PROP_FRAME_WIDTH, 352); 
cvSetCaptureProperty(capture, CV_CAP_PROP_FRAME_HEIGHT, 288);

before cvQueryFrame function which was the next supported resolution and changed skipped some initial frames before saving the image and finally got it working.

I am sharing my working Code

#include "cv.h" 
#include "highgui.h" 
#include <stdio.h> 



using namespace cv;
using namespace std;

int main() 
{
CvCapture* capture = cvCaptureFromCAM( CV_CAP_ANY );
cvSetCaptureProperty(capture, CV_CAP_PROP_FRAME_WIDTH, 352); 
cvSetCaptureProperty(capture, CV_CAP_PROP_FRAME_HEIGHT, 288)


 // Get one frame
IplImage* frame;

for (int i = 0; i < 25; i++) 
{
frame = cvQueryFrame( capture );
}


printf( "Image captured \n" );  
//IplImage* RGB_frame = frame;
//cvCvtColor(frame,RGB_frame,CV_YCrCb2BGR);
//cvWaitKey(1000);
cvSaveImage("test.jpg" ,frame);
//cvSaveImage("cam.jpg" ,RGB_frame);

printf( "Image Saved \n" );

//cvWaitKey(10);

// Release the capture device housekeeping
cvReleaseCapture( &capture );
//cvDestroyWindow( "mywindow" );
return 0;
}

My Suggestions:

  1. Dont grab frame with maximum resolution
  2. Skip some frames for correct camera initialisation

Upvotes: 2

Barney Szabolcs
Barney Szabolcs

Reputation: 12514

If you use C++, it is best to use C++ interface:

using namespace cv;
// Capture the Image from the webcam
VideoCapture cap(0);

// Get the frame
Mat save_img; cap >> save_img;

if(save_img.empty())
{
  std::cerr << "Something is wrong with the webcam, could not get frame." << std::endl;
}
// Save the frame into a file
imwrite("test.jpg", save_img); // A JPG FILE IS BEING SAVED

Upvotes: 34

jmp4281
jmp4281

Reputation: 11

I had the same problem on Windows Vista, I just added this code before cvQueryFrame:

cvSetCaptureProperty(capture, CV_CAP_PROP_FRAME_WIDTH, 720);
cvSetCaptureProperty(capture, CV_CAP_PROP_FRAME_HEIGHT, 480);

Upvotes: 1

Vitor
Vitor

Reputation: 2792

SayntLewis is right. When you activate the camera with cvCaptureFromCAM, the auto white balance is not yet adjusted (it's a slow process), so you may get a mostly white or mostly black (depends on the camera and your lightning conditions) on the first frames. The same happens when there's a sudden change of the lightning of the scene. Just wait some time after opening the camera, flush the buffer and you're ready to go.

Upvotes: 1

nicc
nicc

Reputation: 235

On OSX, saving video frames and still images only worked for me when I gave a full path to cvSaveImage:

cvSaveImage("/Users/nicc/image.jpg",img);

Upvotes: 0

SayntLewis
SayntLewis

Reputation: 11

Sorry to bring up an old post, but I wanted to provide another answer for anyone that comes across this thread.

I had the same problem. No matter what I did, the image just looked like it was complete black. I tried making multiple consecutive calls to cvQueryFrame and noticed that when I made 5 or more, I could see the image. So I started removing the calls one by one to see where the "breaking point" was. What I ended up finding was that the image got darker and darker as I removed each call. Making just a single call provided an image that was almost completely black, but if I looked very closely, I could make out my image.

I tried 10 consecutive calls to test my theory, and sure enough, I was given a very bright image, considering that I'm in a dimly lit room. Hopefully, this was the same problem you were encountering.

I don't know much about imaging, but it looks like multiple consecutive calls to cvQueryFrame increases the length of exposure for the camera. This definitely fixes the problem, though it doesn't seem like the most elegant solution. I'm going to see if I can find a parameter that will increase the exposure, or perhaps some other parameter that will brighten up my images.

Good luck!

Upvotes: 1

sastanin
sastanin

Reputation: 41491

In my experience OpenCV writes a black image when SaveImage is given a matrix with bit depth different from 8 bit. In fact, this is sort of documented:

Only 8-bit single-channel or 3-channel (with ‘BGR’ channel order) images can be saved using this function. If the format, depth or channel order is different, use cvCvtScale and cvCvtColor to convert it before saving, or use universal cvSave to save the image to XML or YAML format.

In your case you may first investigate what kind of image is captured, change capture properties (I suppose CV_CAP_PROP_CONVERT_RGB might be important) or convert it manually afterwards.

This is an example how to convert to 8-bit representation with OpenCV. cc here is an original matrix of type CV_32FC1, cc8u is its scaled version which is actually written by SaveImage:

# I want to save cc here
cc8u = CreateMat(cc.rows, cc.cols, CV_8U)
ccmin,ccmax,minij,maxij = MinMaxLoc(cc)
ccscale, ccshift = 255.0/(ccmax-ccmin), -ccmin
CvtScale(cc, cc8u, ccscale, ccshift)
SaveImage("cc.png", cc8u)

(sorry, this is Python code, but it should be easy to translate it to C/C++)

Upvotes: 5

chronos
chronos

Reputation: 1

i think, simply camera not initialize in first frame. Try to save image after 10 frames.

Upvotes: 0

lf.
lf.

Reputation: 31

I know the problem! You just put a dot after "test.jpg"!

cvSaveImage("test.jpg". ,pSaveImg);

I may be wrong but I think its not good!

Upvotes: 3

Eric
Eric

Reputation: 19863

I suggest you run OpenCV sanity check

Its a serie of small executables located in the bin directory of opencv.

It will check if your camera is ok

Upvotes: 1

Nexus
Nexus

Reputation: 1592

From my experiences the first few frames that are captured when using:

frame = cvQueryFrame( capture );

Tend to be blank. You may want to wait a short while(about 3 seconds) and then try to capture the image.

Upvotes: 0

david h
david h

Reputation: 126

sorry if this is too obvious. Are you sure the webcam is properly seen and detected by OpenCV in other words, do you get an image when you redirect the captured frame to a "highGui" window? For instance like so:

 frame = cvQueryFrame( capture );
 cvNamedWindow( "myWindow", CV_WINDOW_AUTOSIZE );
 cvShowImage( "myWindow", frame );

Upvotes: 3

Yogi
Yogi

Reputation: 2540

I use the following code to capture images:

CvCapture* capture = cvCaptureFromCAM( CV_CAP_ANY );
if(!capture) error((char*)"No Capture");
IplImage *img=cvQueryFrame(capture);

I know this works for sure

Upvotes: 1

nimcap
nimcap

Reputation: 10493

Sometimes the first call to cvQueryFrame() returns an empty image. Try:

IplImage *pSaveImg = cvQueryFrame(pCapturedImage);
pSaveImg = cvQueryFrame(pCapturedImage);

If that does not work, try to select capture device automatically:

CvCapture *pCapturedImage = cvCreateCameraCapture(-1);

Or you may try to select other capture devices where n=1,2,3...

CvCapture *pCapturedImage = cvCreateCameraCapture(n);

PS: Also I believe there is a misunderstanding about captured image looking at your variable name. The variable pCapturedImage is not an Image it is a Capture. You can always 'read' an image from capture.

Upvotes: 5

Related Questions