一文解决Opencv四大经典算子——sobel算子、scharr算子、laplacian算子、canny算子

在这里插入图片描述


边缘是像素值发生跃迁的位置,是图像的显著特征之一,在图像特征提取,对象检测,模式识别等方面都有重要的作用!

Sobel算子

sobel算子对图像求一阶导数。一阶导数越大,说明像素在该方向的变化越大,边缘信号越强。因为图像的灰度值都是离散的数字, sobel算子采用离散差分算子计算图像像素点亮度值的近似梯度.
在这里插入图片描述
在这里插入图片描述
soble x轴和y轴要分别计算,计算完用add添加在一起
cv2.soble(image, ddepth,dx,dy,ksize)

  • image:需要处理的图片
  • ddepth: 输出图像的深度(可以理解为数据类型),-1表示与原图像相同的深度。
  • dx:0即为不计算,1即为计算
  • dy:同dy,0即为不计算,1即为计算。
  • ksize:卷积核的大小,为一个整数

值得注意的是ddepth在函数使用的时候经常会规定为cv2.CV_64F,与变化为绝对值函数cv2.convertScaleAbs一起配套使用。因为默认为-1的话,如果出现卷积核所在区域,左边为黑,右边为白,则会出现负数,opencv默认会进行截断操作,影响轮廓的显示。所有用cv2.CV_64F保留负数的像素 (如果此时直接imshow显示仍然会出现截断为0的情况) ,再用cv2.convertScaleAbs转化为正数,这样才能够保证算子的准确性。接下来我们比较ddepth为-1和cv2.CV_64F然后转化为绝对值这两种情况。
首先是默认-1的情况

#!/usr/bin/env python
# -*- coding: UTF-8 -*-
"""
@Project :Opencv计算机视觉 
@File    :12.sobel算子中ddepth为-1.py
@IDE     :PyCharm 
@Author  :咋
@Date    :2023/1/29 19:04 
"""
import cv2
import numpy as np
image = cv2.imread("za.jpg")
image = cv2.resize(image,(640,480))
# sobel算子
# 计算x方向,-1表示与输入图像的深度一致
dx = cv2.Sobel(image,-1,1,0,ksize = 3)
# 计算y方向
dy = cv2.Sobel(image,-1,0,1,ksize = 3)
# 将两个方向加在一起,addWeighted方法
sobel_img = cv2.addWeighted(dx,0.5,dy,0.5,0)
# 展示图片

cv2.imshow("sobel_dx_dy",np.hstack((dx,dy)))
cv2.imwrite("sobel_dx_dy.jpg",np.hstack((dx,dy)))
cv2.imshow("sobel_img_1",np.hstack((image,sobel_img)))
cv2.imwrite("sobel_img_1.jpg",np.hstack((image,sobel_img)))
cv2.waitKey(0)
cv2.destroyAllWindows()

在这里插入图片描述
在这里插入图片描述

上面左上是dx方向计算的结果,基本上都为竖直方向的轮廓。右上为dy方向计算的结果,基本上都为水平方向的轮廓。左下为原图,右下即为ddepth设置为-1时的边缘检测效果,基本的轮廓已经能够看出来了,但是中间有些地方还是没能检测出来。
ddepth设置为CV_64F:

