在OpenCV中保存图像

时间:2009-05-12 08:07:58

标签: c++ opencv computer-vision

我是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中都尝试了上面的代码 - 结果是两者都是黑色图像。请让我知道我错过了什么。

15 个答案:

答案 0 :(得分:20)

如果使用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

答案 1 :(得分: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。您始终可以从捕获中“读取”图像。

答案 2 :(得分:5)

根据我的经验,当SaveImage被赋予比特深度不同于8位的矩阵时,OpenCV会写入黑色图像。事实上,这有点记录:

  

仅8位单通道或3通道   (带'BGR'通道顺序)图像可以   使用此功能保存。如果   格式,深度或渠道顺序是   不同,请使用cvCvtScale和   cvCvtColor之前转换它   保存,或使用通用cvSave   将图像保存为XML或YAML格式。

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

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

答案 3 :(得分:3)

抱歉,如果这太明显了。您确定OpenCV能够正确查看和检测到网络摄像头吗? 换句话说,当您将捕获的帧重定向到“highGui”窗口时,是否会获得图像?例如:

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

答案 4 :(得分:3)

我知道这个问题! 你只需在“test.jpg”之后放一个点!

cvSaveImage(“test.jpg”。,pSaveImg);

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

答案 5 :(得分:2)

我的微软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. 跳过一些帧以进行正确的相机初始化

答案 6 :(得分:1)

我使用以下代码捕获图像:

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

我知道这肯定有效

答案 7 :(得分:1)

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

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

它会检查你的相机是否正常

答案 8 :(得分:1)

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

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

答案 9 :(得分:1)

很抱歉打开一篇旧帖子,但我想为遇到这个帖子的人提供另一个答案。

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

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

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

祝你好运!

答案 10 :(得分:1)

SayntLewis是对的。当您使用cvCaptureFromCAM激活相机时,自动白平衡尚未调整(这是一个缓慢的过程),因此您可能会在第一帧上获得大部分白色或大部分黑色(取决于相机和闪电条件)。 当场景的闪电突然改变时,也会发生同样的情况。 打开相机后等待一段时间,冲洗缓冲液就可以了。

答案 11 :(得分:0)

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

frame = cvQueryFrame( capture );

趋向于空白。您可能需要等待一会儿(约3秒钟),然后尝试捕获图像。

答案 12 :(得分:0)

我认为,相机不会在第一帧中初始化。 尝试在10帧后保存图像。

答案 13 :(得分:0)

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

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

答案 14 :(得分:0)

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

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