图像增强的目的:改善图像的视觉效果或使图像更适合于人或机器的分析处理。通过图像增强,可以减少图像噪声,提高目标与背景的对比度,也可以增强或抑制图像中的某些细节。

 ---------------------------------------------------------------------------------------------------

灰度变换:把原图像的像素灰度经过某个函数变换成新图像的灰度。可分为直线灰度变换法和直方图修正法。

直线灰度变换法:线性、分段线性、非线性变换。

直方图修正法:直方图均衡化、直方图规定化。

 ---------------------------------------------------------------------------------------------------

图像直方图:是对像素的某种属性(如灰度、颜色、梯度等)分布进行统计分析的重要手段。

灰度直方图:是灰度级的函数,它反映了图像中每一灰度级出现的次数或频率。

直方图均衡化:把原始图像的直方图变换为均匀分布的形式,从而增加图像灰度的动态范围,以达到增强图像对比度的效果。

经过均衡化处理的图像,其灰度级出现的概率相同,此时图像的熵最大,图像所包含的信息量最大。

【注意,离散后是每块区域的概率相等,均衡化后并不是条直线哦。】

  细节概念等省略......

---------------------------------------------------------------------------------------------------

 线性灰度增强、对数变换、指数变换、直方图均衡化。代码见下(代码略粗糙...)【ImageEnhance.cpp部分代码】

 //线性灰度增强
bool CImageEnhance::GrayLinearTransform(Mat &src, Mat &dst, uchar c, uchar d)
{
int b=,a=;
dst = src.clone();
int row = dst.rows, col = dst.cols * dst.channels();
uchar *cc = dst.data;
for(int i = ; i < row; ++i) {
for(int j = ; j < col; ++j) {
int val = *cc;
if(a > val) a = val;
if(b < val) b = val;
cc++;
}
}
cc = dst.data;
float k = float(d - c)/(b-a);
//CString c1; c1.Format(_T("a=%d,b=%d,c=%d,d=%d,k=%.2f\n"), a,b,c,d,k);MessageBox(c1);
for(int i = ; i < row; ++i) {
for(int j = ; j < col; ++j) {
int val = *cc;
int s = (int)(k*(val - a) + c);
*cc = s;
cc++;
}
}
return true;
}
//对数变换
bool CImageEnhance::GraynoLinearlog(Mat &src, Mat &dst) {
dst = src.clone();
int row = dst.rows, col = dst.cols * dst.channels();
uchar *cc = dst.data;
double k = / log10(256.0);
for(int i = ; i < row; ++i) {
for(int j = ; j < col; ++j) {
int val = *cc;
*cc = k * log10(1.0*(val + ));
cc++;
}
}
return true;
}
//指数变换
bool CImageEnhance::GraynoLinearindex(Mat &src, Mat &dst) {
dst = src.clone();
int row = dst.rows, col = dst.cols * dst.channels();
uchar *cc = dst.data;
double k = 1.0 / ;
for(int i = ; i < row; ++i) {
for(int j = ; j < col; ++j) {
int val = *cc;
*cc = k * val * val;
cc++;
}
}
return true;
} MatND CImageEnhance::getHist1(Mat& image)
{
MatND hist;
int channels[] = {};
int dims = ;
int histSize[] = {}; //直方图箱子的个数
float granges[] = {, };
const float *ranges[] = {granges}; //像素值范围
//计算直方图
calcHist(&image, , channels, Mat()/*不使用掩码*/, hist, dims/*这是一维的直方图*/, histSize, ranges);
return hist; //这里得到的hiat是256行一列的Mat
} //直方图均衡化
bool CImageEnhance::Equalize_hist(cv::Mat& src,cv::Mat& dst)
{
//CMFC_Test_lyyDlg pic;
MatND hist;
int channels[] = {};
int dims = ;
int histSize[] = {}; //直方图箱子的个数
float granges[] = {, };
const float *ranges[] = {granges}; //像素值范围
//计算直方图
Mat image = src.clone();
calcHist(&image, , channels, Mat()/*不使用掩码*/, hist, dims/*这是一维的直方图*/, histSize, ranges); //MatND hist = getHist1(src);//pic.getHist(dst);
float s[];
float p[]; cv::Mat lookup(cv::Size(, ), CV_8U);
int pixNum = src.cols * src.rows;//总像素个数
for (int i =; i <; i++) {
s[i] = hist.at<float>(i) / pixNum;
if (i ==) {
p[i] = s[i];
}
else {
p[i] = p[i -] + s[i];
}
}
for (int i =; i <; i++) {
lookup.at <uchar>(i) = static_cast<uchar>(p[i]*255.0);
} cv::LUT(src, lookup, dst);//创建矩阵,把一个像素值映射到另一个像素值
return true;
}

ImageEnhance.cpp

效果如下:

原图像:

线性灰度增强:我这里默认a和b表示原图像灰度值的最小与最大值。以下示例取c=255,d=0,效果为使图像负像,即黑变白,白变黑。

  

对数变换:(使图像的低灰度范围得以扩展而高灰度范围得以压缩,变换后的图像更符合人的视觉效果,因为人眼对高亮度的分辨率要求高于对低亮度的分辨率)

  

指数变换:(指数大于1。与对数变换相反。)

 直方图均衡化:

求原图像的灰度直方图代码:

 //获得直方图
