将HSI转换回RGB

问题描述 投票:1回答:1

所以我试图对图像的强度进行平均。因此,我要做的是将原始图像转换为HSI,找到原始图像的平均强度,然后在将其转换回RGB之前修改HSI图像的强度。但是,我目前面临将HSI重新转换为RGB的问题

def HSI_TO_RGB(Average, img):
     with np.errstate(divide='ignore', invalid='ignore'):

        #Load image with 32 bit floats as variable type
        bgr = np.float32(img)/255

        #Separate color channels
        blue = bgr[:,:,0]
        green = bgr[:,:,1]
        red = bgr[:,:,2]

        #Calculate Saturation
        def calc_saturation(red, blue, green):
            minimum = np.minimum(np.minimum(red, green), blue)
            saturation = 1 - (3 / (red + green + blue + 0.001) * minimum)

            return saturation

        #Calculate Hue
        def calc_hue(red, blue, green):
            hue = np.copy(red)

            for i in range(0, blue.shape[0]):
                for j in range(0, blue.shape[1]):
                    hue[i][j] = 0.5 * ((red[i][j] - green[i][j]) + (red[i][j] - blue[i][j])) / \
                                math.sqrt((red[i][j] - green[i][j])**2 +
                                        ((red[i][j] - blue[i][j]) * (green[i][j] - blue[i][j])))
                    hue[i][j] = math.acos(hue[i][j])

                    if blue[i][j] <= green[i][j]:
                        hue[i][j] = hue[i][j]
                    else:
                        hue[i][j] = ((360 * math.pi) / 180.0) - hue[i][j]

            return hue

        huehue = calc_hue(red, blue, green) * 255
        satsat = calc_saturation(red, blue, green) * 255

        for huehue in range(0,1):
           backR =  (Average + (2 * Average * satsat))
           backG =  (Average - (Average * satsat))
           backB =  (Average - (Average * satsat))
           final = cv2.merge((backR, backG, backB))
           return final

        for huehue in range(1,120):
           backR = (int) (Average + (Average * satsat) * cos(huehue) / cos(60-huehue))
           backG = (int) (Average + (Average * satsat) * (1 - cos(huehue) / cos(60-huehue)))
           backB = (int) (Average - (Average * satsat))
           final = cv2.merge((backR, backG, backB))
           return final
        for huehue in range(120,121):
           backR = (int) (Average - (Average * satsat))
           backG = (int) (Average + (2 * Average * satsat))
           backB = (int) (Average - (Average * satsat))
           final = cv2.merge((backR, backG, backB))
           return final
        for huehue in range(121,240):
           backR = (int) (Average - (Average * satsat))
           backG = (int) (Average + (Average * satsat) * cos(huehue-120) / cos(180-huehue))
           backB = (int) (Average + (Average * satsat) * (1 - cos(huehue-120) / cos(180-huehue)))
           final = cv2.merge((backR, backG, backB))
           return final
        for huehue in range(240,241):
           backR = (int) (Average - (Average * satsat))
           backG = (int) (Average - (Average * satsat))
           backB = (int) (Average + (2 * Average * satsat))
           final = cv2.merge((backR, backG, backB))
           return final
        for huehue in range(241,360): 
           backR = (int) (Average + (Average * satsat) * (1 - cos(huehue-240) / cos(300-huehue)))
           backG = (int) (Average - (Average * satsat))
           backB = (int) (Average + (Average * satsat) * cos(huehue-240) / cos(300-huehue))
           final = cv2.merge((backR, backG, backB))
           return final

        final=final/360*255
        return final   

我主要是从>RGB to HSI and HSI to RGB conversionenter image description here谁能给我一些解决问题的建议?

python rgb
1个回答
0
投票

存在多个问题,但我不确定我是否已解决所有问题:

  • 例如,您使用的是for而不是iffor huehue in range(1,120)应该是if 1 <= huehue_deg[i][j] < 120
  • 您正在混合度数和弧度:函数math.cos使用弧度作为输入。您正在使用度数:cos(60-huehue)另一方面,calc_hue返回以弧度表示的色相,并且您将range(1,120)用作度数。
  • 您正在混合RGB和BGR:开头:blue = bgr[:,:,0]最后:final = cv2.merge((backR, backG, backB))
  • 您乘以255太早了:huehue = calc_hue(red, blue, green) * 255satsat = calc_saturation(red, blue, green) * 255不在这里。
  • 您的帖子尚不清楚Average参数是什么。我假定它是转换为float32(范围[0,1])后的RGB平均值。

以下(更正的)以下代码读取输入图像,将其传递到HSI_TO_RGB并显示输出:

import cv2
import numpy as np
import math
from math import cos, radians