#!/usr/bin/env python
# -*- coding: UTF-8 -*-
"""
@Project :Opencv计算机视觉 
@File    :13.sobel算子中ddepth为cv2.CV_64F.py
@IDE     :PyCharm 
@Author  :咋
@Date    :2023/1/29 19:39 
"""
import cv2
import numpy as np
image = cv2.imread("za.jpg")
image = cv2.resize(image,(640,480))
# sobel算子
# 计算x方向,cv2.CV_64F表示保留计算过程中的负数
dx = cv2.Sobel(image,cv2.CV_64F,1,0,ksize = 3)
dx = cv2.convertScaleAbs(dx)
# 计算y方向
dy = cv2.Sobel(image,cv2.CV_64F,0,1,ksize = 3)
dy = cv2.convertScaleAbs(dy)
# 将两个方向加在一起,add方法
sobel_img = cv2.addWeighted(dx,0.5,dy,0.5,0)
# 展示图片
cv2.imshow("sobel_img",np.hstack((image,sobel_img)))
cv2.imshow("sobel_dx_dy_64",np.hstack((dx,dy)))
#保存图片
cv2.imwrite("sobel_img_64.jpg",np.hstack((image,sobel_img)))
cv2.imwrite("sobel_dx_dy_64.jpg",np.hstack((dx,dy)))
cv2.waitKey(0)
cv2.destroyAllWindows()

在这里插入图片描述
在这里插入图片描述
同样,左上为dx方向,右上为dy方向,左下为原图,右下为ddepth设置为CV_64F时的检测效果,可以看到检测效果比上面好很多,所有的边界轮廓都检测出来了,而且很清晰。实践证明CV_64F比-1的检测效果要更好。那么相信会有同学提问了:为什么要分开计算dx,dy,sobel算子计算时直接都设置为1,一起计算不是更省事吗?
我们一起看下分开计算dx,dy和一起计算dx,dy的对比效果

#!/usr/bin/env python
# -*- coding: UTF-8 -*-
"""
@Project :Opencv计算机视觉 
@File    :14.sobel算子合并运算与分开运算对比.py
@IDE     :PyCharm 
@Author  :咋
@Date    :2023/1/29 19:50 
"""
import cv2
import numpy as np
image = cv2.imread("za.jpg")
image = cv2.resize(image,(640,480))
# sobel算子
# 计算x方向,cv2.CV_64F表示保留计算过程中的负数
dx = cv2.Sobel(image,cv2.CV_64F,1,0,ksize = 3)
dx = cv2.convertScaleAbs(dx)
# 计算y方向
dy = cv2.Sobel(image,cv2.CV_64F,0,1,ksize = 3)
dy = cv2.convertScaleAbs(dy)
# 分别计算dx dy得到的图像
apart_sobel = cv2.addWeighted(dx,0.5,dy,0.5,0)
# 一起计算dx dy得到的图像
all_sobel= cv2.Sobel(image,cv2.CV_64F,1,1,ksize = 3)
all_sobel = cv2.convertScaleAbs(all_sobel)
# 展示图片
cv2.imshow("contrast_img",np.hstack((apart_sobel,all_sobel)))
#保存图片
cv2.imwrite("contrast_img.jpg",np.hstack((apart_sobel,all_sobel)))
cv2.waitKey(0)
cv2.destroyAllWindows()

在这里插入图片描述
左侧为分开计算dxdy时的图片,轮廓非常清楚。右侧是一起计算,不仅会有轮廓的确实,而且有重影的感觉。所以在是用Sobel算子时,建议还是设置ddepth=cv2.CV_64F,再使用cv2.convertScaleAbs()取绝对值,这样的检测效果更好。

Scharr算子

在Opencv中直接提供了Scharr调用的API:cv2.Scharr()
cv2.Scharr() :在这里插入图片描述

#!/usr/bin/env python
# -*- coding: UTF-8 -*-
"""
@Project :Opencv计算机视觉 
@File    :15.Scharr算子.py
@IDE     :PyCharm 
@Author  :咋
@Date    :2023/1/29 20:09 
"""
import cv2
import numpy as np
image = cv2.imread("za.jpg")
image = cv2.resize(image,(640,480))
# scharr算子
# 计算x方向
dx = cv2.Scharr(image,-1,1,0)
# 计算y方向
dy = cv2.Scharr(image,-1,0,1)
# 将两个方向加在一起,addWeighted方法
scharr_img = cv2.addWeighted(dx,0.5,dy,0.5,0)
# 展示图片
cv2.imshow("scharr_img",np.hstack((image,scharr_img)))
cv2.imwrite("scharr.jpg",np.hstack((image,scharr_img)))
cv2.waitKey(0)
cv2.destroyAllWindows()

