mArk
mArk

Reputation: 658

How to change the colors of a binary image using python?

Is their any way to change the colors of a binary image in to other two different colors other than black and white using python. How to achieve this if the input binary image is "unit8" datatype and when the same input image is of "bool" datatype?

d = gdal.Open(....)
band = d.GetRasterBand(1)
arr1 = band.ReadAsArray()
thresh = threshold_otsu(arr1)
binary = arr1 > thresh
plt.imshow(binary)

Upvotes: 0

Views: 8199

Answers (2)

Mark Setchell
Mark Setchell

Reputation: 208003

You could do it with a palette, but here I make a full RGB version.

from PIL import Image
from skimage import data
from skimage.filters import threshold_otsu

# Load image
image = data.camera()

# Threshold image to binary
thresh = threshold_otsu(image)
binary = image > thresh

# Make 3 channel RGB image same dimensions
RGB = np.zeros((binary.shape[0],binary.shape[1],3), dtype=np.uint8)

# Make True pixels red
RGB[binary]  = [255,0,0]
# Make False pixels blue
RGB[~binary] = [0,0,255]

# Display result
Image.fromarray(RGB).show()

enter image description here


You can express the same thing slightly differently like this:

from skimage import data
from skimage.filters import threshold_otsu

# Load image
image = data.camera()

# Threshold image to binary
thresh = threshold_otsu(image)
binary = image > thresh

# Define red and blue
red  = np.array([255,0,0],dtype=np.uint8)
blue = np.array([0,0,255],dtype=np.uint8)

# Make RGB array, pre-filled with blue
RGB = np.zeros((binary.shape[0],binary.shape[1],3), dtype=np.uint8) + blue

# Overwrite with red where threshold exceeded, i.e. where mask is True
RGB[binary] = red

Storing a full RGB image for just 2 colours is rather wasteful of space though, because you have 3 bytes (R, G and B) per pixel. It is probably preferable to make a palettised image where you just store 1 byte per pixel and use that byte as an index into a palette that can hold 256 colours. You can do that like this:

from PIL import Image
from skimage import data
from skimage.filters import threshold_otsu

# Load image
image = data.camera()

# Threshold image to binary
thresh = threshold_otsu(image)
binary = image > thresh

# Make a palette with 2 entries, magenta and yellow
palette = [  
    255, 0, 255,  # magenta
    255, 255, 0   # yellow
]

# Zero-pad the palette to 256 RGB colours, i.e. 768 values
palette += (768-len(palette))*[0]

# Make PIL/Pillow image from the binary array
p = Image.fromarray((binary*1).astype(np.uint8))

# Push the palette into image and save
p.putpalette(palette)
p.save('result.png')

enter image description here

Upvotes: 1

Magellan88
Magellan88

Reputation: 2573

well, generally speaking, given you have an x,y image and thus array of bool type; you need to generate a (x,y,3) array like with numpy:

colImage = np.zeros((x,y,3), dtype="uint8")

the dimension with 3 encodes the color with rgb, so

colImage[:,:,0] = boolImage * 255 # for red
colImage[:,:,1] = boolimage * 255 # for green
colImage[:,:,2] = boolimage * 255 # for blue

if i remember correctly. the * 255 is to get from the boolean "1" to the 8bit maximum of 255

Upvotes: 1

Related Questions