opencv findcontours 数组排序规则

合集下载

cv2.findcontours函数返回物体中心和长宽信息

cv2.findcontours函数返回物体中心和长宽信息

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}")```请注意,上述代码中,我们使用了图像的二值形式(如果存在)。

OpenCV Blob分析-基于FindContours联通区域分析

OpenCV Blob分析-基于FindContours联通区域分析

OpenCV Blob分析-基于FindContours联通区域分析本文是一个较完整的Blob分析思路解说,是用OpenCvSharp联合c#编写的。

思路如下:1、对图像进行二值化2、设定ROI3、腐蚀、膨胀(可选)4、边缘提取(有区分是否需填充孔洞)5、进行筛选看一组使用效果图1 原图图2 提取黑色对象图3 提取黑色对象并填充孔洞部分源代码解说:InputImage来着输入的要处理的图片。

gray_min、gray_max二值化的上下阈值1、对图像进行二值化(根据二值化的上下阈值来判定二值化方式)Mat binaryImage = new Mat(InputImage.Size(), MatType.CV_8UC1, Scalar.Black);if (gray_min != 0 && gray_max != 255){binaryImage = InputImage.Threshold(gray_min, 255, ThresholdTypes.Binary);Mat binaryImage2 = InputImage.Threshold(gray_max, 255, ThresholdTypes.BinaryInv);Mat binaryImage3 = new Mat(InputImage.Size(), MatType.CV_8UC1,Scalar.Black);binaryImage.CopyTo(binaryImage3, binaryImage2);binaryImage = binaryImage3.Clone();binaryImage2.Dispose();binaryImage3.Dispose();}else{if (gray_min == 0) binaryImage = InputImage.Threshold(gray_max, 255, ThresholdTypes.BinaryInv);if (gray_max == 255) binaryImage = InputImage.Threshold(gray_min, 255, ThresholdTypes.Binary);}Mat binaryImage1 = new Mat(InputImage.Size(), MatType.CV_8UC1, Scalar.Black);2、设定ROI(Mask就是ROI感兴趣区域)binaryImage.CopyTo(binaryImage1, Mask);3、腐蚀、膨胀(可选)if (erosion_dilation == "腐蚀"){Cv2.Erode(binaryImage1, binaryImage1, element);}else{Cv2.Dilate(binaryImage1, binaryImage1, element);}4、边缘提取(有区分是否需填充孔洞)if (fill_up_flag == true){Cv2.FindContours(binaryImage1, out contours, hierarchy, RetrievalModes.External, ContourApproximationModes.ApproxSimple);}else{Cv2.FindContours(binaryImage1, out contours, hierarchy, omp, ContourApproximationModes.ApproxSimple);}5、进行筛选Mat uu = hierarchy.GetMat();// 筛选那些面积小的List<MyCenter> centers = new List<MyCenter>();List<RotatedRect> regions = new List<RotatedRect>();var detectorParams = new SimpleBlobDetector.Params{MinDistBetweenBlobs = 10, // 10 pixels between blobsMinRepeatability = 1,MinThreshold = 0,MaxThreshold = 128,ThresholdStep = 2,FilterByArea = area_bool,MinArea = area_min, // 10 pixels squaredMaxArea = area_max,//圆度FilterByCircularity = circularity_bool,MinCircularity = circularity_min,MaxCircularity = circularity_max,// 凸包形状分析 - 过滤凹包FilterByConvexity = false,//FilterByConvexity = true,MinConvexity = 0.001f,MaxConvexity = 10,FilterByInertia = false,//FilterByInertia = true,MinInertiaRatio = 0.001f,FilterByColor = false,//FilterByColor = true,BlobColor = 255 // to extract light blobs};MyCenter center;int j = 0;Vec4i value;Mat cnt = new Mat();foreach (Mat cnt0 in contours){value = uu.Get<Vec4i>(0, j);j++;//int i = hierarchy;// 根据轮廓面积进行筛选if (value[3] != -1){cnt = contours[value[3]];}else{cnt = cnt0;}center.confidence = 1;Moments moms = Cv2.Moments(cnt);if (detectorParams.FilterByArea) //斑点面积的限制{double area = moms.M00; //零阶矩即为二值图像的面积//如果面积超出了设定的范围,则不再考虑该斑点if (area < detectorParams.MinArea || area >= detectorParams.MaxArea)continue;}if (detectorParams.FilterByCircularity) //斑点圆度的限制{double area = moms.M00; //得到斑点的面积//计算斑点的周长double perimeter = Cv2.ArcLength(cnt, true);//由公式3得到斑点的圆度double ratio = 4 * Cv2.PI * area / (perimeter * perimeter);//如果圆度超出了设定的范围,则不再考虑该斑点if (ratio < detectorParams.MinCircularity || ratio >= detectorParams.MaxCircularity)continue;}if (detectorParams.FilterByInertia) //斑点惯性率的限制{//计算公式13中最右侧等式中的开根号的值double denominator = Math.Sqrt(Math.Pow(2 * moms.Mu11, 2) +Math.Pow(moms.Mu20 - moms.Mu02, 2));const double eps = 1e-2; //定义一个极小值double ratio;if (denominator > eps){//cosmin和sinmin用于计算图像协方差矩阵中较小的那个特征值λ2double cosmin = (moms.Mu20 - moms.Mu02) / denominator;double sinmin = 2 * moms.Mu11 / denominator;//cosmin和sinmin用于计算图像协方差矩阵中较大的那个特征值λ1double cosmax = -cosmin;double sinmax = -sinmin;//imin为λ2乘以零阶中心矩μ00double imin = 0.5 * (moms.Mu20 + moms.Mu02) - 0.5 * (moms.Mu20 - moms.Mu02) * cosmin - moms.Mu11 * sinmin;//imax为λ1乘以零阶中心矩μ00double imax = 0.5 * (moms.Mu20 + moms.Mu02) - 0.5 * (moms.Mu20 - moms.Mu02) * cosmax - moms.Mu11 * sinmax;ratio = imin / imax; //得到斑点的惯性率}else{ratio = 1; //直接设置为1,即为圆}//如果惯性率超出了设定的范围,则不再考虑该斑点if (ratio < detectorParams.MinInertiaRatio || ratio >= detectorParams.MaxInertiaRatio)continue;//斑点中心的权值定义为惯性率的平方center.confidence = ratio * ratio;}if (detectorParams.FilterByConvexity) //斑点凸度的限制{Mat hull = new Mat(); //定义凸壳变量//调用convexHull函数,得到该斑点的凸壳Cv2.ConvexHull(cnt, hull);//分别得到斑点和凸壳的面积,contourArea函数本质上也是求图像的零阶矩double area = Cv2.ContourArea(cnt);double hullArea = Cv2.ContourArea(hull);double ratio = area / hullArea; //公式5,计算斑点的凸度//如果凸度超出了设定的范围,则不再考虑该斑点if (ratio < detectorParams.MinConvexity || ratio >= detectorParams.MaxConvexity)continue;}//根据公式7,计算斑点的质心center.location = new Point2d(moms.M10 / moms.M00, moms.M01 / moms.M00);// 根据轮廓近似进行筛选,作用很小double epsilon = 0.001 * Cv2.ArcLength(cnt, true);Mat approx = new Mat();Cv2.ApproxPolyDP(cnt, approx, epsilon, true);// 根据最小矩形进行筛选,该矩形可能有方向RotatedRect rect = Cv2.MinAreaRect(approx);//int row = rect.BoundingRect().X;//int col = rect.BoundingRect().Y;if (width_bool){int width = rect.BoundingRect().Width;if (width < width_min || width > width_max) continue;}if (height_bool){int height = rect.BoundingRect().Height;if (height < height_min || height > height_max) continue;}//根据质心来判断颜色不合理,但是我觉得这个不合理就把它禁用了//if (detectorParams.FilterByColor) //斑点颜色的限制//{// //判断一下斑点的颜色是否正确// if (binaryImage.At(int) (cvRound(center.location.Y),cvRound(center.location.X)) != detectorParams.BlobColor)// continue;// }////compute blob radius//{// Mat dists; //定义距离队列// //遍历该斑点边界上的所有像素// for (size_t pointIdx = 0; pointIdx < contours[contourIdx].size(); pointIdx++)// {// Point2d pt = contours[contourIdx][pointIdx]; //得到边界像素坐标// //计算该点坐标与斑点中心的距离,并放入距离队列中// dists.push_back(norm(center.location - pt));// }// std::sort(dists.begin(), dists.end()); //距离队列排序// //计算斑点的半径,它等于距离队列中中间两个距离的平均值// center.radius = (dists[(dists.size() - 1) / 2] + dists[dists.size() / 2]) / 2.;//}centers.Add(center);outcontours.Add(cnt0);}。

