C++:cv::findContours()查找轮廓说明

cv::findContours 是 OpenCV 库中一个非常重要的函数,用于在二值图像中查找轮廓。该函数可以检测图像中对象的边界,并返回这些轮廓的坐标信息,这些轮廓信息通常用于对象检测、分割和形状分析等任务。以下是对 cv::findContours 函数的详细介绍:

一、函数原型

在 C++ 接口中,cv::findContours 的函数原型通常如下:

void cv::findContours(InputOutputArray image, OutputArrayOfArrays contours, OutputArray hierarchy, int mode, int method, Point offset=Point())

二、参数说明

  1. image:输入的二值图像。这个函数通常在二值图像上操作,因此输入的图像应该是经过阈值处理后的图像,其中对象的像素值为255(白色),背景的像素值为0(黑色)。

  2. contours:用于存储检测到的轮廓的容器。这通常是一个 std::vector<std::vector<cv::Point>> 类型的变量,其中每个内部 vector<cv::Point> 表示一个轮廓,由一系列的点组成。

  3. hierarchy(可选):用于存储轮廓之间的层次结构信息的容器。这是一个可选参数,如果你不需要轮廓之间的层级关系,可以将其设置为空(不传递或使用默认值)。如果传递了这个参数,它将被填充为一个 std::vector<Vec4i> 类型的变量,其中每个 Vec4i 表示一个轮廓的层级信息,包括当前轮廓的下一个轮廓、前一个轮廓、第一个子轮廓和父轮廓的索引。

  4. mode:轮廓检索模式。这个参数决定了 cv::findContours 函数如何检索轮廓。常见的模式有:

    • cv::RETR_EXTERNAL:只检索最外层的轮廓。当有一个大轮廓包裹着一个或多个小轮廓时,cv::RETR_EXTERNAL 只会返回大轮廓,而不会返回被大轮廓包围的小轮廓。
    • cv::RETR_LIST:检索所有的轮廓,但不建立轮廓之间的等级关系。
    • cv::RETR_CCOMP:检索所有的轮廓,并将它们组织为两层:顶层是各部分的外部边界,第二层是空洞的边界。
    • cv::RETR_TREE:检索所有的轮廓,并重构嵌套轮廓的整个层次。
  5. method:轮廓近似方法。这个参数决定了轮廓的近似方式,以减少轮廓上的点的数量,从而提高处理速度。常见的方法有:

    • cv::CHAIN_APPROX_NONE:保存所有的轮廓点,不进行任何压缩。
    • cv::CHAIN_APPROX_SIMPLE:压缩水平、垂直和对角线方向的轮廓,只保留端点。
    • cv::CHAIN_APPROX_TC89_L1cv::CHAIN_APPROX_TC89_KCOS:使用Teh-Chin链近似算法的一种。
  6. offset(可选):轮廓点的偏移量。这是一个可选参数,默认为 cv::Point(0, 0),表示不进行偏移。当轮廓是从图像的某个区域(ROI)中提取的,并且需要在整个图像中分析时,这个参数将很有用。

三、返回值

cv::findContours 函数没有返回值(即返回类型为 void),但它通过修改传入的 contours 和(可选的)hierarchy 参数来输出轮廓和层级信息。

四、使用示例

以下是一个简单的使用 cv::findContours 函数的示例:

#include <opencv2/opencv.hpp>  
  
int main() {  
    cv::Mat image = cv::imread("your_binary_image.jpg", cv::IMREAD_GRAYSCALE); // 加载二值图像  
    cv::Mat binary;  
    cv::threshold(image, binary, 128, 255, cv::THRESH_BINARY); // 确保图像是二值的  
  
    std::vector<std::vector<cv::Point>> contours;  
    std::vector<cv::Vec4i> hierarchy;  
  
    cv::findContours(binary, contours, hierarchy, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE);  
  
    // 在这里可以使用 contours 和 hierarchy 进行进一步的处理,比如绘制轮廓等  
  
    return 0;  
}

五、注意事项

  • 输入图像必须是二值图像,即图像中的像素值只能是0或255。
  • 轮廓检索模式和轮廓近似方法的选择取决于你的具体需求,不同的选择会影响轮廓的检测结果和处理速度。
  • 轮廓的层级信息(如果需要)提供了轮廓之间的父子关系,这对于分析嵌套轮廓非常有用。

