opencv-6 边缘检测(Prewitt算子,Sobel算子,Laplacian算子)

article/2025/11/9 3:45:39

Roberts

filter2D形式实现


import cv2
import numpy as np
import matplotlib.pyplot as pltimg = cv2.imread('lena.jpg')
lenna_img = cv2.cvtColor(img,cv2.COLOR_BGR2RGB)
grayImage = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)kernelx = np.array([[-1,0],[0,1]],dtype=int)
kernely = np.array([[0,-1],[1,0]],dtype=int)
x = cv2.filter2D(grayImage,cv2.CV_16S,kernelx) # cv2.CV_165 表示目标图像所需的深度
y = cv2.filter2D(grayImage,cv2.CV_16S,kernely)absX = cv2.convertScaleAbs(x)#计算绝对值
absY = cv2.convertScaleAbs(y)
Roberts = cv2.addWeighted(absX,0.5,absY,0.5,0)plt.rcParams['font.sans-serif'] = ['SimHei'] #使用参数字典 rcParams 访问并修改已经加载的配置项。
titles = [u'原始图像',u'Roberts算子']
images = [lenna_img,Roberts]for i in range(2):plt.subplot(1, 2, i+1), plt.imshow(images[i],'gray')plt.title(titles[i])plt.xticks([]),   plt.yticks([])plt.show()

Roberts

矩阵相乘实现

import cv2
from pylab import *def RobertsAlogrithm(image):image = cv2.copyMakeBorder(image,1,1,1,1,cv2.BORDER_DEFAULT)# 如果你想给你的图片设置边界框,就像一个相框一样的东西,你就可以使用cv2.copyMakeBorder()函数。但其在卷积操作、零填充等也得到了应用,并且可以用于一些数据增广操作。# 添加的边框像素将是边界元素的镜面反射 类似于gfedcb|abcdefgh|gfedcba# print('大小是: ',image.shape)  #(202,202)for i in range(1,image.shape[0]):for j in range(1,image.shape[1]):image[i,j] = RobertsOperator(image[i-1:i+2,j-1:j+2]) # i-1 , i , i+1return image[ 1:image.shape[0], 1:image.shape[1] ]def RobertsOperator(roi):operator_first = np.array([[-1,0],[0,1]])operator_second = np.array([[0,-1],[1,0]])x = roi[1:,1:]*operator_firsty = roi[1:,1:]*operator_secondreturn np.abs(np.sum(x))+np.abs(np.sum(y))
#np.sum() sum(a, axis=None, dtype=None, out=None, keepdims=np._NoValue)
#1.None,2.整数, 3.整数元组。(在默认/缺省的情况下,axis取None)
#如果axis取None,即将数组/矩阵中的元素全部加起来,得到一个和。
'''
a = np.linspace(1,20,20).reshape(4,5)
print(a)输出:
[[ 1.  2.  3.  4.  5.][ 6.  7.  8.  9. 10.][11. 12. 13. 14. 15.][16. 17. 18. 19. 20.]]如果axis默认/缺失np.sum(a)
即将数组/矩阵中的元素全部加起来,得到一个和:210如果axis为整数,axis的取值不可大于数组/矩阵的维度,且axis的不同取值会产生不同的结果。np.sum(a,axis = 0)
axis为0是压缩行,即将每一列的元素相加,将矩阵压缩为一行,输出:array([34., 38., 42., 46., 50.])np.sum(a,axis = 1)
axis为1是压缩列,即将每一行的元素相加,将矩阵压缩为一列,输出:array([15., 40., 65., 90.])
https://zhuanlan.zhihu.com/p/85790648'''saber = cv2.imread('construction.jpg')
gray_saber = cv2.cvtColor(saber,cv2.COLOR_BGR2GRAY)#转成灰度图
gray_saber = cv2.resize(gray_saber,(200,200))#调整大小Robert_saber = RobertsAlogrithm(gray_saber)plt.imshow(Robert_saber,cmap='binary')
plt.axis('off')
plt.show()

prewitt算子

  Prewitt算子是一种一阶微分算子的边缘检测,利用像素点上下、左右邻点的灰度差,在边缘处达到极值检测边缘,去掉部分伪边缘,对噪声具有平滑作用 。其原理是在图像空间利用两个方向模板与图像进行邻域卷积来完成的,这两个方向模板一个检测水平边缘,一个检测垂直边缘。 

prewitt算子是加权平均算子,对噪声有抑制作用,但是像素平均相当于对图像进行的同滤波,所以prewitt算子对边缘的定位不如robert算子。

cv2.filter2D实现

