opencv 图像边界扩充如何实现计算2个边界点的最大距离

博主最新文章
博主热门文章
您举报文章:
举报原因:
原文地址:
原因补充:
(最多只允许输入30个字)opencv 轮廓的点到边界框的距离_百度知道
opencv 轮廓的点到边界框的距离
如题,现在有一个轮廓还有轮廓的边界框都得到了,但是我想计算一下轮廓上的点到边界框的距离,应该怎么办呢?
我有更好的答案
轮廓上点的像素值与背景像素值是不同的,可以根据这个差异来求取。求出每一行的像素值出现跳变的地方的位置,就得到轮廓上的点到边界框的距离了。
采纳率:47%
来自团队:
为您推荐:
其他类似问题
opencv的相关知识
换一换
回答问题,赢新手礼包
个人、企业类
违法有害信息,请在下方选择后提交
色情、暴力
我们会通过消息、邮箱等方式尽快将举报结果通知您。opencv(122)
1. 边界处理的类型
在图像处理中,经常需要空域或频域的滤波处理,在进入真正的处理程序前,需要考虑图像边界情况。
通常的处理方法是为图像增加一定的边缘,以适应 卷积核 在原图像边界的操作。
1. 增加边界的类型有以下4个类型:
以一行图像数据为例,abcdefgh是原图数据,|是图像边界,为原图加边
aaaaaa|abcdefgh|hhhhhhh
fedcba|abcdefgh|hgfedcb
gfedcb|abcdefgh|gfedcba
反射101,相当于上一行的左右互换
cdefgh|abcdefgh|abcdefg
iiiiii|abcdefgh|iiiiiii
with some specified 'i'
2. opencv的实现
opencv中有几处增加边界的实现,其源码分别散布在Utils.cpp,Filter.cpp,Ts_func.cpp中,功能和实现都基本相同。
以Utils的copyMakeBorder,及Filter中的borderInterpolate为例,这两种的代码风格比较通俗易懂。
边界处理的步骤:
首先,为目的图像(结果图像)分配内存,图像大小为size(src.rows + top + bottom, src.cols + left + right)
然后,以原图为基准,逐行处理,先扩展左边界,复制原图数据到目的图像,再扩展右边界。
最后,扩展上边界,以及下边界。
其中,每扩展一个边界像素,都需要计算出对应的原图中的位置,这个功能被提炼出来,就是borderInterpolate
int cv::borderInterpolate( int p, int len, int borderType )
if( (unsigned)p & (unsigned)len )
else if( borderType == BORDER_REPLICATE )
p = p & 0 ? 0 : len - 1;
else if( borderType == BORDER_REFLECT || borderType == BORDER_REFLECT_101 )
int delta = borderType == BORDER_REFLECT_101;
if( len == 1 )
if( p & 0 )
p = -p - 1 +
p = len - 1 - (p - len) -
while( (unsigned)p &= (unsigned)len );
else if( borderType == BORDER_WRAP )
if( p & 0 )
p -= ((p-len+1)/len)*
if( p &= len )
else if( borderType == BORDER_CONSTANT )
CV_Error( CV_StsBadArg, "Unknown/unsupported border type" );
非常量类型边界扩展:
static void copyMakeBorder_8u( const uchar* src, size_t srcstep, Size srcroi,
uchar* dst, size_t dststep, Size dstroi,
int top, int left, int cn, int borderType )
const int isz = (int)sizeof(int);
int i, j, k, elemSize = 1;
bool intMode = false;
if( (cn | srcstep | dststep | (size_t)src | (size_t)dst) % isz == 0 )
elemSize =
intMode = true;
AutoBuffer&int& _tab((dstroi.width - srcroi.width)*cn);
int* tab = _
int right = dstroi.width - srcroi.width -
int bottom = dstroi.height - srcroi.height -
for( i = 0; i & i++ )
j = borderInterpolate(i - left, srcroi.width, borderType)*
for( k = 0; k & k++ )
tab[i*cn + k] = j +
for( i = 0; i & i++ )
j = borderInterpolate(srcroi.width + i, srcroi.width, borderType)*
for( k = 0; k & k++ )
tab[(i+left)*cn + k] = j +
srcroi.width *=
dstroi.width *=
uchar* dstInner = dst + dststep*top + left*elemS
for( i = 0; i & srcroi. i++, dstInner += dststep, src += srcstep )
if( dstInner != src )
memcpy(dstInner, src, srcroi.width*elemSize);
if( intMode )
const int* isrc = (int*)
int* idstInner = (int*)dstI
for( j = 0; j & j++ )
idstInner[j - left] = isrc[tab[j]];
for( j = 0; j & j++ )
idstInner[j + srcroi.width] = isrc[tab[j + left]];
for( j = 0; j & j++ )
dstInner[j - left] = src[tab[j]];
for( j = 0; j & j++ )
dstInner[j + srcroi.width] = src[tab[j + left]];
dstroi.width *= elemS
dst += dststep*
for( i = 0; i & i++ )
j = borderInterpolate(i - top, srcroi.height, borderType);
memcpy(dst + (i - top)*dststep, dst + j*dststep, dstroi.width);
for( i = 0; i & i++ )
j = borderInterpolate(i + srcroi.height, srcroi.height, borderType);
memcpy(dst + (i + srcroi.height)*dststep, dst + j*dststep, dstroi.width);
常量类型的扩展就更简单了:
static void copyMakeConstBorder_8u( const uchar* src, size_t srcstep, Size srcroi,
uchar* dst, size_t dststep, Size dstroi,
int top, int left, int cn, const uchar* value )
AutoBuffer&uchar& _constBuf(dstroi.width*cn);
uchar* constBuf = _constB
int right = dstroi.width - srcroi.width -
int bottom = dstroi.height - srcroi.height -
for( i = 0; i & dstroi. i++ )
for( j = 0; j & j++ )
constBuf[i*cn + j] = value[j];
srcroi.width *=
dstroi.width *=
uchar* dstInner = dst + dststep*top +
for( i = 0; i & srcroi. i++, dstInner += dststep, src += srcstep )
if( dstInner != src )
memcpy( dstInner, src, srcroi.width );
memcpy( dstInner - left, constBuf, left );
memcpy( dstInner + srcroi.width, constBuf, right );
dst += dststep*
for( i = 0; i & i++ )
memcpy(dst + (i - top)*dststep, constBuf, dstroi.width);
for( i = 0; i & i++ )
memcpy(dst + (i + srcroi.height)*dststep, constBuf, dstroi.width);
对于medianBlur( InputArray _src0, OutputArray _dst, int ksize )的边界扩展方式是 重复复制最边缘像素 BORDER_REPLICATE。
文章:10篇
阅读:34432387人阅读
OpenCV(4)
1.轮廓的多边形逼近&
2.轮廓的关键点&
3.轮廓的周长和面积&
4.轮廓的边界框&
5.轮廓的矩&
6.轮廓的轮廓树&&
7.轮廓的凸包和凸缺陷&
8.轮廓的成对几何直方图&&
9.轮廓的匹配
&&&轮廓的特性:
1.轮廓的多边形逼近
&&&&轮廓的多边形逼近指的是:使用多边形来近似表示一个轮廓。
&&&&多边形逼近的目的是为了减少轮廓的顶点数目。
&&&&多边形逼近的结果依然是一个轮廓,只是这个轮廓相对要粗旷一些。
&&& 可以使用方法cvApproxPoly()
2.轮廓的关键点
&&&&轮廓的关键点是:轮廓上包含曲线信息比较多的点。关键点是轮廓顶点的子集。
&&&&可以使用cvFindDominantPoints函数来获取轮廓上的关键点,该函数返回的结果一个包含 关键点在轮廓顶点中索引 的序列。再次强调:是索引,不是具体的点。如果要得到关键点的具体坐标,可以用索引到轮廓上去找。
3.轮廓的周长和面积
&&&&轮廓的周长可以用cvContourPerimeter或者cvArcLength函数来获取。
&&&&轮廓的面积可以用cvContourArea函数来获取。
4.轮廓的边界框
&&&&有三种常见的边界框:矩形、圆形、椭圆。
&&&&(1)矩形:在图像处理系统中提供了一种叫Rectangle的矩形,不过它只能表达边垂直或水平的特例;OpenCv中还有一种叫Box的矩形,它跟数学上的矩形一致,只要4个角是直角即可。
&&&&如果要获取轮廓的Rectangle,可以使用cvBoundingRect函数。
&&&&如果要获取轮廓的Box,可以使用cvMinAreaRect2函数。
&&&&(2)圆形
&&&&如果要获取轮廓的圆形边界框,可以使用cvMinEnclosingCircle函数。
&&&&(3)椭圆
&&&&如果要获取轮廓的椭圆边界框,可以使用cvFitEllipse2函数。
5.轮廓的矩
&&&&矩是通过对轮廓上所有点进行积分运算(或者认为是求和运算)而得到的一个粗略特征。
在连续情况下,图像函数为&f(x,y),那么图像的p+q阶几何矩(标准矩)定义为:
p ,q = 0,1,2……&
p+q阶中心距定义为:
&p,q = 0,1,2……
其中和代表图像的重心,
对于离散的数字图像,采用求和号代替积分:
= 0,1,2 ……
N和M分别是图像的高度和宽度;
归一化的中心距定义为:;其中
在公式中,p对应x维度上的矩,q对应y维度上的矩,阶数表示对应的部分的指数。该计算是对轮廓界上所有像素(数目为n)进行求和。如果p和q全部为0,那么m00实际上对应轮廓边界上点的数目。
虽然可以直接计算出轮廓的矩,但是经常会用到归一化的矩(因此不同大小但是形状相同的物体会有相同的值)。同样,简单的矩依赖于所选坐标系,这意味着物体旋转后就无法正确匹配。
于是就产生了Hu矩以及其他归一化矩的函数。
Hu矩是归一化中心矩的线性组合。之所以这样做是为了能够获取代表图像某个特征的矩函数。这些矩函数对缩放,旋转和镜像映射出了(h1)具有不变性。
Hu矩是从中心矩中计算得到。即七个由归一化中心矩组合成的矩:&&
&其中中心矩和归一化中心矩的定义为:
&&&我们可以使用cvContoursMoments函数、cvMoments函数方便的得到轮廓的矩集,然后再相应的方法或函数获取各种矩。
&&&&特定的矩:cvGetSpatialMoment函数
&&&&中心矩:cvGetCentralMoment函数
&&&&归一化中心矩:cvGetNormalizedCentralMoment函数
&&&&Hu矩:cvGetHuMoments函数
6.轮廓的轮廓树
&&&&轮廓树用来描述某个特定轮廓的内部特征。注意:轮廓树跟轮廓是一一对应的关系;轮廓树不用于描述多个轮廓之间的层次关系。
&&&&轮廓树的创建过程:
&&&&从一个轮廓创建一个轮廓树是从底端(叶子节点)到顶端(根节点)的。首先搜索三角形突出或者凹陷的形状的周边(轮廓上的每一个点都不是完全和它的相邻点共线的)每个这样的三角形被一条线段代替,这条线段通过连接非相邻点的两点得到;因此实际上三角形或者被削平或者被填满。每个这样的替换都把轮廓的顶点减少,并且给轮廓树创建一个新节点。如果这样的一个三角形的两侧有原始边,那么她就是得到的轮廓树的叶子;如果一侧已是一个三角形,那么它就是那个三角形的父节点。这个过程的迭代最终把物体的外形简称一个四边形,这个四边形也被剖开;得到的两个三角形是根节点的两个子节点。
结果的二分树最终将原始轮廓的形状性比编码。每个节点被它所对应的三角形的信息所注释。
这样建立的轮廓树并不太鲁棒,因为轮廓上小的改变也可能会彻底改变结果的树,同时最初的三角形是任意选取的。为了得到较好的描述需要首先使用函数cvApproxPoly()之后将轮廓排列(运用循环移动)成最初的三角形不怎么收到旋转影响的状态。
&&&&可以用函数cvCreateContourTree来构造轮廓树。
&7.轮廓的凸包和凸缺陷
&&&&轮廓的凸包和凸缺陷用于描述物体的外形。凸包和凸缺陷很容易获得,不过我目前不知道它们到底怎么使用。
&&&&如果要判断轮廓是否是凸的,可以用cvCheckContourConvexity函数。
&&&&如果要获取轮廓的凸包,可以用cvConvexHull2函数,返回的是包含顶点的序列。
&&&&如果要获取轮廓的凸缺陷,可以用cvConvexityDefects函数。
&8.轮廓的成对几何直方图
&&&&成对几何直方图(pairwise geometrical histogram PGH)是链码编码直方图(chain code histogram CCH)的一个扩展或者延伸。CCH是一种直方图,用来统计一个轮廓的Freeman链码编码每一种走法的数字。这种直方图的一个优良性质为当物体旋转45度,那么新直方图是老直方图的循环平移。这样就可以不受旋转影响。
&&&&(1)轮廓保存的是一系列的顶点,轮廓是由一系列线段组成的多边形。对于看起来光滑的轮廓(例如圆),只是线段条数比较多,线段长度比较短而已。实际上,电脑中显示的任何曲线都由线段组成。
&&&&(2)每两条线段之间都有一定的关系,包括它们(或者它们的延长线)之间的夹角,两条线段的夹角范围是:(0,180)。
&&&&(3)每两条线段上的点之间还有距离关系,包括最短(小)距离、最远(大)距离,以及平均距离。最大距离我用了一个偷懒的计算方法,我把轮廓外界矩形的对角线长度看作了最大距离。
&&&&(4)成对几何直方图所用的统计数据包括了夹角和距离。
9.轮廓的匹配
&&&&如果要比较两个物体,可供选择的特征很多。如果要判断某个人的性别,可以根据他(她)头发的长短来判断,这很直观,在长发男稀有的年代准确率也很高。也可以根据这个人尿尿的射程来判断,如果射程大于0.50米,则是男性。总之,方法很多,不一而足。
&&&&我们在上文中得到了轮廓的这么多特征,它们也可以用于进行匹配。典型的轮廓匹配方法有:Hu矩匹配、轮廓树匹配、成对几何直方图匹配。
&1&Hu矩匹配
&&&&轮廓的Hu矩对包括缩放、旋转和镜像映射在内的变化具有不变性。cvMatchShapes函数可以很方便的实现对2个轮廓间的匹配。
&2&轮廓树匹配
&&&&用树的形式比较两个轮廓。cvMatchContourTrees函数实现了轮廓树的对比。
&3&成对几何直方图匹配
&&&&在得到轮廓的成对几何直方图之后,可以使用直方图对比的方法来进行匹。
轮廓匹配源码1:
IplImage* img_8uc1 = cvLoadImage(&flower.jpg&,CV_LOAD_IMAGE_GRAYSCALE);
IplImage* img_edge1 = cvCreateImage(cvGetSize(img_8uc1),8,1);
IplImage* img_8uc3 = cvCreateImage(cvGetSize(img_8uc1),8,3);
cvThreshold(img_8uc1,img_edge1,128,255,CV_THRESH_BINARY);
CvMemStorage* storage1 = cvCreateMemStorage();
CvSeq* first_contour1 = NULL;
int Nc = cvFindContours(
img_edge1,
&first_contour1,
sizeof(CvContour),
CV_RETR_LIST
IplImage* img_8uc12 = cvLoadImage(&flower1.jpg&,CV_LOAD_IMAGE_GRAYSCALE);
IplImage* img_edge12 = cvCreateImage(cvGetSize(img_8uc12),8,1);
IplImage* img_8uc3 = cvCreateImage(cvGetSize(img_8uc1),8,3);
cvThreshold(img_8uc12,img_edge12,128,255,CV_THRESH_BINARY);
CvMemStorage* storage2 = cvCreateMemStorage();
CvSeq* first_contour2 = NULL;
int Nc2 = cvFindContours(
img_edge12,
&first_contour2,
sizeof(CvContour),
CV_RETR_LIST
double n = cvMatchShapes(first_contour1,first_contour2,CV_CONTOURS_MATCH_I1,0);
printf(&%d&,n);
cvWaitKey();
IplImage* img_8uc1 = cvLoadImage(&flower.jpg&,CV_LOAD_IMAGE_GRAYSCALE);
IplImage* img_edge1 = cvCreateImage(cvGetSize(img_8uc1),8,1);
IplImage* img_8uc3 = cvCreateImage(cvGetSize(img_8uc1),8,3);
cvThreshold(img_8uc1,img_edge1,128,255,CV_THRESH_BINARY);
CvMemStorage* storage1 = cvCreateMemStorage();
CvSeq* first_contour1 = NULL;
int Nc = cvFindContours(
img_edge1,
&first_contour1,
sizeof(CvContour),
CV_RETR_LIST
CvContourTree* tree1 = cvCreateContourTree(
first_contour1,
IplImage* img_8uc12 = cvLoadImage(&flower1.jpg&,CV_LOAD_IMAGE_GRAYSCALE);
IplImage* img_edge12 = cvCreateImage(cvGetSize(img_8uc12),8,1);
IplImage* img_8uc3 = cvCreateImage(cvGetSize(img_8uc1),8,3);
cvThreshold(img_8uc12,img_edge12,128,255,CV_THRESH_BINARY);
CvMemStorage* storage2 = cvCreateMemStorage();
CvSeq* first_contour2 = NULL;
int Nc2 = cvFindContours(
img_edge12,
&first_contour2,
sizeof(CvContour),
CV_RETR_LIST
CvContourTree* tree2 = cvCreateContourTree(
first_contour2,
double n = cvMatchContourTrees(tree1,tree1,CV_CONTOURS_MATCH_I1,200);
printf(&%d&,n);
cvWaitKey();
几何直方图匹配方:
#include &gesrec.h&
#include &stdio.h&
//////////////////////////////////////////
#define PI 3.14159f
//轮廓面积比较函数
static int gesContourCompFunc(const void* _a, const void* _b, void* userdata)
double s1, s2;
CvContour* a = (CvContour*)_a;
CvContour* b = (CvContour*)_b;
s1 = fabs(cvContourArea(a));
s2 = fabs(cvContourArea(b));
//s1 = a-&rect.height * a-&rect.
//s2 = b-&rect.height * b-&rect.
if(s1 & s2)
retval = 1;
else if(s1 == s2)
retval = 0;
retval = -1;
//src:BGR dst:
void gesFindContours(IplImage* src, IplImage* dst, CvSeq** templateContour,
CvMemStorage* templateStorage, int flag)
CvMemStorage* first_
CvMemStorage* all_
CvSeq* first_
CvSeq* all_
CvSeq* cur_
//初始化动态内存
first_sto = cvCreateMemStorage(0);
first_cont = cvCreateSeq(CV_SEQ_ELTYPE_POINT, sizeof(CvSeq), sizeof(CvPoint), first_sto);
all_sto = cvCreateMemStorage(0);
all_cont = cvCreateSeq(0, sizeof(CvSeq), sizeof(CvSeq), all_sto);
//创建源图像对应的灰度图像
gray = cvCreateImage(cvGetSize(src), IPL_DEPTH_8U, 1);
cvCvtColor(src, gray, CV_BGR2GRAY);
//得到图像的外层轮廓
count = cvFindContours(gray, first_sto, &first_cont, sizeof(CvContour), CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE);
//如果没有检测到轮廓则返回
if(first_sto == NULL) { }
//将所有的轮廓都放到first_cont中
for(;first_cont != 0;first_cont = first_cont-&h_next) { if(((CvContour* )first_cont)-&rect.height * ((CvContour* )first_cont)-&rect.width &=625) cvSeqPush(all_cont, first_cont); }
//对轮廓按照面积进行排序
cvSeqSort(all_cont, gesContourCompFunc, 0);
//在dst中画出轮廓
cvZero(dst);
for(int i = 0;i & min(all_cont-&total, 3);i++)//次数待改
cur_cont = (CvSeq* )cvGetSeqElem(all_cont, i);
if(flag != 0 && i == 0) {
*templateContour = cvCloneSeq(cur_cont, templateStorage);
CvScalar color = CV_RGB(rand()&255, rand()&255, rand()&255);
cvDrawContours(dst, (CvSeq* )cur_cont, color, color, -1, 1, 8);
//判断原点位置以确定是否需要反转图像
if(src-&origin == 1) {
cvFlip(dst);
//释放内存
cvReleaseMemStorage(&first_sto);
cvReleaseMemStorage(&all_sto);
cvReleaseImage(&gray);
void gesMatchContoursTemplate(IplImage* src, IplImage* dst, CvSeq** templateContour)
CvMemStorage*
//初始化动态内存
storage = cvCreateMemStorage(0);
contour = cvCreateSeq(CV_SEQ_ELTYPE_POINT, sizeof(CvSeq), sizeof(CvPoint), storage);
//得到轮廓并进行匹配
gesFindContours(src, dst, &contour, storage, 1);
if(contour-&total != 0)//如果得到的轮廓不为空
double result = cvMatchShapes((CvContour* )contour, (CvContour* )(*templateContour), CV_CONTOURS_MATCH_I3); printf(&%.2fn&, result);//
//释放内存
cvReleaseMemStorage(&storage); }
//模版匹配法的完整实现
int gesMatchContoursTemplate2(IplImage* src, IplImage* dst, CvSeq* templateContour)
CvSeq* CvSeq* cur_
CvMemStorage*
double minValue, tempV
int i, minI
//初始化动态内存
storage = cvCreateMemStorage(0);
contour = cvCreateSeq(CV_SEQ_ELTYPE_POINT, sizeof(CvSeq), sizeof(CvPoint), storage);
//得到轮廓并进行匹配
minIndex = -1; gesFindContours(src, dst, &contour, storage, 1);
if(contour-&total != 0)//如果得到的轮廓不为空
if(templateContour-&total != 0)
cur_cont = (CvSeq* )cvGetSeqElem(templateContour, 0);
minValue = cvMatchShapes((CvContour* )contour, (CvContour* )cur_cont, CV_CONTOURS_MATCH_I3);
minIndex = 0;
printf(&0:%.2fn&, minValue);
for(i = 1;i & templateContour-&i++)
cur_cont = (CvSeq* )cvGetSeqElem(templateContour, i);
tempValue = cvMatchShapes((CvContour* )contour, (CvContour* )cur_cont, CV_CONTOURS_MATCH_I3);
if(tempValue & minValue)
minValue = tempV minIndex = } printf(&%d:%.2fn&, i, tempValue);
if(minValue &= 0.3)
minIndex = -1;
//打印匹配结果
printf(&the result is %dn&, minIndex);
//释放内存
cvReleaseMemStorage(&storage);
return minI
//找出轮廓最大的5个极大值点
void gesFindContourMaxs(CvSeq* contour)
CvS//重心位置
CvPoint* CvM//存储5个极大值的数组
double initMax[] = {-1, -1, -1, -1, -1};//初始极大值设置为-1
double minValue, maxV
//5个极大值中的最大值与最小值
CvPoint minL//最小值的位置
double preDistance = 0;
bool isCandidate =//是否是候选的极大值点
//初始化重心位置
center = cvScalarAll(0);
//初始化极大值矩阵
max = cvMat(1, 5, CV_64FC1, initMax);
//首先求出轮廓的重心
for(i = 0;i & contour-&i++)
p = (CvPoint* )cvGetSeqElem(contour, i);
center.val[0] += p-&x; center.val[1] += p-&y;
center.val[0] /= contour-&
center.val[1] /= contour-&
//遍历轮廓,找出所有的极大值点
for(i = 0;i & contour-&i++)
p = (CvPoint* )cvGetSeqElem(contour, i);
double distance = sqrt(pow(center.val[0] - p-&x, 2) + pow(center.val[1] - p-&y, 2));
if(distance & preDistance)
isCandidate =
else if(distance & preDistance && isCandidate == true)
cvMinMaxLoc(&max, &minValue, &maxValue, &minLoc);
if(distance & minValue)
cvmSet(&max, minLoc.y, minLoc.x, distance);
isCandidate =
{ isCandidate = }
preDistance =
//打印5个极大值
printf(&%.2f %.2f %.2f %.2f %.2fn&, cvmGet(&max, 0, 0), cvmGet(&max, 0, 1), cvmGet(&max, 0, 2), cvmGet(&max, 0, 3), cvmGet(&max, 0, 4));
//计算轮廓的pair-wise几何直方图
CvHistogram* gesCalcContoursPGH(CvSeq* contour)
CvHistogram*//成对几何直方图
CvContour* tempC
//得到成对几何直方图第二个维度上的范围
tempCont = (CvContour* ) cvBoundingRect(tempCont, 1);
int sizes[2] = {60, 200}; float ranges[2][2] = {{0,PI}, {0,200}};
float** rangesPtr = new float* [2];
rangesPtr[0] = ranges[0]; rangesPtr[1] = ranges[1];
//初始化几何直方图
hist = cvCreateHist(2, sizes, CV_HIST_ARRAY, rangesPtr, 1);
//计算轮廓的成对几何直方图
cvCalcPGH(contour, hist);
//对轮廓的pair-wise几何直方图进行匹配
void gesMatchContoursPGH(CvSeq* contour, CvHistogram* templateHist)
CvHistogram*
//得到轮廓的成对几何直方图
hist = gesCalcContoursPGH(contour);
//归一化直方图
cvNormalizeHist(templateHist, 1); cvNormalizeHist(hist, 1);
//直方图匹配
double result = cvCompareHist(hist, templateHist, CV_COMP_INTERSECT);
printf(&result:%.2fn&, result);
//释放内存
cvReleaseHist(&hist);博主最新文章
博主热门文章
您举报文章:
举报原因:
原文地址:
原因补充:
(最多只允许输入30个字)

我要回帖

更多关于 opencv 图像边界扩充 的文章

 

随机推荐