Reputation: 2965
When I convert an image from PIL to OpenCV, colors change slightly.
from PIL import Image
import cv2
import numpy as np
image = cv2.imread('1.jpg')
image1=Image.open('1.jpg')
image1 = cv2.cvtColor(np.array(image1), cv2.COLOR_RGB2BGR)
print(image[79])
print(image1[79])
The first four rows are:
[144 151 148]
[101 108 105]
[121 128 125]
[108 118 112]
and
[140 152 146]
[ 97 109 103]
[117 129 123]
[104 118 112]
I thought the indexing may be off by one but it isn't. Is there a way to fix this? This is the image (but it's the same on others too):
Upvotes: 2
Views: 2264
Reputation: 433
libjpeg version may by different
Convert the original .jpg
image to .bmp
image
ffmpeg -i 1.jpg 1.bmp
than the opencv output and PIL output will be the same
Upvotes: 1
Reputation: 8334
This behaviour is dependent on different incompatible versions of libjpeg used by cv2 and PIL/Pillow, as @fireant already pointed out.
For example, when I try to run this code with older versions of Pillow (like 3.4.2), it generates same output. In my tests, Pillow 3.4.2 and older (oldest version tried was 2.2.0) all use libjpeg 8, while Pillow 4.0.0 and newer use libjpeg 9.2.
OpenCV, on the other hand, might use different versions on different systems:
On Microsoft Windows* OS and MacOSX*, the codecs shipped with an OpenCV image (libjpeg, libpng, libtiff, and libjasper) are used by default.
On Linux*, BSD flavors and other Unix-like open-source operating systems, OpenCV looks for codecs supplied with an OS image. Install the relevant packages (do not forget the development files, for example, "libjpeg-dev", in Debian* and Ubuntu*) to get the codec support or turn on the OPENCV_BUILD_3RDPARTY_LIBS flag in CMake.
So on Debian/Ubuntu systems opencv might use libjpeg-turbo
which comes with the OS. (My machine, specifically, had version 8 installed.)
The way to fix this is to ensure that both Pillow and OpenCV use same libjpeg version.
You could try this:
if you have relatively new PIL/Pillow, downgrade it to version <= 3.4.2 (this is what worked for me)
pip install Pillow==3.4.2
if you have old Pillow version, you could try to upgrade it to version >= 4.0.0
If that doesn't help, your solution could be either of two:
Upvotes: 1
Reputation: 472
Since OpenCV reads the image in as BGR format with cv2.imread() we need to convert it back to RGB before giving it to PIL.
Here is an example of reading an image with OpenCv and without change saving it with PIL:
image = cv2.imread('test.jpg')
pil_img = PIL.Image.fromarray(image)
pil_img.save('pil_img.jpg', 'JPEG')
The 'test.jpg' Image: enter image description here
The 'pil_img.jpg' Image: enter image description here
To correct this we need to use cv2.cvtColor to change the image to RGB
correct_img = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
pil_img = PIL.Image.fromarray(correct_img)
pil_img.save('pil_correct_img.jpg', 'JPEG')
Result: enter image description here
Upvotes: 0
Reputation: 14538
That suggests PIL and OpenCV are using different versions of libjpeg or using it with different parameters. Also it seems OpenCV tries to use libjpeg-turbo if you don't ask it not to do so, see the code here: https://github.com/opencv/opencv/blob/master/cmake/OpenCVFindLibsGrfmt.cmake#L39
Upvotes: 2