7

I am using OpenCV 3.0 and whenever I read an image and write it back the result is a washed-out image.

code:

cv::Mat img = cv::imread("dir/frogImage.jpg",-1);
cv::imwrite("dir/result.jpg",img);

Does anyone know whats causing this?

Original: enter image description here

Result: enter image description here

zindarod
  • 6,328
  • 3
  • 30
  • 58
  • provide the code of reading and writing.. you are probably write it as jpeg – Humam Helfawi Oct 15 '15 at 07:49
  • 2
    @HumamHelfawi Plz check the code. – zindarod Oct 15 '15 at 07:54
  • 1
    welcome to the difference of lossy and lossless compression. Save as `.png` or another lossless compression technique to obtain 100% identical image data. – Micka Oct 15 '15 at 08:00
  • @Micka But when converting jpg to jpg using ImageMagick it doesn't change the quality of the image. – zindarod Oct 15 '15 at 08:07
  • you can try to add the image quality information for jpeg compression. Afaik it's 95% in OpenCV if not specified manually. So increasing that to 100% might give you the expected results (however in OpenCV you dont have information about the original jpeg comporession quality of the image). After all I'm still quite sure that iterating loading + saving of a jpeg image (without altering the image itself) might add additional compression artifacts. Please keep in mind that OpenCV isn't made for "image editing" but for "computer vision" so you won't find needed informations like tags and quality – Micka Oct 15 '15 at 08:12
  • have a look at this, too: http://petapixel.com/2010/02/04/saving-jpeg-photos-hundreds-of-times/ – Micka Oct 15 '15 at 08:14
  • 1
    @Zindarod both your images look exactly the same if I save them to my pc and open them with IrfanView. However they look differently in the browser, so maybe there is some kind of strange meta information or non-typical jpeg format?!? – Micka Oct 15 '15 at 08:48
  • first google results indicate that cameras MIGHT have some auto-white-balance feature. Maybe that information is given in meta information of an image. Maybe not all image viewer use that meta information. OpenCV definitely doesn't use ANY meta information of images, neither can/will it save those meta information to images. You'll need some more sophisticated image loading/saving libraries to get that information – Micka Oct 15 '15 at 08:58
  • @Micka If you are using ubuntu then you can install ImageMagick then do: convert dir/treefrog.jpg dir/treefrog.png. The same color difference exists. – zindarod Oct 15 '15 at 09:00
  • Is there a possibility to view image meta information in ImageMagick (shutter times etc)? Maybe there is a white-balance information added that is used before displaying, too. – Micka Oct 15 '15 at 09:03
  • @Micka Using "identify /home/haseebullah/Skype/treefrog.jpg": JPEG 1252x1600 1252x1600+0+0 8-bit DirectClass 1.043MB 0.000u 0:00.000 – zindarod Oct 15 '15 at 09:07
  • Ok, maybe it's more about color profiles: If you do understand german read this: http://schoenergesehen.de/technik/farbprofile/mehr-farbe-internet-adobergb-fotos-302 if not: It seems to be because of different color profiles. Opening your first frog image, GIMP tells me that it has `Adobe RGB (1998)` color profile. The german link tells that wrong displaying results (like washed out) might happen if color profile isn't read or applied correctly. Read about sRGB and stuff ;) – Micka Oct 15 '15 at 09:14
  • @Micka Thanks a lot for your time. Unfortunately I don't understand German now but I will by spring 2016 when I join Saarland University for MS CS. ;) – zindarod Oct 15 '15 at 09:30

3 Answers3

4

You can try to increase the compression quality parameter as shown in OpenCV Documentation of cv::imwrite :

cv::Mat img = cv::imread("dir/frogImage.jpg",-1);

std::vector<int> compression_params;
compression_params.push_back(CV_IMWRITE_JPEG_QUALITY);
compression_params.push_back(100);

cv::imwrite("dir/result.jpg",img, compression_params);

Without specifying the compression quality manually, quality of 95% will be applied.

but 1. you don't know what jpeg compression quality your original image had (so maybe you might increase the image size) and 2. it will (afaik) still introduce additional minor artifacts, because after all it is a lossy compression method.

UPDATE your problem seems to be not because of compression artifacts but because of an image with Adobe RGB 1998 color format. OpenCV interprets the color values as they are, but instead it should scale the color values to fit the "real" RGB color space. Browser and some image viewers do apply the color format correctly, while others don't (e.g. irfanView). I used GIMP to verify. Using GIMP you can decide on startup how to interpret the color values by format, either getting your desired or your "washed out" image. OpenCV definitely doesn't care about such things, since it's not a photo editing library, so neither on reading nor on writing, color format will be handled.

