多边形拟合处理轮廓

本文介绍了一种基于OpenCV的图像处理方法,包括开运算、闭运算等形态学操作,用于平滑轮廓并去除图像中的小细节。此外,还详细阐述了如何查找图像中的轮廓,并通过多项式拟合或凸包来简化这些轮廓,最后展示了如何计算每个区域的质量心及边界框。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

#include<vector>
#include"stdio.h"






#include"cmath"
#include"ctime"
#include"iostream"
#include<opencv2\opencv.hpp>




#include"cv.h"
#include"highgui.h"


#include"cstring"
using namespace std;


using namespace cv;


//Just some convienience macros
#define CV_CVX_WHITE CV_RGB(0xff,0xff,0xff)
#define CV_CVX_BLACK CV_RGB(0x00,0x00,0x00)




void ConnectedComponents(Mat &mask_process, int poly1_hull0, float perimScale, int number = 0,
Rect &bounding_box = Rect(), Point &contour_centers = Point(-1, -1))
{
/*下面4句代码是为了兼容原函数接口,即内部使用的是c风格,但是其接口是c++风格的*/
IplImage *mask = &mask_process.operator IplImage();
int *num = &number;
CvRect *bbs = &bounding_box.operator CvRect();
CvPoint *centers = &contour_centers.operator CvPoint();
static CvMemStorage* mem_storage = NULL;
static CvSeq* contours = NULL;
//CLEAN UP RAW MASK
//开运算作用:平滑轮廓,去掉细节,断开缺口
cvMorphologyEx(mask, mask, NULL, NULL, CV_MOP_OPEN, 1);//对输入mask进行开操作,CVCLOSE_ITR为开操作的次数,输出为mask图像
   //闭运算作用:平滑轮廓,连接缺口
cvMorphologyEx(mask, mask, NULL, NULL, CV_MOP_CLOSE, 1);//对输入mask进行闭操作,CVCLOSE_ITR为闭操作的次数,输出为mask图像
//FIND CONTOURS AROUND ONLY BIGGER REGIONS
if (mem_storage == NULL) mem_storage = cvCreateMemStorage(0);
else cvClearMemStorage(mem_storage);
//CV_RETR_EXTERNAL=0是在types_c.h中定义的,CV_CHAIN_APPROX_SIMPLE=2也是在该文件中定义的
CvContourScanner scanner = cvStartFindContours(mask, mem_storage, sizeof(CvContour), CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE);
CvSeq* c;
int numCont = 0;
//该while内部只针对比较大的轮廓曲线进行替换处理
while ((c = cvFindNextContour(scanner)) != NULL)
{
double len = cvContourPerimeter(c);
double q = (mask->height + mask->width) / perimScale;   //calculate perimeter len threshold
if (len < q) //Get rid of blob if it's perimeter is too small
{
cvSubstituteContour(scanner, NULL); //用NULL代替原来的那个轮廓
}
else //Smooth it's edges if it's large enough
{
CvSeq* c_new;
if (poly1_hull0) //Polygonal approximation of the segmentation
c_new = cvApproxPoly(c, sizeof(CvContour), mem_storage, CV_POLY_APPROX_DP, 2, 0);
else //Convex Hull of the segmentation
c_new = cvConvexHull2(c, mem_storage, CV_CLOCKWISE, 1);
cvSubstituteContour(scanner, c_new); //最开始的轮廓用凸包或者多项式拟合曲线替换
numCont++;
}
}
contours = cvEndFindContours(&scanner); //结束轮廓查找操作
// PAINT THE FOUND REGIONS BACK INTO THE IMAGE
cvZero(mask);
IplImage *maskTemp;
//CALC CENTER OF MASS AND OR BOUNDING RECTANGLES
if (*num != 0)
{
int N = *num, numFilled = 0, i = 0;
CvMoments moments;
double M00, M01, M10;
maskTemp = cvCloneImage(mask);
for (i = 0, c = contours; c != NULL; c = c->h_next, i++) //h_next为轮廓序列中的下一个轮廓
{
if (i < N) //Only process up to *num of them
{
//CV_CVX_WHITE在本程序中是白色的意思
cvDrawContours(maskTemp, c, CV_CVX_WHITE, CV_CVX_WHITE, -1, CV_FILLED, 8);
//Find the center of each contour
if (centers != &cvPoint(-1, -1))
{
cvMoments(maskTemp, &moments, 1); //计算mask图像的最高达3阶的矩
M00 = cvGetSpatialMoment(&moments, 0, 0); //提取x的0次和y的0次矩
M10 = cvGetSpatialMoment(&moments, 1, 0); //提取x的1次和y的0次矩
M01 = cvGetSpatialMoment(&moments, 0, 1); //提取x的0次和y的1次矩
centers[i].x = (int)(M10 / M00); //利用矩的结果求出轮廓的中心点坐标
centers[i].y = (int)(M01 / M00);
}
//Bounding rectangles around blobs
if (bbs != &CvRect())
{
bbs[i] = cvBoundingRect(c); //算出轮廓c的外接矩形
}
cvZero(maskTemp);
numFilled++;
}
//Draw filled contours into mask
cvDrawContours(mask, c, CV_CVX_WHITE, CV_CVX_WHITE, -1, CV_FILLED, 8); //draw to central mask
} //end looping over contours
*num = numFilled;
cvReleaseImage(&maskTemp);
}
//ELSE JUST DRAW PROCESSED CONTOURS INTO THE MASK
else
{
for (c = contours; c != NULL; c = c->h_next)
{
cvDrawContours(mask, c, CV_CVX_WHITE, CV_CVX_BLACK, -1, CV_FILLED, 8);
}
}
}


int main()
{


IplImage *sr;
sr = cvLoadImage("E:\\tupian\\peppers256.bmp", 0);
IplImage *sr_2;
sr_2 = cvLoadImage("E:\\tupian\\lene.bmp",0);//lene.bmp
//Mat  mask;
cv::Mat mask(sr_2, true);


//cvtColor(mask, mask, CV_BGR2GRAY);//三通道的图转化为1通道的灰度图  
threshold(mask, mask, 145, 255, THRESH_BINARY);//通过阈值操作把灰度图变成二值图
  //以灰度图像读入
imshow("sr_2", mask);


//mask = sr_2 > 0;     //转换为二值图像
// mask = imread("E:\\二值像素图像保存\\8_3\\aa\\4_30\\5\\(4_1)_2_lenna_平滑_四个方向细化之后_大小边阈值_去除孤立点处理之后_标记结果.bmp",0);
//cout<<mask.
//imshow("mask", mask);


ConnectedComponents(mask, 1, 8.0, 1, Rect(), Point(-1, -1));    //采用多边形拟合处理
imshow("out1", mask);


//ConnectedComponents(mask, 0, 8.0, 1, Rect(), Point(-1, -1));    //c采用凸包进行处理
//imshow("out2", mask);
waitKey(0);


return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值