import cv2
import numpy as np
import matplotlib.pyplot as pltimg = cv2.imread('lena.jpg')
lenna_img = cv2.cvtColor(img,cv2.COLOR_BGR2RGB)grayImage = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)kernelx = np.array([[1,1,1],[0,0,0],[-1,-1,-1]],dtype=int)
kernely = np.array([[-1,0,1],[-1,0,1],[-1,0,1]],dtype=int)
x = cv2.filter2D(grayImage,cv2.CV_16S,kernelx)
y = cv2.filter2D(grayImage,cv2.CV_16S,kernely)absX = cv2.convertScaleAbs(x)
absY = cv2.convertScaleAbs(y)
Prewitt = cv2.addWeighted(absX,0.5,absY,0.5,0)plt.rcParams['font.sans-serif'] = ['SimHei']titles = [u'原始图呀',u'Prewitt算子']
images = [lenna_img,Prewitt]
for i in range(2):plt.subplot(1,2,i+1)plt.imshow(images[i],'gray')plt.title(titles[i])plt.xticks([])plt.yticks([])
plt.show()

prewitt算子

矩阵相乘实现

import cv2
from pylab import *
import numpy as npsaber = cv2.imread('construction.jpg')
gray_saber = cv2.cvtColor(saber,cv2.COLOR_BGR2GRAY)
gray_saber = cv2.resize(gray_saber,(200,200))def PreWittOperator(roi,operator_type):if operator_type =='horizontal':prewitt_operator = np.array([[-1,-1,-1],[0,0,0],[1,1,1]])elif operator_type == 'vertical':prewitt_operator = np.array([[-1,0,1],[-1,0,1],[-1,0,1]])else:raise('type Error')result = np.abs(np.sum(roi * prewitt_operator))return resultdef PrewittAlogrithm(image,operator_type):new_image = np.zeros(image.shape)image = cv2.copyMakeBorder(image,1,1,1,1,cv2.BORDER_DEFAULT)for i in range(1,image.shape[0]-1 ):for j in range(1,image.shape[1]-1):new_image[i-1,j-1] = PreWittOperator(image[i-1:i+2,j-1:j+2],operator_type) #9宫格 处理完的赋值到new_image的左上角new_image = new_image*(255/np.max(image))  #这个不明白啥意思return new_image.astype(np.uint8) #astype转换数据类型plt.subplot(121)#一行两列,第一张图
plt.title("horizontal")
plt.imshow(PrewittAlogrithm(gray_saber,'horizontal'),cmap='binary')
plt.axis('off')
plt.subplot(122)#一行两列,第二张图
plt.title('vertical')
plt.imshow(PrewittAlogrithm(gray_saber,'vertical'),cmap='binary')
plt.axis('off')
plt.show()

prewitt

加入噪声,以后补一下

sobel

简单实现(效果拉跨)

Sobel 算子根据像素点上下,左右邻点灰度加权差,在边缘处达到极值这一现象检测边缘,对噪声具有平滑作用,提供较为精确的边缘方向信息。因为Sobel算子结合了高斯平滑和微分求导(分化),因此结果会具有更多的抗噪性,当对精度要求不是很高时,Sobel 算子是一种较为常用的边缘 检测方法。

由于该算子中引入了类似局部平均的运算,因此对噪声具有平滑作用,能很好的消除噪声的影响。

Sobel算子是滤波算子的形式来提取边缘,X,Y方向各用一个模板,两个模板组合起来构成一个梯度算子。X方向模板对垂直边缘影响最大,Y方向模板对水平边缘影响最大。

缺点是Sobel算子并没有将图像的主题与背景严格地区分开来,换言之就是Sobel算子并没有基于图像灰度进行处理,由于Sobel算子并没有严格地模拟人的视觉生理特征,所以提取的图像轮廓有时并不能令人满意。 

img = cv2.imread("lena.jpg",0)a = cv2.Sobel(img,cv2.CV_16S,1,1)
absa = cv2.convertScaleAbs(a)cv2.imshow("absa",absa)
cv2.waitKey()

水平竖直分别求完再求和(效果较好)

import  cv2
import numpy as npimg = cv2.imread("lena.jpg",0)x = cv2.Sobel(img,cv2.CV_16S,1,0)
y = cv2.Sobel(img,cv2.CV_16S,0,1)absX = cv2.convertScaleAbs(x)
absY = cv2.convertScaleAbs(y)dst = cv2.addWeighted(absX,0.5,absY,0.5,0)cv2.imshow("absX",absX)
cv2.imshow("absY",absY)cv2.imshow("Result",dst)
cv2.waitKey()

