计算机视觉第一课opencv(三)保姆级教学

简介

计算机视觉第一课opencv(一)保姆级教学

计算机视觉第一课opencv(二)保姆级教学

今天继续学习opencv。

一、 图像形态学

        什么是形态学:图像形态学是一种处理图像形状特征的图像处理技术,主要用于描述和处理图像中的形状和结构。形态学可以用于提取图像中的特征、消除噪声、改变图像的形状等。

1.腐蚀

        正如这个名字表面上的意思,侵蚀的基本思想就像土壤侵蚀一样,它侵蚀了前景物体foreground object 的边界(在这,我们会让前景保持为白色)。那么侵蚀的作用是什么呢?这样内核可以在图像中滑动(在二维卷积中)。只有当内核下的所有像素都为1时,原始图像中的像素(要么为1,要么为0)才会被认为是1,否则会被侵蚀(变成0)。这样的结果就是,取决于内核的大小,边界附近的所有像素都会被丢弃。因此,前景对象的厚度或大小会减少,或者只是简单地让图像中的白色区域减少。它对于去除小的白色噪音(正如我们在颜色空间colorspace 疑问中看到的那样),分离两个连接的物体等都很有用。

        腐蚀作用:可以用来消除小且无意义的物体。在这里,作为一个例子,我将使用一个包含内部全都是1的3x3内核。让我们看看它产生什么样的变化。

原图

# 1、图像腐蚀,函数为:
# cv2.erode(src, kernel, dst,anchor,iterations,borderType,borderValue)
# src: 输入的图像
# kernel: 用于腐蚀的结构元件如果element = Mat(), 则使用3 x 3的矩形结构单元。
# dst: 它是与src相同大小和类型的输出图像。
# iterations: 腐蚀操作的迭代次数,默认为1。次数越多, 腐蚀操作执行的次数越多,腐蚀效果越明显import numpy as np
sun = cv2.imread('sun.png')
cv2.imshow('src',sun)
cv2.waitKey(0)
kernel = np.ones((3,3),np.uint8)  # 这里kernel大小,修改为5*5试试
erosion_1 = cv2.erode(sun,kernel,iterations=2)  #iterations改为5试试
cv2.imshow('erosion_1',erosion_1)
cv2.waitKey(0)

2.膨胀

        膨胀操作正好与腐蚀相反。这里,如果内核下至少有一个像素是“1”,那么该像素元素就是“1”。因此,它增加了图像中的白色区域,或则说增加了前景目标对象的尺寸大小。通常情况下,在去除噪声以后,在腐蚀操作之后就是膨胀。因为,腐蚀消除了白色的噪音,但它也缩小了我们的前景物体,所以我们需要扩大回它。因为当噪音消失了,原本应该存在的白色面积也不会自主回来。而且膨胀在连接物体的破碎部分时也很有用。

# 2、图像膨胀, 函数为:
# cv2.dilate(img, kernel, iteration)
# 参数含义:
# img – 目标图片
# kernel – 进行操作的内核,默认为3×3的矩阵
# iterations – 膨胀次数,默认为1wenzi = cv2.imread('wenzi.png')
cv2.imshow('src1',wenzi)
cv2.waitKey(0)
kernel = np.ones((2,2),np.uint8)  # 这里kernel大小
wenzi_new = cv2.dilate(wenzi,kernel,iterations=2)
cv2.imshow('wenzi_new',wenzi_new)
cv2.waitKey(0)

3.开运算

        先进行腐蚀,再进行膨胀就叫做开运算。 通常情况下,含有噪声的图像二值化后,得到的边界是不平滑的,物体区域具有一些错判的孔洞,背景区域散布着一些小的噪声物体。对一个图像先进行腐蚀运算然后再膨胀的操作过程称为开运算,它可以消除细小的物体、在纤细点处分离物体、平滑较大物体的边界时不明显的改变其面积。

        在做对指纹识别的时候,遇到这样的图片对我们的识别效果影响不好,太多嘈杂的点了,我们就需要对其进行开运算。

