【问题标题】:python RGB Image to YUYVpython RGB图像到YUYV
【发布时间】:2018-08-31 07:32:46
【问题描述】:

我想将位图转换为 YUV422 (YUYV) 格式。 我在谷歌上搜索了 YUYV 格式并尝试编写此代码。

path = "C:/Users/hogan/Desktop/red.bmp"
image = Image.open(path).convert("YCbCr")  # YUV
image = np.asarray(image)
width, height, YUYV = image.shape[1], image.shape[0], 4
array = np.empty((height * width * 3), dtype="uint8")
Y, U, V = 0, 1, 2
count = 0
for i in range(len(image)):
    for j in range(len(image[i])):
        for k in range(len(image[i][j])):
            if (count % 4 == 0):
                array[count] = image[i][j][Y]
            if (count % 4 == 1):
                array[count] = image[i][j][U]
            if (count % 4 == 2):
                array[count] = image[i][j][Y]
            if (count % 4 == 3):
                array[count] = image[i][j][V]
            count = count + 1
array.astype('uint8').tofile("C:/Users/hogan/Desktop/tmpdir/1.raw")

我阅读了这张图片,知道我的代码有误,但不知道如何改正。 例如 : YUV 中的红色 (255,0,0) 是 (76,84,255),如果我有很多像素,我不知道应该删除哪个“U”和“V”。

如果使用我的代码转换一个 480*640 (W*H),它将是 960*480。

【问题讨论】:

  • 您不会删除 U 和 V,而是取两个相邻像素的 U 和 V 的平均值并存储平均值。该文件应具有以下格式:Y1, (U1 + U2)/2, Y2, (V1 + V2)/2, Y3, (U3 + U4)/2, Y4, (V3 + V4)/ 2跨度>

标签: python yuv


【解决方案1】:

您可以在此处使用 numpy 高级索引和广播。

假设,你有一张图片:

ycbcr = np.array([
    [['Y00', 'U00', 'V00'], ['Y01', 'U01', 'V01'], ['Y02', 'U02', 'V02']],
    [['Y10', 'U10', 'V10'], ['Y11', 'U11', 'V11'], ['Y12', 'U12', 'V12']],
    [['Y20', 'U20', 'V20'], ['Y21', 'U21', 'V21'], ['Y22', 'U22', 'V22']],
], dtype=str)

使用 3D 数组会很麻烦,所以让我们将其转换为 1D:

ycbcr = ycbcr.reshape(27)

然后,我将为 YUYV 流分配一个数组:

yuyv = np.array(['   ' for _ in range(18)])  # '   ' is basically because
# I use strings in this example. You'd probably want to use arrays of uint8

第一步是最简单的——我们取 ycbcr(Y 分量)的每三个值并将它们放在 yuyv 的偶数位置上:

yuyv[::2] = ycbcr[::3]

然后我们继续处理其他字节。 U00 应该从位置 1 到位置 1,V00 从 2 到 3,U01V01 被省略,U02 从 7 到 5,V02 从 8 到 7,@987654331 @ 被省略等等:

yuyv[1::4] = ycbcr[1::6]  # Moving U, every sixth byte starting from position 1
yuyv[3::4] = ycbcr[2::6][:-1]  # Moving V, dropping last element of V

所以你会得到以下yuyv,就像建议的图片一样:

array(['Y00', 'U00', 'Y01', 'V00', 'Y02', 'U02', 'Y10', 'V02', 'Y11',
       'U11', 'Y12', 'V11', 'Y20', 'U20', 'Y21', 'V20', 'Y22', 'U22'],
dtype='<U3')

如果您想遵循@alkanen 的建议,该方法也是可行的,您只需在两个数组中采样 U 和 V 字节并取平均值。也许它看起来像这样:(未经测试)

u_even = ycbcr[1::6]
u_odd = ycbcr[4::6]
u = (u_even + u_odd) / 2
yuyv[1::4] = u

还会遇到更复杂的边界情况。

【讨论】:

  • 感谢您的回答,我的 (480*640) 图像有问题,如果我创建 (2*2) 图像,您的代码工作正常,YUYV 是正确的。 ValueError:无法将输入数组从形状(153599)广播到形状(153600)
  • @LittleTin 我对示例进行了定制以适用于 3x3 图像,并不打算制作通用代码。也许,对于您的尺寸,您需要 [:-1] 不是 V 通道,而是 U 通道。或者根本没有频道。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-02-14
  • 1970-01-01
  • 2017-04-18
相关资源
最近更新 更多