原理详解:
假设输入图像为I,高为H、宽为W,I(r,c)代表I的第r行第c列的灰度值,将I中出现的最小灰度级记为Imin,最大灰度级记为Imax,即I(r,c)
ϵ
[
I
m
i
n
,
I
m
a
x
]
\epsilon[Imin,Imax]
ϵ[Imin,Imax],为使输出图像O的灰度级范围为[Omin,Omax],I(r,c)和O(r,c)做以下映射关系:
O(r,c)=
O
m
a
x
−
O
m
i
n
I
m
a
x
−
I
m
i
n
\frac{Omax-Omin}{Imax-Imin}
Imax−IminOmax−Omin(I(r,c)-Imin)+Omin
其中0
≤
\leq
≤r
≤
\leq
≤H,0
≤
\leq
≤c
≤
\leq
≤W, O(r,c)代表O的第r行第c列的灰度值。这个过程就是常称的直方图正规化。因为0
≤
\leq
≤
I
(
r
,
c
)
−
I
m
i
n
I
m
a
x
−
I
m
i
n
\frac{I(r,c)-Imin}{Imax-Imin}
Imax−IminI(r,c)−Imin
≤
\leq
≤
1
,
所
以
O
(
r
,
c
)
1, 所以O(r,c)
1,所以O(r,c)
ϵ
\epsilon
ϵ[Omin,Omax],一般令Omin=0,Omax=255。显然,直方图正规化是一种自动选取a和b的值的线性变换方法,其中:
a=
O
m
a
x
−
O
m
i
n
I
m
a
x
−
I
m
i
n
\frac{Omax-Omin}{Imax-Imin}
Imax−IminOmax−Omin,b=Omin-
O
m
a
x
−
O
m
i
n
I
m
a
x
−
I
m
i
n
\frac{Omax-Omin}{Imax-Imin}
Imax−IminOmax−Omin*Imin
在直方图正规化中最核心的步骤之一是计算原图中出现的最小灰度级和最大灰度级,OpenCV提供的函数:
void minMaxLoc(InputArray src, double* minVal, double* maxVal=0,Point* minLoc=0,Point* maxLoc=0,InputArray mask =noArray())
src 输入矩阵
minVal 最小值,double类型指针
maxVal 最大值,double类型指针
minLoc 最小值的位置索引,Point类型指针
maxLoc 最大值的位置索引,Point类型指针
利用minMaxLoc函数不仅可以计算出矩阵中的最大值和最小值,而且可以求出最大值的位置和最小值的位置,当然在使用过程中 如果只想得到最大值和最小值,则将其他的变量值设为NULL即可。例如:
minMaxLoc(src,&minVal,&maxValue,NULL,NULL)
只计算出最大值和最小值。
对于直方图正规化的c++实现,首先利用minMaxLoc函数计算出原图中的最大值和最小值,然后使用函数convertScaleAbs或者成员函数convertTo完成直方图正规化中的线性变换步骤:
//输入图像矩阵
Mat I = imread("E://image1.jpg",CV_LOAD_IMAGE_GRAYSCALE);
//找到I的最大值和最小值
double Imax,Imin;
minMaxLoc(I,&Imin,&Imax,NULL,NULL);
//设置Omin 和Omax
double Omin=0,Omax=255;
//计算a和b
double a =(Omax-Omin)/(Imax-Imin);
double b =Omin-a*Imin;
//线性变换
Mat 0;
convertScaleAbs(I,O,a,b);
//显示原图和直方图正规化的效果
imshow("I",I);
imshow("O",O);
对于图像直方图正规化的操作,OpenCV提供的函数normalize实现了类似的功能。
void normalize(InputArray src, OutputArray dst, double alpha=1,double beta =0, int norm_type = NORM_L2,int dtype=-1,InputArray mask = noArray())
在介绍这个函数的作用之前,首先需要了解矩阵范数的概念。矩阵src范数一般有三种形式:
(1)1-范数----------------计算矩阵中值的绝对值的和:
∣
∣
s
r
c
∣
∣
1
||src||_1
∣∣src∣∣1=
∑
r
=
1
M
\sum\limits_{r=1}^M
r=1∑M
∑
c
=
1
N
\sum\limits_{c=1}^N
c=1∑N|src(r,c)|
(2) 2-范数---------------计算矩阵中值的平方和的平方:
∣
∣
s
r
c
∣
∣
2
||src||_2
∣∣src∣∣2=
∑
r
=
1
M
∑
c
=
1
N
∣
s
r
c
(
r
,
c
)
∣
2
\sqrt{{\sum\limits_{r=1}^M}{\sum\limits_{c=1}^N}|src(r,c)|^2}
r=1∑Mc=1∑N∣src(r,c)∣2
(3) 3-范数---------------计算矩阵中值的绝对值的最大值:
∣
∣
s
r
c
∣
∣
∞
||src||_\infty
∣∣src∣∣∞=max|src(r,c)|
以输入矩阵:
src=
(
−
55
80
100
255
)
\begin{pmatrix}-55 & 80\\100 &255\end{pmatrix}
(−5510080255)为例,介绍函数normalize的计算输出参数dst的过程,
当参数norm_type=NORM_L1时,计算src的1-范数,即
∣
∣
s
r
c
∣
∣
1
||src||_1
∣∣src∣∣1=|-55|+|80|+|100|+|255|=490
dst的计算过程如下:
dst=alpha*
s
r
c
∣
∣
s
r
c
∣
∣
1
\frac{src}{||src||_1}
∣∣src∣∣1src+beta=
(
−
55
490
80
490
100
490
255
490
)
\begin{pmatrix}\frac{-55}{490} &\frac{80}{490}\\\frac{100}{490} &\frac{255}{490} \end{pmatrix}
(490−5549010049080490255)+beta
当norm_type=NORM_L2时,计算src的2-范数,即
∣
∣
s
r
c
∣
∣
2
||src||_2
∣∣src∣∣2=
∣
−
55
∣
2
+
∣
80
∣
2
+
∣
100
∣
2
+
∣
255
∣
2
\sqrt{|-55|^2+|80|^2+|100|^2+|255|^2}
∣−55∣2+∣80∣2+∣100∣2+∣255∣2=290.6
dst的计算过程如下:
dst=alpha*
s
r
c
∣
∣
s
r
c
∣
∣
2
\frac{src}{||src||_2}
∣∣src∣∣2src+beta=
(
−
55
290.6
80
290.6
100
290.6
255
290.6
)
\begin{pmatrix}\frac{-55}{290.6} &\frac{80}{290.6}\\\frac{100}{290.6} &\frac{255}{290.6} \end{pmatrix}
(290.6−55290.6100290.680290.6255)+beta
当norm_type=NORM_INF时,计算src的
∞
\infty
∞-范数,即
∣
∣
s
r
c
∣
∣
∞
||src||_\infty
∣∣src∣∣∞=max{|-55|,|80|,|100|,|255|}=255
dst的计算过程如下:
dst=alpha*
s
r
c
∣
∣
s
r
c
∣
∣
2
\frac{src}{||src||_2}
∣∣src∣∣2src+beta=
(
−
55
255
255
290.6
100
255
255
255
)
\begin{pmatrix}\frac{-55}{255} &\frac{255}{290.6}\\\frac{100}{255} &\frac{255}{255} \end{pmatrix}
(255−55255100290.6255255255)+beta
当norm_type=NORM_MINMAX时,首先计算src的最小值
s
r
c
m
i
n
src_{min}
srcmin=-55,src的最大值
s
r
c
m
a
x
src_{max}
srcmax=255,dst的每一个值是按照以下规则计算的:
dst(r,c)=alpha*
s
r
c
(
r
,
c
)
−
s
r
c
m
i
n
s
r
c
m
a
x
−
s
r
c
m
i
n
\frac{src(r,c)-src_{min}}{src_{max}-src{min}}
srcmax−srcminsrc(r,c)−srcmin+beta
所以
dst=
(
−
55
−
(
−
55
)
255
−
(
−
55
)
80
−
(
−
55
)
255
−
(
−
55
)
100
−
(
−
50
)
255
−
(
−
55
)
255
−
(
−
55
)
255
−
(
−
55
)
)
\begin{pmatrix}{\frac{-55-(-55)}{255-(-55)}}&\frac{80-(-55)}{255-(-55)}\\\frac{100-(-50)}{255-(-55)} &\frac{255-(-55)}{255-(-55)} \end{pmatrix}
(255−(−55)−55−(−55)255−(−55)100−(−50)255−(−55)80−(−55)255−(−55)255−(−55))+beta
使用函数normalize对图像进行对比度增强时,经常令参数norm_type=NORM_MIN-MAX,仔细观察会发现和直方图正规化原理详解中提到的计算方法是相同的,参数alpha相当于Omax,参数beta相当于Omin。注意,使用normalize可以处理多通道矩阵,分别对每一个通道进行正规化操作。
#include<opencv2/opencv.hpp>
using namespace cv;
int main()
{
Mat src = imread("E:/image4.jpg");
if(!src.data)
return -1;
//直方图正规化
Mat dst;
normalize(src,dst,255,0,NORM_MINMAX,CV_8U);
imshow("直方图正规化",dst);
waitKey(0);
return 0;
}