《数字图像处理-OpenCV/Python》第14章:边缘检测与图像轮廓

《数字图像处理-OpenCV/Python》第14章:边缘检测与图像轮廓


本书京东 优惠购书链接 https://item.jd.com/14098452.html
本书CSDN 独家连载专栏 https://blog.csdn.net/youcans/category_12418787.html

在这里插入图片描述


第 14 章 边缘检测与图像轮廓


边缘是图像的基本特征。边缘检测根据灰度的突变检测边缘,检测到的边缘通常是零散的片段,并不是连续的整体,要从图像中提取目标物体,就要将边缘像素连接构成连续闭合的轮廓。边缘主要作为图像的特征使用,而轮廓主要用来分析物体的形态。

本章内容概要

  • 理解边缘检测的原理,学习使用梯度算子进行边缘检测。
  • 学习使用LoG算子、DoG算子和Canny算子进行边缘检测。
  • 学习查找轮廓的方法,绘制轮廓图像。
  • 介绍轮廓的属性、基本参数和形状特征。

14.6 轮廓的查找与绘制

轮廓是一系列相连的像素点组成的曲线,代表物体的基本外形。轮廓常用于形状分析和物体的检测和识别。
边缘检测根据灰度的突变检测边缘,但检测到的边缘通常是零散的片段,并未构成整体。从背景中分离目标,要将边缘像素连接构成轮廓,也就是说,轮廓是连续的,边缘不一定是连续的。边缘主要作为图像的特征使用,而轮廓主要用来分析物体的形态。


OpenCV中的函数cv.findContours用于从黑色背景的二值图像中寻找轮廓。
OpenCV中的函数cv.drawContours用于在图像上绘制轮廓线或填充轮廓。绘制图像轮廓并不是显示图像,而是在原始图像上添加轮廓线。

函数原型

cv.findContours(image, mode, method[, contours, hierarchy, offset]) → contours, hierarchy
cv.drawContours(image, contours, contourIdx, color[, thickness, lineType, hierarchy, maxLevel, offset]) → image

参数说明

  • image:输入图像,是8位单通道二值图像。
  • mode:轮廓查找模式。
    • RETR_EXTERNAL:只查找最外层的轮廓。
    • RETR_LIST:查找所有轮廓,不建立层次关系。
    • RETR_CCOMP:查找所有轮廓,组织为两层,顶层是外部轮廓。
    • RETR_TREE:查找所有轮廓,并重建嵌套轮廓的完整层次结构。
  • method:轮廓的表示方法。
    • CHAIN_APPROX_NONE:输出轮廓所有的像素点(x,y)。
    • CHAIN_APPROX_SIMPLE:对于水平线/垂直线/对角线,只保留线段端点。
    • CHAIN_APPROX_TC89_L1:应用Teh-Chin链近似算法L1。
    • CHAIN_APPROX_TC89_KCOS:应用Teh-Chin 链近似算法KCOS。
  • contours:查找到的所有轮廓,是列表格式,每个轮廓以点的坐标向量表示。
  • hierarchy:轮廓的层次结构,是Numpy数组,形状为(1,L,4)。
  • offset:偏移量,可选项。

注意问题

