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

news2024/10/28 9:59:20

文章目录

  • 前言
  • 1.理论基础
    • 1.1轮廓发现
    • 1.2轮廓发现步骤
    • 1.3相关API
      • (1)轮廓发现(find contour)
      • (2)轮廓绘制(draw contour)
  • 2.代码实现
    • 2.1图像预处理
    • 2.2轮廓发现
    • 2.3绘制轮廓
    • 2.4Trackbar 调整阈值
  • 3.完整代码

前言

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

1.理论基础

1.1轮廓发现

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

1.2轮廓发现步骤

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

1.3相关API

(1)轮廓发现(find contour)

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)

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 边缘检测算法提取图像的边缘。

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

2.2轮廓发现

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

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

2.3绘制轮廓

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

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 函数,通过滑动条实时改变阈值并重新检测轮廓。

createTrackbar("Threshold Value:", output_win, &threshold_value, threshold_max, Demo_Contours);
Demo_Contours(0, 0);

效果展示

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

3.完整代码

#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;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2225357.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

基于SSM+微信小程序的快递的管理系统(快递1)

&#x1f449;文末查看项目功能视频演示获取源码sql脚本视频导入教程视频 1、项目介绍 基于SSM微信小程序的快递管理平台&#xff0c;有管理员&#xff0c;用户&#xff0c;配送员&#xff0c; 1、管理员实现了个人中心&#xff0c;用户管理&#xff0c;配送员管理&#xff0…

IDM下载器 (Internet Download Manager) v6.42.2 中文免激活绿色版

Internet Download Manager (IDM下载器) 是一款先进的下载工具,可以提升您的下载速度高达5倍,支持续传&#xff0c;IDM可以让用户自动下载某些类型的文件&#xff0c;它可将文件划分为多个下载点以更快速度下载&#xff0c;并列出最近的下载&#xff0c;方便访问文件。相对于其…

如何通过sip信令以及抓包文件分析媒体发到哪个地方

前言 问题描述&#xff1a;A的媒体没转发到B&#xff0c;B只能听到回铃音&#xff0c;没有A的说话声音&#xff0c;并且fs这边按正常的信令发送了. 分析流程 分析早期媒体发送到哪一个IP 10.19.0.1发送了一个请求给10.19.0.157这个IP&#xff0c;然而这里的SDP媒体地址&am…

Leetcode 二叉树的右视图

好的&#xff0c;我来用中文详细解释这段代码的算法思想。 问题描述 题目要求给定一个二叉树的根节点&#xff0c;从树的右侧看过去&#xff0c;按从上到下的顺序返回看到的节点值。即&#xff0c;我们需要找到每一层的最右侧节点并将其加入结果中。 算法思想 这道题可以通…

【gRPC】什么是RPC——介绍一下RPC

说起RPC&#xff0c;博主使用CPP手搓了一个RPC项目&#xff0c;RPC简单来说&#xff0c;就是远程过程调用&#xff1a;我们一般在本地传入数据进行执行函数&#xff0c;然后返回一个结果&#xff1b;当我们使用RPC之后&#xff0c;我们可以将函数的执行过程放到另外一个服务器上…

go语言中的Scanf()输入函数

Scanf() 第一种情况 package mainimport "fmt"func main() {var a intfor {fmt.Println("请输入一个整数:")fmt.Scanf("%d", &a)fmt.Println("----------------", a)} }运行结果&#xff1a; 解释&#xff1a; 出现这种现象是因…

Docker下载途径

Docker不是Linux自带的&#xff0c;需要我们自己安装 官网&#xff1a;https://www.docker.com/ 安装步骤&#xff1a;https://docs.docker.com/engine/install/centos/ Docker Hub官网(镜像仓库)&#xff1a;https://hub.docker.com/ 在线安装docker 先卸载旧的docker s…

C/C++小宇宙代码

系列目录 序号直达链接1C/C爱心代码2C/C跳动的爱心3C/C李峋同款跳动的爱心代码4C/C满屏飘字表白代码5C/C大雪纷飞代码6C/C烟花代码7C/C黑客帝国同款字母雨8C/C樱花树代码9C/C奥特曼代码10C/C圣诞树代码11C/C俄罗斯方块12C/C贪吃蛇13C/C小宇宙代码 目录 系列目录 写在前面 …

LVGL显示图片2——显示GIF图片,图片尺寸注意,图片太大无法显示

1进入图像转换网页中 https://lvgl.io/tools/imageconverter 2选择图片 3设置生成的格式 4点击生成 5复制文件&#xff0c;配置环境 6编写代码&#xff08;&#xff09; //显示一张动图 void demo_gif(){lv_obj_t* screenlv_scr_act();//声名对象LV_IMG_DECLARE(GIF_1);//创…