# 开运算:先腐蚀后膨胀  作用:平滑物体的轮廓、断开较窄的狭颈并消除细的突出物。
zhiwen = cv2.imread('zhiwen.png')
cv2.imshow('src2',zhiwen)
cv2.waitKey(0)
kernel = np.ones((2,2),np.uint8)  #设置kenenl大小
zhiwen_new = cv2.morphologyEx(zhiwen,cv2.MORPH_OPEN,kernel) #开运算
cv2.imshow('zhiwen_new',zhiwen_new)
cv2.waitKey(0)

4.闭运算

        先膨胀再腐蚀。它经常被用来填充前景物体中的小洞,或者前景物体上面的小黑点。

        对于这样的指纹,我们发现它中间好多断开了,有很多空洞不太符合我们正常的指纹,需要进行闭运算进行处理

# # 闭运算:先膨胀后腐蚀  作用:弥合较窄的间断和细长的沟壑,消除小的孔洞,填补轮廓线中的断裂。
zhiwen_duan = cv2.imread('zhiwen_duan.png')
cv2.imshow('src3',zhiwen_duan)
cv2.waitKey(0)
kernel = np.ones((4,4),np.uint8)  #设置kenenl大小
zhiwen_new = cv2.morphologyEx(zhiwen_duan,cv2.MORPH_CLOSE,kernel) #闭运算
cv2.imshow('zhiwen_new1',zhiwen_new)
cv2.waitKey(0)
#

5.梯度运算

        其实就是一幅图像膨胀和腐蚀的差别。突出显示图像中强度变化剧烈的地方

wenzi = cv2.imread('wenzi.png')
cv2.imshow('wenzi_new',wenzi)
cv2.waitKey(0)
kernel = np.ones((2,2),np.uint8)  #设置kenenl大小
# 膨胀
pz_wenzi=cv2.dilate(wenzi,kernel,iterations=1)
cv2.imshow('pz_wenzi',pz_wenzi)
cv2.waitKey(0)
#腐蚀
fs_wenzi=cv2.erode(wenzi,kernel,iterations=1)
cv2.imshow('fs_wenzi',fs_wenzi)
cv2.waitKey(0)
# 膨胀-腐蚀
bianyuan = cv2.morphologyEx(wenzi,cv2.MORPH_GRADIENT,kernel)
cv2.imshow('bianyuan',bianyuan)
cv2.waitKey(0)
cv2.destroyAllWindows()

6.顶帽

顶帽 = 原始图像 - 开运算结果(先腐蚀后膨胀)

sun = cv2.imread('sun.png')
cv2.imshow('sun_yuantu',sun)
cv2.waitKey(0)
kernel = np.ones((2,2),np.uint8)  #设置kenenel大小
#开运算
open_sun=cv2.morphologyEx(sun,cv2.MORPH_OPEN,kernel)
cv2.imshow('open_sun',open_sun)
cv2.waitKey(0)
#顶帽
tophat = cv2.morphologyEx(sun,cv2.MORPH_TOPHAT,kernel)
cv2.imshow('TOPHAT',tophat)
cv2.waitKey(0)

7.黑帽

sun = cv2.imread('sun.png')
cv2.imshow('sun_yuantu',sun)
cv2.waitKey(0)
kernel = np.ones((2,2),np.uint8)  #设置kenenel大小
# #闭运算
close_sun=cv2.morphologyEx(sun,cv2.MORPH_CLOSE,kernel)
cv2.imshow('close_sun',close_sun)
cv2.waitKey(0)
#黑帽
blackhat = cv2.morphologyEx(sun,cv2.MORPH_BLACKHAT,kernel)
cv2.imshow('BLACKHAT',blackhat)
cv2.waitKey(0)

二、图像边缘检测

        边缘检测:是图形图像处理、计算机视觉和机器视觉中的一个基本工具,通常用于特征提取和特征检测,旨在检测一张数字图像中有明显变化的边缘或者不连续的区域。