在Sobel函数的第二个参数这里使用了cv2.CV_16S。因为OpenCV文档中对Sobel算子的介绍中有这么一句:“in the case of 8-bit input images it will result in truncated derivatives”。即Sobel函数求完导数后会有负值,还有会大于255的值。而原图像是uint8,即8位无符号数,所以Sobel建立的图像位数不够,会有截断。因此要使用16位有符号的数据类型,即cv2.CV_16S。

  在经过处理后,别忘了用convertScaleAbs()函数将其转回原来的uint8形式。否则将无法显示图像,而只是一副灰色的窗口。

 

 

 absx那个 在竖直方向比较明显,看鼻子就看出来了

absy在水平方向识别的更好,看眉毛眼睛嘴唇

 两者经过 addweight 之后效果更好。

Laplacian 算子

import cv2
import numpy as np
import matplotlib.pyplot as pltimg = cv2.imread('lena.jpg')
lenna_img  = cv2.cvtColor(img , cv2.COLOR_BGR2RGB)
gray_img = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)dst = cv2.Laplacian(gray_img,cv2.CV_16S,ksize=3)
Laplacian = cv2.convertScaleAbs(dst)plt.rcParams['font.sans-serif'] = ['SimHei']titles = [u'原图',u'Laplacian算子']
images = [lenna_img,Laplacian]
for i in range(2):plt.subplot(1,2,i+1)plt.imshow(images[i],'gray')plt.title(titles[i])plt.xticks([]),plt.yticks([])plt.show()

LOG (高斯拉普拉斯函数)

常见的LOG算子是5*5模板,如下图所示:

import cv2
import numpy as np
import matplotlib.pyplot as pltimg = cv2.imread('lena.jpg')
rgb_img = cv2.cvtColor(img,cv2.COLOR_BGR2RGB)
gray_img = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)gaussian = cv2.GaussianBlur(gray_img,(3,3),0)dst = cv2.Laplacian(gaussian,cv2.CV_16S,ksize=3)
LOG = cv2.convertScaleAbs(dst)plt.rcParams['font.sans-serif'] = ['SimHei']
titles = [u'原图',u'LOG']
images = [rgb_img,LOG]for i in range(2):plt.subplot(1,2,i+1)plt.imshow(images[i],'gray')plt.title(titles[i])plt.xticks([])plt.yticks([])
plt.show()


http://chatgpt.dhexx.cn/article/o8y9QVGK.shtml

相关文章

梯度与Roberts、Prewitt、Sobel、Lapacian算子

一、学习心得: 学习图像处理的过程中,刚开始遇到图像梯度和一些算子的概念,这两者到底是什么关系,又有什么不同,一直困扰着我。后来在看到图像分割这一模块后才恍然大悟,其实图像的梯度可以用一阶导数和二…

【计算机视觉】图像分割与特征提取——基于Roberts、Prewitt、Sobel算子的图像分割实验

个人简介: > 📦个人主页:赵四司机 > 🏆学习方向:JAVA后端开发 > ⏰往期文章:SpringBoot项目整合微信支付 > 🔔博主推荐网站:牛客网 刷题|面试|找工作神器 > &#…

边缘检测——Prewitt算子

垂直水平方向边缘 垂直水平方向的Prewitt算子是可分离的卷积核。 45、135方向边缘 算子不可分割。 缺点 没有充分利用边缘的梯度方向最后输出的边缘二值图,只是简单地利用阈值进行处理。如果阈值过大,则会损失很多边缘信息;如果阈值过…

数字图像处理(19): 边缘检测算子(Roberts算子、Prewitt算子、Sobel算子 和 Laplacian算子)

目录 1 边缘检测的基本原理 2 边缘检测算子分类 3 梯度 3.1 图像梯度 3.2 梯度算子 4 Roberts 算子 4.1 基本原理 4.2 代码示例 5 Prewitt 算子 5.1 基本原理 5.2 代码示例 6 Sobel 算子 6.1 基本原理 6.2 代码示例 7 Laplacian 算子 7.1 基本原理 7.2 代码示…

python数字图像处理——边缘检测算子(Laplacian算子、Roberts算子、Prewitt算子和Sobel算子)

1.Laplacian算子 拉普拉斯(Laplacian)算子是n维欧几里德空间中的一个二阶微分算子,常用于图像增强领域和边缘提取。它通过灰度差分计算邻域内的像素,基本流程是:判断图像中心像素灰度值与它周围其他像素的灰度值&…

Prewitt算子边缘检测原理及实现

写在前面 Prewitt算子同样也是一种一阶微分算子,利用像素点上下左右邻点灰度差,在边缘处达到极值检测边缘,对噪声具有平滑的作用。 原理 其原理是在图像空间利用两个方向模板与图像进行邻域卷积来完成的,这两个方向模板一个检测…

Prewitt和Sobel算子

