我尝试使用OpenCV(2.4.0)为C ++加载和显示.PGM图像。
void open(char* location, int flag, int windowFlag)
{
Mat image = imread(location, flag);
namedWindow("Image window", windowFlag);
imshow("Image window", image);
waitKey(0);
}
我这样打开电话:
open("./img_00245_c1.pgm", IMREAD_UNCHANGED, CV_WINDOW_AUTOSIZE);
问题是当窗口打开时显示的图像比我用IrfanView打开文件时更暗。 此外,如果我试图将此图像写入另一个文件:
Mat imgWrite;
imgWrite = image;
imwrite("newImage.pgm", imgWrite)
我将获得与原始文件内容不同的文件内容,IrfanView将显示此内容,因为我的功能显示为imshow。
。imG for .PGM文件中是否有不同的标志,以便我可以显示并保存原始文件?
编辑:图片pgm file
编辑2:注释:IrfanView将图像规范化为最大像素值255。 为了使用OpenCV清楚地看到图像,我应该在Mat中加载时对图像进行标准化。这是否可以直接使用OpenCV函数而无需迭代像素并修改它们的值?
答案 0 :(得分:2)
问题不在于数据加载的方式,而在于它们显示的方式。
您的图片为CV_16UC1
,imshow
和imwrite
都会将值从原始范围[0, 65535]
规范化到范围[0, 255]
,以适应范围类型CV_8U
。
由于PGM图片的max_value
为4096
:
P2
1176 640 // width height
4096 // max_value
应该从范围[0, 4096]
而不是[0, 65535]
进行标准化。
你可以这样做:
Mat img = imread("path_to_image", IMREAD_UNCHANGED);
img.convertTo(img, CV_8U, 255.0 / 4096.0);
imshow("Image", img);
waitKey();
请注意,图片中的值范围与[0, 4096]
不对应,但是:
double minv, maxv;
minMaxLoc(img, &minv, &maxv);
// minv = 198
// maxv = 2414
所以[0,255]
中的直接规范化就像:
normalize(img, img, 0, 255, NORM_MINMAX);
img.convertTo(img, CV_8U);
不会工作,因为它会产生一个比它应该更好的图像更亮。
这意味着要正确显示您的图片,您需要知道max_value
(此处为4096
)。如果它每次都更改,您可以检索它解析.pgm
文件。
同样,它只是可视化的问题。数据是正确的。