调整I420框架的大小

时间:2019-04-11 18:52:57

标签: android image-processing

我是图像处理的新手,我需要有关I420图像帧的帮助。我正在从事一个项目,该项目需要对实时视频进行一些修改。传入帧是YUV-I420编码的帧。我的要求是调整此传入帧的大小。解码I420并转换为RGB然后调整大小是一个昂贵的过程。因此,有什么方法可以直接调整YUV-I420框架的大小。

2 个答案:

答案 0 :(得分:1)

即使认为这个想法看起来不错,它也行不通。它完美地打乱了缓冲区。我用 20x8 的较小“图像”进行了尝试,我将其“缩小”到 10x4,只是为了能够跟踪的小数字。然后我跟踪行中的索引,这些索引从 src 复制到nearestNeighborScale 中的 dst。这是输出,看起来不正确(使用真实图像看起来也不正确):

03-11 18:10:41.558 16334 16617 D ..      : >> Enter
03-11 18:10:41.559 16334 16617 D Scrambler: src-idx 0, dst-idx 0
03-11 18:10:41.559 16334 16617 D Scrambler: src-idx 2, dst-idx 1
03-11 18:10:41.559 16334 16617 D Scrambler: src-idx 4, dst-idx 2
03-11 18:10:41.559 16334 16617 D Scrambler: src-idx 6, dst-idx 3
03-11 18:10:41.559 16334 16617 D Scrambler: src-idx 8, dst-idx 4
03-11 18:10:41.559 16334 16617 D Scrambler: src-idx 10, dst-idx 5
03-11 18:10:41.559 16334 16617 D Scrambler: src-idx 12, dst-idx 6
03-11 18:10:41.559 16334 16617 D Scrambler: src-idx 14, dst-idx 7
03-11 18:10:41.559 16334 16617 D Scrambler: src-idx 16, dst-idx 8
03-11 18:10:41.559 16334 16617 D Scrambler: src-idx 18, dst-idx 9
03-11 18:10:41.559 16334 16617 D Scrambler: src-idx 2, dst-idx 10
03-11 18:10:41.560 16334 16617 D Scrambler: src-idx 4, dst-idx 11
03-11 18:10:41.560 16334 16617 D Scrambler: src-idx 6, dst-idx 12
03-11 18:10:41.560 16334 16617 D Scrambler: src-idx 8, dst-idx 13
03-11 18:10:41.560 16334 16617 D Scrambler: src-idx 10, dst-idx 14
03-11 18:10:41.560 16334 16617 D Scrambler: src-idx 12, dst-idx 15
03-11 18:10:41.560 16334 16617 D Scrambler: src-idx 14, dst-idx 16
03-11 18:10:41.560 16334 16617 D Scrambler: src-idx 16, dst-idx 17
03-11 18:10:41.560 16334 16617 D Scrambler: src-idx 18, dst-idx 18
03-11 18:10:41.560 16334 16617 D Scrambler: src-idx 20, dst-idx 19
03-11 18:10:41.560 16334 16617 D Scrambler: src-idx 4, dst-idx 20
03-11 18:10:41.561 16334 16617 D Scrambler: src-idx 6, dst-idx 21
03-11 18:10:41.561 16334 16617 D Scrambler: src-idx 8, dst-idx 22
03-11 18:10:41.561 16334 16617 D Scrambler: src-idx 10, dst-idx 23
03-11 18:10:41.561 16334 16617 D Scrambler: src-idx 12, dst-idx 24
03-11 18:10:41.561 16334 16617 D Scrambler: src-idx 14, dst-idx 25
03-11 18:10:41.561 16334 16617 D Scrambler: src-idx 16, dst-idx 26
03-11 18:10:41.561 16334 16617 D Scrambler: src-idx 18, dst-idx 27
03-11 18:10:41.561 16334 16617 D Scrambler: src-idx 20, dst-idx 28
03-11 18:10:41.561 16334 16617 D Scrambler: src-idx 22, dst-idx 29
03-11 18:10:41.561 16334 16617 D Scrambler: src-idx 6, dst-idx 30
03-11 18:10:41.562 16334 16617 D Scrambler: src-idx 8, dst-idx 31
03-11 18:10:41.562 16334 16617 D Scrambler: src-idx 10, dst-idx 32
03-11 18:10:41.562 16334 16617 D Scrambler: src-idx 12, dst-idx 33
03-11 18:10:41.562 16334 16617 D Scrambler: src-idx 14, dst-idx 34
03-11 18:10:41.562 16334 16617 D Scrambler: src-idx 16, dst-idx 35
03-11 18:10:41.562 16334 16617 D Scrambler: src-idx 18, dst-idx 36
03-11 18:10:41.562 16334 16617 D Scrambler: src-idx 20, dst-idx 37
03-11 18:10:41.562 16334 16617 D Scrambler: src-idx 22, dst-idx 38
03-11 18:10:41.562 16334 16617 D Scrambler: src-idx 24, dst-idx 39
03-11 18:10:41.562 16334 16617 D ..      : << Leave

答案 1 :(得分:0)

假设您有一个640x480 YUV(I420)图片。

“ Y”数据应恰好为640x480(307200)字节,然后是“ U”数据应为320x240(76800)字节,然后是“ V”数据的另一个“ 320x240”(76800)字节。将每个平面视为3个单色位图。总共460800字节。

比方说,您获得了X by 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);