【深度好文】浅谈图像灰度化优化

在上一节中我们讨论了使用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算法资讯
在这里插入图片描述

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

赵卓不凡

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值