Mat calcGrayHist(const Mat & image){
Mat histogram = Mat::zeros(Size(256,1), CV_32SC1);//存储256个灰度级的像素个数int rows = image.rows;int cols = image.cols;//图像的宽和高//计算灰度级个数for(int r =0; r < rows; r++){
for(int c =0; c < cols; c++){
int index =int(image.at<uchar>(r,c));
histogram.at<int>(0,index)+=1;}}return histogram;}
2.线性变换
假设输入图像为I,宽为W、高为H,输出图像为O,图像线性变换为: O ( r , c ) = a ∗ I ( r , c ) + b , 0 ≤ r < H , 0 ≤ c < W O(r,c)=a*I(r,c)+b, 0 \leq r < H, 0 \leq c < W O(r,c)=a∗I(r,c)+b,0≤r<H,0≤c<W
//examples
Mat I =(Mat_<uchar>(2,2)<<0,200,23,4);
Mat O;
I.convertTo(O, CV_8UC1,2.0,0);//方法1//输出结果为[[0,255],[46,8]]
Mat O =3.5*I;//方法2//输出结果为[[0,255],[80,14]]convertScaleAbs(I, O,2.0,0);//方法3//输出结果为[[0,255],[46,8]]
假设输入图像为I,宽为W、高为H,I(r,c)代表I第r行第c列灰度值,将I的最小灰度级记为Imin,最大灰度级记为Imax,为使输出图像O的灰度级范围为[Omin,Omax],做如下映射: O ( r , c ) = O m a x − O m i n I m a x − I m i n ( I ( r , c ) − I m i n ) + O m i n O(r,c)=\frac{Omax-Omin}{Imax-Imin}(I(r,c)-Imin)+Omin O(r,c)=Imax−IminOmax−Omin(I(r,c)−Imin)+Omin 0 ≤ r < H , 0 ≤ c < W 0 \leq r < H, 0 \leq c < W 0≤r<H,0≤c<W 其中, a = O m a x − O m i n I m a x − I m i n , b = O m i n − O m a x − O m i n I m a x − I m i n ∗ I m i n a=\frac{Omax-Omin}{Imax-Imin},b=Omin-\frac{Omax-Omin}{Imax-Imin}*Imin a=Imax−IminOmax−Omin,b=Omin−Imax−IminOmax−Omin∗Imin
//exampls
Mat I =imread(argv[1], LOAD_IMAGE_GRAYSCALE);//输入图像矩阵double Imax, Imin;minMaxLoc(I,&Imin,&Imax,NULL,NULL);//找到最大、最小值double Omin =0, Omax =255;double a =(Omax - Omin)/(Imax - Imin);double b = Omin - a * Imin;//计算a和b
Mat O;convertScaleAbs(I, O, a, b);//线性变换
正规化函数
首先了解范数的概念
1范数:计算矩阵中值的绝对值的和 ∣ ∣ s r c ∣ ∣ 1 = ∑ r = 1 M ∑ c = 1 N ∣ s r c ( r , c ) ∣ ||src||_1=\sum_{r=1}^{M}\sum_{c=1}^{N}|src(r,c)| ∣∣src∣∣1=∑r=1M∑c=1N∣src(r,c)∣
2范数:计算矩阵中值的平方和的开方 ∣ ∣ s r c ∣ ∣ 2 = ∑ r = 1 M ∑ c = 1 N ∣ s r c ( r , c ) ∣ 2 ||src||_2=\sqrt{\sum_{r=1}^{M}\sum_{c=1}^{N}|src(r,c)|^2} ∣∣src∣∣2=∑r=1M∑c=1N∣src(r,c)∣2
∞范数:计算矩阵中值的平方和的开方 ∣ ∣ s r c ∣ ∣ ∞ = m a x ∣ s r c ( r , c ) ∣ ||src||_∞=max|src(r,c)| ∣∣src∣∣∞=max∣src(r,c)∣
当参数norm_type=NORM_L1: d s t = a l p h a ∗ s r c ∣ ∣ s r c ∣ ∣ 1 + b e t a dst=alpha*\frac{src}{||src||_1}+beta dst=alpha∗∣∣src∣∣1src+beta
当参数norm_type=NORM_L2: d s t = a l p h a ∗ s r c ∣ ∣ s r c ∣ ∣ 2 + b e t a dst=alpha*\frac{src}{||src||_2}+beta dst=alpha∗∣∣src∣∣2src+beta
当参数norm_type=NORM_INF:
d s t = a l p h a ∗ s r c ∣ ∣ s r c ∣ ∣ ∞ + b e t a dst=alpha*\frac{src}{||src||_∞}+beta dst=alpha∗∣∣src∣∣∞src+beta
当参数norm_type=NORM_MINMAX:
d s t = a l p h a ∗ s r c ( r , c ) − s r c m i n s r c m a x − s r c m i n + b e t a dst=alpha*\frac{src(r,c)-src_{min}}{src_{max}-src_{min}}+beta dst=alpha∗srcmax−srcminsrc(r,c)−srcmin+beta
4.伽马变换
伽马变换是一种非线性变换。假设输入图像为I,宽为W、高为H,首先将其灰度值归一化到[0,1]范围, O ( r , c ) = I ( r , c ) γ , 0 ≤ r < H , 0 ≤ c < W O(r,c)=I(r,c)^γ,0 \leq r < H, 0 \leq c < W O(r,c)=I(r,c)γ,0≤r<H,0≤c<W即为伽马变换。
假设输入图像为I,宽为W、高为H, h i s t I hist_I histI代表I的灰度直方图, h i s t I ( k ) hist_I(k) histI(k)代表灰度值等于k的像素点个数, k ∈ [ 0 , 255 ] k\in[0,255] k∈[0,255]。全局直方图均衡化是对I进行改变,使得输出图像O的 h i s t O hist_O histO每一个灰度级像素点相等,即 h i s t O ( k ) ≈ H ∗ W 256 hist_O(k) \approx \frac{H*W}{256} histO(k)≈256H∗W 那么对于任意灰度级p, 0 ≤ p < 255 0 \leq p < 255 0≤p<255,总能找到q, 0 ≤ q < 255 0 \leq q < 255 0≤q<255,使得 ∑ k = 0 p h i s t I ( k ) = ∑ k = 0 q h i s t O ( k ) \sum_{k=0}^{p}hist_I(k)=\sum_{k=0}^{q}hist_O(k) ∑k=0phistI(k)=∑k=0qhistO(k), ∑ k = 0 p h i s t I ( k ) \sum_{k=0}^{p}hist_I(k) ∑k=0phistI(k)和 ∑ k = 0 q h i s t O ( k ) \sum_{k=0}^{q}hist_O(k) ∑k=0qhistO(k)成为I和O 的累加直方图。又因为 h i s t O ( k ) ≈ H ∗ W 256 hist_O(k) \approx \frac{H*W}{256} histO(k)≈256H∗W, ∑ k = 0 p h i s t I ( k ) = ( q + 1 ) H ∗ W 256 \sum_{k=0}^{p}hist_I(k)=(q+1)\frac{H*W}{256} ∑k=0phistI(k)=(q+1)256H∗W 令 O ( r , c ) = ∑ k = 0 I ( r , c ) h i s t I ( k ) H ∗ W ∗ 256 − 1 O(r,c)=\frac{\sum_{k=0}^{I(r,c)}hist_I(k)}{H*W}*256-1 O(r,c)=H∗W∑k=0I(r,c)histI(k)∗256−1
Mat equalHist(Mat image){
CV_Assert(image.type()== CV_8UC1);int rows = image.rows;int cols = image.cols;//1.计算图像灰度直方图
Mat grayHist =calaGrayHist(image);//2.计算累加灰度直方图
Mat zeroCumuMoment = Mat::Zeros(Size(256,1),CV_32SC1);for(int p =0; p <256; p++){
if(P ==0)
zeroCumuMoment.at<int>(0,p)= grayHist.at<int>(0,0);else
zeroCumuMoment.at<int>(0,p)= zeroCumuMoment.at<int>(0,p-1)+grayHist.at<int>(0,p);}//3.根据累加直方图获得映射关系
Mat outPut_q = Mat::Zeros(Size(256,1),CV_8UC1);float cofficient =256.0/(rows*cols);for(int p =0; p <256; p++){
float q = cofficient * zeroCumuMoment.at<int>(0,p)-1;if(q >=0)
outPut_q.at<uchar>(0,p)=uchar(floor(q));else
outPut_q.at<uchar>(0,p)=0;}//4.得到直方图均衡化后的图像
Mat equalHistImage = Mat::zeros(image.size(),CV_8UC1);for(int r =0; r < rows; r++){
for(int c =0; c < cols; c++){
int p = image.at<uchar>(r,c);
equalHistImage .at<uchar>(r,c)= outPut_q.at<uchar>(0,p);}}return equalHistImage;}