OpenCV(cv::findContours())



cv::findContours() 是 OpenCV 中用于检测图像中的轮廓的函数。

1. 函数定义

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

参数:

  1. image:

    • 类型: InputOutputArray(通常是二值化后的图像)
    • 描述: 输入图像,通常是灰度图像或二值图像。该图像会被函数修改,因此如果你想保留原始图像,建议传入其副本。可以使用 cv::Canny()cv::threshold() 生成适合轮廓检测的二值图像。
  2. contours:

    • 类型: OutputArrayOfArrays
    • 描述: 输出的轮廓。每个轮廓是一个点的列表。例如,contours[i] 表示第 i 个轮廓,它是图像中一系列连接的点集。
  3. hierarchy:

    • 类型: OutputArray
    • 描述: 输出的轮廓层次结构。它是一个包含四个整数的向量,分别表示同一级别的前一个轮廓、下一个轮廓、父轮廓和子轮廓。通过该层次结构可以了解轮廓之间的嵌套关系。
  4. mode:

    • 类型: int
    • 描述: 轮廓的检索模式,决定如何组织轮廓数据。取值可以是:
      • cv::RETR_EXTERNAL: 只提取外部轮廓,即不考虑嵌套的轮廓。
      • cv::RETR_LIST: 提取所有的轮廓,但不创建层次关系。
      • cv::RETR_CCOMP: 提取所有的轮廓并将它们组织成两级层次。顶层是外部轮廓,第二层是内部轮廓。
      • cv::RETR_TREE: 提取所有轮廓并重构完整的嵌套轮廓的层次结构。
  5. method:

    • 类型: int
    • 描述: 轮廓的近似方法。取值可以是:
      • cv::CHAIN_APPROX_NONE: 存储所有的轮廓点,不进行压缩。
      • cv::CHAIN_APPROX_SIMPLE: 仅存储拐点信息(去除冗余的中间点)。
      • cv::CHAIN_APPROX_TC89_L1, cv::CHAIN_APPROX_TC89_KCOS: 使用 Teh-Chin 链逼近算法。
  6. offset:

    • 类型: Point
    • 描述: 轮廓中所有点的偏移量。这在需要对轮廓点进行平移时非常有用。

返回值:

该函数没有返回值。轮廓信息通过 contourshierarchy 输出。



2. 示例

#include <opencv2/opencv.hpp>
using namespace cv;
using namespace std;

int main() {
    Mat src = imread("image.png", IMREAD_GRAYSCALE);
    Mat binarized;
    threshold(src, binarized, 128, 255, THRESH_BINARY);

    vector<vector<Point>> contours;
    vector<Vec4i> hierarchy;

    // 检测轮廓
    findContours(binarized, contours, hierarchy, RETR_TREE, CHAIN_APPROX_SIMPLE);

    // 绘制轮廓
    Mat output = Mat::zeros(src.size(), CV_8UC3);
    for (size_t i = 0; i < contours.size(); i++) {
        drawContours(output, contours, static_cast<int>(i), Scalar(0, 255, 0), 2, 8, hierarchy);
    }

    imshow("Contours", output);
    waitKey(0);
    return 0;
}

功能解析:

  • 二值化图像: 为了使 cv::findContours() 正常工作,输入图像通常需要二值化(即背景和前景分离)。通过 cv::threshold()cv::Canny() 可以生成二值图像。

  • 轮廓近似: 使用 CHAIN_APPROX_SIMPLE 会显著减少存储轮廓的点数,因为它只会存储关键点,如直线段的拐点。这在处理复杂图像时,可以显著减少内存消耗。

  • 层次结构: hierarchy 数组能够提供轮廓的嵌套关系。例如,可以通过层次结构分析一个轮廓是否是另一个轮廓的子轮廓(例如洞内的对象)。这在分析复杂的图像时很有用。



3. 常见应用

  1. 对象检测: 检测并标记图像中的物体轮廓。
  2. 形状分析: 使用轮廓数据进行形状匹配和分析,例如计算轮廓的周长、面积等。
  3. 目标分割: 通过检测并处理轮廓,可以将图像中的对象分割出来用于后续处理。


4. 注意事项

  • 输入图像: cv::findContours() 会修改输入图像,因此如果需要保留原始图像,应该传递图像的副本。
  • 轮廓检测模式: 根据应用场景选择合适的 mode,例如在需要层次结构时选择 RETR_TREE,而只需要外部轮廓时选择 RETR_EXTERNAL
  • 图像预处理: 确保输入图像经过适当的预处理(如二值化),以获得正确的轮廓结果。


posted @ 2024-09-03 13:49  做梦当财神  阅读(170)  评论(0编辑  收藏  举报