opencv基础篇 ——(十二)轮廓提取与绘制

16 篇文章 0 订阅

opencv基础篇 ——(十二)轮廓提取与绘制

findContours轮廓提取

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

功能介绍

cv::findContours 是 OpenCV 中用于在图像中查找轮廓的函数之一。它可以帮助你找到图像中所有的轮廓,并且可以选择性地进行轮廓的过滤和处理。主要用于在二值图像中查找对象的边界轮廓。这些轮廓通常是对象之间的分界线,可以通过它们进行形状分析、对象检测等操作。

  • image: 输入图像,必须是单通道的二值图像,即像素值为0或255(或0或1)

  • contours: 输出轮廓的容器。函数会将检测到的轮廓信息存储在这个数据结构中。具体而言,contours应当是一个 std::vector<std::vectorcv::Point> 类型的容器,其中每个内部向量代表一个轮廓,由构成该轮廓的连续边界点(cv::Point)组成。

  • hierarchy: 参数是一个可选输出参数,用于存储轮廓之间的层级关系信息。如果用户不关心轮廓间的嵌套或层次结构,可以将其设置为 noArray() 或者忽略此参数。但若希望获取轮廓间的父子关系、内部轮廓与外部轮廓的关联等信息,应提供一个合适的输出容器(如 std::vector)来接收这些数据。
    每个轮廓在 hierarchy 中对应一个四元组 (h_next, v_next, h_prev, v_prev),其中:

    • h_next:指向同一级别下下一个轮廓的索引。
    • v_next:指向当前轮廓的直接内嵌子轮廓的索引。
    • h_prev:指向同一级别下前一个轮廓的索引。
    • v_prev:指向当前轮廓的直接父轮廓的索引。
      当某个值为 -1 时,表示没有对应的邻居或父/子轮廓。这种层次信息有助于分析图像中轮廓之间的包含关系,例如用于识别内部孔洞、独立对象以及构建多级轮廓树。
  • mode: 轮廓检索模式,指定如何组织和返回检测到的轮廓。常用的模式包括:

    • cv::RETR_EXTERNAL: 只返回最外层轮廓,忽略任何嵌套的轮廓(即内部空洞或子轮廓)。
    • cv::RETR_LIST: 返回所有轮廓,不建立任何层次关系,轮廓按检测顺序排列。
    • cv::RETR_CCOMP: 返回所有轮廓,并按照两个级别构建层次结构:外部轮廓(级别1)和它们的内嵌孔洞(级别2)。
    • cv::RETR_TREE: 返回所有轮廓,并以完整的嵌套层次结构形式组织,即每个轮廓可以有任意数量的直接子轮廓。
  • method: 轮廓逼近方法,用于决定如何将实际轮廓点集近似为更紧凑的点集,以减少轮廓点的数量。常用的逼近方法包括:

    • cv::CHAIN_APPROX_SIMPLE: 仅保留轮廓端点和拐点,将轮廓压缩为一系列直线段。
    • cv::CHAIN_APPROX_TC89_L1, cv::CHAIN_APPROX_TC89_KCOS: 使用 Teh-Chin 链码算法的变种进行更复杂的逼近。
    • cv::CHAIN_APPROX_NONE: 不进行任何压缩,保留轮廓上的所有原始点。
  • offset: 可选的偏移量,表示在检测轮廓前将输入图像平移的像素值。这对于从原图像中裁剪出的部分进行轮廓检测时特别有用,可以确保返回的轮廓坐标与原图像坐标系统保持一致。

功能与用途

cv::findContours 函数的主要功能如下:

  • 轮廓检测:在二值图像中识别并分离出各个连通的白色像素区域,即独立的物体或形状。

  • 轮廓提取:将每个检测到的物体或形状的边界点序列化为一个点集(cv::Point 向量),这些点集构成了轮廓。

  • 轮廓组织:根据指定的 mode 参数,可以将轮廓按不同的层次结构进行组织和返回,如仅返回最外层轮廓、返回所有轮廓的列表,或者构建完整的嵌套轮廓树。

  • 轮廓近似:根据指定的 method 参数,可以选择是否对原始轮廓点集进行近似处理,以减小存储和后续处理的复杂性。

综上所述,cv::findContours 函数提供了一种通用且强大的工具,用于从二值图像中自动提取并结构化表示各种形状的轮廓信息。

drawContours 轮廓绘制

功能介绍

cv::drawContours 是 OpenCV 库中用于在图像上绘制轮廓的函数,常用于可视化检测到的轮廓或创建轮廓相关的图形输出。以下是该函数的功能介绍:

