python RGB 图像转 YUYV
python RGB Image to YUYV
我想将位图转换为 YUV422 (YUYV) 格式。
我 google 了解 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
您可以在此处使用 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,U01
和V01
被省略,U02
从7到5,V02
从 8 到 7,U03
被省略等等:
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
更复杂的边界情况也会遇到
我想将位图转换为 YUV422 (YUYV) 格式。 我 google 了解 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")
我看了这张图片,知道我的代码是错误的,但不知道如何改正。
如果用我的代码把480*640(W*H)转换成960*480
您可以在此处使用 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,U01
和V01
被省略,U02
从7到5,V02
从 8 到 7,U03
被省略等等:
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
更复杂的边界情况也会遇到