在3*3模板中: 我如下定义水平、垂直和两对角线方向的梯度: 该定义下的算子称之为Prewitt算子: Sobel算子是在Prewitt算子的基础上改进的,在中心系数上使用一个权值2,相比较Prewitt算子,Sobel模板能够较好…

Prewitt边缘检测算子

Prewitt算子也是一种一阶微分算子,用于边缘检测。与Robert使用22的模板不同,Prewitt算子使用的是33的模板,利用像素点上下、左右邻点的灰度差来检测边缘,故其边缘检测结果在水平方向和垂直方向均比Robert算子更加明显。 其数学表…

图像边缘检测之Prewitt算子

Prewitt 算子 1. 原理 Prewitt算子是一种图像边缘检测的微分算子,其原理是利用特定区域内像素灰度值产生的差分实现边缘检测。由于Prewitt算子采用 3x3 模板对区域内的像素值进行计算,而Robert算子的模板为 2x2,故Prewitt算子的边缘检测结果…

华为--配置本地环回接口地址

该实验紧接上一节实验 网络拓扑图如下 AR1环回接口配置 AR2环回接口配置 AR3环回接口配置 配置AR1回环接口路由 配置AR2回环接口路由 配置AR3回环接口路由 在AR1上测试回环接口的连通性 在AR2上测试回环接口的连通性 在AR3上测试回环接口的连通性 测试成功 转载于:https://my.o…

【LINUX】ifconfig只有本地环回地址问题的解决方法

问题描述: ifconfig只有lo,没有看到ens33 ifconfig -a看到了ens33,但是没有地址 解决方法: (1)stop network-manager sudo service network-manager stop (2)删除旧有的网络配置…

怎么判断一个ipv4地址是 私有地址,环回地址,实验地址,TEST-NET地址,本地链路地址?

问题的提出: 理论讲解(黄色的为上题的答案): IP地址分为五类: A类保留给政府机构,B类分配给中等规模的公司,C类分配给任何需要的人,D类用于组播,E类用于实验,各类可容纳…

回环地址 127.0.0.1

控制台输入ping 127.0.0.1。 $ ping 127.0.0.1 PING 127.0.0.1 (127.0.0.1): 56 data bytes 64 bytes from 127.0.0.1: icmp_seq0 ttl64 time0.080 ms 64 bytes from 127.0.0.1: icmp_seq1 ttl64 time0.093 ms 64 bytes from 127.0.0.1: icmp_seq2 ttl64 time0.074 ms 64 byte…

环回接口 环回地址 环回路由

网络协议的数据链路层的一些重点我们来讲解一下。这此我们主要讲解的是环回接口的问题。环回接口(loopback):路由器上的一个逻辑、虚拟接口.路由器默认没有任何环回接口.此接口允许运行在同一台主机上的客户程序和服务器程序通过TCP/IP进行通信.一般系统…

什么是环回接口(Loopback Interface、环回地址)

2.7 环回接口 大多数的产品都支持环回接口(Loopback Interface),以允许运行在同一台主机上的客户程序和服务器程序通过TCP/IP进行通信。 A类网络号 127就是为环回接口预留的。根据惯例,大多数系统把 IP地址127.0.0.1分配给这个接…

特殊IP地址——环回地址

环回地址(Loopback Address)127.0.0.1---127.255.255.254 是一种特殊的 IP 地址,它允许计算机的软件组件在本地主机上进行网络通信,也称作本地回环地址。 在计算机网络中,环回地址是一个虚拟地址,它不属于任…

“谁告诉你环回地址就是127.0.0.1?” “老师就是这么说的。”

「作者主页」:士别三日wyx 「作者简介」:CSDN top100、阿里云博客专家、华为云享专家、网络安全领域优质创作者 「专栏简介」:此文章已录入专栏《计算机网络零基础快速入门》 环回地址是本地的「虚拟接口」,默认不会宕掉。 我们经…

带头结点单链表、不带头结点单链表(头指针单链表)

1、头结点和头指针的区别 1.1区别: 头指针表明了链表的结点,可以唯一确定一个单链表。 头指针指向链表的第一个结点,其记录第一个存储数据的结点的地址。 头结点是点链表的第一个结点,若单链表有头结点,则头指针指向头…

不带头结点的单链表------C语言实现

1 /****************************************************/ 3 File name:no_head_link.c4 Author:SimonKly Version:0.1 Date: 2017.5.205 Description:不带头节点的单链表6 Funcion List: 7 ***************************************…

单链表的头结点的作用

问题:在单链表中使用“头结点”,这个哑结点始终是链表的第一个元素,这个技巧的利与弊? 链表中第一个结点的存储位置叫做头指针,那么整个链表的存取就必须从头指针开始进行了。之后的每一个结点,其实就是上…