使用C++、opencv实现对图像的对数变换及非线性变换,实现图像增强

相关API:

void normalize(InputArray src, OutputArray dst, double alpha=1, double beta=0, int norm_type=NORM_L2, int dtype=-1, InputArray mask=noArray() )

normalize函数的作用是进行矩阵的归一化。归一化就是把要处理的数据经过某种算法的处理限制在所需要的范围内。首先归一化是为了后面数据处理的方便,其次归一化能够保证程序运行时收敛加快。归一化的具体作用是归纳同意样本的统计分布性,归一化在0-1之间是统计的概率分布,归一化在某个区间上是统计的坐标分布,在机器学习算法的数据预处理阶段,归一化也是非常重要的步骤。

第一个参数,InputArray类型的src。输入图像,即源图像,填Mat类的对象即可。
第二个参数,OutputArray类型的dst。函数调用后的运算结果存在这里,和源图片有一样的尺寸和类型。
第三个参数,double类型的 alpha。归一化后的最大值,有默认值1。
第四个参数,double类型的beta。归一化后的最大值,有默认值0。
第五个参数,int类型的 norm type。归一化类型,有NORM_INF、 NORM_L1、NORM_L2和 NORM_MINMAX等参数可选,有默认值 NORM_L2。

第六个参数,int类型的 dtype,有默认值-1。当此参数取负值时,输出矩阵和src有同样的类型,否则,它和src有同样的通道数,且此时图像深度为CV_MAT_DEPTH(dtype)。
第七个参数,InputArray类型的mask,可选的操作掩膜,有默认值noArray()。

void meanStdDev(InputArray src, OutputArray mean, OutputArray stddev, InputArray mask=noArray())

第一个参数src,输入数组,应该有1到4个通道,以便结果可以存储在Scalar中。

第二个参数mean,输出参数,计算的平均值。

第三个参数srddev,输出参数,计算标准偏差。

第四个参数mask,可选的操作掩膜,有默认值没有掩膜

meanStdDev计算结果是double类型的。
meanStdDev计算的均值和标准差都以Mat形式返回,这里返回的是1X1的矩阵。所以访问结果,要访问Mat的元素。

以上参考:毛星云《OpenCV3编程入门》、https://blog.csdn.net/billbliss/article/details/44178737


代码通过对图像进行对数变换和非线性变换增强图像暗处细节,适用于彩色图像及灰度图像,但灰度图像不要使用cvtColor函数转换,直接以三通道形式输入。

其中,对数变换使用函数为dst(i,j)=c*log(1+src(i,j)),src(i,j)为源图像(i,j)处的像素值,c为可调节的系数,dst(i,j)为经过对数变换后(i,j)处的像素值。

非线性变换的公式如下图:

#include "stdafx.h"
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/highgui/highgui.hpp"
#include <iostream>
#include <fstream>
#include <iterator>
#include <math.h>
using namespace cv;
using namespace std;//定义声明一些全局变量和函数
Mat src = imread("C:\\Users\\lenovo\\Desktop\\4.jpg");Mat hsv, lab, ycrcb;
Mat logdst, nonlinerdst;
Mat dst(src.size(), src.type(), Scalar::all(0));void LogTransform(cv::Mat& src, cv::Mat& dst, double c);//对数变换函数
void non_liner_tran(Mat& src, Mat& dst);//非线性变换函数
void balance(Mat& src, Mat& logdst, Mat&  nonlinerdst);//平衡图像函数int main(int argc, char** argv)
{system("color 02");/*//获取图像每个像素点的RGBHSVLabYCrCb的值,并写入文件中cvtColor(src, hsv, COLOR_BGR2HSV);cvtColor(src, lab, COLOR_BGR2Lab);cvtColor(src, ycrcb, COLOR_BGR2YCrCb);FILE *fp;fopen_s(&fp, "C:\\Users\\lenovo\\Desktop\\RGB数据.xls", "a");for(int i=0;i<src.rows;i++)for (int j = 0; j < src.cols; j++){fprintf(fp, "%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\n", src.at<Vec3b>(i, j)[2], src.at<Vec3b>(i, j)[1], src.at<Vec3b>(i, j)[0],hsv.at<Vec3b>(i, j)[0], hsv.at<Vec3b>(i, j)[1], hsv.at<Vec3b>(i, j)[2],lab.at<Vec3b>(i, j)[0], lab.at<Vec3b>(i, j)[1], lab.at<Vec3b>(i, j)[2], ycrcb.at<Vec3b>(i, j)[0], ycrcb.at<Vec3b>(i, j)[1], ycrcb.at<Vec3b>(i, j)[2]);}fclose(fp);*///对数变换LogTransform(src, logdst, 8);//非线性变换non_liner_tran(src, nonlinerdst);//平衡图像balance(src, logdst, nonlinerdst);//显示原图namedWindow("src", WINDOW_NORMAL);imshow("src", src);waitKey(0);return 0;
}/*对数变换方法1*(灰度图像和彩色图像都适用)*/
void LogTransform(cv::Mat& src, cv::Mat& dst, double c) {int nr = src.rows;int nc = src.cols*src.channels();src.copyTo(dst);dst.convertTo(dst, CV_64F);if (src.isContinuous() && dst.isContinuous()) {  //判断图像连续性nr = 1;nc = src.rows*src.cols*src.channels(); //行数*列数 * 通道数= 一维数组的个数}for (int i = 0; i < nr; i++) {const uchar* srcdata = src.ptr <uchar>(i);  //采用指针访问像素,获取第i行的首地址double* dstdata = dst.ptr <double>(i);for (int j = 0; j < nc; j++) {dstdata[j] = c*log(double(1.0 + srcdata[j])); //开始处理每个像素}}normalize(dst, dst, 0, 255, NORM_MINMAX); //经过对比拉升(将像素值归一化到0-255)得到最终的图像dst.convertTo(dst, CV_8U);  //转回无符号8位图像namedWindow("logdst", WINDOW_NORMAL);imshow("logdst", dst);
}void non_liner_tran(Mat& src, Mat& dst)
{src.copyTo(dst);//拆分图像,获取每个通道的平均像素值Mat channels[3];Mat mat_mean[3], mat_stddev[3];double vmean[3] = { 0 };split(src, channels);for (int n = 0; n < 3; n++){meanStdDev(channels[n], mat_mean[n], mat_stddev[n]);vmean[n] = mat_mean[n].at<double>(0, 0);}//非线性变换double m = 0, kv = 0, a = 1;for (int i = 0; i < src.rows; i++){for (int j = 0; j < src.cols; j++){for (int n = 0; n < 3; n++){if ((src.at<Vec3b>(i, j)[n] >= 0) && (src.at<Vec3b>(i, j)[n] <= 60)){kv = 7;}else if ((src.at<Vec3b>(i, j)[n] > 60) && (src.at<Vec3b>(i, j)[n] <= 200)){kv = (src.at<Vec3b>(i, j)[n] - 60) / 70 + 7;}else if ((src.at<Vec3b>(i, j)[n] > 200) && (src.at<Vec3b>(i, j)[n] <= 255)){kv = (src.at<Vec3b>(i, j)[n] - 200) / 55 + 9;}m = kv*(src.at<Vec3b>(i, j)[n] / (src.at<Vec3b>(i, j)[n] + a*vmean[n]));dst.at<Vec3b>(i, j)[n] = (int)(2 / (1 + exp(-m)) - 1) * 255 - src.at<Vec3b>(i, j)[n];}}}namedWindow("nonlinerdst", WINDOW_NORMAL);imshow("nonlinerdst", dst);
}void balance(Mat& src, Mat& logdst, Mat&  nonlinerdst)
{for (int i = 0; i < src.rows; i++){for (int j = 0; j < src.cols; j++){for (int n = 0; n < 3; n++){//将源图像、对数变换图像、非线性变换图像以一定比例合并dst.at<Vec3b>(i, j)[n] = (int)(0.05*logdst.at<Vec3b>(i, j)[n] +0.05*nonlinerdst.at<Vec3b>(i, j)[n] + 0.8*src.at<Vec3b>(i, j)[n]);}}}namedWindow("dst", WINDOW_NORMAL);imshow("dst", dst);//显示经直方图均衡化的图像
}

源图像:

    

对数变换后图像:

    

非线性变换后图像:

    

结果图:

    

参考文献:http://xueshu.baidu.com/usercenter/paper/show?paperid=864f24732d62a37915e71dbea2050010&site=xueshu_se&hitarticle=1

代码部分参考:http://www.pianshen.com/article/2960258309/

基于对数变换和非线性变换的图像增强(图像亮度调节)相关推荐

  1. [Python图像处理] 十六.图像的灰度非线性变换之对数变换、伽马变换

    该系列文章是讲解Python OpenCV图像处理知识,前期主要讲解图像入门.OpenCV基础用法,中期讲解图像处理的各种算法,包括图像锐化算子.图像增强技术.图像分割等,后期结合深度学习研究图像识别 ...

  2. [Python从零到壹] 四十五.图像增强及运算篇之图像灰度非线性变换详解

    欢迎大家来到"Python从零到壹",在这里我将分享约200篇Python系列文章,带大家一起去学习和玩耍,看看Python这个有趣的世界.所有文章都将结合案例.代码和作者的经验讲 ...

  3. OpenCV计算机视觉学习(3)——图像灰度线性变换与非线性变换(对数变换,伽马变换)

    人工智能学习离不开实践的验证,推荐大家可以多在FlyAI-AI竞赛服务平台多参加训练和竞赛,以此来提升自己的能力.FlyAI是为AI开发者提供数据竞赛并支持GPU离线训练的一站式服务平台.每周免费提供 ...

  4. python 视频 灰度 伽玛_Python 图像处理实战 | 图像的灰度非线性变换之对数变换、伽马变换...

    作者 | 杨秀璋 来源 | CSDN博客 责编 | 夕颜 头图 | 付费下载自视觉中国 出品 | CSDN(ID:CSDNnews) 本篇文章主要讲解非线性变换,使用自定义方法对图像进行灰度化处理,包 ...

  5. DataScience:深入探讨与分析机器学习中的数据处理之非线性变换—log对数变换、sigmoid/softmax变换

    DataScience:深入探讨与分析机器学习中的数据处理之非线性变换-log对数变换.sigmoid/softmax变换 目录 深入探讨与分析机器学习中的数据处理之非线性变换 log对数变换 sig ...

  6. Python 图像处理实战 | 图像的灰度非线性变换之对数变换、伽马变换

    作者 | 杨秀璋 来源 | CSDN博客 责编 | 夕颜 头图 | 付费下载自视觉中国 出品 | CSDN(ID:CSDNnews) 本篇文章主要讲解非线性变换,使用自定义方法对图像进行灰度化处理,包 ...

  7. 《OpenCv视觉之眼》Python图像处理二十一:Opencv图像处理之图像线性变换和非线性变换的方法及原理

    本专栏主要介绍如果通过OpenCv-Python进行图像处理,通过原理理解OpenCv-Python的函数处理原型,在具体情况中,针对不同的图像进行不同等级的.不同方法的处理,以达到对图像进行去噪.锐 ...

  8. 基于引导滤波的暗通道matlab,基于加权引导滤波的水下图像增强算法

    在水下环境中,由于水分子以及溶解的杂质对光线的吸收和散射作用,导致水下图像出现对比度低.噪声较大等严重的退化问题.这不仅降低了图像的整体视觉效果,而且给后续图像的自动处理和识别产生不利影响.因此,研究 ...

  9. 数字图像处理中对数变换与Gamma变换

    目录 1.对数变换 2.伽马变换 参考链接: 1.对数变换 图像的对数变换主要的作用是压缩动态范围,原因是对数曲线在像素值较低的区域斜率大,在像素值较高的区域斜率较小,所以图像经过对数变换后,较暗区域 ...

  10. 基于边缘检测与Hough变换的车道线检测

    基于边缘检测与Hough变换的车道线检测 第一章:绪论 1.1 研究意义及背景 高速公路的通行里程是一个国家发展水平的重要标志之一.高速公路具有车辆通行能力大.交通事故少.经济效益高的特点,它的不断发 ...

最新文章

  1. 控制src_【聚焦】仙知机器人基于SRC的激光SLAM自动叉车,满足各类场景需求
  2. C++赋值运算符重载
  3. 演练 网站的导航栏 0920
  4. TCP/IP:SCTP报文格式
  5. pr抖动插件_某宝价值135元的PS/AE/PR全套插件合集,一键安装,大神必备这一套就够了【第10期】...
  6. 常见面试算法:朴素贝叶斯
  7. MachineLearning Exercise 7 : K-means Clustering and Principle Component Analysis
  8. 办公技巧分享:如何编辑PDF文件内容
  9. 打开UG10 C语言错误,修复UG软件在win10中出现运行乱码的错误方法
  10. mac电脑谷歌浏览器全屏显示选项卡
  11. [160CRACKME]Chafe.2
  12. 使用canvas 绘制象棋棋盘
  13. 2018 ACM-ICPC, Syrian Collegiate Programming Contest I. Rise of the Robots 最小圆覆盖 模板
  14. FLy_buck 拓扑结构
  15. 泛癌种生物标志物介绍
  16. 让IE6/IE7/IE8浏览器支持CSS3属性
  17. 手机密码用计算机怎么解锁,手机忘记开机密码怎么办,有这四招1分钟就搞定...
  18. Wi-Fi easy Connect介绍
  19. AP微积分到底选AB还是BC?
  20. Microsoft Exchange 2003 pop3 0x800ccc92 0x800ccc90 处理

热门文章

  1. 查看git brach_Excel Go Brach – Excelebrations
  2. 机械臂速成小指南(五):末端执行器
  3. python制作中文词云图_Python3制作中文词云图
  4. 怎样给证件照换背景?教你在线给证件照换底色
  5. 基于深度学习的手写汉字识别
  6. b和kb的换算_KB换算
  7. 如何讲网页保存为pdf文件
  8. How Did Watson Answer? —— Typing Coerced Candidate Answer
  9. 修复软件图标不正常显示问题
  10. word操作 mathtype插入公式 表格