(1) 查找轮廓是针对黑色背景中的白色目标而言的,以得到白色目标的轮廓。如果背景为亮色和浅色,如白纸黑字的印刷书籍,要在查找轮廓前进行反色处理。
(2) 函数将输入图像按二值图像处理,所有非0像素都会被视为1,因此必须先通过阈值分割或边缘检测获得二值图像。推荐在平滑滤波后使用边缘检测方法,可以减少白色噪点,提高轮廓检测的效率和质量。
(3) contours是一个列表(List),不是Numpy数组,而轮廓列表中的元素是Numpy数组,列表长度L是查找到的轮廓总数。
(4) contours列表中的第i个元素contours[i]是形为(k,1,2)的Numpy数组,表示第i个轮廓,k是第i个轮廓中的像素点数量。contours[i]的每一行contours[i][k,1,:]有两个元素,分别表示第i个轮廓的第k个像素点的坐标(x,y)。
注意轮廓处理函数中像素点的坐标为(x,y),与OpenCV中像素点的坐标(y,x)的次序相反。
(5) hierarchy是形为(1,L,4)的Numpy数组。第i个轮廓的层次结构为:hierarchy[0,i,:]=[Next, Previous, FirstChild, Parent]。这4个元素hierarchy[0,i,0]~hierarchy[0,i,3]分别表示轮廓i的同层下一个轮廓Next、同层前一个轮廓Previous、第一个子轮廓FirstChild和父轮廓Parent的编号,-1表示不存在。
(6) 从实际图像中查找的轮廓往往数量很多、拓扑结构复杂,可以基于轮廓的层次结构进行筛选和识别。例如,使用 h i e r a r c h y [ 0 , i , 3 ] = = − 1 hierarchy[0,i,3]==-1 hierarchy[0,i,3]==1可以筛选没有父轮廓的最外层轮廓,使用 h i e r a r c h y [ 0 , i , 2 ] = = − 1 hierarchy[0,i,2]==-1 hierarchy[0,i,2]==1可以筛选没有子轮廓的最内层轮廓。
(7) 轮廓是由很多像素点组成的。使用CHAIN_APPROX_NONE时,contours[i]能保存轮廓所有的像素点,可以计算轮廓长度;而使用CHAIN_APPROX_SIMPLE时,contours[i]对水平线/垂直线/对角线只保留轮廓的线段端点,可以简化轮廓描述。
(8) 在OpenCV的不同版本中,函数cv.findContours的返回值不同,使用返回值格式不当会导致程序报错。例如,在OpenCV3中函数的返回值为[image,contours,hierarchy],而在OpenCV2、OpenCV4、OpenCV5 中函数的返回值为[contours,hierarchy]。


【例程1406】查找和绘制图像轮廓

本例程用于查找和绘制图像轮廓,并基于层次结构对轮廓进行筛选。
注意:在不同OpenCV版本中,函数cv.findContours的用法不同,详见程序注释。


python"># 【1406】查找和绘制图像轮廓
import cv2 as cv
import numpy as np
from matplotlib import pyplot as pltif __name__ == '__main__':img = cv.imread("../images/Fig1402.png", flags=1)gray = cv.cvtColor(img, cv.COLOR_BGR2GRAY)  # 灰度图像_, binary = cv.threshold(gray, 127, 255, cv.THRESH_OTSU + cv.THRESH_BINARY_INV)# 寻找二值图中的轮廓# binary, contours, hierarchy = cv.findContours(binary, cv.RETR_TREE, cv.CHAIN_APPROX_SIMPLE)  # OpenCV3contours, hierarchy = cv.findContours(binary, cv.RETR_TREE, cv.CHAIN_APPROX_SIMPLE)  # OpenCV4~# print("len(contours): ", len(contours))  # contours 是列表,只有长度没有形状print("hierarchy.shape: ", hierarchy.shape)  # 层次结构# 绘制全部轮廓contourTree = img.copy()  # OpenCV 某些版本会修改原始图像contourTree = cv.drawContours(contourTree, contours, -1, (0, 0, 255), 2)  # OpenCV3#  绘制最外层轮廓和最内层轮廓imgContour = img.copy()for i in range(len(contours)):  # 绘制第 i 个轮廓x, y, w, h = cv.boundingRect(contours[i])  # 外接矩形text = "{}#({},{})".format(i, x, y)contourTree = cv.putText(contourTree, text, (x, y), cv.FONT_HERSHEY_DUPLEX, 0.8, (0,0,0))print("i={}\tcontours[{}]:{}\thierarchy[0,{}]={}".format(i, i, contours[i].shape, i, hierarchy[0][i]))if hierarchy[0,i,2]==-1:  # 最内层轮廓imgContour = cv.drawContours(imgContour, contours, i, (0,0,255), thickness=-1)  # 内部填充if hierarchy[0,i,3]==-1:  # 最外层轮廓imgContour = cv.drawContours(imgContour, contours, i, (255,255,255), thickness=5)plt.figure(figsize=(9, 3.2))plt.subplot(131), plt.axis('off'), plt.title("1. Original")plt.imshow(cv.cvtColor(img, cv.COLOR_BGR2RGB))plt.subplot(132), plt.axis('off'), plt.title("2. Contours")plt.imshow(cv.cvtColor(contourTree, cv.COLOR_BGR2RGB))plt.subplot(133), plt.axis('off'), plt.title("3. Selected contour")plt.imshow(cv.cvtColor(imgContour, cv.COLOR_BGR2RGB))plt.tight_layout()plt.show()