1.Sobel算子

        Sobel 算子是一种离散的微分算子,该算子结合了高斯平滑和微分求导运算。该算子利用局部差分寻找边缘,计算所得的是一个梯度的近似值。Sobel算子包含2组3×3的矩阵,分别为横向和纵向模板,将之与图像作平面卷积,即可分别得出横向及纵向的亮度差分近似值。

# sobel算子
# cv2.Sobel(src, ddepth, dx, dy[, ksize[, scale[, delta[, borderType]]]])
# 参数:
# src: 输入图像
# ddepth: 输出图像的深度(可以理解为数据类型),-1表示与原图相同的深度
# dx,dy: 当组合为dx=1,dy=0时为x方向的一阶导数,当组合为dx=0,dy=1时为y方向的一阶导数(如果同时为1,通常效果不佳)
# ksize:(可选参数)Sobel算子的大小,必须是1,3,5或者7,默认为3。yuan = cv2.imread('yuan.png',0)
yuan = cv2.resize(yuan,dsize=None,fy=0.5,fx=0.5)
cv2.imshow('yuan',yuan)
cv2.waitKey(0)
# # x方向上的边缘
yuan_x = cv2.Sobel(yuan,-1,dx=1,dy=0)
cv2.imshow('yuan_x',yuan_x)
cv2.waitKey(0)
# x方向上的边缘,包括负数信息(右减),但显示不出来,因为范围是(0~255)
yuan_x_64 = cv2.Sobel(yuan,cv2.CV_64F,dx=1,dy=0)#数据uint8改为float64,可保存负数
cv2.imshow('yuan_x_64',yuan_x_64)
cv2.waitKey(0)
# #x方向上的边缘,包括负数信息,进行取绝对值的操作,右端的负值信息就可以显示出来了
yuan_x_full = cv2.convertScaleAbs(yuan_x_64)#转换为绝对值,负数转换为正数
cv2.imshow('yuan_x_full',yuan_x_full)
cv2.waitKey(0)
# # y方向上的边缘
yuan_y = cv2.Sobel(yuan,-1,dx=0,dy=1)
cv2.imshow('yuan_y',yuan_y)
cv2.waitKey(0)
# y方向上的边缘,包括负数信息(下减),但显示不出来,因为范围是(0~255)
yuan_y_64 = cv2.Sobel(yuan,cv2.CV_64F,dx=0,dy=1)#数据uint8改为float64,可保存负数
yuan_y_full = cv2.convertScaleAbs(yuan_y_64)#转换为绝对值,负数转换为正数
cv2.imshow('yuan_y_full',yuan_y_full)
cv2.waitKey(0)
# # 如果同时使用x,y方向的结果如何呢?(不建议使用!)
yuan_xy = cv2.Sobel(yuan,-1,dx=1,dy=1)
cv2.imshow('yuan_xy',yuan_xy)
cv2.waitKey(0)
# # 使用图像加权运算组合x和y方向的2个边缘。
yuan_xy_full = cv2.addWeighted(yuan_x_full, 1,yuan_y_full, 1, gamma=0)
cv2.imshow('yuan_xy_full',yuan_xy_full)
cv2.waitKey(0)

dama = cv2.imread('dama.jpg', 0)#不用灰度试试效果
dama=cv2.resize(dama,dsize=None,fx=0.5,fy=0.5)
dama_x_64 = cv2.Sobel(dama,cv2.CV_64F,dx=1,dy=0)#默认int8改为float64,可保存负数
dama_x_full = cv2.convertScaleAbs(dama_x_64)#转换为绝对值,负数转换为正数
dama_y_64 = cv2.Sobel(dama,cv2.CV_64F,dx=0,dy=1)#默认int8改为float64,可保存负数
dama_y_full = cv2.convertScaleAbs(dama_y_64)#转换为绝对值,负数转换为正数
dama_xy_sobel_full = cv2.addWeighted(dama_x_full, 1,dama_y_full, 1, 0)cv2.imshow('dama_xy_sobel_full',dama_xy_sobel_full)
cv2.waitKey(0)

2.Scharr 算子

        Scharr 算子是 Soble 算子在 ksize=3 时的优化,与 Soble 的速度相同,且精度更高。Scharr 算子与 Sobel 算子的不同点是在平滑部分,其中心元素占的权重更重,相当于使用较小标准差的高斯函数,也就是更瘦高的模板。

dama = cv2.imread('dama.jpg',cv2.IMREAD_GRAYSCALE) #Scharr算子
# zl=cv2.cvtColor(zl,cv2.COLOR_BGR2GRAY)
dama_x_64 = cv2.Scharr(dama,cv2.CV_64F,dx=1,dy=0)#默认int8改为float64,可保存负数
dama_x_full = cv2.convertScaleAbs(dama_x_64)#转换为绝对值,负数转换为正数
dama_y_64 = cv2.Scharr(dama,cv2.CV_64F,dx=0,dy=1)#默认int8改为float64,可保存负数
dama_y_full = cv2.convertScaleAbs(dama_y_64)#转换为绝对值,负数转换为正数
dama_xy_Scharr_full = cv2.addWeighted(dama_x_full, 1,dama_y_full, 1, 0)
cv2.imshow('dama_xy_Scharr_full',dama_xy_Scharr_full)
cv2.waitKey(0)

3.Laplacian算子

        不再以x和y的方向计算,而是以圆方向计算变化率。因此不需要Gx+Gy。

# ###### cv2.Laplacian(src, ddepth[, dst[, ksize[, scale[, delta[, borderType]]]]])
# ###### # src: 输入图像,可以是灰度图像,也可以是多通道的彩色图像
# ###### # ddepth: 输出图片的数据深度;
# ###### # ksize: 计算二阶导数滤波器的孔径大小,必须为正奇数,可选项
# ###### # scale: 缩放比例因子,可选项,默认值为 1
# ###### # delta: 输出图像的偏移量,可选项,默认值为 0
# ###### #
#
dama= cv2.imread('yuan.png',cv2.IMREAD_GRAYSCALE)
dama_lap = cv2.Laplacian(dama,cv2.CV_64F)
dama_lap_full = cv2.convertScaleAbs(dama_lap)#转换为绝对值,负数转换为正数
cv2.imshow('dama_lap_full',dama_lap_full)
cv2.waitKey(0)

4.Canny边缘检测

√ 低错误率。因为一般的边缘检测算子可能存在检测到伪边缘的情况,因此Canny算法检测到的边缘尽可能地是真实的边缘。

√ 较好地定位边缘点。由检测器标记的边缘点与真实边缘点中心尽可能地接近。

√ 单一的边缘响应。图像中的边缘只标记出一次。

1.图像降噪

        图像去噪是进行边缘检测的第一步,通过去噪可以去除图像中的一些噪点,从而使边缘检测时免受噪点干扰。高斯滤波

2.梯度计算

        要进行边缘检测,就需要得到图像梯度信息,根据图像的梯度幅值和梯度方向来确定边缘,一般均采用sobel算子对图像进行梯度幅值与梯度方向计算。

3.非极大值抑制NMS(Non-Maximal Suppression)

        一阶微分在灰度值斜坡过渡时不为零且存在较粗的边缘,较粗的边缘会增大边缘检测的误差,因此需要细化边缘,一种较为常用的方法是非极大值抑制。非极大值抑制:即在梯度图像中寻找梯度方向上的最大值作为边缘,不是梯度方向上的最大值则抑制为0。因为梯度方向是灰度变化最大的方向。比较梯度图像中每一点的灰度值与梯度方向上至少两个梯度图像像素点灰度值的大小,根据上述大小关系来确定是否保留该点的灰度值。

4.双阈值边界跟踪

        双阈值处理就是根据实际情况需要设置一个灰度高阈值和一个灰度低阈值对NMS后的图像进行过滤,使得得到的边缘尽可能是真实的边缘。双阈值的基本处理步骤为:

        当然上面这些不需要我们写代码进行一步一步处理,只需要调用Canny边缘检测的函数会自己计算、我们只要简单了解有哪些过程就行。每一个过程有啥用

# ###### canny边缘检测
# ###### cv2.Canny(image, threshold1, threshold2[, apertureSize[, L2gradient]])
# ###### # image 为输入图像。
# ###### # threshold1 表示处理过程中的第一个阈值。
# ###### # threshold2 表示处理过程中的第二个阈值。
# ###### #
#
zl = cv2.imread('dama.jpg',cv2.IMREAD_GRAYSCALE)
zl=cv2.resize(zl,dsize=None,fy=0.5,fx=0.5)
cv2.imshow('dama',zl)
cv2.waitKey(0)
zl_canny = cv2.Canny(zl, 150, 230)#低,高
cv2.imshow('dama_canny',zl_canny)
cv2.waitKey(0)

总结

        读者可以使用自己的图片进行测试,在边缘检测上Canny边缘检测相对于前三个具有更好的检测效果。

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

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

相关文章

24.早期目标检测

早期目标检测 第一步,计算机图形学做初步大量候选框,把物体圈出来 第二步,依次将所有的候选框图片,输入到分类模型进行判断 选择性搜索 选择搜索算法(Selective Search),是一种熟知的计算机图像…

Java基础知识点汇总(三)

一、面向对象的特征有哪些方面 Java中面向对象的特征主要包括以下四个核心方面:封装(Encapsulation) 封装是指将对象的属性(数据)和方法(操作)捆绑在一起,隐藏对象的内部实现细节&am…

GEO优化专家孟庆涛:让AI“聪明”选择,为企业“精准”生长

在生成式AI席卷全球的今天,企业最常遇到的困惑或许是:“为什么我的AI生成内容总像‘模板套娃’?”“用户明明想要A,AI却拼命输出B?”当生成式AI从“能用”迈向“好用”的关键阶段,如何让AI真正理解用户需求…

【交易系统系列04】交易所版《速度与激情》:如何为狂飙的BTC交易引擎上演“空中加油”?

交易所版《速度与激情》:如何为狂飙的BTC交易引擎上演“空中加油”? 想象一下这个场景:你正端着一杯热气腾腾的咖啡,看着窗外我家那只贪睡的橘猫趴在阳光下打着呼噜。突然,手机上的警报开始尖叫,交易系统监…

windows下jdk环境切换为jdk17后,临时需要jdk1.8的处理

近段时间,终于决定把开发环境全面转向jdk17,这不就遇到了问题。 windows主环境已经设置为jdk17了。 修改的JAVA_HOME D:\java\jdk-17CLASSPATH设置 .;D:\java\jdk-17\lib\dt.jar;D:\java\jdk-17\lib\tools.jar;PATH中增加 D:\java\jdk-17\bin但是有些程序…

Android URC 介绍及源码案例参考

1. URC 含义 URC 是 Unsolicited Result Code(非请求结果码)的缩写。 它是 modem(基带)在不需要 AP 主动请求的情况下向上层主动上报的消息。 典型例子:短信到达提示、网络状态变更、来电通知、信号质量变化等。 URC 一般以 AT 命令扩展的形式从 modem 发到 AP,例如串口…

VB.NET发送邮件给OUTLOOK.COM的用户,用OUTLOOK.COM邮箱账号登录给别人发邮件

在VB.NET中通过代码发送邮件时,确实会遇到邮箱服务的身份认证(Authentication)要求。特别是微软Outlook/Hotmail等服务,已经逐步禁用传统的“基本身份验证”(Basic Authentication),转而强制要求…

【网络运维】Shell:变量进阶知识

Shell 变量进阶知识 Shell 中的特殊变量 位置参数变量 Shell 脚本中常用的位置参数变量如下: $0:获取当前执行的 Shell 脚本文件名(包含路径时包括路径)$n:获取第 n 个参数值(n>9 时需使用 ${n}&#xf…

部署Qwen2.5-VL-7B-Instruct-GPTQ-Int3

模型下载 from modelscope import snapshot_download model_dir snapshot_download(ChineseAlpacaGroup/Qwen2.5-VL-7B-Instruct-GPTQ-Int3)相关包导入 import os import numpy as np import pandas as pd from tqdm import tqdm from datetime import datetime,timedelta fro…

sourcetree 拉取代码

提示:文章旨在于教授大家 sourcetree 拉取代码的方式,关于代码的提交合并等操作后续会补充。 文章目录前言一、sourcetree 安装二、http 与 ssh 拉取代码1.http 方式(1)生成 token(2)拼接项目的 url&#x…

epoll模型网络编程知识要领

1、程序初始化创建监听socket调用bind函数绑定ip地址、port端口号调用listen函数监听调用epoll_create函数创建epollfd调用epoll_ctrl函数将listenfd绑定到epollfd上,监测listenfd的读事件在一个无限循环中,调用epoll_wait函数等待事件发生2、处理客户端…

15-day12LLM结构变化、位置编码和投机采样

多头机制transformer结构归一化层选择 归一化层位置归一化层类型激活函数Llama2结构MoE架构 混合专家模型DeepSeek MLA为何需要位置编码目前的主流位置编码正余弦位置编码可学习位置编码ROPE旋转位置编码推导参考: https://spaces.ac.cn/archives/8265 https://zhua…

记录 docker容器打包成镜像 在其他服务器快速启动镜像和容器

我有个nginx服务器 需要在其他服务器直接部署使用 里面都是完整的 使用 docker ps 查看容器id 进行打包成镜像docker commit [容器ID或名称] 新镜像名:版本 docker commit 28f60e2206b2 my-nginx-custom:v1镜像保存成文件 docker save -o my-nginx-custom.tar my-nginx-custom:…

使用LLaMA-Factory对大模型进行微调-详解

书接上回 启动llama Factory可视化页面 llamafactory-cli webui 如果想后台运行 使用 nohup llamafactory-cli webui &浏览器访问 http://127.0.0.1:7860/配置项主要参数: 参考: https://docs.coreshub.cn/console/compute_platform/help/llama_factory/ 模型路径 : 解…

【AI】录制自动生成UI自动化脚本

命令行输入:npx playwright codegen https://myerp.dmyc.XXX.com:9443/打开的浏览器上操作,会自动录制,并生成自动化脚本

深度剖析字节跳动VeOmni框架

背景与设计动机 随着推荐系统和AI模型走向多模态、多任务的趋势,字节跳动面临着训练、迭代效率和系统复杂度的双重挑战。一方面,各类业务(如新闻推荐、短视频、图文广告、电商带货等)都需要处理文本、图像、视频、音频等多种输入模…

OCR库pytesseract安装保姆级教程

本文将介绍使用工具安装OCR库pytesseract的详细流程。 Anaconda安装教程参考Anaconda安装保姆级教程。 目录 一、工具安装 二、创建虚拟环境 三、安装pytesseract 总结 一、工具安装 点击链接前往官网codetou.com,下载安装最新版即可,本篇博客以抠头…

开源im即时通讯软件开发社交系统全解析:安全可控、功能全面的社交解决方案

在即时通讯与社交需求日益增长的今天,一款安全、稳定、功能全面的聊天软件成为不少团队和开发者的刚需。但市面上多数聊天 APP 要么依赖第三方插件,面临数据安全隐患和高额服务费;要么功能单一,难以满足复杂社交场景。今天给大家推…

残差神经网络(ResNet)

残差神经网络(Residual Neural Network,简称 ResNet)是深度学习领域的里程碑式模型,由何凯明等人在 2015 年提出,成功解决了深层神经网络训练中的梯度消失 / 爆炸问题,使训练超深网络(如 152 层…

学习嵌入式之驱动

一、基础搭建1.基础:c语言 软件编程语言 数据结构 软件编程思想2.驱动实现目标如果将Linux系统细致到开发板平台上? Liunx系统与硬件设备的适配3.自我能力的锻炼继续强化C语言锻炼大型代码阅读和分析能力学习大型项目的代码搭建和管理的能力…