1

I am trying to implement image enhancement by first converting RGB color space to HSI color space, do histogram equalization on intensity channel, and convert back to RGB color space.

However, the output image does not look good and I could not figure out why. Please help me.

My RGB HSI conversion method is based on this website : https://hypjudy.github.io/2017/03/19/dip-histogram-equalization/

My input image :enter image description here My output image : enter image description here

import cv2
from math import acos
from math import cos
from math import sqrt
from math import pi


# Read the bmp file
img = cv2.imread('/Users/xxx/xxx/input3.bmp')
# Read the width and height of the image
shape = img.shape

# HSI array to store original histogram
H_origin_hist = [[0 for i in range(0, shape[1])] for j in range(0, shape[0])] 
S_origin_hist = [[0 for i in range(0, shape[1])] for j in range(0, shape[0])] 
I_origin_hist = [0] * 256
I_hist = [0] * 256

# Convert colors from RGB to HSI and calculate histogram
for i in range(0, shape[0]) :
    for j in range(0, shape[1]) :
        # px[0], px[1], and px[2] represents B, G, and R respectively
        px = img[i,j]
        R = int(px[2])
        G = int(px[1])
        B = int(px[0])
        # Calculate HSI original histogram
        numerator = float(0.5 * ((R - G) + (R - B)))
        denominator = float(sqrt((R - G) * (R - G) + (R - B) * (G - B)))
        if (denominator == 0) :
            val = 0.0
        else :
            val = numerator / denominator
        theta = acos(val)
        I = (B + G + R) / 3
        if (B <= G) :
            H_origin_hist[i][j]= theta
        else :
            H_origin_hist[i][j] = 2 * pi - theta
        if(R == 0 or G == 0 or B == 0) :
            S_origin_hist[i][j] = 0
            H_origin_hist[i][j] = 0
        else :
            S_origin_hist[i][j] = 1 - (3.0 / (R + G + B) * min(R, G, B))
        I_origin_hist[I] = I_origin_hist[I] + 1


# Do histogram equalization on the intensity channel
for i in range(0, 256) :
    I_hist[i] = ((sum(I_origin_hist[0:i+1]) - min(I_origin_hist)) * 255) / (shape[0] * shape[1])

# Convert colors from HSI to RGB
for i in range(0, shape[0]) :
    for j in range(0, shape[1]) :
        px = img[i,j]
        R = int(px[2])
        G = int(px[1])
        B = int(px[0])
        I = (R + G + B) / 3
        if (H_origin_hist[i][j] >= 0 and H_origin_hist[i][j] < 2 * pi / 3) :
            H = H_origin_hist[i][j]
            h = ((pi / 3) - H_origin_hist[i][j])
            px[0] = (1 - S_origin_hist[i][j]) * I_hist[I]
            px[2] = (1 + (S_origin_hist[i][j] * cos(H) / cos(h))) * I_hist[I]
            px[1] = 1 - B - R
        elif (H_origin_hist[i][j] >= 2 * pi / 3 and H_origin_hist[i][j] < 4 * pi / 3) :
            H = (H_origin_hist[i][j] - (2 * pi / 3))
            h = (pi - H_origin_hist[i][j])
            px[2] = (1 - S_origin_hist[i][j]) * I_hist[I]
            px[1] = (1 + (S_origin_hist[i][j] * cos(H) / cos(h))) * I_hist[I]
            px[0] = 1 - G - R
        else :
            H = (H_origin_hist[i][j] - (4 * pi / 3))
            h = ((5 * pi / 6) - H_origin_hist[i][j])
            px[1] = (1 - S_origin_hist[i][j]) * I_hist[I]
            px[0] = (1 + (S_origin_hist[i][j] * cos(H) / cos(h))) * I_hist[I]
            px[2] = 1 - B - G

# Write back to bmp file
cv2.imwrite('/Users/xxx/xxx/output3.bmp', img)
AkselA
  • 8,153
  • 2
  • 21
  • 34
Arthur Hsieh
  • 13
  • 1
  • 6
  • check if the intensity values are actually between 0 and 255. Also if you are using opencv, wouldnt just direktly normalizing the histogramm with the function normalize work just as well? – Eumel Nov 09 '17 at 12:25
  • Hi @Eumel, thank you for your reply. Yes I have checked intensity values in I_hist[], and they are all between 0 and 255. Also I know there is a build in function in opencv, but I'm not using those functions on purpose. – Arthur Hsieh Nov 09 '17 at 12:35
  • does this code works on your device without any error? You have calculated intensity value I = (B + G + R) / 3 which will be float data type and you are using this float type intensity value as integer index in I_origin_hist[I] = I_origin_hist[I] + 1 which should give you error. – flamelite Nov 09 '17 at 12:59
  • Hi @flamelite, yes it works fine on my laptop. You can see the output image above. BTW, in python, 5 / 3 equal to 1, not 1.66. So it works fine. – Arthur Hsieh Nov 09 '17 at 13:36
  • ohh i got confused, In python2 / is integer division but in python3 / is float division. – flamelite Nov 09 '17 at 13:40
  • Yes @flamelite, I'm using python2. So do you see any other problems? – Arthur Hsieh Nov 09 '17 at 14:20
  • Weird, I have the same problem. Did you manage to solve it? – Vahni Jun 26 '18 at 10:42
  • Hi @Vahni, no I think I don't. I used another method to achieve this task though, if you are interested, please provide my your email and I'll send you my python source file. – Arthur Hsieh Jun 27 '18 at 12:27
  • I don't think there is a private message option here. Can you upload it somewhere? – Vahni Jun 28 '18 at 03:24
  • @Vahni please send me your email: simon10030950@gmail.com – Arthur Hsieh Jun 28 '18 at 13:11

0 Answers0