运行结果:

python">len(contours):  6
hierarchy.shape:  (1, 6, 4)
i=0	contours[0]:(24, 1, 2)	hierarchy[0,0]=[ 1 -1 -1 -1]
i=1	contours[1]:(24, 1, 2)	hierarchy[0,1]=[ 2  0 -1 -1]
i=2	contours[2]:(4, 1, 2)	hierarchy[0,2]=[-1  1  3 -1]
i=3	contours[3]:(8, 1, 2)	hierarchy[0,3]=[-1 -1  4  2]
i=4	contours[4]:(11, 1, 2)	hierarchy[0,4]=[ 5 -1 -1  3]
i=5	contours[5]:(11, 1, 2)	hierarchy[0,5]=[-1  4 -1  3]

程序说明:

(1) 运行结果,图像轮廓如图14-6所示。图14-6(1)所示为浅色背景的原始图像,进行二值处理时反色为黑色背景和白色目标。
(2) 图14-6(2)所示为在原始图像上绘制查找到的全部轮廓,并标注轮廓编号。图14-6(3)所示为在原始图像上绘制指定的轮廓,外层轮廓以白色线条绘制,内层轮廓以红色填充。
(3) contours是所有轮廓的列表,长度为6,表示查找到6个轮廓。
(4) 查找轮廓时使用CHAIN_APPROX_SIMPLE选项,对水平线/垂直线/对角线只保留线段的端点。矩形轮廓最少可以用4个端点表示,如2#轮廓只有4个像素点,但看起来像矩形的轮廓也可能会有更多顶点,如3# 轮廓有8个像素点。
(5) hierarchy的形状为(1,6,4),每行表示一个轮廓的拓扑信息。结合运行结果逐行讨论如下。
hierarchy[0,0]=[1,-1,-1,-1],表示0#轮廓的同层下一个轮廓为1#,没有同层的前一个轮廓,没有子轮廓,没有父轮廓,因此是单层轮廓。
hierarchy[0,1]=[2,0,-1,-1],表示1#轮廓的同层下一个轮廓为2#,同层前一个轮廓为0#,没有子轮廓,没有父轮廓,因此是单层轮廓。
hierarchy[0,2]=[-1,1,3,-1],表示2# 轮廓没有同层下一个轮廓,同层前一个轮廓为1#,子轮廓为3#,没有父轮廓,因此是外层轮廓。
hierarchy[0,3] =[-1,-1,4,2],表示3#轮廓没有同层下一个轮廓,没有同层前一个轮廓,子轮廓为4#,父轮廓为2#。
hierarchy[0,4]=[5,-1,-1,3],表示4#轮廓的同层下一个轮廓为5#,没有同层前一个轮廓,没有子轮廓,父轮廓为3#,因此是内层轮廓。
hierarchy[0,5] =[-1,4,-1,3],表示5#轮廓没有同层下一个轮廓,同层前一个轮廓为4#,没有子轮廓,父轮廓为3#,因此是内层轮廓。


在这里插入图片描述

图14-6 图像轮廓


