【OpenCV】计算机视觉图像处理基础知识

目录

前言

推荐

1、OpenCV礼帽操作和黑帽操作

2、Sobel算子理论基础及实际操作

3、Scharr算子简介及相关操作

4、Sobel算子和Scharr算子的比较

5、laplacian算子简介及相关操作

6、Canny边缘检测的原理

6.1 去噪

6.2 梯度运算

6.3 非极大值抑制

6.4 滞后阈值

7、Canny边缘检测的函数及使用


前言

本文将非常细致的讲解相关与计算机视觉OpenCV图像处理的相关知识即操作,非常的简单易懂。

推荐

前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到网站

1、OpenCV礼帽操作和黑帽操作

图像顶帽操作也叫图像礼帽操作,实际上就是:
结果图像=原图像-图像开运算
那么我们知道图像的开运算就是对图像先腐蚀操作,然后在进行膨胀操作,得到的图像其实就是进行了取噪的一个处理,然后我们所说的礼帽图像操作就是使用原图像-图像的开运算操作。
函数依旧是:

result = cv2.morphologyEx(img, cv2.MORPH_TOPHAT, kernel)

其中img表示原始图像,cv2.MORPH_TOPHAT表示进行礼帽操作,然后kernel表示卷积核,这里我们之前已经讲过。
核心函数是:

k=np.ones((5,5),np.uint8)
r=cv2.morphologyEx(o,cv2.MORPH_TOPHAT,k)

这样我们显示以下我们处理的图像就可以知道:

处理之后我们得到了相应的噪声结果。

图像黑帽操作就是图像的闭运算-原图像
黑帽结果图像=图像闭运算-原图像
我们之前也介绍过这个闭运算操作就是先对图像进行膨胀操作,然后进行腐蚀操作。
函数是:

result = cv2.morphologyEx(img, cv2.MORPH_BLACKHAT, kernel)

其中cv2.MORPH_BLACKHAT表示的就是黑帽操作的意思,kernel表示卷积核。
然后我们看一下图像处理的核心函数:

k=np.ones((5,5),np.uint8)
r=cv2.morphologyEx(o,cv2.MORPH_BLACKHAT,k)

得到的结果是:

可以看到我们把图像中的小气泡都取出来了。

2、Sobel算子理论基础及实际操作

首先我们来了解一个边界的定义,看一个图来理解更加的明白。

对于如图中的水平梯度,我们看A、B两个地方,右侧像素值减去左侧像素值不为0,那么我们就说在此图中A列和B列是边界,否则不是边界。同样对于垂直梯度我们也是这样定义。
对于Sobel算子,我们先来看x方向他进行了什么操作:

P5x=(p3-p1)+2*(p6-p4)+(p9-p7)
右侧像素值减去左侧像素值,中间行参数稍大为2。
同样对于y轴方向也做了一个同样的操作,
P5y=(p7-p1)+2*(p8-p2)+(p9-p3)
下一行像素值减去上一行像素值,中间列参数稍大为2
然后我们计算了一个近似梯度值:
G= 根号(𝐺𝑥2 + 𝐺𝑦2)
简化版本就是:
G=|𝐺𝑥|+| 𝐺𝑦|

这中心点的P5的Sobel算子就是按照这个方式进行计算。
对于P5点完成的Sobel算子计算就是这样:

那么好,我们来看一下在python中对于Sobel是一个什么样的函数:

dst = cv2.Sobel( src , ddepth , dx , dy , [ksize] )

其中src表示原始图像,ddeph表示图像的深度,那么我们一般设定为-1,用来表示和原图像保持一致。dx,dy表示x轴的方向或者y轴的方向,ksize表示核大小。
其中我们在已经知道的256色位图中,白色点像素值255,黑色点像素值0。
这里对于dx,dy方向为什么我们取绝对值进行一下解答,因为加入一块黑块在一个白色背景下,那么我们在水平方向上,左侧那么得到的数值就是一个负数,对于右侧那么我们得到的是就是一个正常的正数,那么对于OpenCV来说,当我们没有加绝对值得时候如果出现了负数,统一处理成0。
 

根据图我们就可以知道,左侧的线被OpenCV处理成了0。所以我们这里要加上一个绝对的运算。无论对于水平方向还是垂直方向都是如此。
然后我们要将原始图像处理成256为的色位图。其函数是:

dst = cv2.convertScaleAbs( src [, alpha[, beta]] )

