我正在尝试使用 OpenCV(2.4.0) for 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);
}
Run Code Online (Sandbox Code Playgroud)
我是这样调用 open 的:
open("./img_00245_c1.pgm", IMREAD_UNCHANGED, CV_WINDOW_AUTOSIZE);
Run Code Online (Sandbox Code Playgroud)
问题是打开窗口时显示的图像比我用 IrfanView 打开文件时显示的图像更暗。此外,如果我尝试将此图像写入另一个文件,如下所示:
Mat imgWrite;
imgWrite = image;
imwrite("newImage.pgm", imgWrite)
Run Code Online (Sandbox Code Playgroud)
我将获得与原始文件内容不同的文件内容,并且 IrfanView 将在我的函数显示时使用 imshow 显示该内容。
.PGM 文件的 imread 中是否有不同的标志,以便我可以显示和保存原始文件?
编辑:图像pgm 文件
编辑 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
Run Code Online (Sandbox Code Playgroud)
它应该从范围[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();
Run Code Online (Sandbox Code Playgroud)
请注意,图像中的值范围与 不对应[0, 4096],但是:
double minv, maxv;
minMaxLoc(img, &minv, &maxv);
// minv = 198
// maxv = 2414
Run Code Online (Sandbox Code Playgroud)
因此,简单的标准化如下[0,255]:
normalize(img, img, 0, 255, NORM_MINMAX);
img.convertTo(img, CV_8U);
Run Code Online (Sandbox Code Playgroud)
不起作用,因为它会产生比应有的更亮的图像。
这意味着要正确显示您的图像,您需要了解max_value(此处4096)。如果它每次都改变,你可以通过解析.pgm文件来检索它。
再说一遍,这只是可视化的问题。数据正确。
| 归档时间: |
|
| 查看次数: |
7864 次 |
| 最近记录: |