#include "cv.h"
#include "highgui.h"
#include "iostream"
#include "windows.h"
using namespace std;
using namespace cv;
int main()
{
Mat image;
image = cv::imread("2.bmp",0);
//每条轮廓都是一个vector<Point>;所有轮廓存储在vector<vector<Point>>中
std::vector<std::vector<cv::Point>> contours;
cv::findContours(image,contours,
CV_RETR_EXTERNAL, //检索外轮廓(忽略孔)
CV_CHAIN_APPROX_NONE);
// Eliminate too short or too long contours
int cmin = 100; // minimum contour length
int cmax = 1000; //maximum contour length
//创建迭代器,搜索满足条件的(轮廓长度在100到1000之间的轮廓)
std::vector<std::vector<cv::Point>>::
const_iterator itc = contours.begin();
while (itc!=contours.end())
{
if (itc->size()<cmin||itc->size()>cmax)
{
//不满足条件的轮廓,用erase函数清除
itc = contours.erase(itc);
}
else
++itc;
}
//创建显示结果的图像,type为 8位无符号整形。
Mat resultimage(image.size(),CV_8U,cv::Scalar(255));
//testing the bouding box
//创建矩形边框的轮廓约束
cv::Rect r0 = cv::boundingRect(cv::Mat(contours[0]));
//绘制边框
cv::rectangle(resultimage,r0,cv::Scalar(0),2);
//testing the enclosing circle
//创建圆形边框的轮廓约束
float radius; //半径
cv::Point2f center; //圆心
cv::minEnclosingCircle(cv::Mat(contours[1]),center,radius);
//绘制轮廓半径
cv::circle(resultimage,cv::Point(center),
static_cast<int>(radius),cv::Scalar(0),2);
//testing the approximate polygon
//用非凸多边形约束轮廓边界
std::vector<cv::Point>poly; //创建ploy轮廓点向量容器
cv::approxPolyDP(cv::Mat(contours[3]),poly,5,true); //多边形逼近
//Iterate over each segment and draw it
//迭代器方法将ploy容器中保存的点集用line连起来
std::vector<cv::Point>::const_iterator itp =poly.begin();
while (itp!=(poly.end()-1))
{
cv::line(resultimage,*itp,*(itp+1),cv::Scalar(0),2);
++itp;
}
//last point linked to first point
//使轮廓首位相接
cv::line(resultimage,*(poly.begin()),*(poly.end()-1),cv::Scalar(20),2);
//testing the convex hull
//用凸多边形约束轮廓
std::vector<cv::Point> hull; //创建hull轮廓向量容器,存储点集
cv::convexHull(cv::Mat(contours[2]),hull); //凸多边形逼近
//Iterate over each segment and draw it
//用与非凸多边形约束绘制方法相同的方法绘制凸多边形边界,
//迭代器方法将hull容器中保存的点集用line函数链接起来
std::vector<cv::Point>::const_iterator ith =hull.begin();
while (ith!=(hull.end()-1))
{
cv::line(resultimage,*ith,*(ith+1),cv::Scalar(0),2);
++ith;
}
//last point linked to first point
//边界首位相接
cv::line(resultimage,*(hull.begin()),*(hull.end()-1),cv::Scalar(20),2);
//testing the moments计算轮廓的矩,中心位置
//iterate over all contours
itc = contours.begin();
while(itc!=contours.end())
{
//compute all moments
cv::Moments mom = cv::moments(cv::Mat(*itc++));
//draw mass center
cv::circle(resultimage,
//position of mass center converted to integer
cv::Point(mom.m10/mom.m00,mom.m01/mom.m00),
2,cv::Scalar(0),2);
}
cv::drawContours(resultimage,contours,
-1,cv::Scalar(0),1);
cv::namedWindow("imagecontour");cv::imshow("imagecontour",resultimage);
cv::waitKey(0);
}
关于书里面在用凸多边形逼近轮廓的部分,只完成了逼近的工作,将凸的多边形点集存储到hull向量容器中,但并没有做绘制的工作。其实绘制的方法与用approxPolyDP一般多边形逼近后绘制的方法相同,创建一个hull容器下的迭代器,用line函数连接相邻两点,最后令轮廓的首位像素相接即可