目标图像=调整(原始图像*alpha+beta)
其中alpha和beta可以理解为权重的意思。
当我们想要计算水平方向上的Sobel算子的时候,那么我们就设定函数中的参数dx=1,dy=0.对于垂直方向也是如此。那么这里我们就会想:如果我们两个方向都一起设置这样是不是比计算完x的方向然后计算y方向,然后进行结合这样是不是更加的方便一些呢?也就是说下图中的方式一比方式二更加的简介方便呢?

事实上不是这样的,而且两个图像有很大的差异,这个我们后续会看到结果。
那么当我们完成了这一步操作之后,我们还要做两个图像的权重和,其函数是:

dst=cv2.addWeighted( src1 , alpha , src2 , beta , gamma )

这里我们说的通俗一点就是,src1表示计算的x轴方向的图像,alpha表示x轴方向上的图像所占的比重,src2表示计算的y轴方向的图像,beta表示y轴方向上的图像所占的比重是多少,最后gamma表示一个修正数值。

dst(I)=saturate(src1(I)*alpha+src2(I)*beta+gamma)

接下来我们来验证一下各个结果:

import cv2
import numpy as np
o = cv2.imread('image\\sobel4.bmp',cv2.IMREAD_GRAYSCALE)
sobelx = cv2.Sobel(o,-1,1,0)
cv2.imshow("original",o)
cv2.imshow("x",sobelx)
cv2.waitKey()
cv2.destroyAllWindows()

这里我们没有加上绝对值计算x轴方向上的Sobel算子,得到的结果是:

很明显左侧的没有计算出来。

import cv2
import numpy as np
o = cv2.imread('image\\sobel4.bmp',cv2.IMREAD_GRAYSCALE)
sobelx = cv2.Sobel(o,cv2.CV_64F,1,0)
sobelx = cv2.convertScaleAbs(sobelx) # 转回uint8 
cv2.imshow("original",o)
cv2.imshow("x",sobelx)
cv2.waitKey()
cv2.destroyAllWindows()

当我们加上绝对值后的结果是:

对于垂直方向的结果也是如此。最后我们计算出x,y的方向。进行融合并且和直接将x,y表示成1的结果进行一下对比,我们来看结果:
核心代码:

sobelx = cv2.Sobel(o,cv2.CV_64F,1,0)
sobely = cv2.Sobel(o,cv2.CV_64F,0,1)
sobelx = cv2.convertScaleAbs(sobelx) # 转回uint8 
sobely = cv2.convertScaleAbs(sobely) 
sobelxy = cv2.addWeighted(sobelx,0.5,sobely,0.5,0) 
sobelxy11=cv2.Sobel(o,cv2.CV_64F,1,1)
sobelxy11=cv2.convertScaleAbs(sobelxy11)

根据结果我们可以得到:使用了dx,dy的情况下无法检测到边。然后我们用lena来测试一下结果。

在我们相加表示的情况下,边缘检测的线条十分清晰,将分割的地带表达的特别清楚。

3、Scharr算子简介及相关操作

经过大量的科学家验证,发现3*3的Sobel算子可能并不是特别的精确,于是又提出了相应的Scharr算子,其实就是改变了运算的尺度而已。

Sobel算子由原来的121变为了3 10 3,这样的一个组合。其余的操作都是和Sobel算子一致我们来简要的说明一下:
dst=Scharr(src, ddpeth, dx, dy)
这里面少了核的大小,但是和Sobel算子依然一直,参数这里就不解释了,唯一不同的就是我们使用Sobel算子可以设置成dx=1,dy=1。那么对于Scharr算子如果这样设置就会报错。这里需要注意一下。满足条件:
dx >= 0 && dy >= 0 && dx+dy == 1
 

import cv2
import numpy as np
o = cv2.imread('image\\scharr.bmp',cv2.IMREAD_GRAYSCALE)
scharrx = cv2.Scharr(o,cv2.CV_64F,1,0)
scharry = cv2.Scharr(o,cv2.CV_64F,0,1)
scharrx = cv2.convertScaleAbs(scharrx) # 转回uint8 
scharry = cv2.convertScaleAbs(scharry) 
scharrxy = cv2.addWeighted(scharrx,0.5,scharry,0.5,0) 
cv2.imshow("original",o)
cv2.imshow("x",scharrx)
cv2.imshow("y",scharry)
cv2.imshow("xy",scharrxy)
cv2.waitKey()
cv2.destroyAllWindows()

4、Sobel算子和Scharr算子的比较

