2012-12-19 131 views
2

我正试图编写一个C++程序,将平场应用于图像。它应该加载一个图像并将其分割为另一个加载的图像,然后将其导出为PNG。我的程序编译正确,但只生成全黑图像。OpenCV imwrite保存黑色PNG

#include <climits> 
#include <stdio.h> 
#include <string> 
#include <opencv/cv.h> 
#include <opencv/highgui.h> 

using namespace cv; 
using namespace std; 

int main(int argc, char *argv[]) 
{ 
    const char *flat_file = argv[1]; 
    const char *img_file = argv[2]; 
    const char *out_file = argv[3]; 

    Mat flat_img; 
    flat_img = imread(flat_file, CV_LOAD_IMAGE_ANYCOLOR | CV_LOAD_IMAGE_ANYDEPTH); 
    Mat image; 
    image = imread(img_file, CV_LOAD_IMAGE_ANYCOLOR | CV_LOAD_IMAGE_ANYDEPTH); 

    GaussianBlur(flat_img, flat_img, cv::Size(3,3), 0, 0, BORDER_REPLICATE); 
    divide(image, flat_img, image, 1.0, -1); 
    imwrite(out_file, image); 

return 0; 
} 

所有输入文件都是16位TIFF。目前,生成的输出文件是一个16位的PNG,它具有正确的像素尺寸,但是完全是黑色的。

我对C++和OpenCV都很陌生,所以我不完全确定我错过了什么。 This thread似乎表明,浮点值可能是原因。我很好地将浮点数转换出来,但我需要保持源代码的16位本质。我试过在divide命令之后加上一行image.convertTo(image, CV_16U);,并且都是CV_16UCV_8U,两者都不起作用。

任何和所有的帮助,非常感谢!

编辑

每下面的建议,我尝试添加一些imshow命令来实际测试的OpenCV正确处理的事情。似乎一切正常,直到我的分裂命令。之后,我的图像数组刚刚变成空白。

回答

1

原来,这确实是我的分治命令。我一直把我的代码放在一个由同事编写的类似应用程序上,所以我去看看他们是如何完成这个部门的。我不是100%肯定这是什么完成,但是当我改变我的鸿沟这个它的工作原理:

divide(image, flat_img, image, image.depth() == 16 ? UCHAR_MAX : USHRT_MAX);

只是做一个预测,即有条件的基于深度设置为我的数据标的形象。我仍然有一个萦绕不定的问题,那就是我所拥有的和divide(image, flat_img, image, image.depth() == 8 ? UCHAR_MAX : USHRT_MAX);之间的区别。两者都产生似乎是相同的图像。大多数情况下,我试图理解发生了什么好一点。

+1

'image.depth()'的价值是什么?在第一种情况下,如果它是16,则输入图像在被flat_image分割之前乘以UCHAR_MAX(否则由USHRT_MAX)。在第二种情况下,前一句中用8代替16。我期望这两个产生相同输出的唯一方式是如果'image.depth()'既不是8也不是16。 – SSteve

1

答案可能是你已经得到了图像,因为如果你使用一个普通的图像浏览器来打开一个16位图像,它通常是完全黑暗的,因为他们只支持正确显示8位图像。

为了解决这个问题,首先尝试使用OpenCV highgui来显示16位图像。 你可以做imshow("test",image) ; waitKey(0) ;并查看图像是否显示正确。如果是这样,你可以通过Mat img8bit ; image.convertTo(img8bit, CV8U, 255./65535.) ;将你的图像转换为8位,并且写下这个新的Mat。

+0

我假设你的意思是imshow而不是imwrite,所以我测试了一下。 :)无论如何,这也返回了一个空白图片,所以我开始在该过程中的每一步之后放置imshow。这两个图像正确加载和高斯模糊的作品。看起来分隔功能就是图像丢失的地方。 – Seth

+0

你错了。 'imshow()'可以正确处理16位图像。它会自动将它们转换为8位。来自[文档](http://docs.opencv.org/modules/highgui/doc/user_interface.html#imshow):_如果图像是16位无符号或32位整数,则像素除以256。也就是说,值范围[0,255 * 256]被映射到[0,255] ._ – SSteve

+0

sry,错字更正。 –