YUV与RGB的相互转换一直以来都是非常常用的基础算法,如何才能最高效的转换,成为一个难点问题,尤其是目前视频直播火热的时候,这些算法的优化也越发重要。 首先,我们看下最常用的YUV与RGB相互转换的算法公式,如下所示: 注意,RGB取值范围均为0-255: 1,RGB转YUV Y = 0.299R + 0.587G + 0.114B U = -0.147R - 0.289G + 0.436B V = 0.615R - 0.515G - 0.100B 2,YUV转RGB R = Y + 1.14V G = Y - 0.39U - 0.58V B = Y + 2.03U 我的优化方案如下: 优化1:看到上述算法,从算法优化角度来看,算法计算中,最好不要出现浮点运算,浮点运算比较耗时; 基于这一点,我们做如下操作: Y * 256 = 0.299 * 256R + 0.587 * 256G + 0.114 * 256B U * 256 = -0.147 * 256R - 0.289 * 256G + 0.436 * 256B V * 256 = 0.615 * 256R - 0.515 * 256G - 0.100 * 256B R * 256 = Y * 256 + 1.14 * 256V G * 256 = Y * 256 - 0.39 * 256U - 0.58 * 256V B * 256 = Y * 256 + 2.03 * 256U 简化上面的公式如下: 256Y = 76.544R + 150.272G + 29.184B 256U = -37.632R - 73.984G + 111.616B 256V = 157.44R - 131.84G - 25.6B 256R = 256Y + 291.84V 256G = 256Y - 99.84U - 148.48V 256B = 256Y + 519.68U 做到这一步,我这里要说明一下:我们这里的转换是有损的,适用于追求速度,而对效果要求不是100%准确的情况。 然后,我们就可以对上述公式进一步优化,彻底干掉小数: 256Y = 77R + 150G + 29B 256U = -38R - 74G + 112B 256V = 158R - 132G - 26B 256R = 256Y + 292V 256G = 256Y - 100U - 149V 256B = 256Y + 520U 实际上就是四舍五入,为什么要乘以256,这是实际上是为了缩小误差,当然你这个地方乘数越大,误差越小。 优化2:干掉所有乘法,用移位运算表示; 上述公式,我们可以用移位进行简单优化: Y = (77R + 150G + 29B) >> 8 U = (-38R - 74G + 112B) >> 8 V = (158R - 132G - 26B) >> 8 R = (256Y + 292V) >> 8 G = (256Y - 100U - 149V) >> 8 B = (256Y + 520U) >> 8 做到此处,已经没有了浮点运算量了,但是我们发现虽然采用了移位运算,但是,公式中还有很多乘法运算,乘法跟移位运算相比,还是效率太低了,因此,我们将把所有乘法都改成移位运算。 如何将常数乘法改成移位运算? 这里给个例子: Y=Y*9可以改为:Y=(Y<<3)+Y 因此,我们可以讲YUV的公式继续改为最简: RGB转YUV: Y = ((R << 6) + (R << 3) + (R << 2) + R + (G << 7) + (G << 4) + (G << 2) + (G << 1) + (B << 4) + (B << 3) + (B << 2) + B) >> 8; U = (-((R << 5) + (R << 2) + (R << 1)) - ((G << 6) + (G << 3) + (G << 1)) + ((B << 6) + (B << 5) + (B << 4))) >> 8; V = ((R << 7) + (R << 4) + (R << 3) + (R << 2) + (R << 1) - ((G << 7) + (G << 2)) - ((B << 4) + (B << 3) + (B << 1))) >> 8; YUV转RGB: R = ((Y << 8) + ((V << 8) + (V << 5) + (V << 2))) >> 8; G = ((Y << 8) - ((U << 6) + (U << 5) + (U << 2)) - ((V << 7) + (V << 4) + (V << 2) + V)) >> 8; B = ((Y << 8) + (U << 9) + (U << 3)) >> 8; 至此,YUV与RGB的相互转换公式就优化完毕了,这个优化,在移动端,速度会有很大的提高,至于一些测试数据,我就不列举了,只给个效果图吧,大家可以直接试一下就知道了,最后,给出C的代码如下: static void RGBToYUV(int Red, int Green, int Blue, int* Y,int* U,int* V) { *Y = ((Red << 6) + (Red << 3) + (Red << 2) + Red + (Green << 7) + (Green << 4) + (Green << 2) + (Green << 1) + (Blue << 4) + (Blue << 3) + (Blue << 2) + Blue) >> 8; *U = (-((Red << 5) + (Red << 2) + (Red << 1)) - ((Green << 6) + (Green << 3) + (Green << 1)) + ((Blue << 6) + (Blue << 5) + (Blue << 4))) >> 8; *V = ((Red << 7) + (Red << 4) + (Red << 3) + (Red << 2) + (Red << 1) - ((Green << 7) + (Green << 2)) - ((Blue << 4) + (Blue << 3) + (Blue << 1))) >> 8; }; static void YUVToRGB(int Y, int U, int V, int* Red, int* Green, int* Blue) { *Red = ((Y << 8) + ((V << 8) + (V << 5) + (V << 2))) >> 8; *Green = ((Y << 8) - ((U << 6) + (U << 5) + (U << 2)) - ((V << 7) + (V << 4) + (V << 2) + V)) >> 8; *Blue = ((Y << 8) + (U << 9) + (U << 3)) >> 8; }; 效果图: 原图 使用浮点型RGB-YUV-RGB结果图 使用优化版RGB-YUV-RGB结果图 在说一下,这个优化纯粹是追求速度,当然,效果差异很小,如果你需要的是100%的准确,最好还是要使用浮点计算。 |
|
来自: taotao_2016 > 《计算机》