在 uint8 中将 RGB 转换为 YIQ 颜色模式时出现问题,反之亦然

Problem during converting RGB to YIQ color mode and vice versa in uint8

我有一个矩阵,它是一个包含 BGR 值的图像。这是在问题

中被切片以使其更短的图像
img = [[[72, 63,  0],
        [71, 62,  0],
        [70, 61,  0]],

       [[73, 64,  1],
        [71, 62,  0],
        [70, 61,  0]],

       [[73, 64,  1],
        [72, 63,  0],
        [71, 62,  0]],

       [[73, 64,  1],
        [72, 63,  0],
        [71, 62,  0]],

       [[74, 65,  2],
        [72, 63,  0],
        [71, 62,  0]]]

我已经成功制作了一个将 BGR 值转换为 YIQ 的函数,但是这个函数没有将 YIQ 值转换为 uint8。它使 I 和 Q 值可以为负值

import numpy as np

def RGB2YIQ(img):
    BGR = img.copy().astype(float)
    R = BGR[:,:,2]
    G = BGR[:,:,1]
    B = BGR[:,:,0]

    Y = (0.299 * R) + (0.587 * G) + (0.114 * B)
    I = (0.59590059 * R) + (-0.27455667 * G) + (-0.32134392 * B)
    Q = (0.21153661 * R) + (-0.52273617 * G) + (0.31119955 * B)

    YIQ = (np.dstack((Y,I,Q))).astype(int)

    return YIQ

>>> RGB2YIQ(img)
>>> array([[[ 45, -40, -10],
            [ 44, -39, -10],
            [ 43, -39, -10]],

           [[ 46, -40, -10],
            [ 44, -39, -10],
            [ 43, -39, -10]],

           [[ 46, -40, -10],
            [ 45, -40, -10],
            [ 44, -39, -10]],

           [[ 46, -40, -10],
            [ 45, -40, -10],
            [ 44, -39, -10]],

           [[ 47, -40, -10],
            [ 45, -40, -10],
            [ 44, -39, -10]]])

我也已经将转换回 RGB,同样工作正常

def YIQ2RGB(img):
    YIQ = img.copy().astype(int)
    Y = YIQ[:,:,0]
    I = YIQ[:,:,1]
    Q = YIQ[:,:,2]

    R = (1 * Y) + (0.95598634 * I) + (0.6208248 * Q)
    G = (1 * Y) + (-0.27201283 * I)) + (-0.64720424 * Q)
    B = (1 * Y) + (-1.10674021 * I) + (1.70423049 * Q)

    RGB = (np.dstack((R,G,B))).astype(np.uint8)

    return RGB

>>>YIQ2RGB(img)
>>>array([[[ 0, 62, 72],
           [ 0, 61, 70],
           [ 0, 60, 69]],

          [[ 1, 63, 73],
           [ 0, 61, 70],
           [ 0, 60, 69]],
 
          [[ 1, 63, 73],
           [ 0, 62, 72],
           [ 0, 61, 70]],

          [[ 1, 63, 73],
           [ 0, 62, 72],
           [ 0, 61, 70]],

          [[ 2, 64, 74],
           [ 0, 62, 72],
           [ 0, 61, 70]]], dtype=uint8)

当我尝试将 YIQ 数组转换为 uint8 类型然后将其转换回 RGB 时出现问题。我试图将 128 添加到 I 和 Q 通道中,所以我将 RGB2YIQ 函数修改为 return uint8 类型数组

import numpy as np

def RGB2YIQ(img):
    BGR = img.copy().astype(float)
    R = BGR[:,:,2]
    G = BGR[:,:,1]
    B = BGR[:,:,0]

    Y = (0.299 * R) + (0.587 * G) + (0.114 * B)
    I = (0.59590059 * R) + (-0.27455667 * G) + (-0.32134392 * B)
    Q = (0.21153661 * R) + (-0.52273617 * G) + (0.31119955 * B)

    YIQ = (np.dstack((Y,I + 128,Q + 128))).astype(np.uint8)

    return YIQ

>>> RGB2YIQ(img)
>>> array([[[ 45,  87, 117],
            [ 44,  88, 117],
            [ 43,  88, 117]],

           [[ 46,  87, 117],
            [ 44,  88, 117],
            [ 43,  88, 117]],

           [[ 46,  87, 117],
            [ 45,  87, 117],
            [ 44,  88, 117]],

           [[ 46,  87, 117],
            [ 45,  87, 117],
            [ 44,  88, 117]],

           [[ 47,  87, 117],
            [ 45,  87, 117],
            [ 44,  88, 117]]], dtype=uint8)

