why does reading image with cv2 has different behavior from PIL?

Viewed 745

enter image description here

As show in the above image, when I read it with pillow:

from PIL import Image
label = Image.open('example.png')
print(np.unique(array(label)))

The number are within range of [0, 34], which is correct. However, when I read with cv2:

import cv2
label = cv2.imread('example.png')
print(np.unique(label))

The number are with [0, 255] which is not correct in my application. How could I align the behavior of cv2 and pil please ?

Also when I checked the matlab example code parsing this image, it is written like this:

[labels, color_mappings] = imread('example.png')

It seems that the png file has two data fields, one is the fields with values ranges from 0 to 34, and the other is the color pixels, how could I parse it with cv2?

1 Answers

I think Dan has the right answer, but if you want to do some "quick and dirty" testing, you could use the following code to:

  • convert your palette image into a single channel greyscale PGM image of the palette indices that OpenCV can read without any extra libraries, and a separate palette file that you can apply back afterwards

  • load back a PGM file of the indices that OpenCV may have altered, and reapply the saved palette


#!/usr/bin/env python3

import numpy as np
from PIL import Image

# Open palette image and remove pointless alpha channel
im = Image.open('image.png').convert('P')

# Extract palette and save as CSV
np.array(im.getpalette()).tofile('palette.csv',sep=',')

# Save palette indices as single channel PGM image that OpenCV can read
na = np.array(im)
im = Image.fromarray(na).save('indices.pgm')

So that will have split image.png into indices.pgm that OpenCV can read as a single channel image and palette.csv that we can reload later.

And here is the second part, where we rebuild the image from indices.pgm and palette.csv

# First load indices
im = Image.open('indices.pgm')

# Now load palette 
palette = np.fromfile('palette.csv',sep=',').astype(np.uint8)

# Put palette back into image
im.putpalette(palette)

# Save
im.save('result.png')

Remember not to use any interpolation other than NEAREST_NEIGHBOUR in OpenCV else you will introduce new colours not present in the original image.

Keywords: Python, PNG, image processing, palette, palette indices, palette index

Related