Search code examples
pythonopencvmatplotlibpython-imaging-library

Python matplolib ListedColormap paints all image yellow but identical almost image paints correctly


Stumbled to one very strange problem.I create a tgi image from agro images.Althought i have two very simiral agro images with almost the same colours ,one of the tif files produces a good tgi image but the other produces a tgi image as full yellow.I apply a matplolib.ListedColormap where i think my code bugs:

import cv2
import numpy as np
from PIL import Image
from matplotlib import colors




HD_rgb_tgi =  cv2.imread('good_tif.tif',cv2.IMREAD_UNCHANGED)
red = HD_rgb_tgi[:,:,0].astype('float64')
green = HD_rgb_tgi[:,:,1].astype('float64')
blue = HD_rgb_tgi[:,:,2].astype('float64')
tgi=(-1) * 0.5 * ((200*(red-green))-(100 * (red-blue)))
tgi_normalized = ((tgi - np.amin(tgi)) / (np.amax(tgi) - np.amin(tgi)))
tgi_f = Image.fromarray(np.uint8(colors.ListedColormap([ '#C90000', '#CF630A'  , '#EBE42D', '#27FF0F', '#0C750C'])(tgi_normalized) * 255))
tgi_f = tgi_f.convert('RGBA')
tgi_f=cv2.cvtColor(np.float32(tgi_f), cv2.COLOR_RGBA2BGRA)
cv2.imwrite("tgi_good.png",tgi_f)





HD_rgb_tgi =  cv2.imread('bad_tif.tif',cv2.IMREAD_UNCHANGED)
red = HD_rgb_tgi[:,:,0].astype('float64')
green = HD_rgb_tgi[:,:,1].astype('float64')
blue = HD_rgb_tgi[:,:,2].astype('float64')
tgi=(-1) * 0.5 * ((200*(red-green))-(100 * (red-blue)))
tgi_normalized = ((tgi - np.amin(tgi)) / (np.amax(tgi) - np.amin(tgi)))
tgi_f = Image.fromarray(np.uint8(colors.ListedColormap([ '#C90000', '#CF630A'  , '#EBE42D', '#27FF0F','#0C750C'])(tgi_normalized) * 255))
tgi_f = tgi_f.convert('RGBA')
tgi_f=cv2.cvtColor(np.float32(tgi_f), cv2.COLOR_RGBA2BGRA)
cv2.imwrite("tgi_bad.png",tgi_f)

link to the 2 tif images:

https://mega.nz/file/2J0EzbKQ#wPFPr4onmRCwEvdOHyBCwLQnBMqPQYIsZucA8bNERBw https://mega.nz/file/DF0i2BTJ#HuzKxWI60-R0DjAB7lwuqkhOiO5Y8bgEFXUHkHfmwNE

Sorry for the external links but i can't reproduce the problem to other images. Best regards


Solution

  • Even if not visible, apparently the histograms of the photos were not the same. Applying cv2.equalizeHist to the bad image seems to do the trick.

    import cv2
    import numpy as np
    from PIL import Image
    from matplotlib import colors
    
    
    HD_rgb_tgi =  cv2.imread('good_tif.tif',cv2.IMREAD_UNCHANGED)#odm_orthophoto
    red = HD_rgb_tgi[:,:,0].astype('float64')
    green = HD_rgb_tgi[:,:,1].astype('float64')
    blue = HD_rgb_tgi[:,:,2].astype('float64')
    tgi=(-1) * 0.5 * ((200*(red-green))-(100 * (red-blue)))
    tgi_normalized = ((tgi - np.amin(tgi)) / (np.amax(tgi) - np.amin(tgi)))
    tgi_f = Image.fromarray(np.uint8(colors.ListedColormap([ '#C90000', '#CF630A'  , '#EBE42D', '#27FF0F', '#0C750C'])(tgi_normalized) * 255))
    tgi_f = tgi_f.convert('RGBA')
    tgi_f=cv2.cvtColor(np.float32(tgi_f), cv2.COLOR_RGBA2BGRA)
    cv2.imwrite("tgi_good.png",tgi_f)
    
    
    def run_histogram_equalization(image_path):
        rgb_img = cv2.imread(image_path)
        # convert from RGB color-space to YCrCb
        ycrcb_img = cv2.cvtColor(rgb_img, cv2.COLOR_BGR2YCrCb)
        # equalize the histogram of the Y channel
        ycrcb_img[:, :, 0] = cv2.equalizeHist(ycrcb_img[:, :, 0])
        # convert back to RGB color-space from YCrCb
        equalized_img = cv2.cvtColor(ycrcb_img, cv2.COLOR_YCrCb2BGR)
        cv2.imwrite('res.png',equalized_img)
    
    run_histogram_equalization('bad_tif.tif')
    
    
    D_rgb_tgi =  cv2.imread('res.png',cv2.IMREAD_UNCHANGED)#odm_orthophoto
    red = HD_rgb_tgi[:,:,0].astype('float64')
    green = HD_rgb_tgi[:,:,1].astype('float64')
    blue = HD_rgb_tgi[:,:,2].astype('float64')
    tgi=(-1) * 0.5 * ((200*(red-green))-(100 * (red-blue)))
    tgi_normalized = ((tgi - np.amin(tgi)) / (np.amax(tgi) - np.amin(tgi)))
    tgi_f = Image.fromarray(np.uint8(colors.ListedColormap([ '#C90000', '#CF630A'  , '#EBE42D', '#27FF0F', '#0C750C'])(tgi_normalized) * 255))
    tgi_f = tgi_f.convert('RGBA')
    tgi_f=cv2.cvtColor(np.float32(tgi_f), cv2.COLOR_RGBA2BGRA)
    cv2.imwrite("tgi_bad.png",tgi_f)