Reading in indexed color image in Python

An indexed color image is an image with pixels that are integers (1,2, .. N), and for each integer the associated color displays that pixel from a given color map. In MATLAB, reading in an indexed color image can be done as follows:

[im, colormap] = imread('indexed.png'); 

How can I do the same in Python? I tried OpenCV, scikit-image , but all of them are automatically converted to RGB.

+5
source share
1 answer

After some research, this is what I came up with. You can use the Python Imaging Library - specifically the Pillow fork: https://python-pillow.imtqy.com/

Install the package, then you can use the Image.open method from the Image class to open the image. If there is a color map in your image, the image will be automatically loaded as an indexed image. To make this useful, use NumPy and use the numpy.array constructor. I assume you can use NumPy because scikit-image and OpenCV use NumPy as the main basis for image manipulation:

 from PIL import Image import numpy as np im = Image.open("image.png") # Replace with your image name here indexed = np.array(im) # Convert to NumPy array to easier access 

Finally, if you need a color map / palette that was actually used for the image, use the Image.getpalette method, which is part of the Image class. However, this will give you a list of num_colours x 3 elements. Therefore, to determine how many colors you have, simply divide the length of this list by 3. However, the color map loaded in MATLAB is normalized , while getpalette does not normalize this value and the default image type is loaded. So you will need to determine the type of image by looking at the converted version of the NumPy image, then use this to normalize your color map:

In this way:

 # Get the colour palette palette = im.getpalette() # Determine the total number of colours num_colours = len(palette)/3 # Determine maximum value of the image data type max_val = float(np.iinfo(indexed.dtype).max) # Create a colour map matrix map = np.array(palette).reshape(num_colours, 3) / max_val 

To demonstrate that we have this correctly, here is an indexed image from a question that I helped solve a while ago :

Using MATLAB to load in this image:

 [indexed, map] = imread('http://i.stack.imgur.com/OxFwB.png'); 

I get this when I focus on rows 280 through 290 and columns 400 through 410 in the indexed image as a double check:

 >> indexed(280:290, 400:410) ans = 59 60 61 62 65 64 59 56 56 53 49 61 61 64 65 65 60 60 57 58 53 53 67 62 67 56 60 62 60 61 51 59 55 65 60 62 61 58 58 53 55 57 55 54 66 58 56 59 56 56 52 55 52 55 52 68 68 61 61 61 56 56 55 55 57 59 66 59 59 66 68 62 62 60 60 60 53 70 68 64 58 61 63 67 61 67 56 59 69 67 63 64 62 65 63 68 67 64 58 61 68 68 72 71 73 70 66 63 64 64 68 67 70 71 71 69 64 64 65 64 58 

Here is what I get in Python when I run the equivalent code to get the indexed image. Please note that I physically downloaded the image to my computer and downloaded it from the disk. Note that NumPy starts indexing from 0, not 1, so I had to subtract ranges by 1. Also note that the end of the range operator is exclusive :

 In [29]: indexed[279:290, 399:410] Out[29]: array([[59, 60, 61, 62, 65, 64, 59, 56, 56, 53, 49], [61, 61, 64, 65, 65, 60, 60, 57, 58, 53, 53], [67, 62, 67, 56, 60, 62, 60, 61, 51, 59, 55], [65, 60, 62, 61, 58, 58, 53, 55, 57, 55, 54], [66, 58, 56, 59, 56, 56, 52, 55, 52, 55, 52], [68, 68, 61, 61, 61, 56, 56, 55, 55, 57, 59], [66, 59, 59, 66, 68, 62, 62, 60, 60, 60, 53], [70, 68, 64, 58, 61, 63, 67, 61, 67, 56, 59], [69, 67, 63, 64, 62, 65, 63, 68, 67, 64, 58], [61, 68, 68, 72, 71, 73, 70, 66, 63, 64, 64], [68, 67, 70, 71, 71, 69, 64, 64, 65, 64, 58]], dtype=uint8) 

What corresponds ... now what about color cards? Let's take a look at the first 10 lines of color maps between MATLAB and Python:

MATLAB

 >> format long g; >> map(1:10,:) ans = 0 0 0 0.0156862745098039 0.00392156862745098 0.0274509803921569 0.0313725490196078 0.00784313725490196 0.0588235294117647 0.0470588235294118 0.0117647058823529 0.0901960784313725 0.0627450980392157 0.0156862745098039 0.12156862745098 0.0784313725490196 0.0196078431372549 0.152941176470588 0.0941176470588235 0.0235294117647059 0.184313725490196 0.109803921568627 0.0274509803921569 0.215686274509804 0.125490196078431 0.0313725490196078 0.247058823529412 0.141176470588235 0.0352941176470588 0.27843137254902 

Python

 In [30]: map[:10,:] Out[30]: array([[ 0. , 0. , 0. ], [ 0.01568627, 0.00392157, 0.02745098], [ 0.03137255, 0.00784314, 0.05882353], [ 0.04705882, 0.01176471, 0.09019608], [ 0.0627451 , 0.01568627, 0.12156863], [ 0.07843137, 0.01960784, 0.15294118], [ 0.09411765, 0.02352941, 0.18431373], [ 0.10980392, 0.02745098, 0.21568627], [ 0.1254902 , 0.03137255, 0.24705882], [ 0.14117647, 0.03529412, 0.27843137]]) 

... it looks like it matches!

+6
source

Source: https://habr.com/ru/post/1233268/


All Articles