基于Qt的图像处理算法和实现——线性灰度变换

灰度的线性变换使用的变换函数是一个一维的线性函数:y = ax + b

x为原灰度值,y即得到的新灰度。

当a>1时,输出图像的对比度将增大;

当a<1时,输出图像的对比度将减小;

当a=1时且b≠0时,变换将使灰度值上移或下移,其效果是使整个图像变亮或变暗(我们在《基于Qt的图像处理算法和实现——灰度图像、冷暖色调、亮度》这篇文章中改变图像亮度时就是直接对各颜色分量的值进行加减操作);

当a<0时,暗区域将变亮,亮区域将变暗。

特殊情况:a=01,d=255时,输出图像的灰度相反。

示例代码

下面的代码针对所有类型的图像文件,不仅仅是位图,所以第一步操作是根据RGB值计算灰度值。对于彩色转灰度,有一个很著名的心理学公式:

$$Gray = R*0.299 + G*0.587 + B*0.114$$

至于用这个公式而不是直接取平均值,是因为人眼对RGB颜色的感知程度并不相同,所以在转换的时候应该分别为RGB设置不同的权重。至于其背后的详细说明及物理上的原理,请移步知乎的这个帖子:

传送门:知乎 RGB 转为灰度值的心理学公式 Gray = 0.30 * R + 0.59 * G + 0.11 * B 是怎么来的?

考虑到一幅图像的每个像素都需要使用上面的公式,计算量比较大,我们这里采用了:

$$ Gray = (R*299 + G*587 + B*114 + 500) / 1000$$

这个公式,注意后面那个除法是整数除法,所以需要加上500来实现四舍五入。

/*****************************************************************************
 *                           线性灰度变换 y = ax + b
 * **************************************************************************/
QImage Tools::LinearLevelTransformation(const QImage &origin, double _a, double _b)
{
    QImage *newImage = new QImage(origin.width(), origin.height(),
                                   QImage::Format_ARGB32);
    QColor oldColor;
    int grayLevel = 0;

    for (int x=0; x<newImage->width(); x++) {
        for (int y=0; y<newImage->height(); y++) {
            oldColor = QColor(origin.pixel(x,y));
            grayLevel = (oldColor.red()*299+oldColor.green()*587+oldColor.blue()*114+500)/1000;
            int _y = _a*grayLevel + _b;
            // Make sure that the new values are between 0 and 255
            _y = qBound(0, _y, 255);

            newImage->setPixel(x,y,qRgb(_y,_y,_y));
        }
    }
//    qDebug()<<"a:"<<_a<<"\tb:"<<_b;

    return *newImage;
}

注意,变换之后得到的灰度应该控制在 0~255之间。

效果截图

[caption id="attachment_1672" align="aligncenter" width="985"] 线性灰度变换[/caption]

上图中是 a =1.2, b=0时的效果

标签: Qt 图像处理

发表评论: