Python-初学openCV——图像预处理(五)——梯度处理、边缘检测、图像轮廓

目录

一、图像梯度处理

1、垂直边缘提取

2、Sobel算子

3、Laplacian算子

二、图像边缘检测

1、高斯滤波

2、计算图像的梯度、方向

3、非极大值抑制

4、双阈值筛选

 三、绘制图像轮廓

1、概念

2、寻找轮廓

3、绘制轮廓


一、图像梯度处理

        还记得高数中的一阶导数求极值吗?把图片想象成连续函数,因为边缘部分的像素值是与旁边像素明显有区别的,所以对图片局部求极值,就可以得到整幅图片的边缘信息了。不过图片是二维的离散函数,导数就变成了差分,这个差分就称为图像的梯度

        1、垂直边缘提取

        滤波是应用卷积来实现的,卷积的关键就是卷积核

这个核是用来提取图片中的垂直边缘的,当前列左右两侧的元素进行差分,由于边缘的值明显小于(或大于)周边像素,所以边缘的差分结果会明显不同,这样就提取出了垂直边缘

cv2.filter2D(src, ddepth, kernel)

filter2D函数是用于对图像进行二维卷积(滤波)操作。它允许自定义卷积核(kernel)来实现各种图像处理效果,如平滑、锐化、边缘检测等

src: 输入图像

ddepth:输出图像的深度,可以是负值(表示与原图相同)、正值或其他特定值(常用-1 表示输出与输入具有相同的深度)

kernel:卷积核,一个二维数组(通常为奇数大小的方形矩阵),用于计算每个像素周围邻域的加权和

 同理,把上面那个矩阵转置一下,就是提取水平边缘。这种差分操作就称为图像的梯度计算

(将卷积核中的矩阵换成k2矩阵即可实现水平边缘提取,可以找张数独的图片效果对比更清晰)

         2、Sobel算子

        上面的 k1、k2 两个卷积核都叫做Sobel算子,只是方向不同

sobel_image = cv2.Sobel(src, ddepth, dx, dy, ksize)

src:通常应该是一个灰度图像,因为 Sobel 算子是基于像素亮度梯度计算的。在彩色图像的情况下,通常需要先将其转换为灰度图像

ddepth:输出图像的深度,即输出图像的数据类型(-1 表示输出图像的深度与输入图像相同 )

dx,dy:dx=1,dy=0时求x方向的一阶导数,意味着我们想要计算图像在水平方向(x轴)的梯度;

                dx=0,dy=1时求y方向的一阶导数

ksize:Sobel算子的大小,可选择3、5、7,默认为3

        3、Laplacian算子

        Laplacian算子是一种二阶微分算子,通常用于图像处理中,用来检测图像中的边缘和细节。它对图像的每个像素应用一个“加权平均”,通过计算每个像素与其邻域像素的差异,来判断该点的变化程度。Laplacian算子用于捕捉图像中亮度变化剧烈的区域。常常用于边缘检测,因为边缘区域的亮度变化非常大,而平坦区域的亮度变化较小。它的优点是能够检测到图像的细节,包括边缘、角点等

cv2.Laplacian(src, ddepth)

src:输入图像

ddepth:代表输出图像的深度 ,-1 表示输出图像的深度与输入图像相同

二、图像边缘检测

(不是算子,接下来是一整套边缘检测的流程、方案)

        1、高斯滤波

                去除噪点,边缘检测本身属于锐化操作,对噪点比较敏感,所以需要进行平滑处理

        2、计算图像的梯度、方向

                首先使用sobel算子计算中心像素点的两个方向上的梯度G_{x}和G_{y},然后就能够得到           其具体的梯度值:G={\sqrt{G_{x}{}^{2}+G_{y}{}^{2}}}

                也可以使用G=|G_{x}+G_{y}|来代替。在OpenCV中,默认使用G=|G_{x}+G_{y}|来计算           梯度值

                 然后我们根据公式{\frac{G_{\mathrm{y}}}{G_{x}}}=\tan\,(\theta)可以得到一个角度值:\theta=\arctan\,({\frac{G_{\mathrm{y}}}{G_{x}}})

 这个角度值其实是当前边缘的梯度的方向。通过这个公式我们就可以计算出图片中所有的像素点的梯度值与梯度方向,然后根据梯度方向获取边缘的方向

并且如果梯度方向不是0°、45°、90°、135°这种特定角度,那么就要用到插值算法来计算当前像素点在其方向上进行插值的结果了,然后进行比较并判断是否保留该像素点

\theta值为-22.5°~22.5°,或-157.5°~157.5°,则认为边缘为水平边缘;

当法线方向为22.5°~67.5°,或-112.5°~-157.5°,则认为边缘为45°边缘;

当法线方向为67.5°~112.5°,或-67.5°~-112.5°,则认为边缘为垂直边缘;

当法线方向为112.5°~157.5°,或-22.5°~-67.5°,则认为边缘为135°边缘;

        3、非极大值抑制

        得到每个边缘的方向之后,其实把它们连起来边缘检测就算完了,但是为什么还有这一步与下一步呢?是因为经过第二步得到的边缘不经过处理是没办法使用的,因为高斯滤波的原因,边缘会变得模糊,导致经过第二步后得到的边缘像素点非常多,因此我们需要对其进行一些过滤操作,而非极大值抑制就是一个很好的方法,它会对得到的边缘像素进行一个排除,使边缘尽可能细一点。

        在该步骤中,我们需要检查每个像素点的梯度方向上的相邻像素,并保留梯度值最大的像素,将其他像素抑制为零。假设当前像素点为(x,y),其梯度方向是0°,梯度值为G(x,y),那么我们就需要比较G(x,y)与两个相邻像素的梯度值:G(x-1,y)和G(x+1,y)。如果G(x,y)是三个值里面最大的,就保留该像素值,否则将其抑制为零

        4、双阈值筛选

        经过非极大值抑制之后,我们还需要设置阈值来进行筛选,当阈值设的太低,就会出现假边缘,而阈值设的太高,一些较弱的边缘就会被丢掉,因此使用了双阈值来进行筛选,推荐高低阈值的比例为2:1到3:1之间。

        当某一像素位置的幅值超过最高阈值时,该像素必是边缘像素;当幅值低于最低像素时,该像素必不是边缘像素;幅值处于最高像素与最低像素之间时,如果它能连接到一个高于阈值的边缘时,则被认为是边缘像素,否则就不会被认为是边缘。也就是说,上图中的A和C是边缘,B不是边缘。因为C虽然不超过最高阈值,但其与A相连,所以C就是边缘

edges = cv2.Canny(image, threshold1, threshold2)

image:输入的灰度/二值化图像数据(即使读到的是彩色图也可以进行处理 )

threshold1:低阈值,用于决定可能的边缘点

threshold2:高阈值,用于决定强边缘点

 三、绘制图像轮廓

        1、概念

                轮廓是一系列相连的点组成的曲线,代表了物体的基本外形。相对于边缘,轮廓是连续           的,边缘不一定连续,轮廓是一个闭合的、封闭的形状

        (轮廓的作用:形状分析、目标识别、图像分割)

        2、寻找轮廓

                寻找轮廓需要将图像做一个二值化处理,并且根据图像的不同选择不同的二值化方法来           将图像中要绘制轮廓的部分置为白色,其余部分置为黑色。也就是说,我们需要对原始的               图像进行灰度化、二值化的处理,令目标区域显示为白色,其他区域显示为黑色。之后,对           图像中的像素进行遍历,当一个白色像素相邻(上下左右及两条对角线)位置有黑色像素存           在或者一个黑色像素相邻(上下左右及两条对角线)位置有白色像素存在时,那么该像素点           就会被认定为边界像素点,轮廓就是有无数个这样的边界点组成的

contours,hierarchy = cv2.findContours(image,mode,method)

contours:获取到的轮廓点的列表,检测到有多少个轮廓,该列表就有多少子列表,每一个子列表都代表了一个轮廓中所有点的坐标

hierarchy:表示轮廓之间的关系,前一条轮廓、后一条轮廓、子轮廓、父轮廓(该参数的使用情况会比较少 )

image:输入二值化图像

mode:轮廓的检索模式

                RETR_EXTERNAL:只查找最外层的轮廓(只有前、后,没有父、子)

                RETR_LIST:列出所有的轮廓(只有前、后,没有父、子)

                RETR_CCOMP:列出所有的轮廓(分为两个层级:0 外部轮廓,1 内部轮廓)

                RETR_TREE​​​​:列出所有的轮廓(轮廓按照树的方式显示:最外层树根,子轮廓树枝 )

method:轮廓的表示方法

                CHAIN_APPROX_NONE:存储所有轮廓点

                CHAIN_APPROX_SIMPLE:只存储有用的点(默认)

                CHAIN_APPROX_TC89_L1:用 Teh-Chin 算法智能地简化轮廓,点数更少

(对于mode和method这两个参数来说,一般使用RETR_EXTERNAL和CHAIN_APPROX_SIMPLE这两个选项 )

         3、绘制轮廓

                轮廓找出来后,其实返回的是一个轮廓点坐标的列表,因此我们需要根据这些坐标将轮           廓画出来,因此就用到了绘制轮廓的方法

cv2.drawContours(image, contours, contourIdx, color, thickness)

image:原始图像,一般为单通道或三通道的 numpy 数组

contours:包含多个轮廓的列表,每个轮廓是一个由点坐标构成的二维数组(numpy数组)

contourldx:要绘制的轮廓索引。(如果设为 -1,则会绘制所有轮廓)

color:绘制轮廓的颜色,可以是 BGR 值或者是灰度值(对于灰度图像)

thickness:轮廓线的宽度,如果是正数,则画实线;如果是负数,则填充轮廓内的区域

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

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

相关文章

【Redis】安装Redis,通用命令,常用数据结构,单线程模型

目录 一.在Ubuntu系统安装Redis 二. redis客户端介绍 三. 全局命令 3.1.GET和SET命令 3.2.KEYS(生产环境禁止使用) 3.3.EXISTS 3.4.DEL 3.5.EXPIRE 3.6.TTL 3.6.1.Redis的过期策略 3.6.2.基于优先级队列/堆的实现去实现定时器 3.6.3.定时器&a…

ubuntu22.04系统实践 linux基础入门命令(三) 用户管理命令

以下有免费的4090云主机提供ubuntu22.04系统的其他入门实践操作 地址:星宇科技 | GPU服务器 高性能云主机 云服务器-登录 相关兑换码星宇社区---4090算力卡免费体验、共享开发社区-CSDN博客 之所以推荐给大家使用,是因为上面的云主机目前是免费使用的…

DPDK中的TCP头部处理

1. TCP头部结构 TCP头部通常为20字节(不含可选字段),每个字段占据固定的字节位置。以下是TCP头部的结构,按字节位置逐一说明:0 1 2 30 1 2 3 4 5 6 7 8 9 0 1 …

开源在线客服系统Chatwoot配置文件

参考: https://developers.chatwoot.com/self-hosted/deployment/dockerhttps://developers.chatwoot.com/self-hosted/deployment/docker 1、.env 配置文件 # Learn about the various environment variables at # https://www.chatwoot.com/docs/self-hosted/co…

PHP进阶语法详解:命名空间、类型转换与文件操作

掌握了PHP面向对象编程的基础后,就可以深入学习命名空间、类型转换、文档注释、序列化以及文件操作等重要概念。 1、命名空间(Namespace) 命名空间是PHP 5.3引入的重要特性,它解决了类名、函数名和常量名冲突的问题,使…

Webpack 搭建 Vue3 脚手架详细步骤

创建一个新的 Vue 项目 1)初始化项目目录 新建一个文件夹,或者使用以下指令 mkdir webpack-vue_demo cd webpack-vue_demo2)初始化 npm 项目 npm init -y3)安装 vue 和 webpack 相关依赖 npm install vue vue-loader vue-template…

【Git 误操作恢复指南】

Git 误操作恢复指南 适用场景:git reset --hard 误操作后的紧急恢复 风险等级:🔴 高风险 - 可能导致代码丢失 恢复成功率:95%(CI/CD 环境下) 🚨 紧急情况概述 问题描述 在项目开发过程中&am…

Go语言 逃 逸 分 析

逃逸分析是什么 逃逸分析是编译器用于决定变量分配到堆上还是栈上的一种行为。一个变量是在堆上分配,还是在栈上分配,是经过编译器的逃逸分析之后得出的“结论”。Go 语言里编译器的逃逸分析:它是编译器执行静态代码分析后&#xff0c…

LeetCode算法日记 - Day 1: 移动零、复写零

目录 1. 移动零 1.1 思路解析 1.2 代码实现 2. 复写零 2.1 思路解析 2.2 代码实现 1. 移动零 283. 移动零 - 力扣(LeetCode) 给定一个数组 nums,编写一个函数将所有 0 移动到数组的末尾,同时保持非零元素的相对顺序。 请…

Odoo:免费开源的医疗器械行业解决方案

开源智造Odoo专家团队深知,作为医疗器械制造商,您的成功取决于制造卓越产品的能力。您必须遵循严密控制的流程,开发和制造出达到最严格质量标准的产品。“开源智造Odoo医疗器械行业解决方案”是为医疗器械制造商设计的全球企业资源规划(ERP)软…

Redis键值对中值的数据结构

前言 前面我们已经介绍了Redis的键值对存储管理的底层数据结构。如果不清楚的同志可以看我前面的博客 Redis数据库存储键值对的底层原理-CSDN博客 下面,我们来看一下Redis键值对中值的数据结构有那些叭 Redis常见的5种数据类型 string …

MySQL自动化安装工具-mysqldeploy

功能 可在linux系统上安装 mysql5.5/5.6/5.7/8.0/8.4 版本的 MySQL,可以初始化多实例 MySQL。 码云: https://gitee.com/hh688/mysqldeploy guithub: https://github.com/hhkens/mysqldeploy 限制 仅在 centos7 环境进行测试,后期可能支持更多系统。 此程…

简要探讨大型语言模型(LLMs)的发展历史

关注大型语言模型(LLMs) 简要探讨语言模型的发展历史 理解Transformer架构的基本元素和注意力机制 了解不同类型的微调方法 语言模型的大小之分 在语言模型领域,“小”和“大”是相对概念。几年前还被视为“巨大”的模型,如今已被认为相当小。该领域发展迅猛,从参数规模为…

Java试题-选择题(2)

Java试题-选择题(2) 题目 下列语句创建对象的总个数是: String s=“a”+“b”+"c”+“d”+"e” A.4 B.2 C.3 D.1 关于下面的程序段的说法正确的是()? File file1=new File(“e:\xxx\yyy\zzz");file1.mkdir(); A.如目录e:\xxx\yyy\不存在,程序会抛出FileN…

揭秘动态测试:软件质量的实战防线

动态测试概述(扩展版) 目录 动态测试概述(扩展版) 一、动态测试的定义与重要性 ⚡ 二、动态测试类型 🔍 (一)功能测试 🧩 (二)非功能测试 &#x1f4ca…

机器学习①【机器学习的定义以及核心思想、数据集:机器学习的“燃料”(组成和获取)】

文章目录先言一、什么是机器学习1.机器学习的定义以及核心思想2.机器学习的四大类型2.1监督学习(Supervised Learning)2.2半监督学习(Midsupervised Learning)2.3无监督学习(Unsupervised Learning)2.4强化…

GaussDB 数据库架构师(十二) 资源规划

1 硬件和软件要求 1)硬件配置示例 硬件配置示例设备类型 设备型号 数量 备注 计算节点 CPU: 2*64 Cores,Kunpeng 920 内存:32*32GB 系统盘:2*960GB SATA SSD 数据盘:24*960GB SATA SSD RAID卡&#x…

Linux系统文件与目录内容检索(Day.2)

一、文件和目录内容检索处理命令1、uniq去重语法uniq [options] [input_file [output_file]]选项选项作用-c进行计数,并删除文件中重复出现的行-d仅显示连续的重复行-u仅显示出现一次的行-i忽略大小写案例1、删除输入文件中的重复行sort input.txt | uniq2、仅显示重…

如何选择一个容易被搜索引擎发现的域名?

在这个数字化时代,域名不仅是企业线上身份的标识,更是影响网站搜索曝光率的关键因素。一个精心挑选的域名能为品牌带来更多自然流量,下面我们就来探讨几个实用技巧。一、简洁易记是王道好域名首先要让人过目不忘。想象一下,当用户…

树形DP进阶:结合dfn序的线性化树问题求解技巧

树形DP进阶:结合dfn序的线性化树问题求解技巧一、dfn序与树的线性化1.1 dfn序的基本概念1.2 树形DP结合dfn序的优势二、核心应用:子树区间的DP优化2.1 子树权值和的快速查询与更新问题描述结合dfn序的解法代码实现(前缀和版本)优化…