MatND getHistt(Mat& image){
MatND hist;
int channels[] = {};
int dims = ;
int histSize[] = {}; //直方图箱子的个数
float granges[] = {, };
const float *ranges[] = {granges}; //像素值范围
//计算直方图
calcHist(&image, , channels, Mat()/*不使用掩码*/, hist, dims/*这是一维的直方图*/, histSize, ranges);
return hist; //这里得到的hiat是256行一列的Mat
}
// 将图像的直方图展示出来
Mat draw_Hist(Mat &inputImage)
{
cv::MatND hist = getHistt(inputImage);
Mat showImage(, , CV_8U,Scalar());
int i;
double maxValue = ;
minMaxLoc(hist, , &maxValue, , );
for(i = ; i < ; i++)
{
float value = hist.at<float>(i);
int intensity = saturate_cast<int>( - * (value/maxValue));
rectangle(showImage, Point(i, - ), Point((i+)-, intensity), Scalar());
}
//namedWindow("gray"); imshow("gray", showImage);
//cvMoveWindow("gray", 300, 300);
//waitKey(0);
return showImage;
}

 直方图显示:以下展示的 为以上的原图像以及直方图均衡化后的图像的  灰度直方图。

  

【OpenCV】图像增强---灰度变换、直方图均衡化的更多相关文章

  1. opencv:图像直方图均衡化

    // 直方图均衡化 Mat gray, dst; cvtColor(src, gray, COLOR_BGR2GRAY); equalizeHist(gray, dst); imshow(" ...

  2. opencv C++全局直方图均衡化

    cv::Mat histogramEqualization(cv::Mat img){ int rows=img.rows; int cols=img.cols; cv::Mat grayScale= ...

  3. opencv图像直方图均衡化及其原理

    直方图均衡化是什么有什么用 先说什么是直方图均衡化,通俗的说,以灰度图为例,原图的某一个像素为x,经过某个函数变为y.形成新的图.新的图的灰度值的分布是均匀的,这个过程就叫直方图均衡化. 图像直方图均 ...

  4. OpenCV计算机视觉学习(9)——图像直方图 & 直方图均衡化

    如果需要处理的原图及代码,请移步小编的GitHub地址 传送门:请点击我 如果点击有误:https://github.com/LeBron-Jian/ComputerVisionPractice 1, ...

  5. OpenCV图像增强算法实现(直方图均衡化、拉普拉斯、Log、Gamma)

    http://blog.csdn.net/dcrmg/article/details/53677739 1. 基于直方图均衡化的图像增强   直方图均衡化是通过调整图像的灰阶分布,使得在0~255灰阶 ...

  6. OpenCV——直方图均衡化(用于图像增强)

    #include <opencv2/opencv.hpp> #include <iostream> #include <math.h> using namespac ...

  7. 灰度图像--图像增强 直方图均衡化(Histogram equalization)

    灰度图像--图像增强 直方图均衡化(Histogram equalization) 转载请标明本文出处:http://blog.csdn.net/tonyshengtan,欢迎大家转载,发现博客被某些 ...

  8. 图像增强算法(直方图均衡化、拉普拉斯、Log、伽马变换)

    一.图像增强算法原理 图像增强算法常见于对图像的亮度.对比度.饱和度.色调等进行调节,增加其清晰度,减少噪点等.图像增强往往经过多个算法的组合,完成上述功能,比如图像去燥等同于低通滤波器,增加清晰度则 ...

  9. 直方图均衡化的 C++ 实现(基于 openCV)

    这是数字图像处理课的大作业,完成于 2013/06/17,需要调用 openCV 库,完整源码和报告如下: #include <cv.h> #include <highgui.h&g ...

随机推荐

  1. LOJ #6022. 重组病毒

    Description 支持以下操作 1.access一个点 2.问一个点上面的重链的个数 3.换根 , 并access原来的根 Solution 对于重链个数 , 我们在 \(access\) 的时 ...

  2. linux shell学习-1

    今天在使用$()这个命令的时候,如下,一直纳闷为何输出不是 "/usr": 一直在不断换着法子来试,原来是$()会将每个执行的命令单独隔开来的,及时是嵌套的命令,也会在执行逻辑上单 ...

  3. DataGridView 单元格自动填充

    在DataGridView单元格中,当输入指定字符时,自动完成填充. 通过 TextBox实现 AutoCompleteMode AutoCompleteMode.Suggest: AutoCompl ...

  4. JS实现图的创建和遍历

    图分为无向图和有向图 图的存储结构有邻接矩阵.邻接表.十字链表.邻接多重表这四种,最常用的是前两种 本篇主要是利用邻接矩阵实现无向图的创建和遍历(深度优先.广度优先),深度优先其实就是二叉树里的前序遍 ...

  5. Echarts 有点难度的柱状图

    本次的难点在于交叉传数据,又要把四组20个不同日期 显示上! 先看效果图: 数据传递方式:图 function func_echarts_2ba() { var echarts_2bar = echa ...

  6. 三、hive JavaAPI示例

    在上文中https://www.cnblogs.com/lay2017/p/9973370.html 我们通过hive shell去操作hive,本文我们以Java代码的示例去对hive执行加载数据和 ...

  7. 深入辨析jvm内存区域

    Java内存区域 Java虚拟机在执行Java程序的过程中会把它所管理的内存划分为若干个不同的数据区域: 程序计数器.虚拟机栈.本地方法栈.Java堆.方法区(运行时常量池).直接内存 程序计数器 当 ...

  8. pollard_rho 算法进行质因数分解

    //************************************************ //pollard_rho 算法进行质因数分解 //*********************** ...

  9. bzoj P3884 上帝与集合的正确用法

    Description   根据一些书上的记载,上帝的一次失败的创世经历是这样的: 第一天, 上帝创造了一个世界的基本元素,称做“元”. 第二天, 上帝创造了一个新的元素,称作“α”.“α”被定义为“ ...

  10. VS2008和VC6.0下使用pthread.h头文件

    原文:http://www.cppblog.com/liquidx/archive/2009/06/16/87811.html 要在windows环境下使用 #include <pthread. ...