C++OpenCV系统学习(12)——轮廓发现(find contour)

本文详细介绍了Python中OpenCV库的轮廓发现功能,包括findContours和drawContours API的使用,以及通过Canny边缘检测和灰度转换实现轮廓提取的实际步骤。实例展示了如何在图像上绘制轮廓,适合初学者和进阶者学习图像处理基础。

目录

1.概述

1.1轮廓发现概念

1.2相关API

2.API参数解释

 2.1.轮廓发现

2.2绘制轮廓

2.3 实现步骤

 3.实验示例


1.概述

1.1轮廓发现概念

轮廓发现是基于图像边缘提取的基础寻找对象轮廓的方法,所以边缘提取的阈值选定会影响最终轮廓发现的结果

1.2相关API

findContours()发现轮廓

drawContours()绘制轮廓

2.API参数解释

 2.1.轮廓发现

2.2绘制轮廓

2.3 实现步骤

  1. 输入图像转为灰度图像cvtColor

  2. 使用Canny进行边缘提取,得到二值图

  3. 使用findContours寻找轮廓

  4. 使用drawContours绘制轮廓 

 3.实验示例

void MyApi::find_img_contour(Mat& image)
{
	RNG rng;
	Mat dst;
	vector<vector<Point>>contours;
	vector<Vec4i>hierarchy;
	Canny(image, dst, 100, 200, 3, false);
	findContours(dst, contours, hierarchy, RETR_TREE, CHAIN_APPROX_SIMPLE, Point(0, 0));

	Mat drawImage = Mat::zeros(dst.size(), CV_8UC3);
	for (size_t i = 0; i < contours.size(); i++)
	{
		Scalar color = Scalar(rng.uniform(0, 255), rng.uniform(0, 255), rng.uniform(0, 255));
		drawContours(drawImage, contours, i, color, 2, LINE_8, hierarchy, 0, Point(0, 0));
	}
	imshow("轮廓结果", drawImage);
}

左边是输入,右边是轮廓的结果 

### C++OpenCV 的 `findContours` 函数详解 #### 1. 函数概述 `cv::findContours` 是 OpenCV 提供的一个用于检测图像中轮廓的函数。它能够识别二值化图像中的连通区域边界,并返回这些边界的坐标集合[^2]。 #### 2. 参数说明 以下是该函数的主要参数及其作用: - **输入图像 (`inputImage`)** 输入图像是一个单通道的二值图像,通常通过阈值处理(如 `cv::threshold` 或 `cv::Canny`)获得。 - **轮廓存储容器 (`contours`)** 这是一个向量数组,保存找到的所有轮廓点集。每个轮廓由一系列点组成,表示为 `std::vector<std::vector<cv::Point>>` 类型。 - **检索模式 (`mode`)** 定义如何检索轮廓层次结构。常见的选项有: - `cv::RETR_EXTERNAL`: 只检索最外层轮廓; - `cv::RETR_LIST`: 检索所有轮廓但不建立层次关系; - `cv::RETR_CCOMP`: 建立两层等级结构; - `cv::RETR_TREE`: 建立完整的树形结构。 - **近似方法 (`method`)** 控制轮廓的存储方式。常用的方法包括: - `cv::CHAIN_APPROX_NONE`: 存储所有的轮廓点; - `cv::CHAIN_APPROX_SIMPLE`: 将多边形直线上的中间点压缩成端点。 - **偏移量 (`offset`)** (可选)指定每个轮廓点相对于原坐标的平移矢量,默认为 `(0, 0)`。 #### 3. 示例代码 下面提供了一个基于 Ubuntu 22.04 和 OpenCV 4.9 的完整示例代码,展示如何使用 `cv::findContours` 函数提取图像轮廓并绘制它们。 ```cpp #include <opencv2/opencv.hpp> #include <iostream> int main() { // 加载灰度图像 cv::Mat src = cv::imread("example.png", cv::IMREAD_GRAYSCALE); if (src.empty()) { std::cerr << "无法加载图片!" << std::endl; return -1; } // 阈值处理得到二值图像 cv::Mat binary; cv::threshold(src, binary, 0, 255, cv::THRESH_BINARY_INV + cv::THRESH_OTSU); // 创建变量来存储轮廓和分层信息 std::vector<std::vector<cv::Point>> contours; std::vector<cv::Vec4i> hierarchy; // 调用 findContours 函数查找轮廓 cv::findContours(binary, contours, hierarchy, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE); // 绘制轮廓到原始彩色图像上 cv::Mat drawing = cv::Mat::zeros(src.size(), CV_8UC3); for (size_t i = 0; i < contours.size(); ++i) { cv::Scalar color = cv::Scalar(0, 0, 255); // 设置颜色为红色 cv::drawContours(drawing, contours, static_cast<int>(i), color, 2, cv::LINE_8, hierarchy, 0); } // 显示结果 cv::imshow("Contours", drawing); cv::waitKey(0); return 0; } ``` 上述代码实现了以下功能: 1. 读取一张灰度图像作为输入; 2. 对其应用 Otsu 自适应阈值算法生成二值图像; 3. 利用 `cv::findContours` 找出外部轮廓; 4. 在新创建的 RGB 图像上绘制发现轮廓。 #### 4. 异常情况分析 如果在调用 `cv::findContours` 时遇到异常,则可能是由于以下几个原因造成的[^3]: - 输入图像不是有效的二值图像; - 数据类型不符合预期(例如浮点数而非整数); - 内存分配失败或其他内部错误。 针对这些问题可以采取相应的解决措施,比如确保输入数据正确无误以及增加必要的错误捕获逻辑。 ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

AI炮灰

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值