从 RGB 到 YUV 的颜色转换 (YCoCg)
Color conversion from RGB to YUV (YCoCg)
我正在尝试实现颜色转换 Func
以输出到 3 个独立的缓冲区。 rgb_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 中的基本 for 循环)相比,我的性能很差。我知道我需要尝试更好的调度,但我认为我在 input/output 缓冲区方面做错了。我看过教程并试图想出一种输出到多个缓冲区的方法。使用 Pipeline
是我能找到的唯一方法。我最好制作 3 Func
s 并分别调用它们吗?这是 Pipeline
class 的正确用法吗?
这里可能存在的最大问题是,每次要转换单个图像时,您都在制作和编译代码。那真的很慢。使用ImageParams代替Buffers,一次定义Pipeline,然后多次实现。
二阶效应是我认为您实际上想要元组而不是管道。一个 Tuple Func 在同一个内部循环中计算它的所有值,这将重用来自 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 });
}
我正在尝试实现颜色转换 Func
以输出到 3 个独立的缓冲区。 rgb_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 中的基本 for 循环)相比,我的性能很差。我知道我需要尝试更好的调度,但我认为我在 input/output 缓冲区方面做错了。我看过教程并试图想出一种输出到多个缓冲区的方法。使用 Pipeline
是我能找到的唯一方法。我最好制作 3 Func
s 并分别调用它们吗?这是 Pipeline
class 的正确用法吗?
这里可能存在的最大问题是,每次要转换单个图像时,您都在制作和编译代码。那真的很慢。使用ImageParams代替Buffers,一次定义Pipeline,然后多次实现。
二阶效应是我认为您实际上想要元组而不是管道。一个 Tuple Func 在同一个内部循环中计算它的所有值,这将重用来自 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 });
}