【数据集】NCEP辐射数据-用于计算漫射天窗比(diffuse skylight ration)

【数据集】NCEP辐射数据-用于计算漫射天窗比(diffuse skylight ration) 漫射天窗比(diffuse skylight ration)地表反射率计算漫射天窗比计算NCEP辐射数据数据下载参考漫射天窗比(diffuse skylight ration) 基于NCEP辐射数据利用Python代码计算漫射天窗比(diffuse skyli…

【实用知识】Spring Boot 优雅捕捉异常的几种姿势

&#x1f449;博主介绍&#xff1a; 博主从事应用安全和大数据领域&#xff0c;有8年研发经验&#xff0c;5年面试官经验&#xff0c;Java技术专家&#xff0c;WEB架构师&#xff0c;阿里云专家博主&#xff0c;华为云云享专家&#xff0c;51CTO 专家博主 ⛪️ 个人社区&#x…

ATom:加州理工学院化学电离质谱仪(CIT-CIMS)的现场数据,V2版

目录 简介 摘要 代码 引用 网址推荐 知识星球 机器学习 ATom: In Situ Data from Caltech Chemical Ionization Mass Spectrometer (CIT-CIMS), V2 ATom&#xff1a;加州理工学院化学电离质谱仪&#xff08;CIT-CIMS&#xff09;的现场数据&#xff0c;V2版 简介 该数…

Centos7.9安装MySQL(二进制)

安装包 https://downloads.mysql.com/archives/community/ mysql-8.0.39-linux-glibc2.17-x86_64.tar.xz 1.卸载MariaDB 查看 rpm -qa|grep mariadb卸载 可能名称不一样&#xff0c;记得替换 rpm -e --nodeps mariadb-libs-5.5.68-1.el7.x86_64rpm -qa|grep mariadb 执行…

leetcode228:汇总取件

步骤1&#xff1a;定义题目的计算问题性质 题目要求从一个无重复元素且有序的整数数组 nums 中&#xff0c;找出所有恰好覆盖数组中所有数字的最小区间范围列表。这意味着每个数字都必须被某个区间包含&#xff0c;且没有多余的数字在区间内。 输入&#xff1a;一个有序整数数…

Github 2024-10-28 开源项目周报 Top15

根据Github Trendings的统计,本周(2024-10-28统计)共有15个项目上榜。根据开发语言中项目的数量,汇总情况如下: 开发语言项目数量Python项目6JavaScript项目4TypeScript项目4Jupyter Notebook项目2C++项目1C#项目1Svelte: 一种新的Web应用程序构建方法 创建周期:2899 天开发…

软件分享丨ImTip输入状态

ImTip软件介绍 ImTip是一款实用的输入法状态跟踪提示工具&#xff0c;官网为https://imtip.aardio.com。 它具有诸多优势&#xff0c;体积小巧仅696KB且免费开源&#xff0c;是单文件绿色软件&#xff0c;无外部依赖&#xff0c;能在多种流行桌面操作系统上流畅运行。其核心…

软硬件开发面试问题大汇总篇——针对非常规八股问题的提问与应答(代码规范与生态管理)

软硬件开发&#xff0c;对于编码规范、生态管理等等综合问题的考察尤为重要。 阐述下环形缓冲区的用途 环形缓冲区&#xff08;Ring Buffer&#xff09;是一种固定大小的数据结构&#xff0c;常用于实现数据的流式传输或临时存储。在环形缓冲区中&#xff0c;当到达缓冲区的末尾…

react18中的合成事件与浏览器中的原生事件

React 通过将事件 normalize 以让他们在不同浏览器中拥有一致的属性。 合成事件 SyntheticEvent 实例将被传递给你的事件处理函数&#xff0c;它是浏览器的原生事件的跨浏览器包装器。除兼容所有浏览器外&#xff0c;它还拥有和浏览器原生事件相同的接口&#xff0c;包括 stopP…

Atlas800昇腾服务器(型号:3000)—SwinTransformer等NPU推理【图像分类】(九)

服务器配置如下&#xff1a; CPU/NPU&#xff1a;鲲鹏 CPU&#xff08;ARM64&#xff09;A300I pro推理卡 系统&#xff1a;Kylin V10 SP1【下载链接】【安装链接】 驱动与固件版本版本&#xff1a; Ascend-hdk-310p-npu-driver_23.0.1_linux-aarch64.run【下载链接】 Ascend-…

华为配置 之 STP

目录 简介&#xff1a; STP&#xff1a; RSTP: 如何改变根网桥&#xff1a; &#xff08;1&#xff09;改变优先级&#xff1a; &#xff08;2&#xff09;改变root: 各端口的状态&#xff1a; 总结&#xff1a; 简介&#xff1a; STP&#xff08;Spanning Tree Protoco…