c++ opencv findcontours 用法
- 格式:docx
- 大小:36.87 KB
- 文档页数:2
cv2.findcontours函数返回物体中心和长宽信息`cv2.findContours`是OpenCV库中的一个函数,用于在二值图像中查找轮廓。
这个函数返回一个轮廓列表,每个轮廓都是点集。
然而,它本身并不直接提供物体的中心、长宽等信息。
如果你想找到轮廓的中心和长宽,你需要进一步处理。
例如,你可以使用以下步骤来找到轮廓的中心和宽高:1.**获取轮廓点集**:使用`cv2.findContours`获取轮廓点集。
2.**计算中心**:对于每个轮廓,可以通过计算所有点的平均位置来得到中心的坐标。
数学上,你可以使用以下公式:\(center_x=\frac{1}{N}\sum_{i=1}^{N}x_i\)\(center_y=\frac{1}{N}\sum_{i=1}^{N}y_i\)其中\(N\)是点的数量,\(x_i\)和\(y_i\)是点的坐标。
3.**计算宽和高**:轮廓的宽度和高度可以通过计算最大和最小x/y坐标之间的差值得到。
例如:\(width=max(x)-min(x)\)\(height=max(y)-min(y)\)4.**应用到所有轮廓**:对每个轮廓重复上述步骤,以获取每个轮廓的宽度、高度和中心。
这里是一个Python代码示例,说明如何实现这一过程:```pythonimport cv2import numpy as np#读取图像并转为灰度图image=cv2.imread('your_image.png')gray=cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)#二值化图像(如果需要)_,binary=cv2.threshold(gray,127,255, cv2.THRESH_BINARY)#查找轮廓contours,_=cv2.findContours(binary, cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)#遍历每个轮廓并计算中心和宽高for contour in contours:#计算中心M=cv2.moments(contour)if M["m00"]!=0:cX=int(M["m10"]/M["m00"])cY=int(M["m01"]/M["m00"])else:cX,cY=0,0#计算宽度和高度(基于边界框)bbox=cv2.boundingRect(contour)width=bbox[2]height=bbox[3]print(f"Center:({cX},{cY}),Width:{width}, Height:{height}")```请注意,上述代码中,我们使用了图像的二值形式(如果存在)。
findcontour原理(一)使用findcontour进行轮廓检测介绍在计算机视觉领域,轮廓检测是一项重要的技术,用于识别图像中的对象边缘。
而findcontour函数是OpenCV库中提供的一个强大工具,用于在图像中寻找轮廓。
本文将逐步深入,介绍findcontour 的原理和使用方法。
什么是轮廓轮廓是图像中连续的、具有相同颜色或灰度值的像素点边界。
在图像处理中,我们常常希望能够准确地定位和识别图像中的对象,而轮廓检测就是实现这一目标的关键步骤之一。
findcontour函数的原理findcontour函数基于图像的二值化,通过寻找像素点之间的连接关系来寻找轮廓。
其底层原理基于扫描线算法。
findcontour函数的输入是一个二值化图像,提供了多种寻找轮廓的算法,包括”RETR_EXTERNAL”(只寻找最外层轮廓)和”RETR_TREE”(检测所有轮廓并建立全局的轮廓层级关系)等。
使用findcontour函数的步骤1.导入OpenCV库。
2.读取图像并进行预处理,例如灰度化、二值化等操作。
3.使用findcontour函数寻找轮廓。
4.对于每个轮廓,可以进行一些附加操作,例如计算轮廓面积、周长、重心等。
5.根据需求,对轮廓进行进一步处理或绘制到图像上。
示例代码以下是一个使用findcontour函数的简单示例代码:import cv2# 读取图像并进行灰度化操作img = ('')gray = (img, _BGR2GRAY)# 进行二值化处理_, threshold = (gray, 127, 255, _BINARY)# 寻找轮廓contours, _ = (threshold, _EXTERNAL, _APPROX_SIMPLE)# 遍历每个轮廓并进行相关操作for contour in contours:area = (contour)perimeter = (contour, True)(img, [contour], -1, (0, 255, 0), 2)# 显示结果图像('Contours', img)(0)()总结轮廓检测是计算机视觉中的重要技术,findcontour函数是OpenCV中实现轮廓检测的强大工具。
opencv findcontours 数组排序规则在OpenCV中,findContours函数返回的轮廓点数组需要经过排序才能使用。
对于二维点(Point)数组的排序规则可以使用ContourArea函数来判断轮廓的大小。
ContourArea函数返回给定轮廓的面积大小,可用于对轮廓进行排序。
具体的排序规则可以根据自己的需要进行定义。
以下是一种常见的排序规则示例,按轮廓面积大小从大到小进行排序:cpp#include <iostream>#include <vector>#include <opencv2/opencv.hpp>bool compareContourArea(std::vector<cv::Point> contour1,std::vector<cv::Point> contour2) {double area1 = cv::contourArea(contour1);double area2 = cv::contourArea(contour2);return (area1 > area2);}int main() {假设有一个存储轮廓点的向量contoursstd::vector<std::vector<cv::Point>> contours;对轮廓点向量进行排序std::sort(contours.begin(), contours.end(), compareContourArea);输出排序后的轮廓面积for (int i = 0; i < contours.size(); i++) {double area = cv::contourArea(contours[i]);std::cout << "Contour " << i << " area: " << area << std::endl;}return 0;}在上面的示例代码中,我们定义了一个compareContourArea函数用于比较两个轮廓的大小,然后使用std::sort函数对存储轮廓点的向量contours进行排序。
findContours是OpenCV库中的一个函数,用于在二值图像中查找轮廓。
它的基本原理是遍历二值图像中的每个像素,并根据其值(通常是0或255)来确定轮廓。
具体来说,它会查找所有与前景像素相连的像素,并将它们标记为轮廓像素。
重写findContours函数的原理是理解这个过程并手动实现它。
以下是一个简单的步骤概述:
1.遍历图像:从图像的左上角开始,遍历每个像素。
2.检查像素值:对于每个像素,检查其值是否等于前景像素(通常是255)。
如果是
前景像素,则继续查找与它相连的像素。
3.查找相连的像素:对于当前像素,查找其周围的像素。
如果周围的像素也是前景像
素,则将它们标记为轮廓像素。
这可以通过检查当前像素的上下左右四个相邻像素来实现。
4.标记轮廓像素:一旦找到一个轮廓像素,将其标记为轮廓像素,并将其添加到一个
列表中。
5.继续遍历:继续遍历图像中的其他像素,直到所有像素都被检查过。
6.返回轮廓列表:最后,返回包含所有轮廓像素的列表。
这个过程可以通过递归或迭代的方式实现,具体取决于编程语言和实现方式。
需要注意的是,这个过程可能会比较耗时,尤其是在处理大图像时。
因此,在实际应用
中,通常会使用OpenCV的findContours函数,因为它已经进行了优化,并且具有
更好的性能和可靠性。
findcontours函数原理findContours函数是OpenCV提供的一个处理图像轮廓的函数,它主要有三种用法:如果源图像是8位的单通道二值图像,它的表现为抽取“0”值的外围边框;如果源图像是8位的三通道图像,它表现为通过轮廓检测算法抽取物体的视觉轮廓;如果源图像是32位的单通道图像,它返回源图像的梯度变化检测结果,从而抽取物体的视觉轮廓。
findContours函数主要以下四种模式:1.邻的象素的拓扑关系2.图像的某个区域进行拓扑求解3.廓的近似处理4.廓的外接矩形通过这个函数,我们可以求取每个物体的轮廓,整个程序的思路就是:给出一幅图像,所有的轮廓由其内部象素的取值(8位单通道或RGB三通道8位)决定,首先,将图像转化为灰度图,然后,将轮廓给出,即在一定模型下提取一系列点,以此构造每一个物体的轮廓,最后,进行绘制,即以相应的圆和虚线的形式呈现。
#### 二、findcontours函数的实现1.廓定义图像处理中,轮廓是一种弧线形式,用来描述物体表面的轮廓线,也可以是矩形等形状,它们可以用一系列点来表示,这些点可以用来拓扑结构,用来描述物体的形状、求取周长、面积等。
2.缘检测到轮廓之前,需要先进行边缘检测,即检测所有图像中的边缘特征,这是提取轮廓的前提,也就是将图像中的一系列点按照某种方式分类,一般分为边缘点和非边缘点,从而提取图像的轮廓。
边缘检测的方法主要有Sobel、Laplacian以及Canny算法。
3.包法包法是一种用来求取轮廓的算法,它使用外接矩形来求取物体的外接矩形,再连接所有矩形边界的点,从而求取物体的轮廓,这种算法比较简单,效率也较高,也不需要拓扑信息,可以方便地求取比较精确的轮廓。
4.廓近似处理廓近似处理是指针对求取到的轮廓,使用更低级别的轮廓来代替更高级别的轮廓,以此来减少轮廓的点数,从而减少计算量。
这种近似处理的方法有Douglas-Peucker算法,它的原理是将轮廓按照一定的方式分割,然后抛弃分割后的部分,保留最重要的部分,以此来压缩轮廓点数,减少计算量。
OpenCV之findContours函数解读OpenCV之findContours函数解读参考:findContours()函数原型:void findContours(InputOutputArray image, OutputArrayOfArrays contours, OutputArray hierarchy, int mode, int method, Point offset=Point())Parameters:image – Source, an 8-bit single-channel image.contours – Detected contours. Each contour is stored as a vector of points.hierarchy – Optional output vector, containing information about the image topology. It has as many elements as the number of contours. For each i-th contour contours[i] , the elements hierarchy[i][0] , hiearchy[i][1] , hiearchy[i][2] , and hiearchy[i][3] are set to 0-based indices in contours of the next and previous contours at the same hierarchical level, the first child contour and the parent contour, respectively. If for the contour i there are no next, previous, parent, or nested contours, the corresponding elements of hierarchy[i] will be negative.mode – Contour retrieval modeCV_RETR_EXTERNAL retrieves only the extreme outer contours. It sets hierarchy[i][2]=hierarchy[i][3]=-1 for all the contours.CV_RETR_LIST retrieves all of the contours without establishing any hierarchical relationships.CV_RETR_CCOMP retrieves all of the contours and organizes them into a two-level hierarchy. At the top level, there are external boundaries of the components. At the second level, there are boundaries of the holes. If there is another contour inside a hole of a connected component, it is still put at the top level.CV_RETR_TREE retrieves all of the contours and reconstructs a full hierarchy of nested contours. This full hierarchy is built and shown in the OpenCV contours.c demo.method – Contour approximation methodCV_CHAIN_APPROX_NONE stores absolutely all the contour points. That is, any 2 subsequent points (x1,y1) and (x2,y2) of the contour will be either horizontal, vertical or diagonal neighbors, that is, max(abs(x1-x2),abs(y2-y1))==1.CV_CHAIN_APPROX_SIMPLE compresses horizontal, vertical, and diagonal segments and leaves only their end points. For example, an up-right rectangular contour is encoded with 4 points.CV_CHAIN_APPROX_TC89_L1,CV_CHAIN_APPROX_TC89_KCOS applies one of the flavors of the Teh-Chin chain approximation algorithm.offset – Optional offset by which every contour point is shifted. This is useful if the contours are extracted from the image ROI and then they should be analyzed in the whole image context.参数说明image输⼊图像必须为⼀个2值单通道图像contours参数为检测的轮廓数组,每⼀个轮廓⽤⼀个point类型的vector表⽰hiararchy参数和轮廓个数相同,每个轮廓contours[ i ]对应4个hierarchy元素hierarchy[ i ][ 0 ] ~hierarchy[ i ][ 3 ],分别表⽰后⼀个轮廓、前⼀个轮廓、⽗轮廓、内嵌轮廓的索引编号,如果没有对应项,该值设置为负数。
OpenCVfindContours函数参数详解OpenCV中通过使⽤findContours函数,简单⼏个的步骤就可以检测出物体的轮廓,很⽅便。
这些准备继续探讨⼀下findContours⽅法中各参数的含义及⽤法,⽐如要求只检测最外层轮廓该怎么办?contours⾥边的数据结构是怎样的?hierarchy到底是什么⿁?Point()有什么⽤?先从findContours函数原型看起:1 findContours( InputOutputArray image, OutputArrayOfArrays contours,2 OutputArray hierarchy, int mode,3int method, Point offset=Point());第⼀个参数:image,单通道图像矩阵,可以是灰度图,但更常⽤的是⼆值图像,⼀般是经过Canny、拉普拉斯等边缘检测算⼦处理过的⼆值图像;第⼆个参数:contours,定义为“vector<vector<Point>> contours”,是⼀个向量,并且是⼀个双重向量,向量内每个元素保存了⼀组由连续的Point点构成的点的集合的向量,每⼀组Point点集就是⼀个轮廓。
有多少轮廓,向量contours就有多少元素。
第三个参数:hierarchy,定义为“vector<Vec4i> hierarchy”,先来看⼀下Vec4i的定义:typedef Vec<int, 4> Vec4i;Vec4i是Vec<int,4>的别名,定义了⼀个“向量内每⼀个元素包含了4个int型变量”的向量。
所以从定义上看,hierarchy也是⼀个向量,向量内每个元素保存了⼀个包含4个int整型的数组。
向量hiararchy内的元素和轮廓向量contours内的元素是⼀⼀对应的,向量的容量相同。
hierarchy向量内每⼀个元素的4个int型变量——hierarchy[i][0] ~hierarchy[i][3],分别表⽰第i个轮廓的后⼀个轮廓、前⼀个轮廓、⽗轮廓、内嵌轮廓的索引编号。
使用OpenCV的findContours获取轮廓并切割(python)#1 获取轮廓OpenCV2获取轮廓主要是用cv2.findContoursimport numpy as npimport cv2image = cv2.imread('test.jpg')imgray = cv2.cvtColor(image,cv2.COLOR_BGR2GRAY)ret,thresh = cv2.threshold(imgray,127,255,0)#image, contours, hierarchy = cv2.findContours(thresh,cv2.RETR_TREE,cv2.CHAIN_APPROX_SI MPLE) 旧版本返回三个参数,新版本返回2个contours, hierarchy = cv2.findContours(thresh,cv2.RETR_TREE,cv2.CHAIN_APPROX_SI MPLE)其中,findContours的第二个函数很重要,主要分为cv2.RETR_LIST, cv2.RETR_TREE, cv2.RETR_CCOMP, cv2.RETR_EXTERNAL,具体含义可参考官方文档#2 画出轮廓为了看到自己画了哪些轮廓,可以使用cv2.boundingRect()函数获取轮廓的范围,即左上角原点,以及他的高和宽。
然后用cv2.rectangle()方法画出矩形轮廓for i in range(0,len(contours)):x, y, w, h = cv2.boundingRect(contours[i])cv2.rectangle(image, (x,y), (x+w,y+h), (153,153,0), 5)#3 切割轮廓轮廓的切割主要是通过数组切片实现的,不过这里有一个小技巧:就是图片切割的w,h是宽和高,而数组讲的是行(row)和列(column)所以,在切割图片时,数组的高和宽是反过来写的newimage=image[y+2:y+h-2,x+2:x+w-2] # 先用y确定高,再用x确定宽nrootdir=('E:/cut_image/')if not os.path.isdir(nrootdir):os.makedirs(nrootdir)cv2.imwrite( nrootdir+str(i)+'.jpg',newimage)print (i)这样就可以把确定的轮廓都切割出来了。
Python:Opencvcv2.findContours()函数查找轮廓cv.findContours()参数: ①要寻找轮廓的图像只能传⼊⼆值图像,不是灰度图像 ②轮廓的检索模式,有四种: cv2.RETR_EXTERNAL表⽰只检测外轮廓 cv2.RETR_LIST检测的轮廓不建⽴等级关系 cv2.RETR_CCOMP建⽴两个等级的轮廓,上⾯的⼀层为外边界,⾥⾯的⼀层为内孔的边界信息。
如果内孔内还有⼀个连通物体,这个物体的边界也在顶层 cv2.RETR_TREE建⽴⼀个等级树结构的轮廓 ③轮廓的近似办法 cv2.CHAIN_APPROX_NONE存储所有的轮廓点,相邻的两个点的像素位置差不超过1, 即max(abs(x1-x2),abs(y2-y1))==1 cv2.CHAIN_APPROX_SIMPLE压缩⽔平⽅向,垂直⽅向,对⾓线⽅向的元素,只保留该⽅向的终点坐标,例如⼀个矩形轮廓只需4个点来保存轮廓信息返回值: contours:⼀个列表,每⼀项都是⼀个轮廓,不会存储轮廓所有的点,只存储能描述轮廓的点 hierarchy:⼀个ndarray, 元素数量和轮廓数量⼀样, 每个轮廓contours[i]对应4个hierarchy元素hierarchy[i][0] ~hierarchy[i][3],分别表⽰后⼀个轮廓、前⼀个轮廓、⽗轮廓、内嵌轮廓的索引编号,如果没有对应项,则该值为负数坑点!!!:出现如下错误ValueError: need more than 2 values to unpack在Opencv4.0中 cv.findContours()的返回值以从三个变为⼆个,见如下官⽅⽂档查找边框及对圆形、矩形进⾏画框的程序如下:import cv2import numpy as np# 读⼊图像img = cv2.imread(r"D:\360MoveData\Users\KID\Desktop\1.jpg", cv2.IMREAD_UNCHANGED)# ⼆值化ret, thresh = cv2.threshold(cv2.cvtColor(img.copy(), cv2.COLOR_BGR2GRAY), # 转换为灰度图像,130, 255, # ⼤于130的改为255 否则改为0cv2.THRESH_BINARY) # ⿊⽩⼆值化# 搜索轮廓contours, hierarchy = cv2.findContours(thresh,cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)for c in contours:x, y, w, h = cv2.boundingRect(c)"""传⼊⼀个轮廓图像,返回 x y 是左上⾓的点, w和h是矩形边框的宽度和⾼度"""cv2.rectangle(img, (x, y), (x+w, y+h), (0, 255, 0), 2)"""画出矩形img 是要画出轮廓的原图(x, y) 是左上⾓点的坐标(x+w, y+h) 是右下⾓的坐标0,255,0)是画线对应的rgb颜⾊2 是画出线的宽度"""# 获得最⼩的矩形轮廓可能带旋转⾓度rect = cv2.minAreaRect(c)# 计算最⼩区域的坐标box = cv2.boxPoints(rect)# 坐标规范化为整数box = np.int0(box)# 画出轮廓cv2.drawContours(img, [box], 0, (0, 0, 255), 3)# 计算最⼩封闭圆形的中⼼和半径(x, y), radius = cv2.minEnclosingCircle(c)# 转换成整数center = (int(x), int(y))radius = int(radius)# 画出圆形img = cv2.circle(img, center, radius, (0, 255, 0), 2) # 画出轮廓cv2.drawContours(img, contours, -1, (255, 0, 0), 1) cv2.imshow("contours", img)cv2.waitKey()cv2.destroyAllWindows()。
cv.findcontours函数的用法cv.findContours函数(在OpenCV的Python接口中为cv2.findContours)是用于从二值图像中提取轮廓的一个关键函数。
它能够识别并输出图像中的各个连通组件(白色像素集合),这些组件代表了图像中对象的边界。
以下是一个基本的函数签名和参数解释:pythoncontours, hierarchy = cv2.findContours(image, mode, method[, contours[, hierarchy[, offset]]])1)image:输入图像,必须是二值图像(通常通过阈值操作得到,其中物体区域为白色,背景为黑色)。
2)mode:轮廓检索模式,可选参数包括:cv2.RETR_EXTERNAL:只检测最外层轮廓。
cv2.RETR_LIST:检测所有轮廓,不建立层次关系。
cv2.RETR_CCOMP:检测所有轮廓,并且将它们组织成两层结构,上层为外边界,下层为内孔洞。
cv2.RETR_TREE:构建一个完整的层次结构,包含图像中的所有轮廓。
3)method:轮廓逼近方法,决定如何拟合边缘点以形成更平滑的轮廓曲线,可选参数包括:cv2.CHAIN_APPROX_SIMPLE:压缩水平、垂直或对角线上的连续点,仅保留拐点信息,节省存储空间。
cv2.CHAIN_APPROX_NONE:保存所有轮廓点。
cv2.CHAIN_APPROX_TC89_L1,cv2.CHAIN_APPROX_TC89_KCOS:使用Teh-Chin 链码近似算法。
4)hierarchy(可选输出):返回一个包含轮廓层次信息的数组,对于每个轮廓,提供了其父级、子级、兄弟轮廓等信息。
5)offset(可选参数):如果需要,可以添加一个偏移量来移动轮廓点。
示例用法:pythonimport cv2//加载或处理图像到binary_imagebinary_image = cv2.imread('path_to_your_image', cv2.IMREAD_GRAYSCALE)binary_image = cv2.threshold(binary_image, 127, 255, cv2.THRESH_BINARY)//提取轮廓contours, hierarchy = cv2.findContours(binary_image, cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)//现在你可以用提取出的contours进行进一步的操作,例如绘制轮廓等请注意,不同版本的OpenCV可能在函数调用上有细微差别,尤其是在是否需要预先复制图像以便函数修改原图还是直接读取等方面。
c++ opencv findcontours 用法
在使用C++的OpenCV库中,`findContours`函数可以用于从二值图像中检测轮廓。
它的基本用法如下:
```cpp
#include <opencv2/opencv.hpp>
using namespace cv;
int main() {
// 加载图像
Mat image = imread("image.png", IMREAD_GRAYSCALE); if(image.empty()) {
return -1;
}
// 对图像进行二值化处理
Mat binary;
threshold(image, binary, 128, 255, THRESH_BINARY);
// 寻找轮廓
std::vector<std::vector<Point>> contours;
std::vector<Vec4i> hierarchy;
findContours(binary, contours, hierarchy, RETR_EXTERNAL, CHAIN_APPROX_SIMPLE);
// 绘制轮廓
Mat drawing = Mat::zeros(binary.size(), CV_8UC3);
for(int i = 0; i < contours.size(); i++) {
drawContours(drawing, contours, i, Scalar(0, 255, 0), 2,
LINE_8, hierarchy, 0);
}
// 显示结果
imshow("Contours", drawing);
waitKey(0);
return 0;
}
```
在这个例子中,我们首先加载一幅灰度图像,然后使用
`threshold`函数将其转换为二值图像。
接下来,`findContours`函数用于检测图像中的轮廓。
这个函数的参数包括输入图像、输出的轮廓向量、轮廓的层次结构等。
其中,
`RETR_EXTERNAL`代表只检测外部轮廓,
`CHAIN_APPROX_SIMPLE`表示只保存重要的轮廓点。
通过`drawContours`函数,我们可以将检测到的轮廓绘制在一副空图像上,最后显示结果。
需要注意的是,`findContours`函数会修改输入图像,因此如果需要保留原始图像,请先对其进行备份。
另外,本例中使用的是OpenCV 3.x版本的函数和类型,如果使用的是其他版本,可能需要稍作调整。