如何使用 OpenCV 显示 PGM 图像
How to display PGM image using OpenCV
我正在尝试使用适用于 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);
问题是打开 window 时显示的图像比我用 IrfanView 打开文件时显示的图像暗。
另外,如果我尝试将此图像写入另一个文件,如下所示:
Mat imgWrite;
imgWrite = image;
imwrite("newImage.pgm", imgWrite)
我会得到一个与原始文件内容不同的文件内容,IrfanView 会在我的函数显示时使用 imshow 显示它。
.PGM 文件的 imread 中是否有不同的标志,以便我可以显示和保存原始文件?
编辑: 图片 pgm file
编辑 2 : 指出:IrfanView 将图像标准化为最大像素值 255 。
为了使用 OpenCV 清楚地看到图像,我还应该在加载到 Mat 时对图像进行归一化。这是否可以直接使用 OpenCV 函数而不遍历像素并修改它们的值?
问题不在于数据加载的方式,而在于它们显示的方式。
您的图片是 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
文件来检索它。
同样,这只是 可视化 的问题。数据正确。
我正在尝试使用适用于 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);
问题是打开 window 时显示的图像比我用 IrfanView 打开文件时显示的图像暗。 另外,如果我尝试将此图像写入另一个文件,如下所示:
Mat imgWrite;
imgWrite = image;
imwrite("newImage.pgm", imgWrite)
我会得到一个与原始文件内容不同的文件内容,IrfanView 会在我的函数显示时使用 imshow 显示它。
.PGM 文件的 imread 中是否有不同的标志,以便我可以显示和保存原始文件?
编辑: 图片 pgm file
编辑 2 : 指出:IrfanView 将图像标准化为最大像素值 255 。 为了使用 OpenCV 清楚地看到图像,我还应该在加载到 Mat 时对图像进行归一化。这是否可以直接使用 OpenCV 函数而不遍历像素并修改它们的值?
问题不在于数据加载的方式,而在于它们显示的方式。
您的图片是 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
文件来检索它。
同样,这只是 可视化 的问题。数据正确。