对于上述我们的测试图,其实看不出来Sobel算子和Scharr算子到底有什么区别,看起来是一致的,那么我们这里使用大美女lena进行一次Sobel和Scharr,得到结果进行对比一下可以知道:

sobelx = cv2.Sobel(o,cv2.CV_64F,1,0,ksize=3)
sobely = cv2.Sobel(o,cv2.CV_64F,0,1,ksize=3)
sobelx = cv2.convertScaleAbs(sobelx) # 转回uint8 
sobely = cv2.convertScaleAbs(sobely) 
sobelxy = cv2.addWeighted(sobelx,0.5,sobely,0.5,0) 
scharrx = cv2.Scharr(o,cv2.CV_64F,1,0)
scharry = cv2.Scharr(o,cv2.CV_64F,0,1)
scharrx = cv2.convertScaleAbs(scharrx) # 转回uint8 
scharry = cv2.convertScaleAbs(scharry) 
scharrxy = cv2.addWeighted(scharrx,0.5,scharry,0.5,0)

很明显,这里我们看一下了lena的肩膀部分,可以看到使用Shcarr算子进行计算的时候,刻画的更加细致。

5、laplacian算子简介及相关操作

拉普拉斯算子类似于二阶sobel导数。实际上,在OpenCV中通过调用sobel算子来计算拉普拉斯算子。使用的公式为:
∆𝑠𝑟𝑐 = 𝜕2𝑠𝑟𝑐/𝜕𝑥2 + 𝜕2𝑠𝑟𝑐/𝜕𝑦2
使用的卷积核也和Sobel和Shcarr算子的不一致:

看起来有点像高斯的,哈哈哈。
这里我们进行一下讲解,
P5new=(p2+p4+p6+p8)-4*p5

当没有处于边界的时候呢,我们可以得到P5的数值是变化不大的,当处于边界的时候,P5的数值是变化非常大的,这是因为什么呢?

对于拉普拉斯算子的函数估计我们也可以猜到:
dst = cv2.Laplacian( src, ddepth )
自然是没有水平方向和垂直方向的。
实际操作中,计算梯度值可能会出现负数。通常处理的图像是np.uint8类型,如果结果也是该类型,所有负数会自动截断为0,发生信息丢失。所以,通常计算时,使用更高的数据类型cv2.CV_64F,取绝对值后,再转换为np.uint(cv2.CV_8U)类型。
所以我们还是要取一次绝对值的运算:
dst = cv2.convertScaleAbs( src )
 

import cv2
import numpy as np
o = cv2.imread('image\\laplacian.bmp',cv2.IMREAD_GRAYSCALE)
laplacian = cv2.Laplacian(o,cv2.CV_64F)
laplacian = cv2.convertScaleAbs(laplacian) # 转回uint8 
cv2.imshow("original",o)
cv2.imshow("laplacian",laplacian)
cv2.waitKey()
cv2.destroyAllWindows()

我们对lena进行一次拉普拉斯算子操作,得到的结果是:

6、Canny边缘检测的原理

Canny边缘检测算子是John F. Canny于 1986 年开发出来的一个多级边缘检测算法。更为重要的是 Canny 创立了边缘检测计算理论(Computational theory of edge detection)解释这项技术如何工作。
Canny 的目标是找到一个最优的边缘检测算法,最优边缘检测的含义是:
1.最优检测:算法能够尽可能多地标识出图像中的实际边缘,漏检真实边缘的概率和误检非边缘的概率都尽可能小;
2.最优定位准则:检测到的边缘点的位置距离实际边缘点的位置最近,或者是由于噪声影响引起检测出的边缘偏离物体的真实边缘的程度最小;
3.检测点与边缘点一一对应:算子检测的边缘点与实际边缘点应该是一一对应。
Canny边缘检测的一般步骤:1.去噪 2.梯度运算 3.非极大值抑制 4.滞后阈值。下面我们就分别讲解一下这些操作:

6.1 去噪

边缘检测容易受到噪声的影响。因此,在进行边缘检测前,通常需要先进行去噪。我们一般使用高斯滤波进行图像去噪处理。也就是让临近的像素具有更高的重要度。对周围像素计算加权平均值,较近的像素具有较大的权重值。

比较像我们之间讲到的k近邻算法的意思哈。进行去噪处理之后呢,我们对于平滑图像进行一次Sobel算子梯度运算。

6.2 梯度运算