cv::drawContours(
    inputImage,           // InputOutputArray image
    contours,             // InputArrayOfArrays contours
    contourIdx,           // int contourIdx
    color,                // const Scalar& color
    thickness,            // int thickness
    lineType,             // int lineType
    hierarchy,            // InputArray hierarchy
    maxLevel,             // int maxLevel
    offset                // Point offset
);

参数解释:

  • inputImage: 输入/输出图像(cv::Mat 类型),轮廓将在该图像上绘制。图像可以是任意通道数和深度的,但通常为单通道或三通道(彩色)的 8-bit 或 16-bit 图像。

  • contours: 输入的轮廓数组(std::vector<std::vectorcv::Point> 类型)。这是从 cv::findContours 函数或其他方式获取的一系列轮廓,每个轮廓由一组连续的边界点(cv::Point)组成。

  • contourIdx: 要绘制的轮廓索引。可以是单个整数,表示要绘制指定索引的单个轮廓;也可以是负数,此时绘制所有轮廓:

    • -1:绘制所有轮廓。
    • -2:绘制除了最大(面积最大)轮廓以外的所有轮廓。
    • -3:绘制除了最小(面积最小)轮廓以外的所有轮廓。
  • color: 绘制轮廓使用的颜色。对于单通道灰度图像,通常是一个标量值;对于彩色图像,通常是 cv::Scalar 类型的 BGR 或 BGRA 值。

  • thickness: 轮廓线的粗细。可以是正数(表示像素宽度)、负数(表示填充轮廓)或 CV_FILLED(完全填充轮廓,等同于负数的最大值)。

  • lineType: 线型。常见的选项包括:

    • cv::LINE_8:8-connected 直线(默认)。
    • cv::LINE_AA:抗锯齿线条,适用于高质量输出。
  • hierarchy: (可选)轮廓的层级信息。通常是从 cv::findContours 函数返回的,用于遵循轮廓之间的嵌套关系。如果未提供或为空,所有轮廓被视为无层级关系。

  • maxLevel: (仅当提供了 hierarchy 时有效)绘制轮廓的最大嵌套级别。例如,设置为 0 表示只绘制最外层轮廓;设置为 1 表示绘制最外层轮廓及其直接子轮廓,依此类推。

  • offset: (可选)绘制轮廓时应用的偏移量。如果提供了这个参数,所有轮廓将在原位置基础上加上这个偏移量。

功能与用途

cv::drawContours 函数的主要功能如下:

  • 轮廓绘制:在指定的输入图像上绘制给定的轮廓集合,可以是单个轮廓或多组轮廓。

  • 样式定制:允许用户控制轮廓的颜色、线宽(或填充方式)、线型等视觉属性,以满足不同应用场景的需求。

  • 层级支持:结合轮廓的层级信息(hierarchy),可以按照轮廓间的嵌套关系有选择地绘制部分轮廓,如仅绘制最外层轮廓、特定层级的轮廓或整个轮廓树。

  • 坐标变换:通过提供 offset 参数,可以在绘制轮廓时对轮廓坐标进行平移,适应图像裁剪、视窗调整等场景。

综上所述,cv::drawContours 函数为用户提供了一个灵活的工具,用于在图像上可视化表示轮廓数据,便于观察、分析和展示检测到的形状边界。该函数接受轮廓数据、绘制参数及可选的附加信息作为输入,将轮廓绘制到指定的输入图像上,生成包含轮廓图形的输出图像。

示例

#include <opencv2/opencv.hpp>
#include <iostream>

using namespace cv;
using namespace std;

int main() {
    Mat image = imread("image.jpg", IMREAD_GRAYSCALE);
    if (image.empty()) {
        cout << "无法读取图像文件!" << endl;
        return -1;
    }

    Mat binary;
    threshold(image, binary, 128, 255, THRESH_BINARY);

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

    // 查找轮廓
    findContours(binary, contours, hierarchy, RETR_TREE, CHAIN_APPROX_SIMPLE);

    // 绘制轮廓
    Mat result = Mat::zeros(image.size(), CV_8UC3);
    drawContours(result, contours, -1, Scalar(0, 255, 0), 2);

    // 显示结果
    imshow("Contours", result);
    waitKey(0);

    return 0;
}

效果展示

  • RETR_EXTERNAL与RETR_CCOMP的区别
    在这里插入图片描述

设置RETR_CCOMP参数,会返回内部轮廓和内部轮廓,至于上图中thickness=-1的情况下,没有输出填充图,尚未找到缘由。

  • 调整参数,输出想要的格式
    在这里插入图片描述

  • 下图绘制某一图形的内外轮廓:
    在这里插入图片描述

  • 26
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值