Reputation: 2868
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
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
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:
Upvotes: 2
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
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
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
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
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
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
andcvCvtColor
to convert it before saving, or use universalcvSave
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
Reputation: 1
i think, simply camera not initialize in first frame. Try to save image after 10 frames.
Upvotes: 0
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
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
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
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
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
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