有时需要对已有的图像进行处理,使其更清晰或更规则,轮廓检测可以达到这个目的。先介绍几个相关函数:
1.findContours函数
findContours( InputOutputArray image, OutputArrayOfArrays contours,
OutputArray hierarchy, int mode,
int method, Point offset=Point());
第一个参数:image,单通道图像矩阵,可以是灰度图,但更常用的是二值图像
第二个参数:contours,定义为“vector
第三个参数:hierarchy,表示层数,定义为“vector hierarchy”, 定义了一个“向量内每一个元素包含了4个int型变量”的向量。
第四个参数:int型的mode,定义轮廓的检索模式:
取值一:CV_RETR_EXTERNAL只检测最外围轮廓,包含在外围轮廓内的内围轮廓被忽略
取值二:CV_RETR_LIST 检测所有的轮廓,包括内围、外围轮廓,但是检测到的轮廓不建立等级关 系,彼此之间独立,没有等级关系,这就意味着这个检索模式下不存在父轮廓或内嵌轮廓, 所以hierarchy向量内所有元素的第3、第4个分量都会被置为-1,具体下文会讲到
取值三:CV_RETR_CCOMP 检测所有的轮廓,但所有轮廓只建立两个等级关系,外围为顶层,若外围 内的内围轮廓还包含了其他的轮廓信息,则内围内的所有轮廓均归属于顶层
取值四:CV_RETR_TREE, 检测所有轮廓,所有轮廓建立一个等级树结构。外层轮廓包含内层轮廓,内层轮廓还可以继续包含内嵌轮廓。
第五个参数:int型的method,定义轮廓的近似方法:
取值一:CV_CHAIN_APPROX_NONE 保存物体边界上所有连续的轮廓点到contours向量内
取值二:CV_CHAIN_APPROX_SIMPLE 仅保存轮廓的拐点信息,把所有轮廓拐点处的点保存入contours向量内,拐点与拐点之间直线段上的信息点不予保留
2.drawContours函数
void drawContours(InputOutputArray image,
InputArrayOfArrays contours, int contourIdx, const Scalar& color,
int thickness=1, int lineType=8, InputArray hierarchy=noArray(),
int maxLevel=INT_MAX, Point offset=Point() )
其中第一个参数image表示目标图像,
第二个参数contours表示输入的轮廓组,每一组轮廓由点vector构成,
第三个参数contourIdx指明画第几个轮廓,如果该参数为负值,则画全部轮廓,
第四个参数color为轮廓的颜色,
第五个参数thickness为轮廓的线宽,如果为负值或CV_FILLED表示填充轮廓内部,
第六个参数lineType为线型,
第七个参数为轮廓结构信息,
第八个参数为maxLevel
3.approxPolyDP函数
它是用来进行多边形逼近,可以将不规则的图形逼近成规则图形,方便处理
void approxPolyDP(InputArray curve, OutputArray approxCurve, double epsilon, bool closed)
InputArray curve:一般是由图像的轮廓点组成的点集
OutputArray approxCurve:表示输出的多边形点集
double epsilon:主要表示输出的精度,就是另个轮廓点之间最大距离数
bool closed:表示输出的多边形是否封闭,封闭可用true表示
下面举个例子来说明这些函数的用途,以便理解:
#include
#include //opencv申明
#include
#include
#include
#include "highgui.h"
using namespace std;
using namespace cv;
int dis,dis1,dis2,dis3,dis4,dis5,dis6;
int length(Point a,Point b)//两点间距离求边长
{
int d = (a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y);
dis = sqrt(d);
return dis;
}
int main()
{
int sum = 0;
Mat t_image,f_image,src;
vector hierarchy;
vector> contours;
Mat image = imread("D:\\program\\51.png",0);//读入模板图
Mat dstImg(image.size(), CV_8UC3, Scalar::all(0));//纯黑图像
int u1 = image.rows;//阈值化处理
int u2 = image.cols;
for (int i = 0; i < image.rows; i++)
{
for (int j = 0; j < image.cols; j++)
{
sum = sum + image.at(i, j);
}
}
int u = u1*u2;
int average = (int)sum/u*2;
threshold(image, src, average, 255, CV_THRESH_BINARY);
Canny(src,t_image,50,50);
imshow("阈值分割图",t_image);
waitKey(0);
findContours(t_image, contours, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE, Point(0, 0));//得到原图像轮廓点集
drawContours(dstImg, contours,-1, Scalar(0, 255, 255), 2, 8);//根据点集画出图像轮廓
imshow("轮廓图",dstImg);
waitKey(0);
vector> contours_poly(contours.size());//用于存放折线点集
for (int i = 0; i