课题总结报告OpenCV 抠图项目实战边缘检测
Posted 小白YouCans
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了课题总结报告OpenCV 抠图项目实战边缘检测相关的知识,希望对你有一定的参考价值。
Python 小白的课题报告—OpenCV 抠图项目实战(7)
本系列是 Python 小白的课题作业《基于OpenCV 的图像分割和抠图》。
需要说明的是,本系列并不能算是 OpenCV 的抠图项目教程,只是以此为主题的课题报告。其中包括了一个较为完整的 PyQt 项目。
从学生课题作业报告的角度,还是可以晒出来给大家参考的。
欢迎关注『Python 小白的项目实战 @ youcans』 原创作品
Python 小白的课题报告—OpenCV 抠图项目实战(1)
Python 小白的课题报告—OpenCV 抠图项目实战(2)
Python 小白的课题报告—OpenCV 抠图项目实战(3)
Python 小白的课题报告—OpenCV 抠图项目实战(4)
Python 小白的课题报告—OpenCV 抠图项目实战(5)
Python 小白的课题报告—OpenCV 抠图项目实战(6)
Python 小白的课题报告—OpenCV 抠图项目实战(7)边缘检测
第四章 图像分割
4.1 边缘检测
边缘是指图像中两个不同区域的边界线上连续的像素点的集合,是图像局部特征不连续性的反映,体现了灰度、颜色、纹理等图像特性的突变。
边缘检测是图像处理和计算机视觉中的基本问题,边缘检测的目的是标识数字图像中亮度变化明显的点。
边缘的灰度值呈现出阶跃型或屋顶型变化。阶跃型边缘两边像素点的灰度值存在着明显的差异,而屋顶型边缘则位于灰度值上升或下降的转折处。
梯度指出了像素值的最大变化率的方向,使用微分算子可以进行边缘检测:
- 恒定灰度区域,一阶导数为零,二阶导数为零;
- 灰度台阶或斜坡起点区域,一阶导数非零,,二阶导数非零;
- 灰度斜坡区域,一阶导数非零,二阶导数为零。
一阶导数、二阶导数的有限差分公式为:
∂ f / ∂ x = f ( x + 1 ) − f ( x ) ( ∂ 2 f ) / ( ∂ x 2 ) = f ( x + 1 ) − 2 f ( x ) + f ( x − 1 ) ∂f/∂x=f(x+1)-f(x)\\\\ (∂^2 f)/(∂x^2 )=f(x+1)-2f(x)+f(x-1) ∂f/∂x=f(x+1)−f(x)(∂2f)/(∂x2)=f(x+1)−2f(x)+f(x−1)
图像梯度提取方法简单直接,能够有效的描述图像的原始状态,因此发展出多种图像梯度算子,常用的有Laplacian、Soble和Canny算子。
1. 拉普拉斯算子(Laplacian)
最简单的各向同性导数算子(卷积核)是拉普拉斯算子(Laplacian)。
Laplace 是导数算子,会突出图像中的急剧灰度变化,抑制灰度缓慢变化区域,往往会产生暗色背景下的灰色边缘和不连续图像。将拉普拉斯图像与原图叠加,可以得到保留锐化效果的图像。
拉普拉斯卷积核很容易通过卷积操作 cv. filter_2d 实现,OpenCV 也提供了拉普拉斯算子 cv.Laplacian 来实现。
函数说明:
cv.Laplacian(src, ddepth[, dst[, ksize[, scale[, delta[, borderType]]]]]) → dst
参数说明:
- src:输入图像,可以是灰度图像,也可以是多通道的彩色图像
- ddepth:输出图片的数据深度:
- dst:输出图像,大小和类型与 src 相同
- ksize:计算二阶导数滤波器的孔径大小,必须为正奇数,可选项
- scale:缩放比例因子,可选项,默认值为 1
- delta:输出图像的偏移量,可选项,默认值为 0
- borderType:边界扩充的类型,注意不支持对侧填充(BORDER_WRAP)
使用Laplacian算子进行边缘检测的基本程序如下:
# MattingLaplacian.py
# edge detection by Laplacian
# Copyright 2021 youcans, XUPT
# Crated:2021-12-10
import cv2 as cv
from matplotlib.figure import Figure
img = cv2.imread("../images/Fig0338a.tif", flags=0) # NASA 月球影像图
# 使用 cv2.Laplacian 实现 Laplace 卷积算子
imgLaplace2 = cv2.Laplacian(img, -1, ksize=3)
imgRecovery = cv2.add(img, imgLaplace2) # 恢复原图像
# 二值化边缘图再卷积
ret, binary = cv2.threshold(img, 0, 255, cv2.THRESH_BINARY | cv2.THRESH_TRIANGLE)
imgLaplace3 = cv2.Laplacian(binary, cv2.CV_64F)
imgLaplace3 = cv2.convertScaleAbs(imgLaplace3)
plt.figure(figsize=(9, 6))
plt.subplot(131), plt.axis('off'), plt.title("Original")
plt.imshow(img, cmap='gray', vmin=0, vmax=255)
plt.subplot(132), plt.axis('off'), plt.title("cv.Laplacian")
plt.imshow(imgLaplace2, cmap='gray', vmin=0, vmax=255)
plt.subplot(133), plt.axis('off'), plt.title("thresh-Laplacian")
plt.imshow(imgLaplace3, cmap='gray', vmin=0, vmax=255)
plt.tight_layout()
plt.show()
使用Laplacian算子进行边缘检测的结果如下图所示。
图4.1 Laplacian算子进行边缘检测
2. 索贝尔梯度算子(Sobel)
Sobel 算子是一种离散的微分算子,是高斯平滑和微分求导的联合运算,抗噪声能力强。
Sobel 梯度算子利用局部差分寻找边缘,计算得到梯度的近似值。先计算水平、垂直方向的梯度,再求总梯度。编程实现时,可以用绝对值近似平方根。
OpenCV 也提供了函数 cv.Sobel() 实现 Sobel 梯度算子。
函数说明:
cv.Sobel(src, ddepth, dx, dy[, dst[, ksize[, scale[, delta[, borderType]]]]]) → dst
参数说明:
- src:输入图像,灰度图像,不适用彩色图像
- dst:输出图像,大小和类型与 src 相同
- ddepth:输出图片的数据深度,由输入图像的深度进行选择
- dx:x 轴方向导数的阶数,1 或 2
- dy:y 轴方向导数的阶数,1 或 2
- ksize:Sobel算子卷积核的大小
- scale:缩放比例因子,可选项,默认值为 1
- delta:输出图像的偏移量,可选项,默认值为 0
使用Sobel算子进行边缘检测的基本程序如下:
# MattingSobel.py
# edge detection by Sobel
# Copyright 2021 youcans, XUPT
# Crated:2021-12-10
import cv2 as cv
from matplotlib.figure import Figure
img = cv2.imread("../images/imgGaia.tif", flags=0)
# 使用函数 filter2D 实现 Sobel 算子
kernSobelX = np.array([[-1, 0, 1], [-2, 0, 2], [-1, 0, 1]]) # SobelX kernel
kernSobelY = np.array([[-1, -2, -1], [0, 0, 0], [1, 2, 1]]) # SobelY kernel
imgSobelX = cv2.filter2D(img, -1, kernSobelX, borderType=cv2.BORDER_REFLECT)
imgSobelY = cv2.filter2D(img, -1, kernSobelY, borderType=cv2.BORDER_REFLECT)
# 使用 cv2.Sobel 实现 Sobel 算子
SobelX = cv2.Sobel(img, cv2.CV_16S, 1, 0) # 计算 x 轴方向
SobelY = cv2.Sobel(img, cv2.CV_16S, 0, 1) # 计算 y 轴方向
absX = cv2.convertScaleAbs(SobelX) # 转回 uint8
absY = cv2.convertScaleAbs(SobelY) # 转回 uint8
SobelXY = cv2.addWeighted(absX, 0.5, absY, 0.5, 0) # 用绝对值近似平方根
plt.figure(figsize=(10, 6))
plt.subplot(141), plt.axis('off'), plt.title("Original")
plt.imshow(img, cmap='gray', vmin=0, vmax=255)
plt.subplot(142), plt.axis('off'), plt.title("SobelX")
plt.imshow(SobelX, cmap='gray', vmin=0, vmax=255)
plt.subplot(143), plt.axis('off'), plt.title("SobelY")
plt.imshow(SobelY, cmap='gray', vmin=0, vmax=255)
plt.subplot(144), plt.axis('off'), plt.title("SobelXY")
plt.imshow(SobelXY, cmap='gray')
plt.tight_layout()
plt.show()
使用Sobel算子进行边缘检测的结果如下图所示。
图4.2 Sobel算子进行边缘检测
3. Canny 边缘检测
Canny边缘检测是由Jhon F.Canny提出的算法,具有低错误率、定位良好、最小响应的特点。
Canny算子在过滤噪声、计算梯度的同时实现非最大值抑制,不容易受噪声的干扰。采用双阈值法可以分别检测到强边缘和弱边缘,并且仅当弱边缘与强边缘相连时,才将弱边缘包含在输出结果中,这就保障了检测到真正的弱边缘。
Canny算法的工作原理为:
(1)使用高斯滤波器对图像进行平滑去噪;
(2)计算输入图像梯度;
(3)在边缘上使用非极大值抑制(NMS)进行过滤;
(4)在检测到的边缘上使用双阈值法去除假阳性;
(5)分析所有的边缘及其连接,以保留真正的边缘并消除不明显的边缘;
OpenCV 也提供了函数 cv.Sobel() 实现 Sobel 梯度算子。
函数说明:
cv.Canny(image, threshold1, threshold2[, edges[, apertureSize[, L2gradient]]]) → edges
参数说明:
- image:输入图像,灰度图像,不适用彩色图像
- edges:输出图像,单通道 8bit图像,大小与images相同
- threshold1:滞后过程的较小阈值,用于边缘连接
- threshold2:滞后过程的较大阈值,用于查找明显的边缘
- apertureSize:Sobel算子的卷积核大小
- L2gradient:标志,使用 L1范数或 L2范数正则化
使用 Canny()进行边缘检测的基本程序如下:
# MattingCanny.py
# edge detection by Cann
# Copyright 2021 youcans, XUPTy
# Crated:2021-12-10
import cv2 as cv
from matplotlib.figure import Figure
imgOri = cv2.imread("../images/imgGaia.tif", flags=0)
# canny(): 边缘检测
imgBlur = cv2.GaussianBlur(imgOri, (3, 3), 0)
imgCanny = cv2.Canny(imgBlur, 50, 150)
# 形态学:边缘检测
_, imgThr = cv2.threshold(imgOri, 200, 255, cv2.THRESH_BINARY) # 固定阈值二值化
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (5, 5)) # 定义矩形结构元素
gradient = cv2.morphologyEx(Thr_img, cv2.MORPH_GRADIENT, kernel) # 梯度
plt.figure(figsize=(9, 6))
plt.subplot(221), plt.axis('off'), plt.title("Original")
plt.imshow(imgOri, cmap='gray', vmin=0, vmax=255)
plt.subplot(222), plt.axis('off'), plt.title("GaussianBlur")
plt.imshow(imgBlur, cmap='gray', vmin=0, vmax=255)
plt.subplot(223), plt.axis('off'), plt.title("Canny detection")
plt.imshow(imgCanny, cmap='gray', vmin=0, vmax=255)
plt.subplot(224), plt.axis('off'), plt.title("Gradient detection")
plt.imshow(gradient, cmap='gray')
plt.tight_layout()
plt.show()
使用Canny算子进行边缘检测的结果如下图所示。
图4.3 Canny 算子进行边缘检测
【本节完】
版权声明:
欢迎关注『Python 小白的项目实战 @ youcans』 原创作品
原创作品,转载必须标注原文链接:https://blog.csdn.net/youcans/article/details/122296231
Copyright 2022 youcans, XUPT
Crated:2022-01-05
欢迎关注『Python 小白的项目实战 @ youcans』 原创作品
Python 小白的课题报告—OpenCV 抠图项目实战(1)
Python 小白的课题报告—OpenCV 抠图项目实战(2)
Python 小白的课题报告—OpenCV 抠图项目实战(3)
Python 小白的课题报告—OpenCV 抠图项目实战(4)
Python 小白的课题报告—OpenCV 抠图项目实战(5)
Python 小白的课题报告—OpenCV 抠图项目实战(6)
Python 小白的课题报告—OpenCV 抠图项目实战(7)边缘检测
以上是关于课题总结报告OpenCV 抠图项目实战边缘检测的主要内容,如果未能解决你的问题,请参考以下文章