chapter2 空间域图像增强(点增强)
1.图像增强的基本概念
在不考虑图像降质的情况下,通过经验和试探的方法,把图像感兴趣的部分进行选择性突出,而把不在意的部分进行压制,从而得到我们想要的信息。
- 目的: 改善视觉效果,便于人眼或者机器进行分析和辨别
- 分类: 空间域法: 灰度变换 , 直方图均匀化 ,伪彩色处理(没学)等
频域法:高,低通滤波等
2.空域增强
1.什么是空域增强
- 在空间域中,通过
线性
或非线性
变换来增强构成图像的像素.方法是直接对这些像素进行操作的过程。- 公式:g(x,y)=T[f(x,y)] ,表示为通过对像素f(x,y)进行变换,从而得到我们想要的效果像素g(x,y),因此最重要的就是能够知道这个变化函数T是什么
- 常见的T包括:对数,幂函数,进行图像反转(最大灰度-像素)
2.空域增强的方式
- 点处理:作用于单个像素的处理方法
- 模板处理 : 作用于像素邻域的处理方法。
3常见T的应用类型
1.反转变换
适用于增强嵌入于图像暗色区域的白色或灰色细节,从而突出一些暗色区域的特征
2.对数变换
作用:将图像的低灰度值部分扩展,显示出低灰度部分更多的细节,将其高灰度值部分压缩,减少高灰度值部分的细节,从而达到强调图像低灰度部分的目的
公式:s=clogv+1(r*v+1)
, 其中c是常数,v+1是底数,r在[0,1],加一的目的是使得log函数左移动避免小于0。
函数图像如下:
可以看到当V=200时,当r=0.4,s>0.8,可以知道其使得区域增强(变亮),但是对于亮的区域变暗了。
3.幂次变换
作用:幂次变换通过幂次曲线中的γ值把输入的窄带值映射到宽带输出值。
公式:S =cr^(x)
其中c是常数。r是输入灰度
函数图像如下:
可以通过图像看出其特点
4.灰度直方图介绍
1.什么是直方图
直方图是图像灰度级与出现该灰度概率之间的关系的图形,x轴是灰度级,y轴是概率(图像中该灰度级出现的个数)。因此灰度图是反映一幅图像中的灰度级与出现这种灰度的概率之间的关系的图形,只反映概率,不反映像素位置关系,因此相同的直方图,可能图像不一样。
2.直方图的计算定义
5.直方图均匀化
直方图均衡化是一种增强图像对比度的方法,其主要思想是将一副图像的直方图分布变成近似均匀分布,从而增强图像的对比度.(在通信原理我们知道让事件出现的概率一样的时候,总信息量最大,熵也是是最大的,即对比度最大),使用对于图像而谈,图像如果通过T函数,其直方图能够变换成均匀的,那么其对比度就是最大的)
其中T®要满足:
- 在0≤r≤1区间内,T®单值单调增加;
- 对于0≤r≤1,有0≤T®≤1;
简单的推导:
可以理解 T 的作用是将输入图像里面像素点灰度为a的全部变为b,
∫
0
a
p
(
r
)
d
r
\int_0^a p(r) {\rm d}r
∫0ap(r)dr =
∫
0
b
p
(
s
)
d
s
\int_0^b p(s) {\rm d}s
∫0bp(s)ds
p(s)ds的意义是区间(s,s+ds)上的概率
p®dr的意义是区间(r,r+dr)上的概率
显然两者是相等的,有p(r)dr=p(s)ds
,那么有ds/dr =dT(r)/dr = p(r)/p(s)
,如果p(s)
是均匀分布那么p(s)=1/255
,那么有255p(r) =dT(r)/d(r)
,则T®=255*
∫
0
r
p
(
x
)
d
x
\int_0^r p(x) {\rm d}x
∫0rp(x)dx,如果是离散,就用离散的形式表示。这就是均匀化的基本推导
3.作业
1.编写代码,实现Log变换和实现gamma变换
# include<iostream>
# include<opencv2/opencv.hpp>
# include<math.h>
using namespace std;
using namespace cv;
int main()
{
Mat image = imread("D:/1.jpg", 1);
if (image.empty())
{
cout << "未找到文件,请检查文件目录" << endl;
return -1;
};
Mat originalgray_image;
cvtColor(image, originalgray_image, COLOR_BGR2GRAY); //灰度图
imshow("gray_image", originalgray_image); //显示原图的灰度图
Mat gray_image;
gray_image = originalgray_image;
int height = gray_image.rows;
int width = gray_image.cols;
float fVal = 0.0;
float fgammar = 0.2;
for ( int row = 0; row < height; ++row)
{
for (int col = 0; col < width; ++col)
{
//实现log运算
fVal = (gray_image.at<uchar>(row, col) + 1) / 255.0; //归一化
fVal = log10(fVal*(10-1) + 1);
if(fVal > 1)
{
fVal = 1;
}
fVal = fVal * 255;
gray_image.at<uchar>(row, col) =fVal;
/*实现grammer运算
fVal = (gray_image.at<uchar>(row, col) + 1) / 255.0; //归一化
fVal = pow(fVal,fgammar);
if (fVal > 1)
{
fVal = 1;
}
fVal = fVal * 255;
gray_image.at<uchar>(row, col) = fVal;
*/
}
}
imshow("log_image", gray_image); //显示log变换的原图的灰度图
waitKey(0);
return 0;
}
2.使用函数实现直方图均匀化
// 1. 使用函数实现直方图均匀化
// 2. 函数: void equalizeHist(InputArray src,OutputArray dst)
# include<opencv2/opencv.hpp>
# include<ostream>
using namespace std;
using namespace cv;
int main()
{
Mat image = imread("D:/Vistual studio editor/Code/数字图像处理/2.图像增强/直方图/直方图/image.jpg", 0);
if (image.empty())
{
cout << "文件不存在" << endl;
return 1;
}
//namedWindow("image",WINDOW_AUTOSIZE);
imshow("image", image);
waitKey(0);
Mat mEnhanced;
equalizeHist(image, mEnhanced);
imshow("menhanced", mEnhanced);
waitKey(0);
return 0;
}
3.实现直方图计算
# include<opencv2/opencv.hpp>
# include<ostream>
using namespace std;
using namespace cv;
int main()
{
Mat image = imread("D:/Vistual studio editor/Code/数字图像处理/2.图像增强/直方图/直方图/image.jpg", 0);
if (image.empty())
{
cout << "文件不存在" << endl;
return 1;
}
//namedWindow("image",WINDOW_AUTOSIZE);
imshow("image", image);
int hist_number[256] = { 0 };
for (int row = 0 ; row < image.rows; ++row)
{
for (int col = 0; col < image.cols; ++col)
{
int image_number = image.at<uchar>(row, col);
hist_number[image_number] += 1;
}
}
for (int number = 0; number < 256; ++number)
{
cout << number << " : " << hist_number[number] << endl;
}
waitKey(0);
return 0;
}
4.函数进行直方图计算,和绘制
#include<opencv2/core/core.hpp>
#include<opencv2/highgui/highgui.hpp>
#include<opencv2/imgproc/imgproc.hpp>
#include<opencv2/opencv.hpp>
#include<iostream>
using namespace std;
using namespace cv;
int main()
{
//加载图像
Mat image;
image = imread("D:/图片/壁纸/动漫/1.jpg", 0);//生成单通道,灰度图
//判断是否为空
if (image.empty())
{
cerr << "" << endl;
return -1;
}
imshow("src", image);
// 2. 函数 :CV_EXPORTS void calcHist( const Mat* images,int nimages,const int* channels,InputArray mask,OutputArray hist,int dims,const int* histSize,const float** ranges,bool uniform = true,bool accumulate = false );
int image_number = 1;
int channels[] = { 0 };
Mat histA;
int dims = 1;
int histsize[] = { 256 };
float midrange[] = { 0,255 };
const float* ranges[] = { midrange };
calcHist(&image, image_number, channels, Mat(), histA, dims, histsize, ranges);
double min_number;
double mix_number;
minMaxLoc(histA, &min_number, &mix_number, 0, 0);
int hist_number = histA.rows; //255
Mat background(hist_number, hist_number, CV_8UC3, Scalar(255, 255, 255)); //白色
Scalar lines_color(172, 172, 150);
int hpt = static_cast<int>(0.9 * hist_number);
for (int h = 0; h < hist_number; h++)
{
float bin = histA.at<float>(h);
cout << h << ":" << bin << endl;
int intensity = static_cast<int>(bin*hist_number / mix_number);
line(background, Point(h, hist_number), Point(h, hist_number - intensity), lines_color);
}
imshow("ddd", background);
waitKey(0);
return 0;
}
4.参考资料
- 直方图均衡化的数学原理 :
https://blog.csdn.net/superjunenaruto/article/details/52431941 - line()函数来对直线的绘制 :
https://blog.csdn.net/hk121/article/details/81085213