本文主要是介绍OpenCV轮廓、多边形逼近、关键点、周长和面积、边界框、矩、轮廓树、凹凸包、几何直方图、匹配,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
1.轮廓的多边形逼近
2.轮廓的关键点
3.轮廓的周长和面积
4.轮廓的边界框
5.轮廓的矩
6.轮廓的轮廓树
9.轮廓的匹配
1.轮廓的多边形逼近
2.轮廓的关键点
3.轮廓的周长和面积
4.轮廓的边界框
5.轮廓的矩
在连续情况下,图像函数为 f(x,y),那么图像的p+q阶几何矩(标准矩)定义为:
p ,q = 0,1,2……
p+q阶中心距定义为:
其中和代表图像的重心,
,
对于离散的数字图像,采用求和号代替积分:
,,p,q = 0,1,2 ……
N和M分别是图像的高度和宽度;
归一化的中心距定义为:;其中
在公式中,p对应x维度上的矩,q对应y维度上的矩,阶数表示对应的部分的指数。该计算是对轮廓界上所有像素(数目为n)进行求和。如果p和q全部为0,那么m00实际上对应轮廓边界上点的数目。
虽然可以直接计算出轮廓的矩,但是经常会用到归一化的矩(因此不同大小但是形状相同的物体会有相同的值)。同样,简单的矩依赖于所选坐标系,这意味着物体旋转后就无法正确匹配。
于是就产生了Hu矩以及其他归一化矩的函数。
Hu矩是归一化中心矩的线性组合。之所以这样做是为了能够获取代表图像某个特征的矩函数。这些矩函数对缩放,旋转和镜像映射出了(h1)具有不变性。
Hu矩是从中心矩中计算得到。即七个由归一化中心矩组合成的矩:
6.轮廓的轮廓树
结果的二分树最终将原始轮廓的形状性比编码。每个节点被它所对应的三角形的信息所注释。
这样建立的轮廓树并不太鲁棒,因为轮廓上小的改变也可能会彻底改变结果的树,同时最初的三角形是任意选取的。为了得到较好的描述需要首先使用函数cvApproxPoly()之后将轮廓排列(运用循环移动)成最初的三角形不怎么收到旋转影响的状态。
9.轮廓的匹配
1>Hu矩匹配
2>轮廓树匹配
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, storage1, &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, storage2, &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, storage1, &first_contour1, sizeof(CvContour), CV_RETR_LIST ); CvContourTree* tree1 = cvCreateContourTree( first_contour1, storage1, 200 ); 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, storage2, &first_contour2, sizeof(CvContour), CV_RETR_LIST ); CvContourTree* tree2 = cvCreateContourTree( first_contour2, storage2, 200 ); 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)
{
int retval; 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.width;
//s2 = b->rect.height * b->rect.width;
if(s1 < s2)
{
retval = 1;
}
else if(s1 == s2)
{
retval = 0;
}
else
{
retval = -1;
}
return retval;
}
//src:BGR dst:
void gesFindContours(IplImage* src, IplImage* dst, CvSeq** templateContour,
CvMemStorage* templateStorage, int flag) {
int count;//轮廓数
IplImage* gray;
CvMemStorage* first_sto;
CvMemStorage* all_sto;
CvSeq* first_cont;
CvSeq* all_cont; CvSeq* cur_cont; //初始化动态内存
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) { return; }
//将所有的轮廓都放到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)
{ CvSeq* contour;
CvMemStorage* storage;
//初始化动态内存
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* contour; CvSeq* cur_cont;
CvMemStorage* storage;
double minValue, tempValue;
int i, minIndex;
//初始化动态内存
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->total;i++)
{ cur_cont = (CvSeq* )cvGetSeqElem(templateContour, i); tempValue = cvMatchShapes((CvContour* )contour, (CvContour* )cur_cont, CV_CONTOURS_MATCH_I3); if(tempValue < minValue) { minValue = tempValue; minIndex = i; } printf("%d:%.2fn", i, tempValue); } if(minValue >= 0.3) { minIndex = -1; }
}
//打印匹配结果
printf("the result is %dn", minIndex);
//释放内存
cvReleaseMemStorage(&storage); return minIndex;
}
//找出轮廓最大的5个极大值点
void gesFindContourMaxs(CvSeq* contour)
{
int i; CvScalar center;//重心位置
CvPoint* p; CvMat max;//存储5个极大值的数组
double initMax[] = {-1, -1, -1, -1, -1};//初始极大值设置为-1
double minValue, maxValue;
//5个极大值中的最大值与最小值
CvPoint minLoc;//最小值的位置
double preDistance = 0;
bool isCandidate = false;//是否是候选的极大值点
//初始化重心位置
center = cvScalarAll(0);
//初始化极大值矩阵
max = cvMat(1, 5, CV_64FC1, initMax);
//首先求出轮廓的重心
for(i = 0;i < contour->total;i++)
{ p = (CvPoint* )cvGetSeqElem(contour, i); center.val[0] += p->x; center.val[1] += p->y;
} center.val[0] /= contour->total; center.val[1] /= contour->total;
//遍历轮廓,找出所有的极大值点
for(i = 0;i < contour->total;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 = true;
}
else if(distance < preDistance && isCandidate == true)
{ cvMinMaxLoc(&max, &minValue, &maxValue, &minLoc); if(distance > minValue) { cvmSet(&max, minLoc.y, minLoc.x, distance); } isCandidate = false;
}
else
{ isCandidate = false; } preDistance = distance;
}
//打印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* hist;//成对几何直方图
CvContour* tempCont;
//得到成对几何直方图第二个维度上的范围
tempCont = (CvContour* )contour; 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); return hist;
}
//对轮廓的pair-wise几何直方图进行匹配
void gesMatchContoursPGH(CvSeq* contour, CvHistogram* templateHist)
{ CvHistogram* hist;
//得到轮廓的成对几何直方图
hist = gesCalcContoursPGH(contour);
//归一化直方图
cvNormalizeHist(templateHist, 1); cvNormalizeHist(hist, 1);
//直方图匹配
double result = cvCompareHist(hist, templateHist, CV_COMP_INTERSECT);
printf("result:%.2fn", result);
//释放内存
cvReleaseHist(&hist);
}
这篇关于OpenCV轮廓、多边形逼近、关键点、周长和面积、边界框、矩、轮廓树、凹凸包、几何直方图、匹配的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!