目录
直方图均衡化
图像直方图
直方图的计算和绘制
直方图对比
反向投影
模板匹配
直方图均衡化是通过拉伸像素强度分布范围来增强图像对比度的一种方法
应用场景:
应用于图像增强处理。(灰度转换)
void equalizeHist(InputArray src, OutputArray dst)
参数1,输入图像,需为8位单通道的图像。
参数2,运算结果,需和源图片有一样的尺寸和类型。
图像进行直方图均衡化的步骤:
1)计算输入图像的直方图H。
2)进行直方图归一化,直方图的组距的和为255。
3)计算直方图积分:
4)以H'作为查询表进行图像变换:
equalizeHist()函数实现的灰度直方图均衡化算法,就是把直方图的每个灰度级进行归一化处理,求每种灰度的累积分布,得到一个映射的灰度映射表,然后根据相应的灰度值来修正原图中的每个像素。
在统计学中,直方图(Histogram)是一种对数据分布情况的图形表示,是一种二维统计图表,它的两个坐标分别是统计样本和该样本对应的某个属性的度量。
图像直方图(Image Histogram)是用于表示数字图像中亮度分布的直方图,标绘了图像中每个亮度值的像素数。图像直方图来实现图像的二值化。
calcHist() 函数 用于计算一 个或者多个阵列的直方图。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 )
参数1,const Mat*类型的images,输入的数组(或数组集),需为相同的深度(CV_8U
或CV_32F)和相同的尺寸。
参数2,int类型的nimages,输入数组的个数,第一个参数中存放了多少张“图像”,
有几个原数组。
参数3,const int*类型的channels,需要统计的通道索引。第一个数组通道从0 到
images[0].channels() - 1,而第二个数组通道从images[0].channels()计算到
images[0].channels() + images[ 1 ].channels() - 1。
参数4,InputArray类型的mask,可选的操作掩码。如果此掩码不为空,那么它必须为8位,
并且与images[i]有同样大小的尺寸。这里的非零掩码元素用于标记出统计直方图的数
组元素数据。
参数5,OutputArray类型的 hist,输出的目标直方图,一个二维数组。
参数6,int类型的dims,需要计算的直方图的维度,必须是正数,且不大于
CV_MAX_DIMS。
参数7,const int*类型的 histSize,存放每个维度的直方图尺寸的数组。
参数8,const float**类型的ranges,表示每一个维度数组(第六个参数dims)的每一维的
边界阵列,可以理解为每一维数值的取值范围。
参数9,bool类型的uniform,指示直方图是否均匀的标识符,有默认值 true。
参数10,bool类型的 accumulate,累计标识符,默认值 false。若其为true,直方图在配置阶
段不会被清零。此功能主要是允许从多个阵列中计算单个直方图,或者用于在特定
的时间更新直方图。
找寻最值: minMaxLoc()函数 找到全局最大值和最小值。
void minMaxLoc(InputArray src, double* minval, double* maxVal = 0, Point* minLoc=0, Point* maxLoc=0, InputArray mask = noArray())
参数1,InputArray类型的src,输入的单通道阵列。
参数2,double*类型的minVal,返回最小值的指针。若无须返回,此值置为NULL。
参数3,double*类型的maxVal,返回的最大值的指针。若无须返回,此值置为NULL。
参数4,Point*类型的minLoc,返回最小位置的指针(二维情况下)。
若无须返回,此值置为NULL。
参数5,Point*类型的maxLoc,返回最大位置的指针(二维情况下)。
若无须返回,此值置为NULL。
参数6,InputArray类型的 mask,用于选择子阵列的可选掩膜。
-------------------------------------------------------------------------------------------------------------------------
绘制H--S直方图:如何计算彩色图像的色调(Hue),饱和度(Saturation)二维直方图。
//载入源图,转化为HSV颜色模型 Mat srcImage, hsvImage; srcImage=imread ("1.jpg" ); cvtColor (srcImage , hsvImage, COLOR_BGR2HSV) ; //将色调量化为30个等级,将饱和度量化为32个等级 int hueBinNum = 30; //色调的直方图直条数量 int saturationBinNum = 32; //饱和度的直方图直条数量 int histsize[ ] ={ hueBinNum, saturationBinNum } ; //定义色调的变化范围为0到179 float hueRanges[ ]= { 0, 180 }; //定义饱和度的变化范围为0(黑、白、灰)到255(纯光谱颜色) float saturationRanges [ ] = { 0, 256 }; const float* ranges[ ]= { hueRanges, saturationRanges }; MatND dstHist; //calcHist 函数中将计算第0通道和第1通道的直方图 int channels [ ]= { 0, 1 }; //进行直方图计算 calcHist(&hsvImage , // 输入的数组 1, // 数组个数为1 channels, // 通道索引 Mat (), // 不使用掩膜 dstHist, // 输出的目标直方图 2, // 需要计算的直方图的维度为2 histsize, // 存放每个维度的直方图尺寸的数组 ranges, // 每一维数值的取值范围数组 true, // 指示直方图是否均匀的标识符,true表示均匀的直方图 false ); // 累计标识符,false表示直方图在配置阶段会被清零 //为绘制直方图准备参数 double maxValue = 0; //最大值 //查找数组和子数组的全局最小值和最大值存入maxvalue中 minMaxLoc(dstHist, 0, &maxValue, 0, 0); int scale = 10; Mat histImg = Mat::zeros(saturationBinNum * scale, hueBinNum * 10, CV_8UC3); //进行直方图绘制 for( int hue = 0; hue < hueBinNum; hue++ ) { for ( int saturation = 0; saturation < saturationBinNum; saturation++ ) { float binValue = dstHist.at
(hue, saturation); //直方图直条的值 int intensity = cvRound(binValue * 255 / maxValue) ; //强度 //正式进行绘制 rectangle(histImg, Point(hue*scale, saturation*scale), Point((hue + 1) * scale - 1, (saturation + 1) * scale - 1), Scalar::all(intensity), FILLED ); } } 计算并绘制图像一维直方图
//载入原图 Mat srcImage = imread ( "1.jpg", 0); MatND dstHist; //在cv中用cvHistogram *hist = cvcreateHist int dims = 1; float hranges [ ] = {0, 255}; const float *ranges[ ] = { hranges } ; //这里需要为const类型 int size = 256; int channels = 0; //计算图像的直方图 calcHist (&srcImage, 1, &channels, Mat(), dstHist, dims, &size, ranges); // cv中是cvCalcHist int scale = 1; Mat dstImage(size * scale, size, CV_8U, Scalar(0)); //获取最大值和最小值 double minValue = 0; double maxValue = 0 ; minMaxLoc(dstHist, &minValue, &maxValue, 0, 0); //在cv中用的是cvGetMinMaxHistValue //绘制出直方图 int hpt = saturate_cast
(0.9 * size); for (int i = 0; i < 256; i++) { float binValue = dstHist.at (i); int realvalue = saturate_cast (binValue * hpt / maxValue) ; rectangle(dstImage, Point(i * scale, size - 1), Point((i + 1) * scale - 1, size - realvalue), Scalar(255)); } 绘制RGB三色直方图
Mat srcImage; srcImage = imread("1.jpg") ; int bins = 256; int hist_size [ ] = { bins }; float range[ ] = { 0, 256 }; const float* ranges[ ]= { range } ; Mat redHist, grayHist, blueHist; int channels_r[]= { 0 }; //进行直方图的计算(红色分量部分) calcHist( &srcImage, 1, channels_r, Mat (), //不使用掩膜 redHist, 1, hist_size, ranges, true, false ); //进行直方图的计算(绿色分量部分) int channels_g[ ] = { 1 }; calcHist( &srcImage, 1, channels_g, Mat(), grayHist, 1, hist_size, ranges, true, false ); //进行直方图的计算(蓝色分量部分) int channels_b[ ] = { 2 }; calcHist( &srcImage, 1, channels_b, Mat(), blueHist, 1, hist_size, ranges, true, false); //绘制出三色直方图 double maxValue_red, maxValue_green, maxValue_blue; minMaxLoc(redHist, 0, &maxValue_red, 0, 0) ; minMaxLoc(grayHist, 0, &maxValue_green, 0, 0); minMaxLoc(blueHist, 0, &maxValue_blue, 0, 0); int scale = 1; int histHeight = 256; Mat histImage = Mat::zeros(histHeight, bins * 3, CV_8UC3); //开始绘制 for(int i = 0; i < bins; i++) { //参数准备 float binValue_red = redHist.at
(i); float binValue_green = grayHist.at (i); float binValue_blue = blueHist.at (i); //要绘制的高度 int intensity_red = cvRound(binValue_red * histHeight / maxValue_red); //要绘制的高度 int intensity_green = cvRound(binValue_green * histHeight / maxValue_green); //要绘制的高度 int intensity_blue = cvRound(binValue_blue * histHeight / maxValue_blue); //绘制红色分量的直方图 rectangle (histImage, Point( i*scale, histHeight-1 ), Point((i + 1) * scale - 1, histHeight - intensity_red), Scalar (255, 0, 0 )); //绘制绿色分量的直方图 rectangle (histImage, Point((i + bins) * scale, histHeight - 1) , Point((i + bins + 1) * scale - 1, histHeight - intensity_green), Scalar(0, 255, 0)) ; //绘制蓝色分量的直方图 rectangle(histImage, Point((i+bins * 2 ) * scale, histHeight - 1 ), Point((i + bins * 2 + 1) * scale - 1, histHeight - intensity_blue), Scalar (0, 0, 255)); }
计算两副图像的直方图,然后比较得出相似度。
直方图可选择不同的维度,如灰度空间计算直方图,其他色彩空间计算灰度图,或者其他任何维度用来计算直方图作为比较的依据。
double compareHist(InputArray H1, InputArray H2, int method) double compareHist(const SparseMat& H1, const SparseMat& H2, int method)
前两个参数是要比较的大小相同的直方图
第三个变量是所选择的距离标准。
序号
枚举
值
描述
1
HISTCMP_CORREL
0
相关性比较
2
HISTCMP_CHISQR
1
卡方比较
3
HISTCMP_INTERSECT
2
十字交叉性
4
HISTCMP_BHATTACHARYYA
3
巴氏距离
5
HISTCMP_HELLINGER
3
等同于HISTCMP_BHATTACHARYYA
6
HISTCMP_CHISQR_ALT
4
替代开放:通常用于纹理比较
7
HISTCMP_KL_DIV
5
KL散度
采用4种方法,比较两个直方图(H1表示第一个,H2表示第二个):
1.相关,Correlation (method = CV_COMP_CORREL)
且N等于直方图中 bin(译为“直条”或“组距”)的个数。
2. 卡方,Chi-Square (method = CV_COMP_CHISQR)
3. 直方图相交,Intersection(method = CV_COMP_INTERSECT)
4. Bhattacharyya距离(method = CV_COMP_BHATTACHARYYA)
这里的 Bhattacharyya距离和Hellinger距离相关,也可以写作method = CV_COMP_ HELLINGER
//声明储存基准图像和另外两张对比图像的矩阵(RGB和HSV ) Mat srcImage_base, hsvImage_base; Mat srcImage_test1, hsvImage_test1; Mat srcImage_test2, hsvImage_test2; Mat hsvImage_halfDown; //载入基准图像(srcImage_base)和两张测试图像srcImage_test1、srcImage_test2, srcImage_base = imread( "l.jpg", 1 ); srcImage_testl = imread( "2.jpg", 1 ); srcImage_test2 = imread( "3.jpg", 1 ); //将图像由BGR色彩空间转换到HSV色彩空间 cvtColor(srcImage_base, hsvimage_base, COLOR_BGR2HSV); cvtColor(srcimage_test1, hsvImage_test1, COLOR_BGR2HSV); cvtColor(srcImage_test2, hsvImage_test2, COLOR_BGR2HSV); //创建包含基准图像下半部的半身图像(HSV格式) hsvImage_halfDown = hsvImage_base(Range(hsvImage_base.rows / 2, hsvImage_base.rows - 1 ), Range(0, hsvImage_base.cols - 1 )); //初始化计算直方图需要的实参 //对hue通道使用30个bin,对saturatoin通道使用32个bin int h_bins = 50; int s_bins = 60 ; int histSize [ ] = { h_bins, s_bins }; // hue的取值范围从0到256, saturation取值范围从0到180 float h_ranges[ ] = { 0, 256 }; float s_ranges[ ] = { 0, 180 }; const float* ranges[ ] = { h_ranges, s_ranges }; //使用第0和第1通道 int channels[ ] = { 0, 1 }; //创建储存直方图的 MatND类的实例 Mat baseHist; Mat halfDownHist; Mat testHistl; Mat testHist2; //计算基准图像,两张测试图像,半身基准图像的HSV直方图 calcHist(&shsvImage_base, 1, channels, Mat(), baseHist, 2, histSize, ranges, true, false ); normalize(baseHist, baseHist, 0, 1, NORM_MINMAX, -1, Mat()); calcHist(&hsvImage_halfDown, 1, channels, Mat(), halfDownHist, 2, histSize, ranges, true, false ); normalize(halfDownHist, halfDownHist, 0, 1, NORM_MINMAX, -1, Mat()); calcHist (&hsvImage_test1, 1, channels, Mat(), testHist1, 2, histSize, ranges, true, false ) ; normalize(testHist1, testHist1, 0, 1, NORM_MINMAX, -1, Mat()); calcHist (&hsvImage_test2, 1, channels, Mat(), testHist2, 2, histSize, ranges, true, false) ; normalize(testHist2, testHist2, 0, 1, NORM_MINMAX, -1, Mat()); //按顺序使用4种对比标准将基准图像的直方图与其余各直方图进行对比 for( int i = 0; i< 4; i++ ) { //进行图像直方图的对比 int compare_method = i; double base_base = compareHist(baseHist, baseHist, compare_method); double base_half = compareHist(baseHist, halfDownHist, compare_method); double base_testl = compareHist(baseHist, testHist1, compare_method); double base_test2 = compareHist(baseHist, testHist2, compare__method) ; }
反向投影(back projection)是一种记录给定图像中的像素点如何适应直方图模型像素分布方式的一种方法。
反向投影是首先计算某一特征的直方图模型,然后使用模型去寻找图像中存在该特征的方法。
反向投影中一般使用HSV色彩空间,使用HS两个通道直方图模型去进行匹配计算。HSV是一种将RGB色彩空间中的点在倒圆锥体中的表示方法。HSV即色相(Hue)、饱和度(Saturation)、明度(Value),又称HSB(B即Brightness)。色相是色彩的基本属性,就是平常说的颜色的名称,如红色、黄色等。饱和度(S)是指色彩的纯度,越高色彩越纯,低则逐渐变灰,取0-100%的数值。明度(V),取0-max(计算机中HSV取值范围和存储的长度有关)。
作用:
用于输入图像(通常较大)中查找与特定图像(通常较小或者仅1个像素(模板图像))最匹配的点或者区域,也就是定位模板图像出现在输入图像的位置。
结果:
反向投影的结果包含了以每个输入图像像素点为起点的直方图对比结果。可以把它看成是一个二维的浮点型数组、二维矩阵,或者单通道的浮点型图像。
计算反向投影: calcBackProject()函数
void calcBackProject(const Mat* images, int nimages, const int* channels, InputArray hist, OutputArray backProject, const float** ranges, double scale = 1, bool uniform = true)
参数1,const Mat*类型的images,输入的数组(或数组集),须为相同的深度(CV_8U或
CV_32F)和相同的尺寸,而通道数则可以任意。
参数2,int类型的nimages,输入数组的个数,参数1中存放了多少张“图像”,有几个原数组。
参数3,const int*类型的channels,需要统计的通道(dim)索引。第一个数组通道从0到
images[ 0 ].channels() - 1,而第二个数组通道从images[0].channels()计算到
images[ 0 ].channels() + images[ 1 ].channels() - 1.
参数4,InputArray类型的hist,输入的直方图。
参数5,OutputArray类型的 backProject,目标反向投影阵列,须为单通道,
且和 image[0]有相同的大小和深度。
参数6,const float**类型的ranges,表示每一个维度数组(参数6 dims)的每一维的边界阵
列,可以理解为每一维数值的取值范围。
参数7,double scale,有默认值1,输出的方向投影可选的缩放因子,默认值为1。
参数8,bool类型的uniform,指示直方图是否均匀的标识符,默认值true。
通道复制: mixChannels()函数 由输入参数复制某通道到输出参数特定的通道中
void mixChannels( const Mat* src, //输入的数组,所有的矩阵必须有相同的尺寸和深度 size_t nsrcs , //参数1 src输入的矩阵数 Mat* dst, //输出的数组,所有矩阵必须被初始化,且大小和深度必须与src[0]相同 size_t ndsts, //参数3 dst输入的矩阵数 const int* fromTo, //对指定的通道进行复制的数组索引 size_t npairs) //参数5 fromTo的索引数 void mixChannels ( const vector
& src, //输入的矩阵向量,所有的矩阵必须有相同的尺寸和深度 vector & dst, //输出的矩阵向量,所有矩阵须被初始化,且大小和深度须与src[0]相同 const int* fromTo, //对指定的通道进行复制的数组索引 size_t npairs ) //第三个参数fromTo的索引数 例如:将一个4通道的RGBA图像转化为3通道BGR(R通道和B通道交换)和一个单独的Alpha通道的图像。
Mat rgba(100, 100, CV_80C4, scalar(1, 2, 3, 4)); Mat bgr(rgba.rows, rgba.cols, CV_8UC3); Mat alpha(rgba.rows, rgba.cols, CV_8UC1); //组成矩阵数组来进行操作 Mat out [ ] = { bgr, alpha }; //说明:将rgba[0] -> bgr[2], rgba[1] -> bgr[1], //说明:将rgba[2] -> bgr[0], rgba[3] -> alpha[0] int from_to[ ]= { 0, 2, 1, 1, 2, 0, 3, 3}; mixChannels(&rgba, 1, out, 2, from_to, 4);
将图像转换到hsv空间
Mat srcImg, hsvImg; cvtColor(srcImg, hsvImg, COLOR_BGR2HSV);
模板匹配是在一幅图像中寻找与另一幅模板图像最匹配(相似)部分的技术。模板匹配由matchTemplate()函数完成。模板匹配不是基于直方图的,而是通过在输入图像上滑动图像块, 对实际的图像块和输入图像进行匹配的一种匹配方法。
void matchTemplate(InputArray image, InputArray templ, OutputArray result, int method)
参数1,InputArray类型的 image,待搜索的图像,且需为8位或32位浮点型图像。
参数2,InputArray类型的 templ,搜索模板,需和源图片有一样的数据类型, 且尺寸不能大
于源图像。
参数3,OutputArray类型的result,比较结果的映射图像。其必须为单通道、32位浮点型
图像。如果图像尺寸是W x H而templ尺寸是 w x h ,则此参数result一定是
(W-w+1) × (H-h+1).
参数4,int类型的method,指定的匹配方法,OpenCV提供了6种图像匹配方法可供使用。
序号 枚举 值 描述 1 TM_SQDIFF
0 平方差匹配法,最好匹配为0,匹配越差值越大。 2 TM_SQDIFF_NORMED
1 平方差匹配法后,进行归一化 3 TM_CCORR
2 相关匹配法,采用模板和图像间的乘法操作,数值越大表示匹配程度越高,0表示最坏的匹配 4 TM_CCORR_NORMED
3 相关匹配法后,进行归一化 5 TM_CCOEFF 4 系数匹配法,将模板对其均值的相对值与图像对其均值的相关值进行匹配,1表示完美匹配,-1表示糟糕的匹配,0表示没有任何相关性《随机序列) 6 TM_CCOEFF_NORMED
5 系数匹配法后,进行归一化 1.平方差匹配法 method = TM_SQDIFF
这类方法利用平方差来进行匹配,最好匹配为0。而若匹配越差,匹配值则越大。
2. 归一化平方差匹配法 method = TM_SQDIFF_NORMED
3. 相关匹配法 method = TM_CCORR
这类方法采用模板和图像间的乘法操作,所以较大的数表示匹配程度较高,0标识最坏的
匹配效果。
4. 归一化相关匹配法 method = TM_CCORR_NORMED
5.系数匹配法 method = TM_CCOEFF
这类方法将模版对其均值的相对值与图像对其均值的相关值进行匹配,1表示完美匹
配,-1表示糟糕的匹配,而0表示没有任何相关性(随机序列)。
6.化相关系数匹配法 method = TM_CCOEFF_NORMED