[OpenCV] 数字图像处理 C++ 学习——17轮廓发现详细讲解+附完整代码

文章目录

前言

轮廓发现是图像处理中一个重要的操作,可以帮助找到图像中的边界并识别物体的形状。在 OpenCV 中,findContours 函数可以用来检测图像中的轮廓,广泛应用于图像分割、形状分析、物体检测等场景。本篇文章将详细介绍如何在 OpenCV 中实现轮廓发现,并通过完整的 C++ 代码示例进行演示。

1.理论基础

1.1轮廓发现

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

1.2轮廓发现步骤

  • 图像预处理cvtColor将输入的图像转为灰度图像,并使用 Canny 边缘检测算法来提取边缘。
  • 发现轮廓 :使用 findContours 函数从二值图像中发现轮廓。findContours 函数会输出一个包含轮廓的列表。
  • 绘制轮廓 :使用 drawContours 函数将发现的轮廓绘制在图像上。

1.3相关API

(1)轮廓发现(find contour)

cpp 复制代码
cv::findContours(
InputOutputArray image, // 输入图像,非0的像素被看成1,0的像素值保持不变,8-bit  
OutputArrayOfArrays contours,//  全部发现的轮廓对象
OutputArray hierachy,// 图该的拓扑结构,可选,该轮廓发现算法正是基于图像拓扑结构实现。
int mode, //  轮廓返回的模式
int method,// 发现方法
Point offset=Point()//  轮廓像素的位移,默认(0, 0)没有位移
)

(2)轮廓绘制(draw contour)

cpp 复制代码
void drawContours( 
InputOutputArray image, //输出图像 
InputArrayOfArrays contours,//全部发现的轮廓对象
int contourIdx, //轮廓索引号
const Scalar& color,//绘制时候颜色
int thickness = 1, //绘制线宽
int lineType = LINE_8,//线的类型LINE_8
InputArray hierarchy = noArray(),//拓扑结构图
int maxLevel = INT_MAX,// 最大层数, 0只绘制当前的,1表示绘制绘制当前及其内嵌的轮廓 
Point offset = Point() // 轮廓位移,可选
);

2.代码实现

2.1图像预处理

对输入图像进行预处理。将图像转为灰度图,然后使用 Canny 边缘检测算法提取图像的边缘。

cpp 复制代码
// 将图像转为灰度图
cvtColor(src, src, COLOR_BGR2GRAY);
// 使用Canny边缘检测
Canny(src, dst, threshold_value, threshold_value * 2, 3, false);

2.2轮廓发现

在二值化图像上使用 findContours 函数来发现轮廓,findContours 返回轮廓列表 contours 以及层次结构 hierarchy

cpp 复制代码
vector<vector<Point>> contours;
vector<Vec4i> hierarchy;
// 寻找轮廓
findContours(dst, contours, hierarchy, RETR_TREE, CHAIN_APPROX_SIMPLE, Point(0, 0));

2.3绘制轮廓

通过 drawContours 函数在图像上绘制检测到的轮廓。为了直观显示不同的轮廓,可以为每个轮廓使用不同颜色。

cpp 复制代码
Mat drawImg = Mat::zeros(dst.size(), CV_8UC3);
RNG rng(12345);
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(drawImg, contours, i, color, 2, LINE_8, hierarchy);
}

2.4Trackbar 调整阈值

动态调整 Canny 算法的阈值,使用 OpenCV 的 createTrackbar 函数,通过滑动条实时改变阈值并重新检测轮廓。

cpp 复制代码
createTrackbar("Threshold Value:", output_win, &threshold_value, threshold_max, Demo_Contours);
Demo_Contours(0, 0);

效果展示

3.完整代码

cpp 复制代码
#include<opencv2/opencv.hpp>
#include<highgui.hpp>
#include<iostream>
#include<math.h>

using namespace cv;
using namespace std;

Mat src, dst;
int threshold_value = 100;
int threshold_max = 255;

const char* output_win = "findcontours-demo";
void Demo_Contours(int, void*)
{
	vector<vector<Point>>contours;
	vector<Vec4i>hierarchy;
	Canny(src, dst, threshold_value, threshold_value * 2, 3, false);
	findContours(dst, contours, hierarchy, RETR_TREE, CHAIN_APPROX_SIMPLE, Point(0, 0));
	Mat drawImg = Mat::zeros(dst.size(), CV_8UC3);
	RNG rng(12345);
	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(drawImg, contours, i, color, 2, LINE_8, hierarchy);
	}
	imshow(output_win, drawImg);
}

void find_contour()
{
	src = imread("fish.jpg");
	if (src.empty())
	{
		cout << "ERROR: Could not load image." << endl;
		return;
	}
	namedWindow("input_image", WINDOW_AUTOSIZE);
	namedWindow(output_win, WINDOW_AUTOSIZE);
	cvtColor(src, src, COLOR_BGR2GRAY);

	const char* trackbar_title = "Threshold Value:";
	createTrackbar(trackbar_title, output_win, &threshold_value, threshold_max, Demo_Contours);
	Demo_Contours(0, 0);

	imshow("input_image", src);
	waitKey(0);
  
}
int main() 
{
  find_contour();
  return 0;
}
相关推荐
Chef_Chen4 分钟前
从0开始学习计算机视觉--Day07--神经网络
神经网络·学习·计算机视觉
钱彬 (Qian Bin)25 分钟前
一文掌握Qt Quick数字图像处理项目开发(基于Qt 6.9 C++和QML,代码开源)
c++·开源·qml·qt quick·qt6.9·数字图像处理项目·美观界面
双叶8361 小时前
(C++)学生管理系统(正式版)(map数组的应用)(string应用)(引用)(文件储存的应用)(C++教学)(C++项目)
c语言·开发语言·数据结构·c++
源代码•宸1 小时前
C++高频知识点(二)
开发语言·c++·经验分享
加油吧zkf2 小时前
YOLO目标检测数据集类别:分类与应用
人工智能·计算机视觉·目标跟踪
jyan_敬言3 小时前
【C++】string类(二)相关接口介绍及其使用
android·开发语言·c++·青少年编程·visual studio
liulilittle3 小时前
SNIProxy 轻量级匿名CDN代理架构与实现
开发语言·网络·c++·网关·架构·cdn·通信
加油吧zkf4 小时前
水下目标检测:突破与创新
人工智能·计算机视觉·目标跟踪
加油吧zkf4 小时前
AI大模型如何重塑软件开发流程?——结合目标检测的深度实践与代码示例
开发语言·图像处理·人工智能·python·yolo
tan77º4 小时前
【Linux网络编程】Socket - UDP
linux·服务器·网络·c++·udp