OpenCV imwrite gives washed-out result for jpeg images

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]


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.