cv2findcontours 原理

cv2findcontours 原理

cv2findcontours 原理CV2 FindContours原理CV2 FindContours是一种计算图像轮廓的函数,它是OpenCV库中的一个重要函数。

该函数可以帮助我们找到图像中的所有轮廓,并将它们存储在一个列表中。

在本文中,我们将深入探讨CV2 FindContours的原理。

CV2 FindContours的原理是基于图像处理中的边缘检测算法。

边缘检测算法是一种用于检测图像中物体边缘的技术。

它可以通过检测图像中像素值的变化来确定物体的边缘。

在CV2 FindContours中,边缘检测算法被用来找到图像中的所有轮廓。

CV2 FindContours的工作原理可以分为以下几个步骤:1. 图像预处理在使用CV2 FindContours之前,我们需要对图像进行预处理。

预处理的目的是为了使图像中的轮廓更加明显。

常见的预处理方法包括灰度化、二值化、滤波等。

2. 边缘检测在预处理完成后,我们需要使用边缘检测算法来检测图像中的边缘。

常见的边缘检测算法包括Sobel算子、Canny算子等。

3. 轮廓查找在检测到图像中的边缘后,CV2 FindContours会根据边缘的像素点来查找轮廓。

它会将所有相邻的像素点组成一个轮廓,并将轮廓存储在一个列表中。