𝐸𝑑𝑔𝑒𝐺𝑟𝑎𝑑𝑖𝑒𝑛𝑡 𝐺 = 根号下(𝐺𝑥2 + 𝐺𝑦2)
对于方向:𝐴𝑛𝑔𝑙𝑒 𝜃 = 𝑡𝑎𝑛−1(𝐺𝑦/𝐺𝑥)

对于每一个点计算之后的方向就是这样。大小和方向在图中都已经进行了标记。梯度的方向一般总是与边界垂直。梯度方向被归为四类:垂直,水平,和两个对角线。

6.3 非极大值抑制

在获得了梯度和方向后,遍历图像,去除所有不是边界的点。实现方法:逐个遍历像素点,判断当前像素点是否是周围像素点中具有相同方向梯度的最大值。

点A、点B、点C三点具有相同的方向,梯度方向垂直于边缘。判断点A是否为点A、点B、点C的局部最大值 :如果是,保留该点;否则,它被抑制(归零)。

这里就表示在垂直方向上进行了抑制,取出最大值。

6.4 滞后阈值

这里对非极大值抑制之后,我们进行了一次滞后阈值操作,分别取一个最小阈值和一个最大阈值,然后图像像素点的曲线与最大最小阈值相连则保留,如果不相连则抛弃。

我们来看一下边缘检测的结果图:

7、Canny边缘检测的函数及使用

Canny边缘检测的函数是:
edges = cv2.Canny( image, threshold1, threshold2 )
threshold1表示阈值1,threshold2表示阈值2。也就是我们刚刚介绍到的最大最小阈值。

import cv2
import numpy as np
o=cv2.imread("image\\canny.bmp",cv2.IMREAD_GRAYSCALE)
r=cv2.Canny(o,100,200)
cv2.imshow("original",o)
cv2.imshow("result",r)
cv2.waitKey()
cv2.destroyAllWindows()

然后我们在对lena做一次,结果是:

调整阈值,可以控制边缘细节。maxVal、minVal变小,有更多的细节信息。

如果觉得博主的文章还不错或者您用得到的话,可以免费的关注一下博主,如果三连收藏支持就更好啦!这就是给予我最大的支持!

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

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

相关文章

vue 用Nginx实现负载均衡

Nginx负载均衡的作用(相当于客户端的请求是发到Nginx上的,然后由Nginx决定到底调用哪台服务器): 在 .net core 中的具体实现步骤 1.在nginx官网上下载安装包,推荐稳定版; 建议1.18版本 2.下载完成后,到所在目录执行 nginx绿色图…

易点易动二维码巡检方案:提升企业巡检效率的智慧选择

在当今科技发达的时代,传统的纸质设备巡检方式已经无法满足企业管理的需求。纸质巡检方式存在诸多弊端,如巡检效率低、数据管理困难等问题。然而,随着易点易动二维码巡检方案的出现,企业可以迎来一种全新的巡检方式,极…

无需公网IP!Apache服务器本地部署与内网穿透实现公网访问

Apache服务安装配置与结合内网穿透实现公网访问 文章目录 Apache服务安装配置与结合内网穿透实现公网访问前言1.Apache服务安装配置1.1 进入官网下载安装包1.2 Apache服务配置 2.安装cpolar内网穿透2.1 注册cpolar账号2.2 下载cpolar客户端 3. 获取远程桌面公网地址3.1 登录cpo…

实战分析和精华总结:服务器端请求伪造SSRF漏洞数据劫持、复现、分析、利用及修复过程

