首页 > 解决方案 > 在 uint8 中将 RGB 转换为 YIQ 颜色模式时出现问题,反之亦然

问题描述

我有一个矩阵,它是一个带有 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 函数以返回一个 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 之间来回切换,仍然给我相同的结果

标签: pythonnumpyimage-processingpython-imaging-library

解决方案


基本问题只是一个虚幻的错误......

以下代码行:

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

它应该是:

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

其他问题:

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

这是您的代码稍作修改的版本:

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(由于舍入而不是零)。


推荐阅读