• 计算机视觉全系列实战教程:(八)图像变换-点运算、灰度变换、直方图变换


    1.点运算

    (1)What

    通过点运算,输出图像的每个像素的灰度值仅仅取决于输入图像中相对应像素的灰度值。

    (2)Why

    点运算的作用:实现图像增强的常用方法之一

    2.灰度变换

    (1)What

    灰度变换是一种点运算的具体形式,换句话说,灰度变换是点运算的一种运用

    (2)Why(作用)

    增强对比度,是增强图像的重要手段(途径)和方法

    • 改善图像的质量:显示更多细节,进行对比度拉伸
    • 突出感兴趣的特征:针对图像中感兴趣的区域进行突出或抑制

    (3)Which(有哪些灰度变换)

    核心:灰度变换函数的不同

    • A.线性灰度变换
      y = k * f(x) + b
      当k>1:对比度将增大
      当k<1:对比度将减小
      当k=1,b!=0:图像整体变亮或变暗
      当k=-1,b=255:图像灰度正好相反
      当k<0,b>0:暗区域变亮,亮区域变暗
    • B.分段线性灰度变换

    在这里插入图片描述
    确定分段函数的三个k值和b值即可实现分段灰度变换效果。
    分段线性灰度变换的效果对参数的选取依赖很高,当参数选取不好的时候,不但无法实现增强图像的效果,还可能变得更加糟糕。为此实现自适应选取成为分段线性灰度变换的关键。目前常用的方法有:自适应最小误差法多尺度逼近方法
    恒增强率方法等。

    • C.非线性变换-对数变换
      g(x) = c * log(1+f(x))
    • D.非线性变换-反对数变换
      g(x) = ( (f(x)+1)^r -1 ) / f(x)
    • E.非线性变换-幂律变换
      g(x) = c*f(x)^alpha

    3.直方图修正

    (1)直方图均衡化

    直方图均衡化可实现图像的自动增强,但效果不易控制,得到的是全局增强的结果
    
    • step01:统计每一个灰度级的数量
    // 统计输入图像的灰度级数量
    std::vector<int> vNk(256, 0);
    int iTotal = imDst.total();
    for (int i = 0; i < imDst.total(); ++i)
    {
    	vNk[imDst.data[i]]++;
    }
    
    • step02:求累积分布
    // 求累积分布函数
    for (int i = 1; i < 256; ++i)
    {
    	vNk[i] = vNk[i] + vNk[i - 1];
    }
    
    • step03:建立映射关系
    // 确定映射关系
    std::vector<double> vMPk(256, 0.0);
    for (int i = 0; i < 256; ++i)
    {
    	vMPk[i] = 255.0f * (double)vNk[i] / iTotal;
    }
    // 重新赋值实现均衡化
    for (int i = 0; i < iTotal; ++i)
    {
    	imDst.data[i] = vMPk[imDst.data[i]];
    }
    

    代码汇总如下(可直接使用):

    /* 图像均衡化 */
    int ImgEqualize(const cv::Mat& imSrc, cv::Mat& imDst) {
    	// 对输入的数据进行可靠性判定
    	if (imSrc.empty()) return -1;
    	// 对输入图像进行灰度化处理
    	if (imSrc.channels() == 3)
    		cv::cvtColor(imSrc, imDst, cv::COLOR_RGB2GRAY);
    	else imDst = imSrc;
    	// 统计输入图像的灰度级数量
    	std::vector<int> vNk(256, 0);
    	int iTotal = imDst.total();
    	for (int i = 0; i < imDst.total(); ++i)
    	{
    		vNk[imDst.data[i]]++;
    	}
    	// 求累积分布函数
    	for (int i = 1; i < 256; ++i)
    	{
    		vNk[i] = vNk[i] + vNk[i - 1];
    	}
    	// 确定映射关系
    	std::vector<double> vMPk(256, 0.0);
    	for (int i = 0; i < 256; ++i)
    	{
    		vMPk[i] = 255.0f * (double)vNk[i] / iTotal;
    	}
    	// 重新赋值实现均衡化
    	for (int i = 0; i < iTotal; ++i)
    	{
    		imDst.data[i] = vMPk[imDst.data[i]];
    	}
    
    }
    
  • 相关阅读:
    HR问:有没有免费的人才测评工具?
    剑指offer.平衡二叉树
    九、【漏洞复现】Struts 2 远程代码执行漏洞s2-046(CVE-2017-5638)
    切记这三点 避免你的虾皮Shopee店铺被计分
    {版本发布公告}HMS Core 6.6.0来啦
    机器学习之线性回归之第一课
    原子搜索算法改进的深度极限学习机DELM的分类
    飞桨paddlespeech语音唤醒推理C INT8 定点实现
    基于android的健身管理APP(ssm+uinapp+Mysql)
    Java项目:SSM实现的一个在线文具学习用品购买商城网站
  • 原文地址:https://blog.csdn.net/qq_42279379/article/details/139603909