0

I have this image and I read as a PIL file. Then, I save it back using save method in PIL and imwrite method in cv2. Saving the image with imwrite downgrades the image quality (it becomes black and white and text can't be read).

image = Image.open("image.png")

cv2_image = numpy.asarray(image)

image.save("pil.png")
cv2.imwrite("opencv.png", cv2_image)

Here are the output files:

pil.png
opencv.png

Christoph Rackwitz
  • 11,317
  • 4
  • 27
  • 36
Dalireeza
  • 107
  • 3
  • 13
  • Have you tried the solutions from [here](https://stackoverflow.com/questions/14134892/convert-image-from-pil-to-opencv-format)? You need to convert the PIL image to an OpenCV image before saving with cv2.imwrite. – AJH Mar 12 '22 at 15:13
  • Also, just remembered, I believe PIL and OpenCV have the color channels in different orders - one of them's BGR and the other's RGB. And it might be prudent to check if whether each module takes int values between 0 and 255 or float values between 0 and 1. – AJH Mar 12 '22 at 15:43
  • please work on a [mre], including the required input. that code could not have produced the output you show. something more must be going on. – Christoph Rackwitz Mar 12 '22 at 17:19
  • The PNG file is 8-bit indexed. I'm guessing cv2 is not copying the palette. – Mark Ransom Mar 12 '22 at 17:41
  • PIL isn't giving *numpy* the palette. – Christoph Rackwitz Mar 13 '22 at 11:15

1 Answers1

4

The input image is a palette image - see here. So, you need to convert it to RGB otherwise you just pass OpenCV the palette indices but without the palette.

So, you need:

image = Image.open(...).convert('RGB')

Now make it into a Numpy array:

cv2image = np.array(image)

But that will be in RGB order, so you need to reverse the channel order:

cv2image = cv2image[..., ::-1]
Mark Setchell
  • 191,897
  • 31
  • 273
  • 432