在这里插入图片描述
和之前的sobel算子ddepth设置为-1时非常相似,在这里就不过多介绍。

laplacian算子

laplacian算子又称为拉普拉斯算子,在opencv中的API为cv2.Laplacian(),注意大小写。
cv2.Laplacian()
在这里插入图片描述
在这里插入图片描述

#!/usr/bin/env python
# -*- coding: UTF-8 -*-
"""
@Project :Opencv计算机视觉 
@File    :16.Laplacian算子.py
@IDE     :PyCharm 
@Author  :咋
@Date    :2023/1/29 20:14 
"""
import cv2
import numpy as np
image = cv2.imread("za.jpg")
image = cv2.resize(image,(640,480))
# 拉普拉斯算子
lap_image = cv2.Laplacian(image,-1,ksize = 5)
# 展示图片
cv2.imshow("lap_image",np.hstack((image,lap_image)))
# 保存图片
cv2.imwrite("lap_image.jpg",np.hstack((image,lap_image)))
cv2.waitKey(0)
cv2.destroyAllWindows()

在这里插入图片描述
虽然代码很简单,但是效果确非常好!轮廓非常清晰!

canny算子

canny算子称得上是最经典且强大的算子,其主要步骤如下:

  1.    使用高斯滤波器,以平滑图像,滤除噪声。
    
  2.    计算图像中每个像素点的梯度强度和方向。
    
  3.    应用非极大值(Non-Maximum Suppression)抑制,以消除边缘检测带来的杂散响应。
    
  4.    应用双阈值(Double-Threshold)检测来确定真实的和潜在的边缘。
    
  5.    通过抑制孤立的弱边缘最终完成边缘检测。
    

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

#!/usr/bin/env python
# -*- coding: UTF-8 -*-
"""
@Project :Opencv计算机视觉 
@File    :17.canny算子.py
@IDE     :PyCharm 
@Author  :咋
@Date    :2023/1/29 20:23 
"""
import cv2
import numpy as np
image = cv2.imread("za.jpg",cv2.IMREAD_GRAYSCALE)
image = cv2.resize(image,(640,480))
# canny
v1=cv2.Canny(image,50,100)
# 展示图片
cv2.imshow("canny_image",np.hstack((image,v1)))
# 保存图片
cv2.imwrite("canny_image.jpg",np.hstack((image,v1)))
cv2.waitKey(0)
cv2.destroyAllWindows()

在这里插入图片描述
从上图可以看出来,canny算子而是非常的清楚,能够很好的完成任务!

总结

本篇博客详细介绍了Opencv四大经典算子——sobel算子、scharr算子、laplacian算子、canny算子,通过实际的图片轮廓检测对不同算子的检测效果进行评估。虽然各算子名称不同,但是实际上是卷积核的使用不同,不同的卷积核会对图片产生不同的印象。卷积的存在也为计算机视觉提供了多种多样的可能性和无穷的创造性,人工智能依旧很广阔,计算机视觉的学习依旧在路上!继续加油,感兴趣的小伙伴欢迎私信博主!

原创不易,还希望各位大佬支持一下 \textcolor{blue}{原创不易,还希望各位大佬支持一下} 原创不易,还希望各位大佬支持一下

👍 点赞,你的认可是我创作的动力! \textcolor{green}{点赞,你的认可是我创作的动力!} 点赞,你的认可是我创作的动力!

⭐️ 收藏,你的青睐是我努力的方向! \textcolor{green}{收藏,你的青睐是我努力的方向!} 收藏,你的青睐是我努力的方向!

✏️ 评论,你的意见是我进步的财富! \textcolor{green}{评论,你的意见是我进步的财富!} 评论,你的意见是我进步的财富!

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

爱睡觉的咋

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值