4. 轮廓绘制CV2 FindContours会将找到的轮廓绘制在原始图像上。

这样我们就可以看到图像中所有的轮廓了。

总结CV2 FindContours是一种非常重要的图像处理函数。

它可以帮助我们找到图像中的所有轮廓,并将它们存储在一个列表中。

CV2 FindContours的原理是基于边缘检测算法,它可以通过检测图像中像素值的变化来确定物体的边缘。

在使用CV2 FindContours之前,我们需要对图像进行预处理,包括灰度化、二值化、滤波等。

最后,CV2 FindContours会将找到的轮廓绘制在原始图像上,以便我们更好地观察图像中的轮廓。

opencv drawcontours函数

opencv drawcontours函数

opencv drawcontours函数OpenCV是一个开源的计算机视觉库,它提供了各种图像处理和分析功能,包括图像读取、过滤、转换、处理、特征检测、物体识别等。

其中,drawcontours函数是OpenCV中常用的函数之一,主要用于绘制轮廓线。

drawcontours函数的代码格式如下:cv2.drawContours(image, contours, contourIdx, color, thickness=None, lineType=None, hierarchy=None, maxLevel=None, offset=None)参数说明:- image:输入图像,必须为8位或32位单通道图像。

- contours:轮廓线数组,由cv2.findContours函数得到。

- contourIdx:要绘制的轮廓线的索引,如果为负数则表示绘制所有轮廓线。

- color:轮廓线的颜色,可以为一个三元素的元组。

- thickness:轮廓线的宽度,如果为-1则表示填充轮廓。

- lineType:轮廓线的类型,可以选择线条类型,如CV_AA。

- hierarchy:轮廓的层次结构,由cv2.findContours函数得到。

- maxLevel:绘制的轮廓线的最大层级。

- offset:轮廓线的偏移量。

drawcontours函数可以绘制图像中的轮廓线,通常用于图像分割和物体检测。

轮廓线是指图像中黑色物体和白色背景的边缘线,可以通过cv2.findContours函数获取。

drawcontours函数可以将轮廓线绘制到输入图像的相应位置上,以便于后续的处理和分析。

在使用drawcontours函数时,需要注意以下几点:1.需要先确定轮廓线的坐标和轮廓线数组,在使用cv2.findContours函数时可以获取到。

