【OpenCV】图像增强---灰度变换、直方图均衡化
图像增强的目的:改善图像的视觉效果或使图像更适合于人或机器的分析处理。通过图像增强,可以减少图像噪声,提高目标与背景的对比度,也可以增强或抑制图像中的某些细节。
---------------------------------------------------------------------------------------------------
灰度变换:把原图像的像素灰度经过某个函数变换成新图像的灰度。可分为直线灰度变换法和直方图修正法。
直线灰度变换法:线性、分段线性、非线性变换。
直方图修正法:直方图均衡化、直方图规定化。
---------------------------------------------------------------------------------------------------
图像直方图:是对像素的某种属性(如灰度、颜色、梯度等)分布进行统计分析的重要手段。
灰度直方图:是灰度级的函数,它反映了图像中每一灰度级出现的次数或频率。
直方图均衡化:把原始图像的直方图变换为均匀分布的形式,从而增加图像灰度的动态范围,以达到增强图像对比度的效果。
经过均衡化处理的图像,其灰度级出现的概率相同,此时图像的熵最大,图像所包含的信息量最大。
【注意,离散后是每块区域的概率相等,均衡化后并不是条直线哦。】
细节概念等省略......
---------------------------------------------------------------------------------------------------
线性灰度增强、对数变换、指数变换、直方图均衡化。代码见下(代码略粗糙...)【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】图像增强---灰度变换、直方图均衡化的更多相关文章
- opencv:图像直方图均衡化
// 直方图均衡化 Mat gray, dst; cvtColor(src, gray, COLOR_BGR2GRAY); equalizeHist(gray, dst); imshow(" ...
- opencv C++全局直方图均衡化
cv::Mat histogramEqualization(cv::Mat img){ int rows=img.rows; int cols=img.cols; cv::Mat grayScale= ...
- opencv图像直方图均衡化及其原理
直方图均衡化是什么有什么用 先说什么是直方图均衡化,通俗的说,以灰度图为例,原图的某一个像素为x,经过某个函数变为y.形成新的图.新的图的灰度值的分布是均匀的,这个过程就叫直方图均衡化. 图像直方图均 ...
- OpenCV计算机视觉学习(9)——图像直方图 & 直方图均衡化
如果需要处理的原图及代码,请移步小编的GitHub地址 传送门:请点击我 如果点击有误:https://github.com/LeBron-Jian/ComputerVisionPractice 1, ...
- OpenCV图像增强算法实现(直方图均衡化、拉普拉斯、Log、Gamma)
http://blog.csdn.net/dcrmg/article/details/53677739 1. 基于直方图均衡化的图像增强 直方图均衡化是通过调整图像的灰阶分布,使得在0~255灰阶 ...
- OpenCV——直方图均衡化(用于图像增强)
#include <opencv2/opencv.hpp> #include <iostream> #include <math.h> using namespac ...
- 灰度图像--图像增强 直方图均衡化(Histogram equalization)
灰度图像--图像增强 直方图均衡化(Histogram equalization) 转载请标明本文出处:http://blog.csdn.net/tonyshengtan,欢迎大家转载,发现博客被某些 ...
- 图像增强算法(直方图均衡化、拉普拉斯、Log、伽马变换)
一.图像增强算法原理 图像增强算法常见于对图像的亮度.对比度.饱和度.色调等进行调节,增加其清晰度,减少噪点等.图像增强往往经过多个算法的组合,完成上述功能,比如图像去燥等同于低通滤波器,增加清晰度则 ...
- 直方图均衡化的 C++ 实现(基于 openCV)
这是数字图像处理课的大作业,完成于 2013/06/17,需要调用 openCV 库,完整源码和报告如下: #include <cv.h> #include <highgui.h&g ...
随机推荐
- ADO MFC SQL2000
对于初学VC的朋友来说,连接数据库其实是一件不容易的事情.记得我当时为了与数据库连接上,找了好多资料,上网看了好多文章,都没有解决这个问题.后 来,有个网友帮我解决了,我再次表示感谢.为了后来VC初学 ...
- [C语言] 数据结构-预备知识结构体
结构体 为什么出现结构体 为了表示一些复杂的数据,而普通的基本类型变量无法满足需求 什么叫结构体 结构体是用户根据实际需要自己定义的复合数据类型 如何使用结构体 1.两种方式 一般使用结构体指针的形 ...
- 二、多线程之Atomic包
一.简介 1.原子操作 我们在使用变量的时候,经常会出现资源竞争的情况,为了保证变量安全,我们就会对对应的方法添加"synchronized"同步锁来达到目的,以保证线程安全. 而 ...
- JDBC的DAO设计模式
在javaEE中,java类的属性通过getter和setter来定义,get(或set)方法去除get(set)后,首字母小写即为Java类的属性.操作java类的属性有一个工具包,BeanUtil ...
- HBase—列族数据库的术语
1. 列族数据库的基本组件 键空间,行键,列,列族 2. 什么是键空间 keyspace? 键空间 keyspace 是列族数据库的顶级数据结构,它在逻辑上能够容纳列族,行键以及与之相关的其他数据结构 ...
- Java 的 委托 是什么?
前言:在学习设计模式时,发现书中有多次提到委托二字,所以经过网上搜索得到结果,并自己写了个小小的例子. 什么是委托? 委托模式是软件设计模式中的一项基本技巧.在委托模式中,有两个对象参与处理同一个请求 ...
- String拾遗
简介: String作为日常最常用的类,还是有必要对其中的细节做一些了解的,这篇就结合源码来看看这个常用的类. 一. 总述 类图如下: 从图中可以看到String是实现了 java.io.Serial ...
- python学习之老男孩python全栈第九期_day017知识点总结——初识递归、算法
一. 递归函数 如果一个函数在内部调用自身本身,这个函数就是递归函数. 最大递归深度默认是997 -- python从内存角度出发做得限制(而不是程序真的报错),最大深度可以修改 def func(n ...
- 有关动态规划(主要是数位DP)的一点讨论
动态规划(dynamic programming)是运筹学的一个分支,是求解决策过程(decision process)最优化的数学方法.20世纪50年代初美国数学家在研究多阶段决策过程的优化问题时, ...
- Swiper轮播图
今天咱们来说一下.Swiper轮播图. 超级简单的: 翠花,上代码: <!DOCTYPE html> <html lang="en"> < ...