但是当我修改 YIQ2RGB 函数并尝试它时,它给了我不同的 Y 值,这很奇怪,因为我唯一改变的是加 128 并减去它,但它只给我一个通道的不同值.

def YIQ2RGB(img):
    YIQ = img.copy().astype(int)
    Y = YIQ[:,:,0]
    I = YIQ[:,:,1] - 128
    Q = YIQ[:,:,2] - 128

    R = (1 * Y) + (0.95598634 * I) + (0.6208248 * Q)
    G = (1 * Y) + (-0.27201283 * I) + (-0.64720424 * Q)
    B = (1 * Y) + (-1.10674021 * I) + (1.70423049 * Q)

    RGB = (np.dstack((R,G,B))).astype(np.uint8)

    return RGB

>>>YIQ2RGB(img)
>>>array([[[255,  63,  71],
           [255,  61,  69],
           [254,  60,  68]],

          [[  0,  64,  72],
           [255,  61,  69],
           [254,  60,  68]],

          [[  0,  64,  72],
           [255,  63,  71],
           [255,  61,  69]],

          [[  0,  64,  72],
           [255,  63,  71],
           [255,  61,  69]],

          [[  0,  65,  73],
           [255,  63,  71],
           [255,  61,  69]]], dtype=uint8)

我怀疑这是因为类型转换问题,但我在 np.uint8 之间来回切换 和 int,仍然给我相同的结果

基本问题只是虚幻的bug...

以下代码行:

R = BGR[:,:,2]
G = BGR[:,:,1]
B = BGR[:,:,0]

应该是:

R = BGR[:,:,0]
G = BGR[:,:,1]
B = BGR[:,:,2]

其他问题:

  • 在投射到 uint8 之前,您需要将 RGB 的范围裁剪到 [0, 255]。
  • 为了更准确,您可以在从 float 转换为整数之前使用 np.round

这里是你的代码的一个稍微修改的版本:

import numpy as np

def RGB2YIQ(img):
    BGR = img.copy().astype(float)
    R = BGR[:,:,0]
    G = BGR[:,:,1]
    B = BGR[:,:,2]

    Y = (0.299 * R) + (0.587 * G) + (0.114 * B)
    I = (0.59590059 * R) + (-0.27455667 * G) + (-0.32134392 * B)
    Q = (0.21153661 * R) + (-0.52273617 * G) + (0.31119955 * B)

    YIQ = np.round(np.dstack((Y,I + 128,Q + 128))).astype(np.uint8)

    return YIQ


def YIQ2RGB(img):
    YIQ = img.copy().astype(float)
    Y = YIQ[:,:,0]
    I = YIQ[:,:,1] - 128
    Q = YIQ[:,:,2] - 128

    R = (1 * Y) + (0.95598634 * I) + (0.6208248 * Q)
    G = (1 * Y) + (-0.27201283 * I) + (-0.64720424 * Q)
    B = (1 * Y) + (-1.10674021 * I) + (1.70423049 * Q)

    RGB = np.round(np.clip(np.dstack((R,G,B)), 0, 255)).astype(np.uint8)

    return RGB


img = np.array([[[72, 63,  0],
               [71, 62,  0],
               [70, 61,  0]],
       
              [[73, 64,  1],
               [71, 62,  0],
               [70, 61,  0]],
       
              [[73, 64,  1],
               [72, 63,  0],
               [71, 62,  0]],
       
              [[73, 64,  1],
               [72, 63,  0],
               [71, 62,  0]],
       
              [[74, 65,  2],
               [72, 63,  0],
               [71, 62,  0]]], np.uint8)

yiq_img = RGB2YIQ(img)

rgb_img = YIQ2RGB(yiq_img)

print(rgb_img.astype(np.int16) - img.astype(np.int16))  # Print the difference.

结果:

[[[1 1 0]
  [0 0 1]
  [0 0 0]]

 [[1 1 0]
  [0 0 1]
  [0 0 0]]

 [[1 1 0]
  [1 1 0]
  [0 0 1]]

 [[1 1 0]
  [1 1 0]
  [0 0 1]]

 [[1 1 0]
  [1 1 0]
  [0 0 1]]]

最大差值为 1(由于四舍五入而不为零)。