5
votes

I'm trying to load and display a .PGM image using OpenCV(2.4.0) for C++.

void open(char* location, int flag, int windowFlag)
{
    Mat image = imread(location, flag);
    namedWindow("Image window", windowFlag);
    imshow("Image window", image);
    waitKey(0);
}

I'm calling open like this:

open("./img_00245_c1.pgm", IMREAD_UNCHANGED, CV_WINDOW_AUTOSIZE);

The problem is that the image shown when the window is opened is darker than if I'm opening the file with IrfanView. Also if I'm trying to write this image to another file like this:

Mat imgWrite;
imgWrite = image;
imwrite("newImage.pgm", imgWrite)

I will get a different file content than the original one and IrfanView will display this as my function displays with imshow.

Is there a different flag in imread for .PGM files such that I can get the original file to be displayed and saved ?

EDIT: Image pgm file

EDIT 2 : Remarked that: IrfanView normalizes the image to a maximum pixel value of 255 . In order to see the image clearly using OpenCV I should normalize the image also when loading in Mat. Is this possible directly with OpenCV functions without iterating through pixels and modifying their values ?

1
Maybe Irfanview is automatically normalising, i.e. contrast stretching your image and OpenCV is not... maybe try saving a normalised, contrast-stretched image in Irfanview and loading that into OpenCV, or contrast stretching a dark one in OpenCV before displaying it.Mark Setchell
maybe you could find the answer here ( take a look COMPATIBILITY ). could you give a link to your PGM file ?sturkmen
I've added a link to the photo !John Smith
The link is to a PNG file.Mark Setchell
Try now, the site were I uploaded changed the file....John Smith

1 Answers

2
votes

The problem is not in the way data are loaded, but in the way they are displayed.

Your image is a CV_16UC1, and both imshow and imwrite normalize the values from original range [0, 65535] to the range [0, 255] to fit the range of the type CV_8U.

Since your PGM image has max_value of 4096:

P2        
1176 640  // width height
4096      // max_value 

it should be normalized from range [0, 4096] instead of [0, 65535]. You can do this with:

Mat img = imread("path_to_image", IMREAD_UNCHANGED);
img.convertTo(img, CV_8U, 255.0 / 4096.0);

imshow("Image", img);
waitKey();

Please note that the values range in your image doesn't correspond to [0, 4096], but:

double minv, maxv;
minMaxLoc(img, &minv, &maxv);

// minv = 198
// maxv = 2414

So the straightforward normalization in [0,255] like:

normalize(img, img, 0, 255, NORM_MINMAX);
img.convertTo(img, CV_8U);

won't work, as it will produce an image brighter than it should be.


This means that to properly show your image you need to know the max_value (here 4096). If it changes every time, you can retrieve it parsing the .pgm file.

Again, it's just a problem with visualization. Data are correct.