版权声明:
youcans@xupt 原创作品,转载必须标注原文链接:(https://blog.csdn.net/youcans/article/details/138395918)
Copyright 2024 youcans, XUPT
Crated:2024-05-01

《数字图像处理-OpenCV/Python》 独家连载专栏 : https://blog.csdn.net/youcans/category_12418787.html


http://www.ppmy.cn/devtools/29613.html

相关文章

设计模式:策略模式

一,策略模式 策略模式(Strategy Pattern)是一种常用的软件设计模式,属于行为型模式。它的目的是定义一系列算法,并将每个算法封装起来让它们可以互换使用,算法的变化不会影响使用算法的用户。策略模式常用…

UML图(总结)

一、静态建模 1、类图: 展现了一组对象、接口、协作和它们之间的关系。 2、对象图 展现了某一时刻一组对象以及它们之间的关系。 3、用例图 展现了用例、参与者(Action)以及它们之间的关系。 二、动态建模 1、序列图(顺序图,时序图) 描述了以…

2.1 Java全栈开发前端+后端(全栈工程师进阶之路)-前端框架VUE3-基础-初识Vue

Vue概述 早期前后端分离模式 早期的前后端分离开发模式是这样的&#xff1a; <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta http-equiv"X-UA-Compatible" content"IEedge">&l…

更深层次理解传输层两协议【UDP | TCP】【UDP 缓冲区 | TCP 8种策略 | 三次握手四次挥手】

博客主页&#xff1a;花果山~程序猿-CSDN博客 文章分栏&#xff1a;Linux_花果山~程序猿的博客-CSDN博客 关注我一起学习&#xff0c;一起进步&#xff0c;一起探索编程的无限可能吧&#xff01;让我们一起努力&#xff0c;一起成长&#xff01; 目录 再谈端口号 端口号的返回…

【网站项目】家庭理财系统

&#x1f64a;作者简介&#xff1a;拥有多年开发工作经验&#xff0c;分享技术代码帮助学生学习&#xff0c;独立完成自己的项目或者毕业设计。 代码可以私聊博主获取。&#x1f339;赠送计算机毕业设计600个选题excel文件&#xff0c;帮助大学选题。赠送开题报告模板&#xff…

机器翻译常用指标BLEU

诸神缄默不语-个人CSDN博文目录 文章目录 什么是BLEU指标&#xff1f;BLEU指标的原理BLEU的计算公式BLEU指标的Python实现 什么是BLEU指标&#xff1f; BLEU&#xff08;Bilingual Evaluation Understudy&#xff09;指标是一种评估机器翻译质量的方法&#xff0c;广泛用于自然…

RFC 6071: IP Security (IPsec) and Internet Key Exchange (IKE) Document Roadmap

![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/96882d1fb67b4383bc77c4dd421f7b

Dashboard 安装部署

Dashboard 安装部署 Dashboard 安装部署 一&#xff1a;下载 二&#xff1a;部署步骤 1.镜像下载及导入 国内直接拉外网镜像会失败&#xff0c;可在境外下载镜像 查看 deployment 里的镜像版本 Dashboard Deploymentcontainers:- name: kubernetes-dashboardimage: k8s.g…

Git使用指北

目录 创建一个Git仓库本地仓库添加文件文件提交到本地仓库缓冲区添加远程仓库地址本地仓库推送到远程仓库创建新的分支拉取代码同步删除缓冲区的文件&#xff0c;远程仓库的文件.gitignore文件 创建一个Git仓库 Git仓库分为远程和本地两种&#xff0c;远程仓库如Githu上创建的…

Adobe软件全家桶:从平面到视频再到音频的创意之旅

在创意设计的广阔天地里&#xff0c;Adobe公司旗下的系列软件无疑是设计师们手中的魔法棒&#xff0c;它们串联起平面设计、视频剪辑直至音频处理的每一个环节&#xff0c;成为跨越视觉创意门槛的必备工具集。本文将深入浅出地介绍这些软件的应用场景、特色功能及其相互间的协作…

ubuntu sudo apt-get install neo4j 配置安装与设置远程访问

文章目录 下载Adding the Debian repositoryInstalling Neo4j安装流程设置远程访问 下载 neo4j 官方的下载地址&#xff0c;进入页面之后&#xff0c;往下滑&#xff1a; https://neo4j.com/deployment-center/#community 点击 Visit https://debian.neo4j.com/ Adding the …

MYSQL数据库专业术语及创建数据表详细讲解[详细版]{sql语句创建数据库语句及条件子句解析,编码格式解析,创建数据表解析,表定义字段解析,主键约束解析}

MYSQL数据库中的专业术语 数据库&#xff08;Database&#xff09;&#xff1a;存储数据的集合&#xff0c;是数据的逻辑容器。 表&#xff08;Table&#xff09;&#xff1a;数据库中存储数据的结构&#xff0c;由行&#xff08;记录&#xff09;和列&#xff08;字段&#x…

设计模式之空对象模式

空对象模式&#xff08;Null Object Pattern&#xff09;也称为零对象模式&#xff0c;是一种设计模式&#xff0c;用于代表空值的对象&#xff0c;而不是返回null。它的目的是让空对象能够像任何其他非空对象一样被使用&#xff0c;从而避免在代码中进行空值检查&#xff0c;提…

JavaEE >> Spring MVC(1)

MVC MVC&#xff1a;Model View Controller 的缩写&#xff0c;是一种软件架构模式&#xff0c;将软件系统分为模型、视图和控制器三个部分。 Mode&#xff08;模型&#xff09;&#xff1a;是应⽤程序中⽤于处理应⽤程序数据逻辑的部分。通常模型对象负责在数据库中存取数据…

用栈实现队列——leetcode刷题

题目要求我们只用栈的基本操作 push to top 入栈&#xff0c;peek from top 返回栈顶元素&#xff0c;pop from top 移除并返回栈顶元素&#xff0c;size 栈的大小&#xff0c;is_empty 判断栈是否为空&#xff0c;这几个函数来实现队列&#xff0c;也就是说&#xff0c;我们在…

webpack学习笔记

webpack基础配置 plugins:可以在webpack运行到某个阶段时帮我们做一些事情,可以监听事件并执行特定的功能,有点像vue的生命周期 webpack.config.js中 const path requeire(path)module.exports {mode:development,entry:path.join(__dirname,src,index.js)//把哪个文件作为…

使用FPGA发送一个经过曼彻斯特编码的伪随机序列

介绍 这几天突然就不知道要使用FPGA实现什么样的功能了,然后就跑去学习数电了,学的也是晕晕的。正好之前写了一个使用FPGA发送伪随机序列的代码,然后因为需要使用曼彻斯特编码,所以又加了一个模块吧,使得最后输出的波形经过曼彻斯特编码。 曼彻斯特编码 首先,曼彻斯特编…

【GitHub】如何在github上提交PR(Pull Request) + 多个pr同时提交、互不干扰

【GitHub】如何在github上提交PR(Pull Request 写在最前面1. 准备工作1.1 注册 GitHub 账号1.2 了解 Git 基础1.3 找到一个项目 2. 创建你的 PR2.1 Fork 和克隆仓库2.2 创建一个新的分支2.3 进行更改2.4 推送更改到 GitHub2.5 创建 Pull Request 3. 优化你的 PR3.1 保持提交清晰…

IDEA 2022.1版本开始,可以直接运行Markdown里的命令行

参照这种格式&#xff1a; shell mvn clean install注意idea支持的版本&#xff1a;是从 2022.1版本开始的。 ps&#xff1a;之前有人写过了&#xff0c;感觉很实用但是蛮多开发者不一定会知道的功能。 参考资料&#xff1a; https://www.cnblogs.com/didispace/p/16144107.h…

ASP.NET网络商店设计与实现

摘 要 本文首先系统地研究了开发电子商务网站的背景和意义&#xff0c;分析了当今B2C电子商务交易的网站特点和共性&#xff0c;从而得出设计本网站的思路和方法。接着介绍了实现系统开发的ASP.NET和IIS5.0环境&#xff0c;数据库用ACCESS实现。同时简要介绍了以上工具的功能…