5

我正在尝试使用 C++ 的 OpenCV(2.4.0) 加载和显示 .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 显示时显示此内容。

.PGM 文件的 imread 中是否有不同的标志,以便我可以显示和保存原始文件?

编辑:图像pgm 文件

编辑 2:备注: IrfanView 将图像标准化为最大像素值 255 。为了使用 OpenCV 清楚地看到图像,我应该在加载 Mat 时对图像进行归一化。这是否可以直接使用 OpenCV 函数而无需遍历像素并修改它们的值?

4

1 回答 1

2

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

您的图像是 a CV_16UC1,并且两者都imshowimwrite值从原始范围标准化为[0, 65535]范围[0, 255]以适合类型的范围CV_8U

由于您的 PGM 图像max_value具有4096

P2        
1176 640  // width height
4096      // max_value 

它应该从 range[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文件来检索它。

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

于 2015-11-22T13:11:09.657 回答