def HSI_TO_RGB(Average, img):
     with np.errstate(divide='ignore', invalid='ignore'):

        #Load image with 32 bit floats as variable type
        bgr = np.float32(img)/255

        #Separate color channels
        blue = bgr[:,:,0]
        green = bgr[:,:,1]
        red = bgr[:,:,2]

        #Calculate Saturation
        def calc_saturation(red, blue, green):
            minimum = np.minimum(np.minimum(red, green), blue)
            saturation = 1 - (3 / (red + green + blue + 0.001) * minimum)

            return saturation

        #Calculate Hue
        def calc_hue(red, blue, green):
            hue = np.copy(red)

            for i in range(0, blue.shape[0]):
                for j in range(0, blue.shape[1]):
                    hue[i][j] = 0.5 * ((red[i][j] - green[i][j]) + (red[i][j] - blue[i][j])) / \
                                math.sqrt((red[i][j] - green[i][j])**2 +
                                        ((red[i][j] - blue[i][j]) * (green[i][j] - blue[i][j])))
                    hue[i][j] = math.acos(hue[i][j])

                    if blue[i][j] <= green[i][j]:
                        hue[i][j] = hue[i][j]
                    else:
                        hue[i][j] = ((360 * math.pi) / 180.0) - hue[i][j]

            return hue

        huehue = calc_hue(red, blue, green) # * 255
        satsat = calc_saturation(red, blue, green) # * 255

        huehue = np.nan_to_num(huehue)  # Replace nan with zeros

        # Convert from radians to degrees
        huehue_deg = np.rad2deg(huehue)

        # Initiazlie with zeros
        backR = np.zeros_like(satsat)
        backG = np.zeros_like(satsat)
        backB = np.zeros_like(satsat)

        for i in range(0, satsat.shape[0]):
            for j in range(0, satsat.shape[1]):

                if 0 <= huehue_deg[i][j] < 1:
                   backR[i][j] =  (Average[i][j] + (2 * Average[i][j] * satsat[i][j]))
                   backG[i][j] =  (Average[i][j] - (Average[i][j] * satsat[i][j]))
                   backB[i][j] =  (Average[i][j] - (Average[i][j] * satsat[i][j]))                   

                elif 1 <= huehue_deg[i][j] < 120:
                   backR[i][j] = (Average[i][j] + (Average[i][j] * satsat[i][j]) * cos(huehue[i][j]) / cos(radians(60)-huehue[i][j]))
                   backG[i][j] = (Average[i][j] + (Average[i][j] * satsat[i][j]) * (1 - cos(huehue[i][j]) / cos(radians(60)-huehue[i][j])))
                   backB[i][j] = (Average[i][j] - (Average[i][j] * satsat[i][j]))

                elif 120 <= huehue_deg[i][j] < 121:
                   backR[i][j] = (Average[i][j] - (Average[i][j] * satsat[i][j]))
                   backG[i][j] = (Average[i][j] + (2 * Average[i][j] * satsat[i][j]))
                   backB[i][j] = (Average[i][j] - (Average[i][j] * satsat[i][j]))

                elif 121 <= huehue_deg[i][j] < 240:
                   backR[i][j] = (Average[i][j] - (Average[i][j] * satsat[i][j]))
                   backG[i][j] = (Average[i][j] + (Average[i][j] * satsat[i][j]) * cos(huehue[i][j]-radians(120)) / cos(radians(180)-huehue[i][j]))
                   backB[i][j] = (Average[i][j] + (Average[i][j] * satsat[i][j]) * (1 - cos(huehue[i][j]-radians(120)) / cos(radians(180)-huehue[i][j])))

                elif 240 <= huehue_deg[i][j] < 241:
                   backR[i][j] = (Average[i][j] - (Average[i][j] * satsat[i][j]))
                   backG[i][j] = (Average[i][j] - (Average[i][j] * satsat[i][j]))
                   backB[i][j] = (Average[i][j] + (2 * Average[i][j] * satsat[i][j]))

                else: #elif 241 <= huehue_deg[i][j] < 360:
                   backR[i][j] = (Average[i][j] + (Average[i][j] * satsat[i][j]) * (1 - cos(huehue[i][j]-radians(240)) / cos(radians(300)-huehue[i][j])))
                   backG[i][j] = (Average[i][j] - (Average[i][j] * satsat[i][j]))
                   backB[i][j] = (Average[i][j] + (Average[i][j] * satsat[i][j]) * cos(huehue[i][j]-radians(240)) / cos(radians(300)-huehue[i][j]))

        #final = cv2.merge((backR, backG, backB))

        # The correct order is BGR and not RGB (at the beginning of the funtion: blue = bgr[:,:,0])
        final = cv2.merge((backB, backG, backR))

        #final = final/360*255

        # Convert from flot32 to uint8:
        final = np.round(final * 255).astype(np.uint8)
        return final


##### Converting to HSI using OpenCV is simple, converting back is difficult #####
def bgr2hsi(bgr):
    """Convert image from BGR color format to HSI color format"""
    # Convert from BGR to HSV using OpenCV
    hsv = cv2.cvtColor(bgr, cv2.COLOR_BGR2HSV)

    # Difference between HSV and HSI:
    # In HSV: V = max(R, G, B)
    # In HSI: I = (R + G + B)/3
    hsi = hsv
    hsi[:, :, 2] = np.mean(bgr, 2)

    return hsi


bgr = cv2.imread('tree.png')

#hsi = bgr2hsi(bgr)

average = np.mean(np.float32(bgr)/255, 2)
new_bgr = HSI_TO_RGB(average, bgr)

cv2.imshow('new_bgr', new_bgr)
cv2.waitKey(0)
cv2.destroyAllWindows()

注意:我没有尝试优化性能,也没有在寻找RGB到HSI的现有实现。我只是试图更正您发布的代码。


结果:enter image description here

© www.soinside.com 2019 - 2024. All rights reserved.