实战分析和精华总结:服务器端请求伪造SSRF漏洞数据劫持、复现、分析、利用及修复过程。 SSRF漏洞(服务器端请求伪造):是一种由攻击者构造形成由服务端发起请求的一个安全漏洞。一般情况下,SSRF攻击的目标是从外网无法访问的内部系统。(正是因为它是由服务端发起的,所以…

“丝路电商”与泛欧在线公共采购平台Peppol

近期上海商务委员会公布《关于在上海市创建“丝路电商”合作先行区的方案》(以下简称方案),方案中提出:“全面贯彻落实党的二十大精神,立足新发展阶段,完整、准确、全面贯彻新发展理念,加快构建…

React--引入第三方插件时,标签名是小写报错问题

报错信息 报错原因 1.组件名得大写 2.缺少 import 语句 解决方案 declare global{namespace JSX{interface IntrinsicElements {micro-app: any}} }

基于Python实现的滑动验证码自动识别工具源码

滑动验证码识别 今天的目标地址是字节的巨量纵横,目前东家是一家广告营销型的公司,专注于在各大平台投放信息流广告。巨量纵横为字节跳动的广告平台,用于管理推广账户。今天破解一下这个平台的登陆入口,为今后的数据爬取开个头。…

Go 程序编译过程(基于 Go1.21)

版本说明 Go 1.21 官方文档 Go 语言官方文档详细阐述了 Go 语言编译器的具体执行过程,Go1.21 版本可以看这个:https://github.com/golang/go/tree/release-branch.go1.21/src/cmd/compile 大致过程如下: 解析 (cmd/compile/internal/synt…

【数电笔记】06-码制

目录 说明: 二进制代码 1. 二 - 十进制码 2. 常用二 - 十进制代码表 2.1 例题 可靠性代码 1. 格雷码 2. 奇偶校验码 3. 8421奇偶校验码表 说明: 笔记配套视频来源:B站;本系列笔记并未记录所有章节,只对个人认…

SAP_ABAP_内表数据重复问题,解决思路

SAP ABAP 顾问(开发工程师)能力模型_Terry谈企业数字化的博客-CSDN博客文章浏览阅读516次。目标:基于对SAP abap 顾问能力模型的梳理,给一年左右经验的abaper 快速成长为三年经验提供超级燃料!https://blog.csdn.net/j…

ESP32-Web-Server编程-简单的照片浏览器

ESP32-Web-Server编程-简单的照片浏览器 概述 从本节开始我们开始制作一些有趣的多媒体 Web 的示例。 当你希望在网页上展示一些广告、照片,或者你的开发板带摄像头,能够采集一些图片,这时你希望可以通过手头的浏览器查看图片,…

第二证券:国际金价创新高 国内锂电企业有望加速出海

12月首个交易日,两市股指盘中弱势下探,午后止跌回升,沪指、创业板指翻红,北证50指数再度跳水。到收盘,沪指微涨0.07%报3031.64点,深成指跌0.07%报9720.57点,创业板指涨0.19%报1926.28点&#xf…

如何打印社保参保凭证

西安市: 陕西政务服务网: 个人服务 珠海市: 广东政务服务网: 用户登录 | 珠海市人力资源和社会保障网上服务平台 武汉市: 湖北政务服务网: 湖北政务服务网

vue: 线上项目element-ui的icon偶尔乱码问题

线上环境偶尔会复现, 具体: 一般使用不会出现这个问题,因为一般引入的是element-ui的css文件,问题出在于为了主题色变化啊,需要用到scss变量引入了scss文件。 import “~element-ui/packages/theme-chalk/src/index”…

Python练习题(四)

本文主要是【Python】——Python练习题的文章,如果有什么需要改进的地方还请大佬指出⛺️ 🎬作者简介:大家好,我是听风与他🥇 ☁️博客首页:CSDN主页听风与他 🌄每日一句:狠狠沉淀&a…

图像语义分割算法(FCN/U-net)

Some definitions  与目标检测不同,语义分割任务不但要对图片中的物体的位置和类别进行预测,还要精确地描绘出不同类物体之间的边界(注意是不同类物体,而不是不同物体。若对同一类的不同物体也进行区分,则…

iptables防火墙之SNAT与DNET

NAT 1.SNAT:让内网可以访问外网 2.DNAT:让外网可以访问到内网的机器 网关服务器,要开启路由功能 内核功能: sysctl -a 列出所有参数 内核参数,然后grep可以查看到默认的内核参数 内核参数配置文件 /etc/sysctl.…

【ArcGIS Pro微课1000例】0046:深度学习--汽车检测

本实验讲述ArcGIS Pro中人工智能深度学习应用之–汽车检测。 文章目录 一、学习效果二、工具介绍三、案例实现四、注意事项一、学习效果 采用深度学习工具,可以很快速精准的识别汽车。 案例一: 案例二: 下面讲解GIS软件实现流程。 二、工具介绍 该案例演示的是ArcGIS Pro中…

L1-018:大笨钟

题目描述 微博上有个自称“大笨钟V”的家伙,每天敲钟催促码农们爱惜身体早点睡觉。不过由于笨钟自己作息也不是很规律,所以敲钟并不定时。一般敲钟的点数是根据敲钟时间而定的,如果正好在某个整点敲,那么“当”数就等于那个整点数…

Java笔记

md5加密 spring框架我我们提供了一个工具类DigestUtils 调用类中的md5digestAsHes对密码进行加密 但是要将密码转成bytes数组 password DigestUtils.md5DigestAsHex(password.getBytes()); 对象的属性拷贝 BeanUtils.copyProperties(有数据的对象,空对象)&#…