通过 cv::findContours 函数,你可以轻松地在二值图像中检测对象的轮廓

在图像处理中,当您处理一个二值图像,其中黑色代表背景,白色代表物体时,确实,如果每个白色区域(即物体)在图像中是连续且未被打断的,那么通过findContours函数检测到的每个物体的轮廓通常是闭合的。这是因为findContours函数会沿着物体的边界(即白色到黑色的像素变化处)查找并返回轮廓点集,这些点集自然地形成了一个闭合的环,包围了物体的内部区域。

然而,需要注意的是,有几个因素可能会影响轮廓的闭合性:

  1. 图像噪声:如果图像中存在噪声,可能会导致物体边界上的像素值发生不必要的变化,这可能会干扰轮廓的闭合性。虽然这种影响可能很小,但在某些情况下可能需要通过图像预处理步骤(如滤波、去噪等)来减少噪声。

  2. 物体接触或重叠:如果图像中的物体相互接触或重叠,那么它们的轮廓可能会合并成一个更复杂的形状,这可能会使得单个物体的轮廓不再是完全闭合的。在这种情况下,您可能需要使用更复杂的图像处理技术(如分水岭算法、图割算法等)来分割和识别接触或重叠的物体。

  3. 二值化阈值:二值化过程中选择的阈值对轮廓的闭合性也有影响。如果阈值设置不当,可能会导致物体的内部出现空洞或物体的边界被切断,从而影响轮廓的闭合性。因此,选择合适的阈值对于获得准确的轮廓至关重要。

  4. 轮廓近似方法findContours函数允许您指定轮廓的近似方法。在某些情况下,为了减少轮廓上的点数以提高处理速度,可能会选择使用近似方法。然而,过度的近似可能会导致轮廓失去其原有的闭合性。因此,在选择近似方法时需要考虑其对轮廓闭合性的影响。

总的来说,在大多数情况下,如果图像中的物体是连续且未被打断的,并且图像处理步骤得当(如适当的二值化、滤波等),那么通过findContours函数检测到的物体轮廓通常是闭合的。然而,在处理复杂的图像时,可能需要考虑上述因素以确保获得准确的轮廓。

`findContours` 是 OpenCV(开源计算机视觉库)中的一个重要函数,用于从二值图像中检测和提取轮廓。在 C++ 中,`findContours` 函数帮助我们识别出图像中的边缘并将其转换为可操作的对象,如轮廓点列表或轮廓矩。 以下是一个简单的 C++ 示例,展示了如何使用 `findContours` 函数: ```cpp #include <opencv2/opencv.hpp> #include <opencv2/imgproc/imgproc.hpp> int main() { // 读取二值图像 cv::Mat src = cv::imread("binary_image.jpg", cv::IMREAD_GRAYSCALE); cv::Mat thresholded; cv::threshold(src, thresholded, 127, 255, cv::THRESH_BINARY); // 二值化处理 // 寻找轮廓 std::vector<std::vector<cv::Point>> contours; std::vector<cv::Vec4i> hierarchy; cv::findContours(thresholded, contours, hierarchy, cv::RETR_TREE, cv::CHAIN_APPROX_SIMPLE); // 处理轮廓(例如,绘制轮廓) for (size_t i = 0; i < contours.size(); ++i) { cv::drawContours(src, contours, i, cv::Scalar(0, 0, 255), 2); // 绘制轮廓,红色 } // 显示结果 cv::imshow("Contours", src); cv::waitKey(0); return 0; } ``` 在这个例子中: - `imread` 用于加载图像 - `threshold` 对图像进行二值化处理,以便后续识别边缘 - `findContours` 传入二值图像、轮廓存储容器、轮廓层次结构、轮廓检索模式(这里为树形结构)和轮廓逼近方法(简单连接) - 循环遍历找到的轮廓,并使用 `drawContours` 在原图上绘制它们 - 最后,使用 `imshow` 显示包含轮廓的结果 相关问题: 1. `findContours` 的参数含义是什么? 2. 如何根据 `hierarchy` 参数理解轮廓之间的关系? 3. 除了 `CHAIN_APPROX_SIMPLE`,还有哪些轮廓逼近方法?
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值