博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
OpenCV —— 直方图与匹配
阅读量:5322 次
发布时间:2019-06-14

本文共 5637 字,大约阅读时间需要 18 分钟。

直方图就是对数据进行统计,将统计值组织到一系列事先定义好的bin中。bin中的数值是从数据中计算出来的特征的统计量,这些数据可以是诸如梯度,方向,色彩或任何其他特征。

直方图获得是是数据分布的统计图

直方图的基本数据结构 CvHistogram

创建一个新的直方图 cvCreateHist

dims   直方图维数的数目

sizes  直方图维数尺寸的数组

type  直方图的表示格式: CV_HIST_ARRAY 意味着直方图为多维密集数组 CvMatND; CV_HIST_TREE 意味着直方图数据表示为多维稀疏数组 CvSparseMat.

ranges  图中方块范围的. 它的内容取决于参数 uniform 的值。这个范围的用处是确定何时计算直方图或决定反向映射(backprojected ),每个方块对应于输入图像的哪个/哪组值。

uniform  归一化标识。 如果不为0,则ranges[i](0<=i<cDims,译者注:cDims为直方图的维数,对于灰度图为1,彩色图为3)是包含两个元素的范围,包括直方图第i维的上界和下界。在第i维上的整个区域 [lower,upper]被分割成 dims[i] 个相等的块(译者注:dims[i]表示直方图第i维的块数),这些块用来确定输入象素的第 i 个值(译者注:对于彩色图像,i确定R, G,或者B)的对应的块;如果为0,则ranges[i]是包含dims[i]+1个元素的范围,包括lower0, upper0, lower1, upper1 == lower2, ..., upperdims[i]-1, 其中lowerj 和upperj分别是直方图第i维上第 j 个方块的上下界(针对输入象素的第 i 个值)。任何情况下,输入值如果超出了一个直方块所指定的范围外,都不会被 cvCalcHist 计数,而且会被函数 cvCalcBackProject 置零。

cvSetHistBinRanges —— 在使用直方图之前给rangs设置数值

cvSetHistRanges()

cvClearHist  对直方图进行清零         cvReleaseHist   释放直方图

cvMakeHistHeaderForArray  根据已给出的数据创建直方图  (直方图的内部数据类型描述永远是浮点数)

 

访问直方图

cvQueryHistValue_1D     cvQueryHistValue_2D    cvQueryHistValue_3D  每个函数都返回相应bin中的值的浮点数,同样,可以利用函数返回的bin的指针来设置直方图bin的值

cvGetHistValue_1D   cvGetHistValue_2D 

在稀疏直方图中,如果想利用函数 GetHist*() 来访问不存在的bin,这个不存在的bin会被自动创建,并且其值被设置为0

直方图的基本操作

cvNormalizeHist  归一化直方图

cvThreshHist   直方图阈值函数,小于给定阈值的各个bin都被社为0

cvCopyHist   将一个直方图的信息复制到另一个直方图

cvGetMinMaxHistValue  输出直方图中找到的最小值和最大值 (如果不需要其中的一个,可以设置为NULL)

cvCalcHist  自动从图像中计算直方图 (对于多通道图像,先要用函数cvSplit将图像分为单通道的)

对比两个直方图

cvCompareHist

相关 CV_COMP_CORREL 线性相关 —— 两个向量协方差除以两个变量的标准差

卡方 CV_COMP_CHISQR  低分比高分的匹配程度高,完全匹配的值为0

直方图相交  CV_COMP_INTERSECT  高分表示好匹配

Bhattacharyya  距离  CV_COMP_BHATTACHARYYA  低分表示好匹配

在对比直方图之前,都应该自行进行归一化操作,因为如果不规一化,没有任何意义