Micka
  • 19,585
  • 4
  • 56
  • 74
  • I was trying to do the same you have done. Looking at this: http://stackoverflow.com/questions/801054/opencv-cvsaveimage-jpeg-compression-factor – zindarod Oct 15 '15 at 08:26
  • hope you like the `C++ interface` with `std::vector` more than the `C interface` with `cvSaveImage` and int-array. But does it solve your problem? – Micka Oct 15 '15 at 08:29
  • Nope, the result image is sill washed-out. – zindarod Oct 15 '15 at 08:31
  • in fact I didnt really realize the difference between your input and output images... so you mean that the colors are a bit brighter for example in the greeen leaf area? Those aren't jpeg artifacts... are you sure not to perform any other task before saving? (or saving some modified image later to the same path?) – Micka Oct 15 '15 at 08:33
  • imho that looks like some color normalization, like white balance normalization or sth... that should not happen by jpeg compression, but I'll try ;) – Micka Oct 15 '15 at 08:35
  • Nothing but reading and writing the image back. The difference in color is very obvious throughout the image not just the leafy areas. – zindarod Oct 15 '15 at 08:36
  • 1
    that's true, but not if you have to scroll 1 whole screen down to see the second image ;) – Micka Oct 15 '15 at 08:39
  • Last time I checked, even with quality 100% it was still lossy. – Miki Oct 15 '15 at 08:42
  • @Miki the image differences the poster observes aren't related to compression artifacts as far as I think to understand him now. If you open both images full sized in your browser in different tabs and switch those tabs, you'll see the colors shifted like after color normalization. However saved to files, Irfan View renders both images identically without color differences. – Micka Oct 15 '15 at 08:51
  • @Micka hmm, wierd... Sounds interesting – Miki Oct 15 '15 at 08:56
  • @Micka Good catch, now that I open them in shotwell they look the same but the ubuntu default image viewer display a difference in color. – zindarod Oct 15 '15 at 08:58
  • @Miki first google results indicate that cameras MIGHT have some auto-white-balance feature. Maybe that information is given in meta information of an image. Maybe not all image viewer use that meta information. OpenCV definitely doesn't use ANY meta information of images, neither can/will it save those meta information to images. You'll need some more sophisticated image loading/saving libraries to get that information – Micka Oct 15 '15 at 08:59
  • 1
    first image is in `Adobe RGB 1998` color profile. https://en.wikipedia.org/wiki/RGB_color_space – Micka Oct 15 '15 at 09:19
  • 1
    @Micka The problem actually is with different color spaces. I solved it by using Magick++ sdk and converting the AdobeRGB1998 colorspace to sRGB colorspace. Thank you for your time. – zindarod Oct 26 '15 at 11:29
2

This is because you are saving the image as JPG. When doing this the OpenCV will compress the image. try to save it as PNG or BMP and no difference will be exist.

However, the IMPORTANT QUESTION : I am loading the image as jpg and saving it as JPG. So, how there is a difference?!

Yes, this is because there is many not identical compression/decompression algorithms for JPG.

if you want to get into some details see this question: Reading jpg file in OpenCV vs C# Bitmap


EDIT: You can see what I mean exactly here:

auto bmp(cv::imread("c:/Testing/stack.bmp"));
cv::imwrite("c:/Testing/stack_OpenCV.jpg", bmp);
auto jpg_opencv(cv::imread("c:/Testing/stack_OpenCV.jpg"));

auto jpg_mspaint(cv::imread("c:/Testing/stack_mspaint.jpg"));
cv::imwrite("c:/Testing/stack_mspaint_opencv.jpg", jpg_mspaint);
jpg_mspaint=(cv::imread("c:/Testing/stack_mspaint_opencv.jpg"));

cv::Mat jpg_diff;
cv::absdiff(jpg_mspaint, jpg_opencv, jpg_diff);
std::cout << cv::mean(jpg_diff);

The Result: [0.576938, 0.466718, 0.495106, 0]

Community
  • 1
  • 1
Humam Helfawi
  • 19,566
  • 15
  • 85
  • 160
  • 1
    It seems that the issue here is that Adobe JPEG format is rendered differently than OpenCV JPEG format. So I removed my downvote and my previous comments since this is not about JPEG compression artifacts. – Miki Oct 15 '15 at 09:25
0

As @Micha commented:

cv::Mat img = cv::imread("dir/frogImage.jpg",-1);
cv::imwrite("dir/result.bmp",img);

I was always annoyed when mspaint.exe did the same to jpeg images. Especially for the screenshots...it ruined them everytime.

LovaBill
  • 5,107
  • 1
  • 24
  • 32
  • 1
    well he might want to use `jpeg`. Maybe some application like: `1. read image; 2. perform some operations; 3. save in old format` but it's important to tell @Zindarod that for jpeg images there will be additional artifacts in this case. That's one of the reasons why GIMP etc use their own image format and only create jpegs/pngs/etc by exporting. – Micka Oct 15 '15 at 08:08
  • @William Thank you but as Micka has said, I do indeed need the result as jpg. – zindarod Oct 15 '15 at 08:16