C++ 在 OpenCV 中保存图像
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/851679/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Saving an image in OpenCV
提问by Sujay Ghosh
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.
我是 OpenCV 的新手,并尝试捕获图像,然后将其保存到文件中。我在下面发布代码供您参考。
The jpg file is being saved, but it is black.
正在保存 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
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.
所有的功能都成功了。我已经在 XP 和 Vista 中尝试了上述代码 - 结果都是黑色图像。请让我知道我错过了什么。
回答by Barney
If you use C++, it is best to use C++ interface:
如果使用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
回答by sastanin
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:
根据我的经验,当SaveImage
给定一个位深不同于 8 位的矩阵时,OpenCV 会写出一个黑色图像。事实上,这是有记录的:
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.
使用此功能只能保存 8 位单通道或 3 通道(带有“BGR”通道顺序)图像。如果格式、深度或通道顺序不同,在保存前使用
cvCvtScale
和cvCvtColor
进行转换,或者使用通用cvSave
将图像保存为 XML 或 YAML 格式。
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.
在您的情况下,您可能首先调查捕获的图像类型,更改捕获属性(我认为CV_CAP_PROP_CONVERT_RGB
可能很重要)或之后手动转换。
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
:
这是一个如何使用 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)
(sorry, this is Python code, but it should be easy to translate it to C/C++)
(抱歉,这是 Python 代码,但将其转换为 C/C++ 应该很容易)
回答by nimcap
Sometimes the first call to cvQueryFrame() returns an empty image. Try:
有时第一次调用 cvQueryFrame() 会返回一个空图像。尝试:
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...
或者您可以尝试选择其他捕获设备,其中 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.
PS:此外,我认为对查看您的变量名称的捕获图像存在误解。变量 pCapturedImage 不是图像,而是捕获。您始终可以从捕获中“读取”图像。
回答by david h
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:
对不起,如果这太明显了。您确定 OpenCV 可以正确地看到和检测到网络摄像头,换句话说,当您将捕获的帧重定向到“highGui”窗口时,您是否获得了图像?例如像这样:
frame = cvQueryFrame( capture );
cvNamedWindow( "myWindow", CV_WINDOW_AUTOSIZE );
cvShowImage( "myWindow", frame );
回答by lf.
I know the problem! You just put a dot after "test.jpg"!
我知道问题所在!你只需在“test.jpg”后面加一个点!
cvSaveImage("test.jpg". ,pSaveImg);
cvSaveImage("test.jpg".,pSaveImg);
I may be wrong but I think its not good!
我可能是错的,但我认为它不好!
回答by Dhanish_Elementz
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.
我的 Microsoft 网络摄像头遇到了类似的问题。我在Matlab中查看图像采集工具箱,发现支持的最大分辨率为640*480。
I just changed the code in openCV and added
我只是更改了 openCV 中的代码并添加了
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.
在 cvQueryFrame 函数这是下一个支持的分辨率并更改之前,在保存图像并最终使其工作之前跳过了一些初始帧。
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:
我的建议:
- Dont grab frame with maximum resolution
- Skip some frames for correct camera initialisation
- 不要以最大分辨率抓帧
- 跳过一些帧以获得正确的相机初始化
回答by SayntLewis
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.
我有同样的问题。无论我做什么,图像看起来都像是全黑的。我尝试多次连续调用 cvQueryFrame 并注意到当我调用 5 个或更多时,我可以看到图像。于是我开始一一删除调用,看看“断点”在哪里。我最终发现的是,当我删除每个电话时,图像变得越来越暗。只打一次电话就提供了一个几乎全黑的图像,但如果我仔细观察,我可以辨认出我的图像。
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.
我连续尝试了 10 次调用来测试我的理论,果然,考虑到我在一个光线昏暗的房间里,我得到了一个非常明亮的图像。希望这与您遇到的问题相同。
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.
我对成像了解不多,但看起来多次连续调用 cvQueryFrame 会增加相机的曝光时间。这绝对可以解决问题,尽管它似乎不是最优雅的解决方案。我将看看我是否能找到一个可以增加曝光的参数,或者其他一些可以使我的图像变亮的参数。
Good luck!
祝你好运!
回答by Vitor
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.
SayntLewis 是对的。当您使用 cvCaptureFromCAM 激活相机时,自动白平衡尚未调整(这是一个缓慢的过程),因此您可能会在第一帧中获得大部分白色或大部分黑色(取决于相机和您的闪电条件)。当场景的闪电突然变化时,也会发生同样的情况。只需在打开相机后等待一段时间,刷新缓冲区,就可以开始了。
回答by Eric
I suggest you run OpenCV sanity check
我建议你运行 OpenCV 健全性检查
Its a serie of small executables located in the bin directory of opencv.
它是一系列位于 opencv 的 bin 目录中的小型可执行文件。
It will check if your camera is ok
它会检查你的相机是否正常
回答by jmp4281
I had the same problem on Windows Vista, I just added this code before cvQueryFrame
:
我在 Windows Vista 上遇到了同样的问题,我只是在之前添加了这段代码cvQueryFrame
:
cvSetCaptureProperty(capture, CV_CAP_PROP_FRAME_WIDTH, 720);
cvSetCaptureProperty(capture, CV_CAP_PROP_FRAME_HEIGHT, 480);