从RGB到YUV(YCoCg)的颜色转换

Color conversion from RGB to YUV (YCoCg)

本文关键字:颜色 转换 YCoCg RGB YUV      更新时间:2023-10-16

我正在尝试实现一个输出到 3 个独立缓冲区的颜色转换Funcrgb_to_ycocg函数具有一个 4x8 位通道交错缓冲区 (BGRA( 和 3 个输出缓冲区(Y、Co 和 Cg(,每个缓冲器均为 16 位值。目前,我正在使用这段代码:

void rgb_to_ycocg(const uint8_t *pSrc, int32_t srcStep, int16_t *pDst[3], int32_t dstStep[3], int width, int height)
{
    Buffer<uint8_t> inRgb((uint8_t *)pSrc, 4, width, height);
    Buffer<int16_t> outY(pDst[0], width, height);
    Buffer<int16_t> outCo(pDst[1], width, height);
    Buffer<int16_t> outCg(pDst[2], width, height);
    Var x, y, c;
    Func calcY, calcCo, calcCg, inRgb16;
    inRgb16(c, x, y) = cast<int16_t>(inRgb(c, x, y));
    calcY(x, y) = (inRgb16(0, x, y) + ((inRgb16(2, x, y) - inRgb16(0, x, y)) >> 1)) + ((inRgb16(1, x, y) - (inRgb16(0, x, y) + ((inRgb16(2, x, y) - inRgb16(0, x, y)) >> 1))) >> 1);
    calcCo(x, y) = inRgb16(2, x, y) - inRgb16(0, x, y);
    calcCg(x, y) =  inRgb16(1, x, y) - (inRgb16(0, x, y) + ((inRgb16(2, x, y) - inRgb16(0, x, y)) >> 1));
    Pipeline p =Pipeline({calcY, calcCo, calcCg});
    p.vectorize(x, 16).parallel(y);
    p.realize({ outY, outCo, outCg });
}

问题是,与参考实现(c 中的基本循环(相比,我的性能很差。我知道我需要尝试更好的调度,但我认为我在输入/输出缓冲区方面做错了什么。我已经看过教程并试图想出一种输出到多个缓冲区的方法。使用Pipeline是我能找到的唯一方法。我做 3 个Func并单独调用它们会更好吗?这是对Pipeline类的正确用法吗?

这里可能出现的最大问题是,每次要转换单个图像时,您都要制作和编译代码。那真的会很慢。使用 ImageParams 而不是 Buffers,定义一次管道,然后多次实现它。

二阶效应是,我认为你实际上想要一个元组而不是一个管道。元组函数在同一个内部循环中计算其所有值,这将重用来自 inRGB 等的负载。暂时忽略重新编译问题,请尝试:

void rgb_to_ycocg(const uint8_t *pSrc, int32_t srcStep, int16_t *pDst[3], int32_t dstStep[3], int width, int height)
{
    Buffer<uint8_t> inRgb((uint8_t *)pSrc, 4, width, height);
    Buffer<int16_t> outY(pDst[0], width, height);
    Buffer<int16_t> outCo(pDst[1], width, height);
    Buffer<int16_t> outCg(pDst[2], width, height);
    Var x, y, c;
    Func calcY, calcCo, calcCg, inRgb16;
    inRgb16(c, x, y) = cast<int16_t>(inRgb(c, x, y));
    out(x, y) = {
        inRgb16(0, x, y) + ((inRgb16(2, x, y) - inRgb16(0, x, y)) >> 1)) + ((inRgb16(1, x, y) - (inRgb16(0, x, y) + ((inRgb16(2, x, y) - inRgb16(0, x, y)) >> 1))) >> 1),
        inRgb16(2, x, y) - inRgb16(0, x, y),
        inRgb16(1, x, y) - (inRgb16(0, x, y) + ((inRgb16(2, x, y) - inRgb16(0, x, y)) >> 1))
    };
    out.vectorize(x, 16).parallel(y);
    out.realize({ outY, outCo, outCg });
}