2.需要确定绘制的轮廓线的颜色和宽度,可以通过设置color和thickness参数来实现。

opencv drawcontour 填充的算法

opencv drawcontour 填充的算法

opencv drawcontour 填充的算法全文共四篇示例,供读者参考第一篇示例:OpenCV是一个开源的计算机视觉库,其中的drawContour函数可以用来绘制轮廓并进行填充。

填充算法是指在轮廓内部填充颜色或图案。

在本文中,我们将探讨OpenCV中drawContour填充的算法原理和实现方法。

在使用drawContour函数进行填充时,首先需要定义一个二维的图像矩阵,并用轮廓检测算法(如findContour函数)找到图像中的所有轮廓。

接下来,我们需要遍历每个轮廓,并使用fillPoly函数将轮廓内部的所有像素点进行填充。

fillPoly函数的参数包括图像矩阵、轮廓点集和填充颜色。

通过调用fillPoly函数,我们可以在轮廓内部绘制出填充效果。

除了使用单一颜色进行填充外,我们还可以通过设置复杂的填充图案来美化轮廓的显示效果。

在OpenCV中,我们可以创建一个填充图案矩阵,并通过调用实现填充方法来实现对轮廓的填充。

填充图案可以是简单的几何图案,如斜线、格子或点阵,也可以是复杂的纹理图案。

在实际应用中,填充算法不仅可以用于美化图像的显示效果,还可以在图像分割、目标检测等领域发挥重要作用。

通过对目标轮廓进行填充,我们可以更清晰地展示目标的形状和大小,从而提高图像处理的准确性和效率。

OpenCV中drawContour填充的算法是一个简单但重要的功能。

通过理解其原理和实现方法,我们可以更好地利用这一功能对图像进行处理和分析。

希望本文能对读者的学习和实践有所帮助,激发大家对计算机视觉技术的兴趣和热情。

【本篇文章共计800字】接下来我们来说说OpenCV drawContour填充的算法原理和实现细节,更深入地探讨这一功能的实现方式。

在OpenCV中,填充算法的实现过程涉及到图像的遍历和像素点的着色。

具体而言,我们需要遍历整个图像矩阵,并判断每个像素点是否在轮廓内部。

对于在轮廓内部的像素点,我们需要对其进行着色,填充颜色或图案。

c++ opencv findcontours 用法

c++ opencv findcontours 用法

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`函数用于检测图像中的轮廓。

cv.findcontours函数的用法

cv.findcontours函数的用法

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可能在函数调用上有细微差别,尤其是在是否需要预先复制图像以便函数修改原图还是直接读取等方面。

opencv findcontours用法

opencv findcontours用法

opencv findcontours用法opencv是一个广泛使用的计算机视觉库,它可以帮助开发人员创建高质量的图像和视频处理应用程序。

其中,findContours函数是opencv中的一个常用函数,用于查找图像中的复杂图形轮廓。

以下是使用opencv findContours函数查找图像中的轮廓的一般步骤:1. 导入所需的库并设置环境变量首先,需要导入opencv库并设置环境变量,以便可以使用opencv findContours函数。

可以使用以下命令:```#include <opencv2/opencv.hpp>```2. 创建输入文件接下来,需要创建一个输入文件,用于存储要查找轮廓的图像数据。

可以使用以下命令:```#include <opencv2/core/core.hpp>#include <opencv2/imgproc/imgproc.hpp>#include <opencv2/videoio/videoio.hpp>int main(int argc, char** argv) {// Create input filecv::Mat inputImage = cv::imreadimread("inputImage.jpg",cv::IMREAD_GRAYSCALE);// Create output filecv::Mat outputImage = cv::Mat(inputImage.rows, inputImage.cols, CV_8UC3);cv::imwrite("contours.jpg", outputImage);return 0;}```在上面的示例中,我们使用了cv::imreadimread函数来读取图像文件,并使用cv::imwrite函数来创建输出文件。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

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() {
假设有一个存储轮廓点的向量contours
std::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进行排序。

最后输出排序后的轮廓面积。

当然,您可以根据具体需求自定义其他的排序规则。

相关文档
最新文档