opencv中contourarea轮廓面积算法
- 格式:docx
- 大小:12.70 KB
- 文档页数:2
轮廓转矩模式1. 什么是轮廓转矩模式?轮廓转矩模式(Contour Moment Pattern)是一种用于描述图像中物体轮廓形状的特征提取方法。
它通过计算轮廓的矩来表示轮廓的几何特征,进而实现对图像中物体的识别、分类和匹配等应用。
2. 轮廓矩的计算方法轮廓矩是对轮廓曲线上的点进行数学处理得到的一组特征值。
常用的轮廓矩包括面积、重心、边界长度、方向、伸展率等。
2.1 面积轮廓的面积是指轮廓内部的像素点的数量。
计算轮廓的面积可以使用OpenCV库中的cv2.contourArea()函数。
该函数接受一个轮廓数组作为输入,并返回轮廓的面积值。
import cv2# 读取图像并转换为灰度图image = cv2.imread('image.jpg')gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)# 二值化处理ret, binary = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY)# 轮廓提取contours, hierarchy = cv2.findContours(binary, cv2.RETR_EXTERNAL, cv2.CHAIN_AP PROX_SIMPLE)# 计算轮廓的面积area = cv2.contourArea(contours[0])print("轮廓的面积为:", area)2.2 重心轮廓的重心是指轮廓内部像素点的平均位置。
计算轮廓的重心可以使用OpenCV库中的cv2.moments()函数。
该函数接受一个轮廓数组作为输入,并返回包含轮廓重心信息的字典。
import cv2import numpy as np# 读取图像并转换为灰度图image = cv2.imread('image.jpg')gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)# 二值化处理ret, binary = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY)# 轮廓提取contours, hierarchy = cv2.findContours(binary, cv2.RETR_EXTERNAL, cv2.CHAIN_AP PROX_SIMPLE)# 计算轮廓的重心M = cv2.moments(contours[0])cx = int(M["m10"] / M["m00"])cy = int(M["m01"] / M["m00"])print("轮廓的重心坐标为:({}, {})".format(cx, cy))2.3 边界长度轮廓的边界长度是指轮廓曲线的长度。
Opencv提取连通区域轮廓的⽅法本⽂实例为⼤家分享了Opencv提取连通区域轮廓的具体代码,供⼤家参考,具体内容如下在进⾏图像分割后,可能需要对感兴趣的⽬标区域进⾏提取,⽐较常⽤的⽅法是计算轮廓。
通过轮廓可以获得⽬标的⼀些信息:(1)⽬标位置(2)⽬标⼤⼩(即⾯积)(3)⽬标形状(轮廓矩)当然,轮廓不⼀定代表希望⽬标区域,阈值分割时可能造成⼀部分信息丢失,因此可以计算轮廓的质⼼坐标,再进⾏漫⽔填充。
程序中有寻找质⼼+填充,但效果不好,因此就不放填充后的图了。
实验结果:#include "opencv2/imgproc/imgproc.hpp"#include "opencv2/highgui/highgui.hpp"#include <stdio.h>using namespace cv;using namespace std;vector<vector<Point> > contours; //轮廓数组vector<Point2d> centers; //轮廓质⼼坐标vector<vector<Point> >::iterator itr; //轮廓迭代器vector<Point2d>::iterator itrc; //质⼼坐标迭代器vector<vector<Point> > con; //当前轮廓int main(){double area;double minarea = 100;double maxarea = 0;Moments mom; // 轮廓矩Mat image,gray,edge,dst;namedWindow("origin");namedWindow("connected_region");image = imread("view.jpg");cvtColor(image, gray, COLOR_BGR2GRAY);blur(gray, edge, Size(3,3)); //模糊去噪threshold(edge,edge,200,255,THRESH_BINARY); //⼆值化处理/*寻找轮廓*/findContours( edge, contours,CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE );itr = contours.begin(); //使⽤迭代器去除噪声轮廓while(itr!=contours.end()){area = contourArea(*itr);if(area<minarea){itr = contours.erase(itr); //itr⼀旦erase,需要重新赋值}else{itr++;}if (area>maxarea){maxarea = area;}}dst = Mat::zeros(image.rows,image.cols,CV_8UC3);/*绘制连通区域轮廓,计算质⼼坐标*/Point2d center;itr = contours.begin();while(itr!=contours.end()){area = contourArea(*itr);con.push_back(*itr);if(area==maxarea)drawContours(dst,con,-1,Scalar(0,0,255),2); //最⼤⾯积红⾊绘制elsedrawContours(dst,con,-1,Scalar(255,0,0),2); //其它⾯积蓝⾊绘制con.pop_back();//计算质⼼mom = moments(*itr);center.x = (int)(mom.m10/mom.m00);center.y = (int)(mom.m01/mom.m00);centers.push_back(center);itr++;}imshow("origin",image);imshow("connected_region",dst);waitKey(0);/*漫⽔填充连通区域*/Point2d seed;int new_scalar = 0;int loDiff = 8, upDiff = 8;int connectivity = 4;itrc = centers.begin();while(itrc!=centers.end()){seed = *itrc;floodFill(image,seed,Scalar::all(new_scalar),NULL,Scalar::all(loDiff),Scalar::all(upDiff),connectivity);itrc++;}waitKey(0);return 0 ;}以上就是本⽂的全部内容,希望对⼤家的学习有所帮助,也希望⼤家多多⽀持。
OpenCV计算轮廓长度周长和⾯积本⽂实例为⼤家分享了OpenCV计算轮廓长度/周长和⾯积的具体代码,供⼤家参考,具体内容如下轮廓⾯积轮廓⾯积是指每个轮廓中所有的像素点围成区域的⾯积,单位为像素。
double contourArea( InputArray contour, bool oriented = false );contour:轮廓的像素点oriented:区域⾯积是否具有⽅向的标志,true表⽰⾯积具有⽅向性,false表⽰不具有⽅向性,默认值为不具有⽅向性的false。
函数的返回值是统计轮廓⾯积的结果,数据类型为double。
函数第⼀个参数表⽰轮廓的像素点,数据类型为vector或者Mat,相邻的两个像素点之间逐⼀相连构成的多边形区域即为轮廓⾯积的统计区域。
连续的三个像素点之间的连线有可能在同⼀条直线上,因此为了减少输⼊轮廓像素点的数⽬,可以只输⼊轮廓的顶点像素点,例如⼀个三⾓形的轮廓,轮廓中可能具有每⼀条边上的所有像素点,但是在统计⾯积时可以只输⼊三⾓形的三个顶点。
函数第⼆个参数是区域⾯积是否具有⽅向的标志,参数为true时表⽰统计的⾯积具有⽅向性,轮廓顶点顺时针给出和逆时针给出时统计的⾯积互为相反数;参数为false时表⽰统计的⾯积不具有⽅向性,输出轮廓⾯积的绝对值。
轮廓长度 /周长double arcLength( InputArray curve, bool closed );curve:轮廓或者曲线的2D像素点。
closed:轮廓或者曲线是否闭合标志,true表⽰闭合。
该函数能够统计轮廓或者曲线的长度,函数返回值为统计长度,单位为像素,数据类型为double。
函数的第⼀个参数是轮廓或者曲线的2D像素点,数据类型为vector或者Mat。
函数的第⼆个参数是轮廓或者曲线是否闭合的标志,true表⽰闭合。
函数统计的长度是轮廓或者曲线相邻两个像素点之间连线的距离,例如计算三⾓形三个顶点A、B和C构成的轮廓长度时,并且函数第⼆个参数为true时,统计的长度是三⾓形三个边AB、BC和CA的长度之和;当参数为false时,统计的长度是由A到C 三个点之间依次连线的距离长度之和,即AB和BC的长度之和。
OpenCV学习之路(十)轮廓的一些操作contours返回值详解轮廓类似详解在findContours()函数中,我们一共返回了三个参数:image,contours,hierarchy。
其中image代表的是修改之后的原图,contours代表的是轮廓,hierarchy代表的是轮廓的层次结构。
我们主要来讨论一下第二个返回值:contours。
以及轮廓可以进行的一些操作。
contourscontours代表的是找到的轮廓,它是一个numpy中的列表结构,那么接下来就让我们探究一下这个列表究竟是怎么存储轮廓的。
import numpy as npimport cv2img=cv2.imread('D://zopencv//contours.png')imgcopy=img.copy()imgray=cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)ret,img_thre=cv2.threshold(imgray,127,255,cv2.THRESH_BIN ARY)image,contours,hierarchy=cv2.findContours(img_thre,cv2.RE TR_TREE,cv2.CHAIN_APPROX_NONE)mask1=cv2.drawContours(imgcopy,contours,-1,(0,0,255),2)cv2.imshow('mask1',mask1)cv2.waitKey(0)cv2.destroyAllWindows()之前我们已经讨论过了,drawContours()函数的第三个参数是轮廓的索引,如果我们定为-1就会把所有轮廓画出。
那你有没有想过,他既然是索引,我们是不是可以一个一个轮廓的画出来。
我们将索引定为0:mask1=cv2.drawContours(imgcopy,contours,0,(0,0,255),2)只有正方形的轮廓被画了出来,也就是说,正方形的轮廓在轮廓列表contours中的索引是0.同理,我们可以把索引分别设置成1,2。
opencv绘制图形轮廓并筛选面积操作1、类比halcon的筛选区域面积的操作select_shape算子,opencv也可以对图形的轮廓进行面积的筛选,剔除无效区域。
int main(){Mat srcImage = imread('D:\\Opencv\\Project\\ConnectionProject\\modules_08.p ng');imshow('【原图】', srcImage);//首先对图像进行空间的转换Mat grayImage;cvtColor(srcImage, grayImage, CV_BGR2GRAY);//对灰度图进行滤波GaussianBlur(grayImage, grayImage, Size(3, 3), 0, 0);imshow('【滤波后的图像】', grayImage);//为了得到二值图像,对灰度图进行边缘检测Mat cannyImage;Canny(grayImage, cannyImage, 128, 255, 3);//在得到的二值图像中寻找轮廓vector<vector<Point>> contours;vector<Vec4i> hierarchy;findContours(cannyImage, contours, hierarchy, RETR_TREE, CHAIN_APPROX_SIMPLE, Point(0, 0));//绘制轮廓for (int i = 0; i < (int)contours.size(); i++){drawContours(cannyImage, contours, i, Scalar(255), 1, 8);}imshow('【处理后的图像】', cannyImage);//计算轮廓的面积cout << '【筛选前总共轮廓个数为】:' << (int)contours.size() << endl;for (int i = 0; i < (int)contours.size(); i++){double g_dConArea = contourArea(contours[i], true);cout << '【用轮廓面积计算函数计算出来的第' << i << '个轮廓的面积为:】' << g_dConArea << endl;}//筛选剔除掉面积小于100的轮廓vector <vector<Point>>::iterator iter = contours.begin();for (; iter != contours.end();){double g_dConArea = contourArea(*iter);if (g_dConArea < 100){iter = contours.erase(iter);}else{++iter;}}cout << '【筛选后总共轮廓个数为:' << (int)contours.size() << endl;for (int i = 0; i < (int)contours.size(); i++){double g_dConArea = contourArea(contours[i], true);cout << '【用轮廓面积计算函数计算出来的第' << i << '个轮廓的面积为:】' << g_dConArea << endl;}Mat result(srcImage.size(), CV_8U, Scalar(0));drawContours(result, contours, -1, Scalar(255), 1); // -1 表示所有轮廓namedWindow('result');imshow('result', result);waitKey(0);return 0;}筛选前和筛选后的面积对比:控制台输出数据:第一次轮廓面积个数为295,第二次筛选后面积个数为145,注意这里轮廓面积有正有负。
C语⾔实现opencv提取直线、轮廓及ROI实例详解⼀、Canny检测轮廓在上⼀篇⽂章中有提到sobel边缘检测,并重写了soble的C++代码让其与matlab中算法效果⼀致,⽽soble边缘检测是基于单⼀阈值的,我们不能兼顾到低阈值的丰富边缘和⾼阈值时的边缘缺失这两个问题。
⽽canny算⼦则很好的弥补了这⼀不⾜,从⽬前看来,canny边缘检测在做图像轮廓提取⽅⾯是最优秀的边缘检测算法。
canny边缘检测采⽤双阈值值法,⾼阈值⽤来检测图像中重要的、显著的线条、轮廓等,⽽低阈值⽤来保证不丢失细节部分,低阈值检测出来的边缘更丰富,但是很多边缘并不是我们关⼼的。
最后采⽤⼀种查找算法,将低阈值中与⾼阈值的边缘有重叠的线条保留,其他的线条都删除。
本篇⽂章中不对canny的算法原理作进⼀步说明,稍后会在图像处理算法相关的⽂章中详细介绍。
下⾯我们⽤OpenCV中的Canny函数来检测图像边缘int main(){Mat I=imread("../cat.png");cvtColor(I,I,CV_BGR2GRAY);Mat contours;Canny(I,contours,125,350);threshold(contours,contours,128,255,THRESH_BINARY);namedWindow("Canny");imshow("Canny",contours);waitKey();return 0;}显⽰效果如下:⼆、直线检测⽤到的是霍夫变换检测直线的算法直线在图像中出现的频率⾮常之⾼,⽽直线作为图像的特征对于基本内容的图像分析有着很重要的作⽤,本⽂通过OpenCV中的hough变换来检测图像中的线条。
我们先看最基本的Hough变换函数HoughLines,它的原型如下:void HoughLines(InputArray image, OutputArray lines, double rho, double theta, int threshold, double srn=0, double stn=0 );它的输⼊是⼀个⼆值的轮廓图像,往往是边缘检测得到的结果图像;它的输出是⼀个包含多个Vec2f点的数组,数组中的每个元素是⼀个⼆元浮点数据对<rou,theta>,rou代表直线离坐标原点的距离,theta代表⾓度。
Python+Opencv实现计算闭合区域⾯积⽬录⼀、cv2.contourArea⼆、按像素个数计算连通域⾯积⼀、cv2.contourArea起初使⽤该函数的时候看不懂返回的⾯积,有0有负数的,于是研究了⼀下。
opencv计算轮廓内⾯积函数使⽤的是格林公式计算轮廓内⾯积的,公式如下:由于格林公式计算单连通域⾯积是以逆时针为正⽅向的,⽽有时候我们输⼊的边缘数组是按照顺时针输⼊的,所以导致计算⾯积会出现负数;计算⾯积存在0的情况⼀般是只存在⼀个像素点作为边缘点,所以⾯积为0。
代码如下:img = cv2.imread('test.png', 0)contours, hierarchy = cv2.findContours(img, cv2.RETR_CCOMP, cv2.CHAIN_APPROX_TC89_L1)area = []topk_contours =[]for i in range(len(contours)):a = cv2.contourArea(contours[i], True)area.append(abs(a))topk = 2 #取最⼤⾯积的个数for i in range(2):top = area.index(max(area))area.pop(top)topk_contours.append(contours[top])x, y = img.shapemask = np.zeros((x, y, 3))mask_img = cv2.drawContours(mask, topk_contours, -1, (255, 255, 255), 1)cv2.imwrite('mask_img.png', mask_img, [int(cv2.IMWRITE_JPEG_QUALITY), 100])cv2.imshow('mask_img:', mask_img)cv2.waitKey(0)cv2.destroyAllWindows()结果如下:⼆、按像素个数计算连通域⾯积这边再给出⼀种⽤边缘内像素个数来计算连通域⾯积的⽅法:img = cv2.imread('test.png', 0)contours, hierarchy = cv2.findContours(img, cv2.RETR_CCOMP, cv2.CHAIN_APPROX_TC89_L1)area = []topk_contours =[]x, y = img.shapefor i in range(len(contours)):# 对每⼀个连通域使⽤⼀个掩码模板计算⾮0像素(即连通域像素个数)single_masks = np.zeros((x, y))fill_image = cv2.fillConvexPoly(single_masks, contours[i], 255)pixels = cv2.countNonZero(fill_image)area.append(pixels)topk = 2 #取最⼤⾯积的个数for i in range(2):top = area.index(max(area))area.pop(top)topk_contours.append(contours[top])mask = np.zeros((x,y,3))mask_img = cv2.drawContours(mask, topk_contours, -1, (255, 255, 255), 1)cv2.imwrite('mask_img.png', mask_img, [int(cv2.IMWRITE_JPEG_QUALITY), 100])cv2.imshow('mask_img:', mask_img)cv2.waitKey(0)cv2.destroyAllWindows()到此这篇关于Python+Opencv实现计算闭合区域⾯积的⽂章就介绍到这了,更多相关Python Opencv⾯积内容请搜索以前的⽂章或继续浏览下⾯的相关⽂章希望⼤家以后多多⽀持!。
Cv中文参考手册之二------图像轮廓处理Cv中文参考手册之二 - Cv结构分析下面的链接是OPENCV之CV部分用户参考手册的中文翻译,在此感谢Z.M.Zhang对模式识别、照相机定标与三维重建部分所做的翻译,Y.C.WEI对全文做了统一细致的更改Cv结构分析目录• 1 轮廓处理函数o 1.1 ApproxChainso 1.2 StartReadChainPointso 1.3 ReadChainPointo 1.4 ApproxPolyo 1.5 BoundingRecto 1.6 ContourAreao 1.7 ArcLengtho 1.8 CreateContourTreeo 1.9 ContourFromContourTreeo 1.10 MatchContourTrees• 2 计算几何o 2.1 MaxRecto 2.2 CvBox2Do 2.3 PointSeqFromMato 2.4 BoxPointso 2.5 FitEllipseo 2.6 FitLineo 2.7 ConvexHull2o 2.8 CheckContourConvexityo 2.9 CvConvexityDefecto 2.10 ConvexityDefectso 2.11 PointPolygonTesto 2.12 MinAreaRect2o 2.13 MinEnclosingCircleo 2.14 CalcPGH• 3 平面划分o 3.1 CvSubdiv2Do 3.2 CvQuadEdge2Do 3.3 CvSubdiv2DPointo 3.4 Subdiv2DGetEdgeo 3.5 Subdiv2DRotateEdgeo 3.6 Subdiv2DEdgeOrgo 3.7 Subdiv2DEdgeDsto 3.8 CreateSubdivDelaunay2Do 3.9 SubdivDelaunay2DInserto 3.10 Subdiv2DLocateo 3.11 FindNearestPoint2Do 3.12 CalcSubdivVoronoi2Do 3.13 ClearSubdivVoronoi2D轮廓处理函数ApproxChains用多边形曲线逼近 Freeman 链CvSeq* cvApproxChains( CvSeq* src_seq, CvMemStorage* storage,int method=CV_CHAIN_APPROX_SIMPLE,double parameter=0, int minimal_perimeter=0, int recursive=0 );src_seq•涉及其它链的链指针storage•存储多边形线段位置的缓存method•逼近方法 (见函数 cvFindContours 的描述).parameter•方法参数(现在不用).minimal_perimeter•仅逼近周长大于minimal_perimeter 轮廓。
opencv实现图形轮廓检测要想实现轮廓检测,⾸先我们需要对待检测的图像进⾏图像处理:图像灰度化、⾼斯滤波、Canny 边缘检测、边缘检测放⼤处理、提取轮廓。
⼀、实现简单的全图型检测即只要将drawContours第三个参数设置为-1 既能实现图像的全图型检测。
程序:#include <iostream>#include <opencv2/highgui.hpp> // 说是说gui 具体什么gui 不清楚#include <opencv2/imgcodecs.hpp> // 图像头⽂件#include <opencv2/imgproc.hpp> // 图像处理头⽂件using namespace std;using namespace cv;/*要进⾏图像形貌检测之前*⾸先要⼆值化,再进⾏滤波处理,再进⾏Canny边缘检测*最后才能检测出图形轮廓*/Mat imgGray, imgBlur, imgCanny,imgDil;void getContours(Mat imgDil,Mat& img);int main(){string path = "resources/shapes.png"; // 导⼊图形的时候,先要在右边点击显⽰所有⽂件Mat img = imread(path); // 在opencv 中所有的图像信息都使⽤Mat// pre-processing image 图像预处理cvtColor(img, imgGray, COLOR_BGR2GRAY);GaussianBlur(imgGray, imgBlur,Size(3,3),3,0); // ⾼斯滤波Canny(imgBlur, imgCanny, 25, 75);// Canny 边缘检测Mat kernel = getStructuringElement(MORPH_RECT, Size(3, 3)); // 其中 Size 和边缘检测的放⼤倍数有关系dilate(imgCanny, imgDil, kernel);getContours(imgDil,img); // 第⼀个参数是寻找轮廓的参数,第⼆个参数是显⽰图案的参数imshow("Image", img);waitKey(0); // 延时,0即相当于⽆穷⼤}void getContours(Mat imgDil, Mat& img){/* contour is a vector inside that vector there is more vector* {{Point(20,30),Point(50,60)},{},{}} each vector like a contour and each contour have some points***/vector<vector<Point>> contours;vector<Vec4i> hierarchy; // Vec4i 即代表该向量内有4个 int 变量typedef Vec<int, 4> Vec4i; 这四个向量每⼀层级代表⼀个轮廓findContours(imgDil, contours, hierarchy, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE); // CV_CHAIN_APPROX_SIMPLE - 简单的链式接近法 drawContours(img, contours, -1, Scalar(255,0,255),2); // contouridx = -1 代表需要绘制所检测的所有轮廓}运⾏结果:细⼼的读者会发现,该程序还将微⼩的瑕疵检测到了。
opencv 矩形面积如何使用OpenCV计算矩形的面积在计算机视觉领域中,使用OpenCV是一个非常常见的选择。
OpenCV 是一个用于图像处理和计算机视觉任务的强大库,它提供了众多的功能和算法。
其中一个常见的任务是计算矩形的面积。
在本文中,我将逐步介绍如何使用OpenCV计算矩形的面积。
第一步:安装OpenCV要开始使用OpenCV进行矩形面积的计算,首先需要安装OpenCV库。
可以在OpenCV官方网站上找到安装指南,并按照指南一步一步进行安装。
一旦安装完成,就可以继续第二步。
第二步:导入必要的库在使用OpenCV进行矩形面积计算之前,我们需要导入必要的库。
以下是导入的代码示例:pythonimport cv2import numpy as np在这个代码片段中,我们导入了两个最常用的库:cv2和numpy。
cv2是OpenCV的Python接口,而numpy是一个用于科学计算的Python库。
第三步:创建一个矩形要计算矩形的面积,首先需要创建一个矩形。
在OpenCV中,矩形由其左上角和右下角的坐标定义。
以下是创建矩形的代码示例:python# 创建矩形rectangle = np.array([[100, 100], [300, 200]])在这个代码片段中,我们使用了numpy库中的array函数来创建一个2x2的数组,表示矩形的左上角和右下角坐标。
这个矩形的左上角坐标是(100, 100),右下角坐标是(300, 200)。
第四步:计算矩形的面积一旦创建了矩形,就可以开始计算其面积。
在OpenCV中,可以使用contourArea函数来计算轮廓的面积。
以下是计算矩形面积的代码示例:python# 计算矩形的面积area = cv2.contourArea(rectangle)print("矩形的面积为:", area)在这个代码片段中,我们使用了cv2库中的contourArea函数来计算矩形的面积。
opencv中contourarea轮廓面积算法
在计算机视觉中,轮廓检测是常见的任务之一。
在OpenCV中,我们可以使用f indContours函数来检测图像中的轮廓。
该函数返回一个轮廓列表,每个轮廓都是一个点集,表示图像中物体的边缘。
轮廓面积是轮廓的一个重要属性,可以通过计算轮廓所围成的区域的像素数量来获得。
在OpenCV中,可以使用contourArea函数来计算轮廓面积。
下面是一个简单的示例代码,演示如何使用OpenCV中的findContours和cont ourArea函数来检测图像中的轮廓并计算其面积:
在上面的代码中,我们首先读取一张图像,并将其转换为灰度图像。
然后,我们对灰度图像进行二值化处理,以便更好地检测轮廓。
接下来,我们使用cv2. findContours函数查找图像中的轮廓,并返回轮廓列表和层次结构。
最后,我们遍历每个轮廓并使用cv2.contourArea函数计算其面积,并打印结果。
需要注意的是,在使用cv2.findContours函数时,我们需要指定轮廓检索模式、轮廓近似方法和层次结构。
在本例中,我们使用cv2.RETR_EXTERNAL模式来检索最外层的轮廓,使用cv2.CHAIN_APPROX_SIMPLE方法来近似轮廓,并返回层次结构。