【Compute Vision】【Color】图像RGB与YUV转换优化
来源:互联网 发布:曦力 mac 编辑:程序博客网 时间:2024/06/07 15:43
转载之:http://blog.csdn.net/songzitea
本文主要介绍如何优化您自己的CODE,实现软件的加速。我们一个图象模式识别的项目,需要将RGB格式的彩色图像先转换成黑白图像。图像转换的公式如下:
- Y = 0.299 * R + 0.587 * G + 0.114 * B
图像尺寸640*480*24bit,RGB图像已经按照RGBRGB顺序排列的格式,放在内存里面了。以下是输入和输出的定义:
- #define XSIZE 640
- #define YSIZE 480
- #define IMGSIZE XSIZE * YSIZE
- typedef struct RGB
- {
- unsigned char R;
- unsigned char G;
- unsigned char B;
- }RGB;
- struct RGB in[IMGSIZE]; //需要计算的原始数据
- unsigned char out[IMGSIZE]; //计算后的结果
- void calc_lum()
- {
- int i;
- for(i = 0; i < IMGSIZE; i++)
- {
- double r,g,b,y;
- unsigned char yy;
- r = in[i].r;
- g = in[i].g;
- b = in[i].b;
- y = 0.299 * r + 0.587 * g + 0.114 * b;
- yy = y;
- out[i] = yy;
- }
- }
这大概是能想得出来的最简单的写法了,实在看不出有什么毛病,好了,编译一下跑一跑吧。这个代码分别用vc6.0和gcc编译,生成2个版本,分别在pc上和我的embedded system上面跑。速度多少?在PC上,由于存在硬件浮点处理器,CPU频率也够高,计算速度为20秒。我的embedded system,没有以上2个优势,浮点操作被编译器分解成了整数运算,运算速度为120秒左右。
去掉浮点运算
上面这个代码还没有跑,我已经知道会很慢了,因为这其中有大量的浮点运算。只要能不用浮点运算,一定能快很多。Y = 0.299 * R + 0.587 * G + 0.114 * B;这个公式怎么能用定点的整数运算替代呢?0.299 * R可以如何化简?
- Y = 0.299 * R + 0.587 * G + 0.114 * B;
- Y = D + E + F;
- D = 0.299 * R;
- E = 0.587 * G;
- F = 0.114 * B;
- Y = (R * 299 + G * 587 + B * 114) / 1000
0.299 * R可以如何化简
- Y = 0.299 * R + 0.587 * G + 0.114 * B;
- Y = (R * 299 + G * 587 + B * 114) / 1000;
- 0.299=299/1000=1224/4096
- Y=(R*1224)/4096+(G*2404)/4096+(B*467)/4096
- Y=(R*1224+G*2404+B*467)/4096
这里的/4096除法,因为它是2的N次方,所以可以用移位操作替代,往右移位12bit就是把某个数除以4096了。
- void calc_lum()
- {
- int i;
- for(i = 0; i < IMGSIZE; i++){
- int r,g,b,y;
- r = 1224 * in[i].r;
- g = 2404 * in[i].g;
- b = 467 * in[i].b;
- y = r + g + b;
- y = y >> 12; //这里去掉了除法运算
- out[i] = y;
- }
- }
这个代码编译后,又快了20%。虽然快了不少,还是太慢了一些,20秒处理一幅图像。
查表方式
我们回到这个式子:
- Y = 0.299 * R + 0.587 * G + 0.114 * B;
- Y=D+E+F;
- D=0.299*R;
- E=0.587*G;
- F=0.114*B;
查表数组初始化
- int D[256],F[256],E[256];
- void table_init( ){
- int i;
- for(i=0;i<256;i++){
- D[i]=i*1224;
- D[i]=D[i]>>12;
- E[i]=i*2404;
- E[i]=E[i]>>12;
- F[i]=i*467;
- F[i]=F[i]>>12;
- }
- }
- void calc_lum(){
- int i;
- for(i = 0; i < IMGSIZE; i++){
- int r,g,b,y;
- r = D[in[i].r];//查表
- g = E[in[i].g];
- b = F[in[i].b];
- y = r + g + b;
- out[i] = y;
- }
- }
这一次的成绩把我吓出一身冷汗,执行时间居然从30秒一下提高到了2秒!在PC上测试这段代码,眼皮还没眨一下,代码就执行完了。一下提高15倍,爽不爽?
继续优化.很多embedded system的32bit CPU,都至少有2个ALU,能不能让2个ALU都跑起来?
- void calc_lum(){
- int i;
- for(i = 0; i < IMGSIZE; i += 2){ //一次并行处理2个数据
- int r,g,b,y,r1,g1,b1,y1;
- r = D[in[i].r];//查表 //这里给第一个ALU执行
- g = E[in[i].g];
- b = F[in[i].b];
- y = r + g + b;
- out[i] = y;
- r1 = D[in[i + 1].r];//查表 //这里给第二个ALU执行
- g1 = E[in[i + 1].g];
- b1 = F[in[i + 1].b];
- y = r1 + g1 + b1;
- out[i + 1] = y;
- }
- <span style="font-family:SimSun;">}</span>
- int D[256],F[256],E[256]; //查表数组
- void table_init(){
- int i;
- for(i=0;i<256;i++) {
- D[i]=i*1224;
- D[i]=D[i]>>12;
- E[i]=i*2404;
- E[i]=E[i]>>12;
- F[i]=i*467;
- F[i]=F[i]>>12;
- }
- }
到这里,似乎已经足够快了,但是我们反复实验,发现,还有办法再快!可以将
- int D[256],F[256],E[256]; //查表数组
- unsigned short D[256],F[256],E[256]; //查表数组
这是因为编译器处理int类型和处理unsigned short类型的效率不一样。再改动
- inline void calc_lum(){
- int i;
- for(i = 0; i < IMGSIZE; i += 2){ //一次并行处理2个数据
- int r,g,b,y,r1,g1,b1,y1;
- r = D[in[i].r];//查表 //这里给第一个ALU执行
- g = E[in[i].g];
- b = F[in[i].b];
- y = r + g + b;
- out[i] = y;
- r1 = D[in[i + 1].r];//查表 //这里给第二个ALU执行
- g1 = E[in[i + 1].g];
- b1 = F[in[i + 1].b];
- y = r1 + g1 + b1;
- out[i + 1] = y;
- }
- }
RGB到YUV的转换算法做以总结。
Y = 0.299R + 0.587G + 0.114B
U = -0.147R - 0.289G + 0.436B
V = 0.615R - 0.515G - 0.100B
- #deinfe SIZE 256
- #define XSIZE 640
- #define YSIZE 480
- #define IMGSIZE XSIZE * YSIZE
- typedef struct RGB{
- unsigned char r;
- unsigned char g;
- unsigned char b;
- }RGB;
- struct RGB in[IMGSIZE];
- unsigned char out[IMGSIZE * 3];
- unsigned short Y_R[SIZE],Y_G[SIZE],Y_B[SIZE],U_R[SIZE],U_G[SIZE],U_B[SIZE],V_R[SIZE],V_G[SIZE],V_B[SIZE]; //查表数组
- void table_init(){
- int i;
- for(i = 0; i < SIZE; i++){
- Y_R[i] = (i * 1224) >> 12; //Y
- Y_G[i] = (i * 2404) >> 12;
- Y_B[i] = (i * 467) >> 12;
- U_R[i] = (i * 602) >> 12; //U
- U_G[i] = (i * 1183) >> 12;
- U_B[i] = (i * 1785) >> 12;
- V_R[i] = (i * 2519) >> 12; //V
- V_G[i] = (i * 2109) >> 12;
- V_B[i] = (i * 409) >> 12;
- }
- }
- inline void calc_lum(){
- int i;
- for(i = 0; i < IMGSIZE; i += 2) {
- out[i] = Y_R[in[i].r] + Y_G[in[i].g] + Y_B[in[i].b]; //Y
- out[i + IMGSIZE] = U_B[in[i].b] - U_R[in[i].r] - U_G[in[i].g]; //U
- out[i + 2 * IMGSIZE] = V_R[in[i].r] - V_G[in[i].g] - V_B[in[i].b]; //V
- out[i + 1] = Y_R[in[i + 1].r] + Y_G[in[i + 1].g] + Y_B[in[i + 1].b]; //Y
- out[i + 1 + IMGSIZE] = U_B[in[i + 1].b] - U_R[in[i + 1].r] - U_G[in[i + 1].g]; //U
- out[i + 1 + 2 * IMGSIZE] = V_R[in[i + 1].r] - V_G[in[i + 1].g] - V_B[in[i + 1].b]; //V
- }
- }
这种算法应该是非常快的了.
- 【Compute Vision】【Color】图像RGB与YUV转换优化
- 图像RGB与YUV转换优化
- 图像RGB与YUV转换优化
- 图像 YUV与RGB格式转换
- RGB与YUV转换
- RGB与YUV转换
- RGB与YUV转换
- RGB与YUV转换
- RGB与YUV图像视频格式的相互转换
- RGB与YUV图像视频格式的相互转换
- RGB与YUV图像视频格式的相互转换
- RGB与YUV图像视频格式的相互转换(转)
- RGB与YUV图像视频格式的相互转换
- RGB与YUV图像视频格式的相互转换
- RGB与YUV图像视频格式的相互转换
- RGB与YUV图像视频格式的相互转换
- RGB与YUV图像视频格式的相互转换
- 24位BMP图像RGB与YUV转换
- MySQL存储过程中的3种循环
- Objective-C学习1
- 【Android学习】Android服务之Service(2)--绑定本地Service
- Python yield 使用浅析
- c++11 线程:让你的多线程任务更轻松
- 【Compute Vision】【Color】图像RGB与YUV转换优化
- python pip 安装
- java 服务 cpu 问题跟进
- Mac App 的发布
- 安卓 切换页面
- Hmaster 启动讲解
- androidl40 之前不支持 支持硬件加速的问题
- eclipse svn is not a working copy 错误的解决办法
- 删除指定目录下所有文件及目录