34

我是 OpenCV 的新手,正在尝试捕获图像,然后将其保存到文件中。我在下面发布代码供您参考。

正在保存 jpg 文件,但它是黑色的。

// 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

所有的功能都成功了。我在 XP 和 Vista 中都尝试过上面的代码——结果都是黑色图像。请让我知道我错过了什么。

4

15 回答 15

28

如果你使用 C++,最好使用 C++ 接口

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
于 2012-12-04T17:27:42.180 回答
5

有时第一次调用 cvQueryFrame() 会返回一个空图像。尝试:

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

如果这不起作用,请尝试自动选择捕获设备:

CvCapture *pCapturedImage = cvCreateCameraCapture(-1);

或者您可以尝试选择 n=1,2,3... 的其他捕获设备

CvCapture *pCapturedImage = cvCreateCameraCapture(n);

PS:另外,我认为查看您的变量名时捕获的图像存在误解。变量 pCapturedImage 不是 Image 它是 Capture。您始终可以从捕获中“读取”图像。

于 2009-05-12T21:22:30.170 回答
5

SaveImage根据我的经验,当给定一个位深度不同于 8 位的矩阵时, OpenCV 会写入一个黑色图像。事实上,这是有记录的:

使用此功能只能保存 8 位单通道或 3 通道(具有“BGR”通道顺序)图像。如果格式、深度或通道顺序不同,保存前使用cvCvtScaleand cvCvtColor进行转换,或者使用universalcvSave将图像保存为XML或YAML格式。

在您的情况下,您可以首先调查捕获的图像类型,更改捕获属性(我想CV_CAP_PROP_CONVERT_RGB可能很重要)或之后手动转换它。

这是一个如何使用 OpenCV 转换为 8 位表示的示例。cc这是一个类型的原始矩阵CV_32FC1cc8u是它的缩放版本,实际上是由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)

(抱歉,这是 Python 代码,但应该很容易将其翻译成 C/C++)

于 2011-02-22T12:25:58.630 回答
3

对不起,如果这太明显了。您确定 OpenCV 正确地看到和检测到网络摄像头,换句话说,当您将捕获的帧重定向到“highGui”窗口时,您是否得到图像?比如像这样:

 frame = cvQueryFrame( capture );
 cvNamedWindow( "myWindow", CV_WINDOW_AUTOSIZE );
 cvShowImage( "myWindow", frame );
于 2009-05-13T22:28:10.617 回答
3

我知道问题所在!您只需在“test.jpg”之后添加一个点!

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

我可能错了,但我认为它不好!

于 2010-04-18T21:50:45.773 回答
2

我的 Microsoft WebCam 也有类似的问题。我查看了Matlab中的图像采集工具箱,发现最大支持的分辨率为640*480。

我只是更改了openCV中的代码并添加了

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

在 cvQueryFrame 函数(它是下一个支持的分辨率并更改之前)在保存图像之前跳过了一些初始帧并最终让它工作。

我正在分享我的工作代码

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

我的建议:

  1. 不要以最高分辨率抓取帧
  2. 跳过一些帧以进行正确的相机初始化
于 2013-05-05T05:21:40.510 回答
1

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

于 2009-05-13T22:16:14.270 回答
1

萨恩特刘易斯是对的。当您使用 cvCaptureFromCAM 激活相机时,尚未调整自动白平衡(这是一个缓慢的过程),因此您可能会在第一帧上获得大部分白色或大部分黑色(取决于相机和您的光照条件)。当场景的闪电突然变化时,也会发生同样的情况。打开相机后稍等片刻,冲洗缓冲区即可。

于 2011-06-20T18:51:43.837 回答
1

我建议你运行 OpenCV 健全性检查

它是一系列位于 opencv 的 bin 目录中的小型可执行文件。

它将检查您的相机是否正常

于 2009-07-07T15:42:06.530 回答
1

我在 Windows Vista 上遇到了同样的问题,我之前只是添加了这段代码cvQueryFrame

cvSetCaptureProperty(capture, CV_CAP_PROP_FRAME_WIDTH, 720);
cvSetCaptureProperty(capture, CV_CAP_PROP_FRAME_HEIGHT, 480);
于 2010-08-19T16:21:05.177 回答
1

很抱歉提出一个旧帖子,但我想为遇到此线程的任何人提供另一个答案。

我有同样的问题。无论我做什么,图像看起来都是全黑的。我尝试对 cvQueryFrame 进行多次连续调用,并注意到当我进行 5 次或更多时,我可以看到图像。于是我开始一一删除调用,看看“断点”在哪里。我最终发现,当我删除每个呼叫时,图像变得越来越暗。只打一个电话就提供了一个几乎全黑的图像,但如果我仔细观察,我可以辨认出我的图像。

我连续尝试了 10 次电话来测试我的理论,果然,考虑到我在一个光线昏暗的房间里,我得到了一个非常明亮的图像。希望这与您遇到的问题相同。

我对成像知之甚少,但看起来多次连续调用 cvQueryFrame 会增加相机的曝光时间。这绝对可以解决问题,尽管它似乎不是最优雅的解决方案。我将看看是否可以找到一个可以增加曝光的参数,或者是否可以找到其他可以使我的图像变亮的参数。

祝你好运!

于 2011-03-17T23:31:58.893 回答
1

希望这会从您的网络摄像头中保存图像

#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); 
}
于 2017-01-26T15:49:58.697 回答
0

根据我的经验,使用时捕获的前几帧:

frame = cvQueryFrame( capture );

倾向于空白。您可能需要稍等片刻(约 3 秒),然后尝试捕捉图像。

于 2009-07-04T07:54:51.777 回答
0

在 OSX 上,仅当我提供 cvSaveImage 的完整路径时,保存视频帧和静止图像才对我有用:

cvSaveImage("/Users/nicc/image.jpg",img);
于 2011-04-25T09:15:18.303 回答
0

我想,只是相机没有在第一帧初始化。尝试在 10 帧后保存图像。

于 2010-05-15T11:10:54.530 回答