// 直方图的计算与显示#include 
#include
int main(int argc,char** argv){ IplImage* src=cvLoadImage("wukong.jpg",CV_LOAD_IMAGE_COLOR); IplImage* hsv=cvCreateImage(cvGetSize(src),8,3); cvCvtColor(src,hsv,CV_RGB2HSV); IplImage* h_plane=cvCreateImage(cvGetSize(src),8,1); IplImage* s_plane=cvCreateImage(cvGetSize(src),8,1); IplImage* v_plane=cvCreateImage(cvGetSize(src),8,1); IplImage* planes[]={h_plane,s_plane}; cvCvtPixToPlane(hsv,h_plane,s_plane,v_plane,0); int h_bins=30,s_bins=32; CvHistogram* hist; { int hist_size[]={h_bins,s_bins}; float h_ranges[]={
0,180}; float s_ranges[]={
0,255}; float* ranges[]={h_ranges,s_ranges}; hist=cvCreateHist(2,hist_size,CV_HIST_ARRAY,ranges,1); } cvCalcHist(planes,hist,0,0); cvNormalizeHist(hist,1.0); int scale=10; IplImage* hist_img=cvCreateImage(cvSize(h_bins*scale,s_bins*scale),8,3); cvZero(hist_img); float max_value=0; cvGetMinMaxHistValue(hist,0,&max_value,0,0); for (int h=0;h

陆地移动距离

光线引起图像颜色值的漂移(没有改变颜色直方图的形状,但引起了颜色位置的变化,导致匹配策略失效)

陆地移动距离 —— 实际上度量的是怎样将一个直方图的形状转变为另一个直方图的形状,包括移动直方图的部分到一个新的位置,可以在任何维的直方图上进行这种度量

EMD 算法本身是一个通用的算法 —— 允许用户自己设置距离度量或者自己的移动代价矩阵  cvCalcEMD2

#include 
#include 
#include 
 
int main(int argc, char** argv)
{
IplImage *src = cvLoadImage("wukong.jpg",CV_LOAD_IMAGE_COLOR);
IplImage *hsv = cvCreateImage(cvGetSize(src),8,3);
cvCvtColor(src,hsv,CV_BGR2HSV);
IplImage *h_plane = cvCreateImage(cvGetSize(src),8,1);
IplImage *s_plane = cvCreateImage(cvGetSize(src),8,1);
IplImage *v_plane = cvCreateImage(cvGetSize(src),8,1);
IplImage *planes[]={h_plane,s_plane};
cvSplit(hsv,h_plane,s_plane,v_plane,0);
 
//求得直方图
int h_bins=30,s_bins=32;
CvHistogram *hist1,*hist2;
int size[]={h_bins,s_bins};
float h_ranges[]={0,180};
float s_ranges[]={0,255};
float *ranges[]={h_ranges,s_ranges};
 
hist1=cvCreateHist(2,size,CV_HIST_ARRAY,ranges,1);
cvCalcHist(planes,hist1,0,0);//只能一个通道一个通道的写入直方图,所以上面分成H、S、V
cvNormalizeHist(hist1,1.0);//归一化直方图,使所有块的值加起来为1
hist2=cvCreateHist(2,size,CV_HIST_ARRAY,ranges,1);
cvCalcHist(planes,hist2,0,0);
cvNormalizeHist(hist2,1.0);
 
//求得signature用于比较直方图
CvMat *sig1,*sig2;
int numrows=h_bins*s_bins;
sig1=cvCreateMat(numrows,3,CV_32FC1);//由于是2维图像直方图,所以只需保存每个点的(值,横坐标,纵坐标)三个数,一共numrows个点
sig2=cvCreateMat(numrows,3,CV_32FC1);
for(int h=0;h
{
for(int s=0;s
{
float bin_val=cvQueryHistValue_2D(hist1,h,s);
cvSet2D(sig1,h*s_bins+s,0,cvScalar(bin_val));
cvSet2D(sig1,h*s_bins+s,1,cvScalar(h));
cvSet2D(sig1,h*s_bins+s,2,cvScalar(s));
bin_val=cvQueryHistValue_2D(hist2,h,s);
cvSet2D(sig2,h*s_bins+s,0,cvScalar(bin_val));
cvSet2D(sig2,h*s_bins+s,1,cvScalar(h));
cvSet2D(sig2,h*s_bins+s,2,cvScalar(s));
}
}
float emd=cvCalcEMD2(sig1,sig2,CV_DIST_L2);
 
cout<
<
return 0;
}

反向投影

一种记录像素点或像素块如何适应直方图模型中分布的方式  —— 有一个颜色直方图,可以利用反向投影在图象中找到该区域

cvCalcBackProject —— 在输入图像平面上的滑动块来设置目标图像上相应的像素(块的中心);对于归一化直方图模型来说,结果图像可以被解释为一个概率图(存储的数值代表了该像素属于皮肤区域的概率)

可以通过 cvMinMaxLoc () 来寻找目标


模板匹配

cvMatchTemplate —— 在另一幅图像上移动模板图像块来寻找匹配

CV_TM_SQDIFF 平方差匹配法

CV_TM_CCORR 相关匹配法

CV_TM_CCOEFF 相关匹配法

归一化方法

#include 
#include
#include
#include
int main(int argc,char** argv){ IplImage *src,*templ,*ftmp[6]; // ftmp 用来保存结果 int i; src=cvLoadImage("wukong.jgp",CV_LOAD_IMAGE_COLOR); templ=cvLoadImage("templ.jpg",CV_LOAD_IMAGE_COLOR); int iwidth=src->width-templ->width+1; int iheight=src->height-templ->height+1; for (i=0;i<6;i++) { ftmp[i]=cvCreateImage(cvSize(iwidth,iheight),32,1); } for (i=0;i<6;i++) { cvMatchTemplate(src,templ,ftmp[i],i); cvNormalize(ftmp[i],ftmp[i],1,0,CV_MINMAX); } cvNamedWindow("template",0); cvShowImage("template",templ); cvNamedWindow("image",0); cvShowImage("image",src); cvNamedWindow("sqdiff"); cvShowImage("sqdiff",ftmp[0]); // 各种显示太烦了,不写了 cvDestroyAllWindows();}

转载于:https://www.cnblogs.com/sprint1989/p/3809001.html

你可能感兴趣的文章
泛型子类_属性类型_重写方法类型
查看>>
eclipse-将同一个文件分屏显示
查看>>
NOIP2013提高组 解题报告
查看>>
Qt中文乱码解决思路
查看>>
mysql5.x升级至mysql5.7后导入之前数据库date出错的解决方法!
查看>>
[Apple开发者帐户帮助]六、配置应用服务(3)创建地图标识符和私钥
查看>>
poj2388---求奇数个数字的最中间的数
查看>>
对闭包的理解
查看>>
java.lang.OutOfMemoryError异常解决方法
查看>>
Css让文字自适应Table宽度[转]
查看>>
[Javascript] Flattening nested arrays: a little exercise in functional refactoring
查看>>
练习10-1 使用递归函数计算1到n之和(10 分
查看>>
使用maven构建多模块项目,分块开发
查看>>
Oracle MySQL yaSSL 不明细节缓冲区溢出漏洞2
查看>>
jffs2镜像制作
查看>>
windows编程ASCII问题
查看>>
.net webService代理类
查看>>
C#高级编程笔记(一)
查看>>
工作时如何利用空闲时间熟悉项目
查看>>
大道至简第五章读后感
查看>>