网站上传不了图片不显示不出来吗,柳州住房和城乡建设厅网站,如何下载音乐到wordpress,创意网络营销案例第9章 直方图与匹配
9.1 图像直方图概述
直方图广泛运用于很多计算机视觉运用当中#xff0c;通过标记帧与帧之间显著的边 缘和颜色的统计变化#xff0c;来检测视频中场景的变化。在每个兴趣点设置一个有相近 特征的直方图所构成“标签”,用以确定图像中的兴趣点。边缘、色…第9章 直方图与匹配
9.1 图像直方图概述
直方图广泛运用于很多计算机视觉运用当中通过标记帧与帧之间显著的边 缘和颜色的统计变化来检测视频中场景的变化。在每个兴趣点设置一个有相近 特征的直方图所构成“标签”,用以确定图像中的兴趣点。边缘、色彩、角度等直 方图构成了可以被传递给目标识别分类器的一个通用特征类型。色彩和边缘的直 方图序列还可以用来识别网络视频是否被复制。如图9. 1所示。 其实简单点说直方图就是对数据进行统计的一种方法并且将统计值组 织到一系列事先定义好的bin 当 中 。 其 中 bin 为直方图中经常用到的一个概念 可翻译为“直条”或组距,其数值是从数据中计算出的特征统计量这些数据 可以是诸如梯度、方向、色彩或任何其他特征。且无论如何直方图获得的是数 据分布的统计图。通常直方图的维数要低于原始数据。总而言之直方图是计算 机视觉中最经典的工具之一。
在统计学中直方图(Histogram) 是一种对数据分布情况的图形表示是一 种二维统计图表它的两个坐标分别是统计样本和该样本对应的某个属性的度量。
我们在图像变换的那一章中讲过直方图的均衡化它是通过拉伸像素强度分 布范围来增强图像对比度的一种方法。大家在自己的心目中应该已经对直方图有 一定的理解和认知。下面就来看一看对图像直方图比较书面化的解释。 图像直方图(Image Histogram) 是用以表示数字图像中亮度分布的直方图 标绘了图像中每个亮度值的像素数。可以借助观察该直方图了解需要如何调整亮 度分布。这种直方图中横坐标的左侧为纯黑、较暗的区域而右侧为较亮、纯 白的区域。因此 一张较暗图片的图像直方图中的数据多集中于左侧和中间部分 而整体明亮、只有少量阴影的图像则相反。计算机视觉领域常借助图像直方图来 实现图像的二值化。
直方图的意义如下。
直方图是图像中像素强度分布的图形表达方式。它统计了每一个强度值所具有的像素个数。 上面已经讲到直方图是对数据的统计集合并将统计结果分布于一系列预定义的bins 中。这里的数据不仅仅指的是灰度值且统计数据可能是任何能有效 描述图像的特征。下面看一个例子假设有一个矩阵包含一张图像的信息(灰度 值0-255),让我们按照某种方式来统计这些数字。既然已知数字的范围包含256 个值于是可以将这个范围分割成子区域(也就是上面讲到bins), 如 [ 0 , 255 ] [ 0 , 15 ] ∪ [ 16 , 31 ] ∪ … ∪ [ 240 , 255 ] r a n g e b i n i ∪ b i n 2 ∪ … ∪ b i n n 15 [0,255][0,15] \cup [16,31] \cup…\cup [240,255] \\ rangebin_i \cup bin_2 \cup…\cup bin_{n15} [0,255][0,15]∪[16,31]∪…∪[240,255]rangebini∪bin2∪…∪binn15
然后再统计每一个bin; 的像素数目。采用这一方法来统计上面的数字矩阵 可以得到图9.2(其中x 轴表示bin,y 轴表示各个bin 中的像素个数)。 以上就是一个说明直方图的用途的简单示例。其实直方图并不局限于统计 颜色灰度而是可以统计任何图像特征如梯度、方向等。 让我们具体讲讲直方图的一些术语和细节。
dims:需要统计的特征的数目。在上例中dims 1因为我们仅仅统计了 灰度值(灰度图像)。bins:每个特征空间子区段的数目可翻译为“直条”或“组距”。在上例 中 bins16。range: 每个特征空间的取值范围。在上例中range[0,255]。
9.2 直方图的计算与绘制
直方图的计算在OpenCV 中可以使用calcHist() 函数而计算完成之后可以 采用OpenCV 中的绘图函数如绘制矩形的rectangle() 函数绘制线段的line() 来 完成。
9.2.1 计 算 直 方 图 calcHist() 函 数
在OpenCV 中 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)第一个参数const Mat*类型的images, 输入的数组(或数组集),它们需为相同的深度(CV_8U 或 CV_32F) 和相同的尺寸。第二个参数int 类 型 的nimages, 输入数组的个数也就是第一个参数中 存放了多少张“图像”,有几个原数组。第三个参数const int*类型的channels, 需要统计的通道(dim) 索引。第 一 个 数 组 通 道 从 0 到 images[0].channels)-1, 而 第 二 个 数 组 通 道 从 images[0].channels() 计算到images[0].channels()images[1].channels()-1。第四个参数InputArray 类型的mask, 可选的操作掩码。如果此掩码不为 空那么它必须为8位并且与images[i] 有同样大小的尺寸。这里的非零 掩码元素用于标记出统计直方图的数组元素数据。第五个参数OutputArray类 型 的hist,输出的目标直方图 一个二维数组。第六个参数int类 型 的dims, 需要计算的直方图的维度必须是正数且 不大于CV_MAX_DIMS (在当前版本的OpenCV 中等于32)。第七个参数const int*类型的histSize,存放每个维度的直方图尺寸的数组。第八个参数const float**类型的ranges, 表示每一个维度数组(第六个参 数dims) 的每一维的边界阵列可以理解为每一维数值的取值范围。第九个参数bool 类 型 的uniform,指示直方图是否均匀的标识符有默认 值 true。第十个参数bool类型的accumulate, 累计标识符有默认值false。若 其 为 true, 直方图在配置阶段不会被清零。此功能主要是允许从多个阵列中 计算单个直方图或者用于在特定的时间更新直方图。
9.2.2 找寻最值minMaxLoc() 函数
minMaxLoc(函数的作用是在数组中找到全局最小值和最大值。它有两个版 本的原型在此介绍常用的那一个版本。
void minMaxLoc(InputArray src, double *minVal, double *maxVal 0, Point *minLoc 0, Point *maxLoc 0, InputArray mask noArrayO)第 一 个参数InputArray类 型 的src, 输入的单通道阵列。第二个参数double* 类型的minVal, 返回最小值的指针。若无须返回此 值置为NULL。\第三个参数double*类型的maxVal, 返回的最大值的指针。若无须返回 此值置为NULL。第四个参数Point*类型的minLoc, 返回最小位置的指针(二维情况下)。 若无须返回此值置为NULL。第五个参数Point*类型的maxLoc, 返回最大位置的指针(二维情况下)。 若无须返回此值置为NULL。第六个参数InputArray类型的mask, 用于选择子阵列的可选掩膜。
9.2.3 示例程序绘制H—S 直方图
下面的示例说明如何计算彩色图像的色调饱和度二维直方图。
注意色调(Hue), 饱和度(Saturation)。所 以“H-S 直方图”就是“色调— 饱和度直方图”。
void Test59() {Mat srcImage, hsvImage;srcImage imread(image.jpg);cvtColor(srcImage, hsvImage, COLOR_BGR2HSV); //转换为HSV图像//将色调量化为30个等级将饱和度量化为32个等级int hueBinNum 30, saturationBinNum 32;int histSize[] { hueBinNum ,saturationBinNum };//定义色调变化范围为0到179float hueRanges[] { 0,180 };//定义饱和度的范围为0(黑/白/灰到255(纯光谱颜色))float saturationRange[] { 0,256 };const float* ranges[] { hueRanges,saturationRange };MatND dstHist;//calcHist函数将计算第0通道和第1通道的直方图int channels[] { 0,1 };//调用calcHist,进行直方图计算calcHist(hsvImage, 1, channels, Mat(), dstHist, 2, histSize, ranges, true, false);//为绘制直方图准备参数double maxValue 0;minMaxLoc(dstHist, 0, maxValue, 0, 0);int scale 10;Mat histImage 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.atfloat(hue, saturation);int intensity cvRound(binValue * 255 / maxValue);//绘制直方图rectangle(histImage, Point(hue * scale, saturation * scale),Point((hue 1) * scale - 1, (saturation 1) * scale - 1),Scalar::all(intensity), FILLED);}}imshow(srcImage, srcImage);imshow(histImage, histImage);waitKey(0);} 9.2.4 示例程序计算并绘制图像一维直方图
上 文 中 已 经 讲 解 了calcHist ( 函 数 的 用 法 并 绘 制 出 了 图 像 的H-S 二 维 直 方 图 。 而本节我们会通过一个示例 来学习图像一维直方图的计算和绘制过程 。
**void Test60() {Mat srcImage imread(image.jpg, 0); //灰度图imshow(srcImage, srcImage);MatND dstHist;int dims 1;float hranges[] { 0,255 };const float* ranges[] { hranges };int size 256, channels 0;int scale 1;//计算图像的直方图calcHist(srcImage, 1, channels, Mat(), dstHist, dims, size, ranges);//获取最大值和最小值double maxValue 0, minValue 0;minMaxLoc(dstHist, minValue, maxValue, 0, 0);//输出直方图Mat dstImage(size * scale, size, CV_8U, Scalar(0));int hpt saturate_castint(0.9 * size);for (int i 0; i 256; i) {float binValue dstHist.atfloat(i);int realValue saturate_castint(binValue * hpt / maxValue);rectangle(dstImage, Point(i * scale, size - 1), Point((i 1) * scale - 1, size - realValue), Scalar(255));}imshow(dstImage, dstImage);waitKey(0);
}9.2.5 示 例 程 序 绘 制RGB 三色直方图
上文我们讲解的是单个分量的一维直方图的绘制接下来看看如何分别绘制 图像的RGB 三色直方图。详细注释的代码如下。
void Test61() {Mat srcImage imread(image.jpg);imshow(srcImage, srcImage);int bins 256;int hist_size[] { bins };float range[] { 0, 256 };const float* ranges[] { range };MatND redHist, greenHist, 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(), greenHist, 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(greenHist, 0, maxValue_green, 0, 0);minMaxLoc(blueHist, 0, maxValue_blue, 0, 0);// 确保最大值至少为1以避免除以零的错误maxValue_red max(maxValue_red, 1.0);maxValue_green max(maxValue_green, 1.0);maxValue_blue max(maxValue_blue, 1.0);int scale 2; int histHeight 256; // 创建空白图像用于绘制直方图Mat histImage Mat::zeros(histHeight, bins * 3 * scale, CV_8UC3);for (int i 0; i bins; i) {// 获取每个通道的直方图数据float binValue_red redHist.atfloat(i);float binValue_green greenHist.atfloat(i);float binValue_blue blueHist.atfloat(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(0, 0, 255));// 绘制绿色分量的直方图rectangle(histImage, Point(i * scale, histHeight - 1),Point((i 1) * scale - 1, histHeight - intensity_green), Scalar(0, 255, 0));// 绘制蓝色分量的直方图rectangle(histImage, Point(i * scale, histHeight - 1),Point((i 1) * scale - 1, histHeight - intensity_blue), Scalar(255, 0, 0));}imshow(histImage, histImage);waitKey(0);} 9.3 直方图对比
对于直方图来说 一个不可或缺的工具便是用某些具体的标准来比较两个 直方图的相似度。要对两个直方图(比如说H₁ 和 H₂) 进行比较首先必须选 择一个衡量直方图相似度的对比标准(d(H₁,H₂))。 在OpenCV 2.X中我们用 compareHist()函数来对比两个直方图的相似度而此函数的返回值就是 d(H,H₂)。
9.3.1 对 比 直 方 图 compareHist ( 函 数
compareHist(函数用于对两幅直方图进行比较。有两个版本的C 原型如 下。
double compareHist(InputArray H1, InputArray H2, int method) C : double compareHist(const SparseMat H1, const SparseMat H2, int method)它们的前两个参数是要比较的大小相同的直方图第三个变量是所选择的距离 标准。可采用如下4种方法比较两个直方图 (H1 表示第一个H2 表示第二个): 相 关 Correlation(methodCV_COMP_CORREL) 卡 方 Chi-Square (methodCV_COMP_CHISQR) 直方图相交Intersection(methodCV_COMP_INTERSECT) Bhattacharyya 距 离(methodCV_COMP_BHATTACHARYYA) 这 里 的 Bhattacharyya 距 离 和 Hellinger 距 离 相 关 也 可 以 写 作 methodCV_COMP_HELLINGER 此处的宏定义在当前版本的OpenCV3 中 依 然 沿 用“CV_” 前缀在未 来版本中应该会有更改。如需使用可以分别用int 类型的1、2、3、4替 代 CV_COMP_CORREL 、CV_COMP_CHISQR、CV_COMP_INTERSECT、 CV_COMP_BHATTACHARYYA 这四个宏。或者“#includecv.h” 加 入cv.h 头文件。
9.3.2 示 例 程 序 直 方 图 对 比
此次的示例程序为大家演示了如何用compareHist() 函数进行直方图对比。代 码中的MatND 类是用于存储直方图的一种数据结构用法简单在这里就不多做 讲解大家看到详细注释的示例程序就会明白。
void Test62() {Mat srcImage_base, hsvImage_base;Mat srcImage_test1, hsvImage_test1;Mat srcImage_test2, hsvImage_test2;Mat hsvImage_halfDown;srcImage_base imread(image.jpg);srcImage_test1 imread(image2.jpg);srcImage_test2 imread(image3.jpg);imshow(image1, srcImage_base);imshow(image2, srcImage_test1);imshow(image3, srcImage_test2);//转换到HSV色彩空间cvtColor(srcImage_base, hsvImage_base, COLOR_BGR2HSV);cvtColor(srcImage_test1, hsvImage_test1, COLOR_BGR2HSV);cvtColor(srcImage_test2, hsvImage_test2, COLOR_BGR2HSV);//创建包含基准图像下半部的半身图像hsvImage_halfDown hsvImage_base(Range(hsvImage_base.rows / 2, hsvImage_base.rows - 1),Range(0, hsvImage_base.cols - 1));//初始化计算直方图需要的实参int h_bins 50, s_bins 60;int histSize[] { h_bins,s_bins };float h_ranges[] { 0,256 };float s_ranges[] { 0,180 };const float* ranges[] { h_ranges ,s_ranges };int channels [] {0,1};MatND baseHist, halfDownHist, testHist1, testHist2;//计算基准图像两张测试图像半身基准图像的HSV直方图calcHist(hsvImage_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());//进行直方图对比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_test1 compareHist(baseHist, testHist1, compare_method);double base_test2 compareHist(baseHist, testHist2, compare_method);printf(----------------------\n);printf(methon [%d] result \n\n base-base:%f,base-halfbase:%f,base-test1:%f,base-test2:%f\n, i, base_base, base_test1, base_test2);}printf(finished\n);waitKey(0);}需要注意的是在上述代码中还会将基准图像与它自身及其半身图像进行对 比。而我们知道当将基准图像直方图及其自身进行对比时会产生完美的匹配 当与来源于同一样的背景环境的半身图对比时应该会有比较高的相似度当与 来自不同亮度光照条件的其余两张测试图像对比时匹配度应该不是很好。输出 的匹配结果如图9.12所示。
其中的方法0至3,分别表示之前讲过的Correlation 、Chi-square 、Intersection 、 Bhattacharyya 对比标准。其中对于Correlation ( 方 法 0 ) 和Intersection ( 方 法 2 ) 标准值越大表示相似度越高。可以发现【基准图一基准图】的匹配数值结果相 对于其他几种匹配方式是最大的符合实际情况。【基准图—半身图】的匹配结果 次大正如我们预料。而【基准—测试图1】和【基准图—测试图2】的匹配结果却不尽人意同样和之前的预料吻合。
9.4 反 向 投 影
9.4.1 引 言
如果一幅图像的区域中显示的是一种结构纹理或者一个独特的物体那么这 个区域的直方图可以看作一个概率函数其表现形式是某个像素属于该纹理或物 体的概率。 而反向投影(back projection) 就是一种记录给定图像中的像素点如何适应直 方图模型像素分布方式的一种方法。 简单的讲所谓反向投影就是首先计算某一特征的直方图模型然后使用模 型去寻找图像中存在的该特征的方法。
9.4.2 反向投影的工作原理
下面我们将使用H-S 肤色直方图为例来解释反向投影的工作原理。 首先通过之前讲过的求H-S 直方图的示例程序得到如图9.139.16所示的 H-S 肤色直方图。 而我们要做的就是使用模型直方图(代表手掌的皮肤色调)来检测测试图 像中的皮肤区域。以下是检测步骤。
(1)对测试图像中的每个像素(p(ij)), 获取色调数据并找到该色调(hi,sj) 在直方图中的bin 的位置。 (2)查询模型直方图中对应bin 的数值。 (3)将此数值储存在新的反射投影图像中。也可以先归一化直方图数值到 0-255范围这样可以直接显示反射投影图像(单通道图像)。 (4)通过对测试图像中的每个像素采用以上步骤可以得到最终的反射投影 图像。如图9.17所示。 (5)使用统计学的语言进行分析。反向投影中储存的数值代表了测试图像中 该像素属于皮肤区域的概率。比如以图9.17为例亮起的区域是皮肤区域的概 率更大而更暗的区域则表示是皮肤的概率更低。另外可以注意到手掌内部 和边缘的阴影影响了检测的精度。
9.4.3 反向投影的作用
反向投影用于在输入图像(通常较大)中查找与特定图像(通常较小或者仅 1个像素以下将其称为模板图像)最匹配的点或者区域也就是定位模板图像 出现在输入图像的位置。
9.4.4 反向投影的结果
反向投影的结果包含了以每个输入图像像素点为起点的直方图对比结果。可 以把它看成是一个二维的浮点型数组、二维矩阵或者单通道的浮点型图像。
9.4.5 计算反向投影calcBackProject() 函 数
calcBackProject()函数用于计算直方图的反向投影。
void calcBackProject(const Mat *images,int nimages,const int *channels,InputArray hist,OutputArray backProject, const float **ranges,double scale 1,bool uniform true)第一个参数const Mat*类型的images,输入的数组(或数组集),它们须为 相同的深度(CV_8U 或 CV_32F) 和相同的尺寸而通道数则可以任意。第二个参数int 类型的nimages,输入数组的个数也就是第一个参数中 存放了多少张“图像”,有几个原数组。第三个参数const int*类型的channels,需要统计的通道(dim)索引。第一 个 数 组 通 道 从 0 到 images[0].channels()-1, 而 第 二 个 数 组 通 道 从 images[0].channelsO计算到images[0].channels(images[1].channels()-1。第 四 个 参 数 InputArray 类 型 的hist, 输入的直方图。第五个参数OutputArray类型的backProject,目标反向投影阵列其须为 单通道并且和image[0] 有相同的大小和深度。第六个参数const float**类型的ranges,表示每一个维度数组(第六个参 数dims) 的每一维的边界阵列可以理解为每一维数值的取值范围。第七个参数double scale,有默认值1,输出的方向投影可选的缩放因子 默 认 值 为 1 。第八个参数bool类型的uniform,指示直方图是否均匀的标识符有默认 值true。
9.4.6 通道复制 mixChannelsO 函 数
此函数由输入参数复制某通道到输出参数特定的通道中。有两个版本的C 原型采用函数注释方式分别介绍如下。
void mixChannels(const Mat *src, // 输入的数组所有的矩阵必须有相同的尺寸和深度size_t nsrcs, // 第一个参数src 输入的矩阵数Mat *dst, // 输出的数组所有矩阵必须被初始化且大小和深度必须与src[0] 相同size_t ndsts, // 第三个参数dst 输入的矩阵数const int *fromTo, // 对指定的通道进行复制的数组索引size_t npairs) // 第五个参数fromTo 的索引数void mixChannels(const vectorMat src, // 输入的矩阵向量所有的矩阵必须有相同的尺寸和深度 vectorMatdst,// 输出的矩阵向量所有矩阵须被初始化且大小和深度须与src[0] 相同const int *fromTo, // 对指定的通道进行复制的数组索引size_t npairs) // 第三个参数fromTo 的索引数
此函数为重排图像通道提供了比较先进的机制。其实之前我们接触到的 split( 和merge), 以 及cvtColor(的某些形式都只是mixChannels(的一部分。
下面给出一个示例将一个4通道的RGBA 图像转化为3通道BGR(R 通道和B 通道交换)和一个单独的Alpha 通道的图像。
Mat rgba(100, 100, CV_8UC4, 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);9.4.7 综合程序反向投影
下面将给大家展示一个浓缩了本节内容的讲解内容经过详细注释的反向投影 示例程序 。
namespace test63 {Mat g_srcImage, g_hsvImage, g_hueImage;int g_bins 30;void on_BinChange(int, void*) {MatND hist;int histSize MAX(g_bins, 2);float hue_range[] { 0,180 };const float* ranges { hue_range };//计算直方图并归一化calcHist(g_hueImage, 1, 0, Mat(), hist, 1, histSize, ranges, true,false);normalize(hist, hist, 0, 255, NORM_MINMAX, -1, Mat());MatND backproj;calcBackProject(g_hueImage, 1, 0, hist, backproj, ranges, 1, true);//显示反向投影imshow(backproj, backproj);//绘制直方图int w 400, h 400;int bin_w cvRound(w * 1.0 / histSize);Mat histImage Mat::zeros(w, h, CV_8UC3);//绘制直方图for (int i 0; i g_bins; i) {rectangle(histImage, Point(i * bin_w, h), Point((i 1) * bin_w, h - cvRound(hist.atfloat(i) * h / 255.0)), Scalar(100, 123, 255), -1);}imshow(histImage2, histImage);}void Test() {g_srcImage imread(hand.jpg);cvtColor(g_srcImage, g_hsvImage, COLOR_BGR2HSV);if (g_srcImage.empty()) {return;}//分离Hue色调通道g_hueImage.create(g_hsvImage.size(), g_hsvImage.depth());int ch[] { 0,0 };mixChannels(g_hsvImage,1, g_hueImage,1,ch,1);//创建滑动条namedWindow(srcImage);createTrackbar(value, srcImage, g_bins, 180, on_BinChange);imshow(srcImage, g_srcImage);waitKey(0);}}void Test63() {test63::Test();
} 9.5 模 板 匹 配
9.5.1 模板匹配的概念与原理
模板匹配是一项在一幅图像中寻找与另一幅模板图像最匹配(相似)部分的 技术。在OpenCV2 和 OpenCV3 中模板匹配由MatchTemplate() 函数完成。需要 注意模板匹配不是基于直方图的而是通过在输入图像上滑动图像块对实际 的图像块和输入图像进行匹配的一种匹配方法。 如图9.23所示通过一个人脸“图像模板”,在整幅输入图像上移动这张“脸”, 来寻找和这张脸相似的最优匹配。
9.5.2 实现模板匹配matchTemplate() 函数
matchTemplate() 用于匹配出和模板重叠的图像区域。
void matchTemplate(InputArray image, InputArray templ, OutputArray result, int method)第一个参数InputArray 类 型 的image, 待搜索的图像且需为8位或32 位浮点型图像。第二个参数InputArray类型的 templ, 搜索模板需和源图片有一样的数 据类型且尺寸不能大于源图像。第三个参数OutputArray 类型的 result,比较结果的映射图像。其必须为 单通道、32位浮点型图像.如果图像尺寸是W×H 而 templ 尺 寸 是w×h,则 此 参 数result 一 定是(W-w1)×(H-h1).第四个参数int 类 型 的method, 指定的匹配方法OpenCV 为我们提供了 如下6种图像匹配方法可供使用。 平方差匹配法 methodTM_SQDIFF 这类方法利用平方差来进行匹配最好匹配为0。而若匹配越差匹配值则 越大。 归一化平方差匹配法 methodTM_SQDIFF_NORMED 相关匹配法 methodTM_CCORR 这类方法采用模板和图像间的乘法操作所以较大的数表示匹配程度较高0标识最坏的匹配效果。 归一化相关匹配法 methodTM_CCORR_NORMED 系数匹配法methodTM_CCOEFF 这类方法将模版对其均值的相对值与图像对其均值的相关值进行匹配1表 示完美匹配-1表示糟糕的匹配而0表示没有任何相关性(随机序列)。
其中 T ′ ( x ′ , y ′ ) T ( x ′ , y ′ ) − 1 / ( w . h ) ⋅ ∑ x ′ ′ , y ′ ′ T ( x ′ ′ , y ′ ′ ) I ′ ( x x ′ , y y ′ ) I ( x x ′ , y y ′ ) − 1 / ( w . h ) ⋅ ∑ x ′ ′ , y ′ ′ I ( x x ′ ′ , y y ′ ′ ) T(x,y)T(x,y)-1/(w.h)·\sum_{x,y} T(x,y) \\ I(xx,yy)I(xx,yy)-1/(w.h)·\sum_{x,y}I(xx,yy) T′(x′,y′)T(x′,y′)−1/(w.h)⋅x′′,y′′∑T(x′′,y′′)I′(xx′,yy′)I(xx′,yy′)−1/(w.h)⋅x′′,y′′∑I(xx′′,yy′′)
化相关系数匹配法 methodTM_CCOEFF_NORMED
上述的6个宏在OpenCV2 依然是可以加上“CV_” 前缀分别写作 CV_TM_SQDIFF 、CV_TM_SQDIFF_NORMED 、CV_TM_CCORR、CV_ TM_CCORR_NORMED 、CV_TM_CCOEFF 、CV_TM_CCOEFF_ NORMED。
通常随着从简单的测量(平方差)到更复杂的测量(相关系数),我们可获得越来越准确的匹配。然而这同时也会以越来越大的计算量为代价。比较科学 的办法是对所有这些方法多次测试实验以便为自己的应用选择同时兼顾速度和 精度的最佳方案 。
9.5.3 综合示例模板匹配
讲解完成基本概念和函数用法下面依然是放出一个经过详细注释的示例程 序源代码演示了如何种不同的模板匹配方法对人脸进行检测。 namespace test64 {Mat g_srcImage, g_templateImage, g_resultImage;int g_nMatchMethod;int g_nMaxTrackbarNum 5;void on_Matching(int, void*) {Mat srcImage;g_srcImage.copyTo(srcImage);int resultImage_cols g_srcImage.cols - g_templateImage.cols 1;int resultImage_rows g_srcImage.rows - g_templateImage.rows 1;g_resultImage.create(resultImage_cols, resultImage_rows, CV_32FC1);//进行匹配和标准化matchTemplate(g_srcImage, g_templateImage, g_resultImage, g_nMatchMethod);normalize(g_resultImage, g_resultImage, 0, 1, NORM_MINMAX, -1, Mat());//通过MinMaxLoc单位最匹配的位置double minValue, maxValue;Point minLocation, maxLocation, matchLocation;minMaxLoc(g_resultImage, minValue, maxValue, minLocation, maxLocation, Mat());if (g_nMatchMethod TM_SQDIFF || g_nMatchMethod TM_SQDIFF_NORMED) {matchLocation minLocation;}else {matchLocation maxLocation;}//绘制出矩形显示最后的结果rectangle(srcImage, matchLocation, Point(matchLocation.x g_templateImage.cols, matchLocation.y g_templateImage.rows),Scalar(0, 0, 255), 2, 8, 0);rectangle(g_resultImage, matchLocation, Point(matchLocation.x g_templateImage.cols, matchLocation.y g_templateImage.rows),Scalar(0, 0, 255), 2, 8, 0);imshow(srcImage1, srcImage);imshow(srcImage2, g_resultImage);}void Test() {g_srcImage imread(image.jpg);g_templateImage imread(template.jpg);namedWindow(srcImage1);namedWindow(srcImage2);createTrackbar(method:, srcImage1, g_nMatchMethod, g_nMaxTrackbarNum, on_Matching);on_Matching(0, nullptr);waitKey(0);}}void Test64() {test64::Test();
} 可以发现除了相关匹配法 (TM_CCORR) 得到了错误的匹配结果之外其 他的5种匹配方式结果都匹配较为准确。
9.6 本章小结
本章我们学习了广泛运用于很多计算机视觉运用当中的直方图而简单点说 直方图就是对数据进行统计的一种方法。然后还讲到了反向投影和模板匹配。所 谓反向投影就是首先计算某一特征的直方图模型最后使用模型去寻找图像中存 在的该特征的方法。而模板匹配是一项在一幅图像中寻找与另一幅模板图像最匹 配(相似)部分的技术。
本章核心函数清单
函数名称说明对应讲解章节calcHist计算一个或者多个阵列的直方图9.2.1minMaxLoc在数组中找到全局最小值和最大值9.2.2compareHist对两幅直方图进行比较9.3.1calcBackProject计算直方图的反向投影9.4.5mixChannels由输入参数复制某通道到输出参数特定的通道中9.4.6matchTemplate匹配出和模板重叠的图像区域9.5.2
本章示例程序清单
示例程序序号程序说明对应章节79H-S二维直方图的绘制9.2.380一维直方图的绘制9.2.481RGB三色直方图的绘制9.2.582直方图对比9.3.283反向投影9.4.784模板匹配9.5.3 文章转载自: http://www.morning.zcyxq.cn.gov.cn.zcyxq.cn http://www.morning.ymwrs.cn.gov.cn.ymwrs.cn http://www.morning.lsfzq.cn.gov.cn.lsfzq.cn http://www.morning.fnrkh.cn.gov.cn.fnrkh.cn http://www.morning.jntcr.cn.gov.cn.jntcr.cn http://www.morning.slfmp.cn.gov.cn.slfmp.cn http://www.morning.trqsm.cn.gov.cn.trqsm.cn http://www.morning.zxybw.cn.gov.cn.zxybw.cn http://www.morning.pmnn.cn.gov.cn.pmnn.cn http://www.morning.xhftj.cn.gov.cn.xhftj.cn http://www.morning.prddj.cn.gov.cn.prddj.cn http://www.morning.qcfgd.cn.gov.cn.qcfgd.cn http://www.morning.zfqdt.cn.gov.cn.zfqdt.cn http://www.morning.xwgbr.cn.gov.cn.xwgbr.cn http://www.morning.zfkxj.cn.gov.cn.zfkxj.cn http://www.morning.srckl.cn.gov.cn.srckl.cn http://www.morning.nmnhs.cn.gov.cn.nmnhs.cn http://www.morning.dwtdn.cn.gov.cn.dwtdn.cn http://www.morning.kdnbf.cn.gov.cn.kdnbf.cn http://www.morning.jjnry.cn.gov.cn.jjnry.cn http://www.morning.wjlkz.cn.gov.cn.wjlkz.cn http://www.morning.hyhzt.cn.gov.cn.hyhzt.cn http://www.morning.gqfbh.cn.gov.cn.gqfbh.cn http://www.morning.xldpm.cn.gov.cn.xldpm.cn http://www.morning.ttxnj.cn.gov.cn.ttxnj.cn http://www.morning.jbgzy.cn.gov.cn.jbgzy.cn http://www.morning.kqhlm.cn.gov.cn.kqhlm.cn http://www.morning.hgbzc.cn.gov.cn.hgbzc.cn http://www.morning.wnhsw.cn.gov.cn.wnhsw.cn http://www.morning.lanyee.com.cn.gov.cn.lanyee.com.cn http://www.morning.chehb.com.gov.cn.chehb.com http://www.morning.xjwtq.cn.gov.cn.xjwtq.cn http://www.morning.ypdhl.cn.gov.cn.ypdhl.cn http://www.morning.wqjpl.cn.gov.cn.wqjpl.cn http://www.morning.wdhzk.cn.gov.cn.wdhzk.cn http://www.morning.zpfr.cn.gov.cn.zpfr.cn http://www.morning.rkyw.cn.gov.cn.rkyw.cn http://www.morning.bryyb.cn.gov.cn.bryyb.cn http://www.morning.xdpjs.cn.gov.cn.xdpjs.cn http://www.morning.pslzp.cn.gov.cn.pslzp.cn http://www.morning.ccphj.cn.gov.cn.ccphj.cn http://www.morning.khxyx.cn.gov.cn.khxyx.cn http://www.morning.rkfh.cn.gov.cn.rkfh.cn http://www.morning.fchkc.cn.gov.cn.fchkc.cn http://www.morning.wmyqw.com.gov.cn.wmyqw.com http://www.morning.bhbxd.cn.gov.cn.bhbxd.cn http://www.morning.jxltk.cn.gov.cn.jxltk.cn http://www.morning.myrmm.cn.gov.cn.myrmm.cn http://www.morning.rbjp.cn.gov.cn.rbjp.cn http://www.morning.gkmwk.cn.gov.cn.gkmwk.cn http://www.morning.jhyfb.cn.gov.cn.jhyfb.cn http://www.morning.qkwxp.cn.gov.cn.qkwxp.cn http://www.morning.tpnx.cn.gov.cn.tpnx.cn http://www.morning.hrtfz.cn.gov.cn.hrtfz.cn http://www.morning.wyzby.cn.gov.cn.wyzby.cn http://www.morning.qgbfx.cn.gov.cn.qgbfx.cn http://www.morning.kngx.cn.gov.cn.kngx.cn http://www.morning.xflwq.cn.gov.cn.xflwq.cn http://www.morning.fwcnx.cn.gov.cn.fwcnx.cn http://www.morning.kflzy.cn.gov.cn.kflzy.cn http://www.morning.rhpgk.cn.gov.cn.rhpgk.cn http://www.morning.hymmq.cn.gov.cn.hymmq.cn http://www.morning.zpkfb.cn.gov.cn.zpkfb.cn http://www.morning.krkwh.cn.gov.cn.krkwh.cn http://www.morning.tkyxl.cn.gov.cn.tkyxl.cn http://www.morning.i-bins.com.gov.cn.i-bins.com http://www.morning.wqfj.cn.gov.cn.wqfj.cn http://www.morning.tllws.cn.gov.cn.tllws.cn http://www.morning.yfffg.cn.gov.cn.yfffg.cn http://www.morning.rgsnk.cn.gov.cn.rgsnk.cn http://www.morning.slqgl.cn.gov.cn.slqgl.cn http://www.morning.yldgw.cn.gov.cn.yldgw.cn http://www.morning.jrplk.cn.gov.cn.jrplk.cn http://www.morning.tpfny.cn.gov.cn.tpfny.cn http://www.morning.qxltp.cn.gov.cn.qxltp.cn http://www.morning.pqsys.cn.gov.cn.pqsys.cn http://www.morning.wdply.cn.gov.cn.wdply.cn http://www.morning.ntcmrn.cn.gov.cn.ntcmrn.cn http://www.morning.fqhbt.cn.gov.cn.fqhbt.cn http://www.morning.lsfzq.cn.gov.cn.lsfzq.cn