Во время преобразования XYZ в линейный sRGB ответ выходит за пределы диапазона [0,1]

Моей задачей было преобразовать RGB-изображение в LuvImage. Выполните линейное растяжение в этой области. А потом конвертировать обратно в домен RGB.

Исходное изображение:

[[0 0 0]

[255 0 0]

[100 100 100]

[0 100 100]]

Luv изображение после линейного растяжения в Luv Domain

[[0, 0, 0],

[100, 175, 37,7],

[79,64, 0, 0],

[71,2,-29,29,-6,339]]

Теперь я конвертирую его в изображение XYZ. Ответ,

[[0,0, 0],

[1,5, 1, 0,53],

[0,533, 0,56, 0,61],

[0,344, 0,425, 0,523]]

Теперь, после этого я преобразую его в линейное изображение sRGB, умножив изображение на матрицу:

[[3.240479, -1.53715, -0.498535],

[-0,969256, 1,875991, 0,041556],

[0.055648, -0.204043, 1.057311]]

Ответ для этого преобразования - линейное изображение sRGB,

[[0. 0. 0.],

[3.07132001 0.44046801 0.44082034],

[0,55904669 0,55972465 0,55993322],

[0.20106868 0.4850426 0.48520307]]

Проблема здесь заключается в том, что для 2-го пикселя значения sRGB не находятся в диапазоне [0,1]. Для всех остальных пикселей я получаю правильное значение.

def XYZToLinearRGB(self, XYZImage):
    '''
    to find linearsRGBImage, we multiply XYZImage with static array
    [[3.240479, -1.53715, -0.498535],
     [-0.969256, 1.875991, 0.041556],
     [0.055648, -0.204043, 1.057311]]

    '''
    rows, cols, bands = XYZImage.shape # bands == 3

    linearsRGBImage =  np.zeros([rows, cols, bands], dtype=float)
    multiplierMatrix = np.array([[3.240479, -1.53715, -0.498535],
                                 [-0.969256, 1.875991, 0.041556],
                                 [0.055648, -0.204043, 1.057311]])

    for i in range(0, rows):
        for j in range(0, cols):
            X,Y,Z = XYZImage[i,j]
            linearsRGBImage[i,j] = np.matmul(multiplierMatrix, np.array([X,Y,Z]))
        #for j -ends
    #for i -ends

    return linearsRGBImage 

Код для этого преобразования, как указано выше. Может кто-нибудь указать, что я делаю неправильно для 2-го пикселя, и как это исправить?

1 ответ

Решение

Ну, одно простое решение, которое я нашел после исследования, это просто обрезать значения. Таким образом, если значение выходит за пределы диапазона, скажем, если r<0, то мы назначим r как 0. То же самое для больших значений. Если r>1 (в моем случае 3.07), то мы будем назначать r как 1.

Итак, последняя версия моего кода:

def XYZToLinearRGB(self, XYZImage):
    '''
    to find linearsRGBImage, we multiply XYZImage with static array
    [[3.240479, -1.53715, -0.498535],
     [-0.969256, 1.875991, 0.041556],
     [0.055648, -0.204043, 1.057311]]

    '''
    rows, cols, bands = XYZImage.shape # bands == 3

    linearsRGBImage =  np.zeros([rows, cols, bands], dtype=float)
    multiplierMatrix = np.array([[3.240479, -1.53715, -0.498535],
                                 [-0.969256, 1.875991, 0.041556],
                                 [0.055648, -0.204043, 1.057311]])

    for i in range(0, rows):
        for j in range(0, cols):
            X,Y,Z = XYZImage[i,j]
            rgbList = np.matmul(multiplierMatrix, np.array([X,Y,Z]))
            for index, val in enumerate(rgbList):
                if val<0:
                    rgbList[index]=0
                #if val -ends
                if val>1:
                    rgbList[index]=1
                #if val -ends
            #for index, val -ends
            linearsRGBImage[i,j]=rgbList
        #for j -ends
    #for i -ends

    return linearsRGBImage 

Хотя, если у кого-то есть лучшее предложение, оно приветствуется.

Другие вопросы по тегам