如何使用OpenCV显示PGM图像

时间:2015-11-20 22:22:19

标签: c++ opencv pgm

我尝试使用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函数而无需迭代像素并修改它们的值?

1 个答案:

答案 0 :(得分:2)

问题不在于数据加载的方式,而在于它们显示的方式

您的图片为CV_16UC1imshowimwrite都会将值从原始范围[0, 65535]规范化到范围[0, 255],以适应范围类型CV_8U

由于PGM图片的max_value4096

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文件。

同样,它只是可视化的问题。数据是正确的。