我是图像处理新手,我需要有关 I420 图像帧的帮助。我正在开发一个需要对实时视频进行一些修改的项目。传入帧是 YUV-I420 编码帧。我的要求是调整这个传入帧的大小。解码 I420 并转换为 RGB,然后调整大小是一个成本高昂的过程。那么有没有办法直接调整这个YUV-I420帧的大小。
最佳答案
假设您有一张 640x480 YUV(I420) 图像。
应该正好有 640x480 (307200) 字节的“Y”数据,后跟 320x240 (76800) 字节的“U”数据,最后是另一个“320x240”(76800) 字节的“V”数据。将每个平面视为 3 个单色位图。总共 460800 字节。
假设您获得了 X x Y
大小的图像的图像字节。让我们保持简单,假设 X 和 Y 甚至可以被 4 整除,就像大多数视频格式一样。我们假设比例尺的宽度和高度也都可以被 4 整除。
如果您有一个 I420 字节字节数组,如下所示:
byte [] image_bytes = <some array of image bytes>;
因此,平面是该数组中的以下偏移量:
Y_offset = 0;
U_offset = WIDTH*HEIGHT;
V_offset = U_OFFSET + (WIDTH/2)*(HEIGHT/2);
现在是一个非常简单的单色平面最近邻函数:
void nearestNeighborScale(int srcWidth, int srcHeight, int dstWidth, int dstHeight, byte [] src, int src_offset, byte [] dst, int dst_offset)
{
for (int y = 0; y < dstHeight; y++)
{
int dstRowOffset = y * dstWidth;
int srcRowOffset = (y*srcHeight) / dstHeight;
for (int x = 0; x < dstWidth; x++)
{
int srcX = (x*srcWidth) / dstWidth;
dst[dstRowOffset + x + dst_offset] = src[srcRowOffset + srcX + src_offset];
}
}
}
因此,要将图像缩放至 NEW_WIDTH 和 NEW_HEIGHT,只需执行以下操作:
int new_size = (NEW_WIDTH*NEW_HEIGHT * 3)/2;
byte [] scaled_image = new byte[new_size];
Y_offset = 0;
U_offset = WIDTH*HEIGHT;
V_offset = U_OFFSET + (WIDTH/2)*(HEIGHT/2);
Y_Dst_offset = 0;
U_Dst_offset = NEW_WIDTH*NEW_HEIGHT;
V_Dst_offset = U_OFFSET + (NEW_WIDTH/2)*(NEW_HEIGHT/2);
然后要转换图像,只需调用最近邻函数 3 次:
nearestNeighborScale(WIDTH, HEIGHT, NEW_WIDTH, NEW_HEIGHT, image_bytes, Y_offset, scaled_image, Y_Dst_offset);
nearestNeighborScale(WIDTH/2, HEIGHT/2, NEW_WIDTH/2, NEW_HEIGHT/2, image_bytes, U_offset, scaled_image, U_Dst_offset);
nearestNeighborScale(WIDTH/2, HEIGHT/2, NEW_WIDTH/2, NEW_HEIGHT/2, image_bytes, V_offset, scaled_image, V_Dst_offset);
关于android - 调整 I420 框架大小,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55639383/