什么是边缘?
- 图像的边缘时指图像局部区域亮度变化显著的部分,该区域的灰度剖面一般可以看做是一个阶跃,既从一个灰度值很小的缓冲区域内急剧变化到另一个灰度相差较大的灰度值
- 边缘有正负之分,就像导数有正值也有负值一样
边缘检测
-
步骤:
- 滤波:边缘检测的算法主要是基于图像强度的一阶和二阶导数,但导数常对噪声很敏感,因此必须采用滤波器来改善与噪声有关的边缘检测器的性能。
- 增强:增强边缘的基础就是确定图像各点领域强度发变化值。增强算法可以将图像灰度点邻域强度值有显著变化的点凸显出来。在具体编程实现时,可通过计算梯度幅值来确定
- 检测:经过增强的图像,往往邻域中有很多点的梯度值比较大,而在特定的应用中,这些点并不是我们要找的边缘点,所以应该采用某种方法来对这些点进行取舍
-
原理:
- 边缘检测的基础就是在边缘部分,像素出现阶跃(较大的变化),如果在此边缘部分求一阶导数,就会看到极值的出现
- 在一阶导数为极值的地方,二阶导数为0,基于这个原理,就可以进行边缘检测
-
图像锐化
- 图像锐化是补偿图像的轮廓,增强图像的边缘及灰度跳变的部分,使图像变的更清晰,分为空域处理和频域处理两类
- 图像锐化是为了突出图像上地物的边缘、轮廓,或某些线性目标要素的特征。
- 这种滤波方法提高了地物边缘与周围像元之间的反差,因此也被称为边缘增强
-
图像平滑
- 图像平滑是指用于突出图像的宽大区域、低频成分、主干部分或抑制图像噪声和干扰高频成分的图像处理方式,目的是使图像亮度平缓渐变,减小突变梯度、改善图像质量
- 常见的算法为sobel
常见边缘算子
Sobel算子
- sobel算子是典型的基于一阶导数的边缘检测算子,由于该算子中引入了类似局部平均的运算,因此对噪声具有平滑的作用,能很好的消除噪声的影响。
- 作用
- 边缘提取
- 此算子也常用于图像平滑
- 算子结构
- Sobel算子包含两组3x3的矩阵,分别为横向以及纵向模板,两个模板分别提取图像中的垂直和水平特征
- 实现
# 以OpenCV为例实现
import cv2
img = cv2.imread('jc.png') # 读取图像,此图像读入为三通道BGR,如果想要直接将图像直接读入为灰度图cv2.imread('timg.jpg',0)
img_to_rgb = cv2.cvtColor(img,cv2.COLOR_BGR2RGB) # OpenCV读入的图像为BGR,如果使用plt展示的话需要转成RGB
# cv2.imshow('src',img) # 查看原图
gay = cv2.cvtColor(img,cv2.COLOR_RGB2GRAY) # 将三通道彩色图转为灰度图,毕竟在使用中能用灰度图做提起就用灰度图,这样也是为了提高计算效率(灰度图数据量少呀!)
# cv2.imshow('gay',gay)
sobel_x = cv2.Sobel(gay,-1,0,1) # 求Y方向导数
sobel_y = cv2.Sobel(gay,-1,1,0) # 求X方向导数
sobel_x_y = cv2.addWeighted(sobel_x,0.5,sobel_y,0.5,0) # 参数:图像1,图像1占比权重,图像2,图像2占比权重,图1与图2作和后添加的数值,不要太大,不然图片一片白。总和等于255以上就是纯白色了
# 可以使用以下代码展示图片
# sobels_x = cv2.convertScaleAbs(sobel)
# sobels_y = cv2.convertScaleAbs(sobel2)
# cv2.imshow('sobels_x',sobels_x)
# cv2.imshow('sobels_y',sobels_y)
# cv2.waitKey(0)
# cv2.destroyAllWindows()
# 也可以使用 plt进行展示
from matplotlib import pyplot as plt
#显示图像
titles = [u'src',u'src_rgb',u'src_gay',u'sobels_x',u'sobels_y', u'sobels_x_y']
images = [img,img_to_rgb , gay , sobel_x,sobel_y,sobel_x_y]
for i in range(6):
plt.subplot(2,3,i+1),
if i == 0:
plt.imshow(images[i]),
else:
plt.imshow(images[i], 'gray'),
plt.title(titles[i])
plt.xticks([]),plt.yticks([])
plt.show()
- 执行结果
Laplacian算子
-
拉普拉斯算子为二阶微分算子,常作为图像边缘提取和图像锐化的一种常见算子
-
作用
- 图像锐化
-
函数的定义:
-
算子结构
-
实现
import cv2
from matplotlib import pyplot as plt
img = cv2.imread('jc.png') # 读取图像,此图像读入为三通道BGR,如果想要直接将图像直接读入为灰度图cv2.imread('timg.jpg',0)
img_to_rgb = cv2.cvtColor(img,cv2.COLOR_BGR2RGB) # OpenCV读入的图像为BGR,如果使用plt展示的话需要转成RGB
# cv2.imshow('src',img) # 查看原图
gay = cv2.cvtColor(img,cv2.COLOR_RGB2GRAY) # 将三通道彩色图转为灰度图,毕竟在使用中能用灰度图做提
laplacian = cv2.Laplacian(gay,16,ksize=3) # 参数:原图像,图像深度(L=2^k^ L为像素的灰度级数,k为图像深度),核大小(必须是正数和奇数)
titles = [u'src_rgb',u'src_gay',u'laplacian']
images = [img_to_rgb,gay ,laplacian]
for i in range(3):
plt.subplot(1,3,i+1),
plt.imshow(images[i], 'gray'),
plt.title(titles[i])
plt.xticks([]),plt.yticks([])
plt.show()
- 执行结果
canny算子
- 基本介绍
- canny算子是一个组合算子,是基于sobel算子的一种改进的算法方式,是目前最优秀的边缘检测算法
- 其目标为找到一个最优的边缘,最优边缘的定义
- 好的检测:算法能够尽可能的标出图像中的实际边缘
- 好的定位:标识出的边缘尽可能与实际图像中的边缘接近
- 最小响应:图像中的边缘只能标记一次
- 作用
- 边缘检测
- 实现流程
-
对原始图像进行灰度处理(这是因为在做边缘提取的时候彩色维度不会对结果产生影响,从而舍弃彩色通道,提高计算速度)
- 方式1:Gray = (R,G,B)/3
- 方式2:Gray = 0.299R+0.587G+0.114B(这种参数考虑到了人眼的生理特点)
-
对图像进行高斯滤波(这一步的目的就是去除噪声)
-
对图像进行垂直、水平和对角边缘检测(sobel、prewitt算子)
-
对梯度幅值进行最大值抑制(NMS)
- 什么是梯度幅值?
-
用双阈值算法检测和连接边缘
- 阈值的策略:大于高阈值的为强边缘、低于低阈值的不是边缘(会被抑制),介于中间的为弱边缘
-
- 实现代码:
import cv2
from matplotlib import pyplot as plt
img = cv2.imread('jc.png') # 读取图像,此图像读入为三通道BGR,如果想要直接将图像直接读入为灰度图cv2.imread('timg.jpg',0)
img_to_rgb = cv2.cvtColor(img,cv2.COLOR_BGR2RGB) # OpenCV读入的图像为BGR,如果使用plt展示的话需要转成RGB
# cv2.imshow('src',img) # 查看原图
gay = cv2.cvtColor(img,cv2.COLOR_RGB2GRAY) # 将三通道彩色图转为灰度图,毕竟在使用中能用灰度图做提
gay_g = cv2.GaussianBlur(gay,(3,3),0) # 高斯模糊
canny = cv2.Canny(gay_g,50,100,(3,3),L2gradient=True) # canny算子 参数一:灰度图像 参数二:低阈值 参数三:高阈值 参数四:使用的范数
titles = [u'src_rgb',u'src_gay',u'gay_g',u'canny']
images = [img_to_rgb,gay,gay_g ,canny]
for i in range(4):
plt.subplot(1,4,i+1),
plt.imshow(images[i], 'gray'),
plt.title(titles[i])
plt.xticks([]),plt.yticks([])
plt.show()
- 执行结果