在上一节中我们讨论了使用opencv中访问图像进行彩色图像灰度化操作的几种方式,遗留给我们的问题在于还可以速度更快吗?还有优化的空间吗?
【优化浮点数】
计算机中的浮点数一般都采用单精度表示,运算较为费时。故我们首先想到的优化方式为将浮点数操作转化为整形操作,即将:
Gray(i,j)=0.299*R(i,j)+0.587*G(i,j)+0.144*B(i,j)
优化为:
Gray(i,j)= (2990*R(i,j)+5870*G(i,j)+1440*B(i,j))/10000
代码实现为:
void rgbtogray_4(Mat& image, Mat &result)
{
int n = image.rows * image.cols;
uchar * src = image.ptr<uchar>(0);
uchar * dest = result.ptr<uchar>(0);
for(int i=0;i<n;i++)
{
int B = *(src);
int G = *(src+1);
int R = *(src+2);
*dest = cv::saturate_cast<uchar>((1140*B + 5870*G + 2989*R)/10000);
dest++;
src += 3;
}
}
【优化除法】
我们知道大部分的C++编译器,用移位的方法得到代码比调用乘除法子程序生成的代码效率高。基于此,我们将上述公式再次优化为移位实现,如下:
Gray(i,j)= (4898*R(i,j)+9618*G(i,j)+1868*B(i,j))>>14
代码实现为:
void rgbtogray_5(Mat& image, Mat &result)
{
int n = image.rows * image.cols;
uchar * src = image.ptr<uchar>(0);
uchar * dest = result.ptr<uchar>(0);
for(int i=0;i<n;i++)
{
int B = *(src);
int G = *(src+1);
int R = *(src+2);
*dest = cv::saturate_cast<uchar>((4898*B + 9618*G + 1868*R)>>14);
dest++;
src += 3;
}
}
【使用查找表】
Lookup Table(LUT) 对于uint8表示的图像来说,每个值的范围为[0,255]之间的整数,因此可建立LUT查询表,其内含256个数值,表示对256种像素值的操作。使用时只需将像素值p视为LUT表的索引,即可得到对应变换值f( p )。
代码实现为:
void rgbtogray_6(Mat& image, Mat &result)
{
int LUT_B[256]={0};
int LUT_G[256]={0};
int LUT_R[256]={0};
for(int i=0;i<256;i++)
{
LUT_B[i] = (i * 4898);
LUT_G[i] = (i * 9618);
LUT_R[i] = (i * 1868);
}
int n = image.rows * image.cols;
uchar * src = image.ptr<uchar>(0);
uchar * dest = result.ptr<uchar>(0);
for(int i=0;i<n;i++)
{
int B = *(src);
int G = *(src+1);
int R = *(src+2);
*dest = cv::saturate_cast<uchar>( (LUT_B[B] + LUT_G[G] + LUT_R[R]) >>14);
dest++;
src += 3;
}
}
【基线】
为了对比上述集中方法,选用上一篇文章中最快的方式作为基线,即
void rgbtogray_3(Mat& image, Mat &result)
{
int n = image.rows * image.cols;
uchar * src = image.ptr<uchar>(0);
uchar * dest = result.ptr<uchar>(0);
for(int i=0;i<n;i++)
{
int B = *(src);
int G = *(src+1);
int R = *(src+2);
*dest = cv::saturate_cast<uchar>(0.114*B + 0.587*G + 0.2989*R);
dest++;
src += 3;
}
}
【耗时对比】
选取同一副1920X1080的图像作为测试图像,上述各个函数执行100次,计算平均耗时。得到结果如下:
【结论】
通过将浮点运算转化为整形运算,耗时由8.96ms变为5.9ms;通过使用移位运算代替除法操作,时间优化为3.73毫秒;进一步通过使用LUT表耗时减小至3.46ms。
关注公众号《AI算法之道》,获取更多AI算法资讯