一、环境
本文使用环境为:
- Windows10
- Python 3.9.17
- opencv-python 4.8.0.74
二、canny原理
OpenCV中的Canny边缘检测算法是一种基于图像处理的计算机视觉技术,主要用于检测图像中的边缘。Canny边缘检测算法的原理是通过计算图像中像素点之间的梯度值来寻找边缘。这种方法可以有效地消除噪声,同时保留图像中的主要特征。本文将对Canny边缘检测算法的原理进行详细介绍。
2.1 基本原理
Canny边缘检测算法的基本原理是利用图像的梯度信息来寻找边缘。在图像中,边缘通常表现为颜色或亮度的突然变化。为了检测这些边缘,我们需要计算图像中每个像素点的梯度值。梯度是一个向量,表示图像在该点的方向和幅度的变化。梯度的大小和方向可以用来确定边缘的位置和方向。
Canny边缘检测算法主要包括以下几个步骤:
(1) 对图像进行平滑处理,以消除噪声。
(2) 计算图像中每个像素点的梯度值和方向。
(3) 对梯度值进行非极大值抑制,以得到细化的边缘。
2.2 平滑处理
在进行边缘检测之前,首先需要对图像进行平滑处理,以消除噪声。常用的平滑方法有高斯滤波、中值滤波等。高斯滤波是一种线性滤波方法,它可以有效地消除高斯噪声。中值滤波是一种非线性滤波方法,它可以有效地消除椒盐噪声。
在OpenCV中,可以使用cv2.GaussianBlur()
函数进行高斯滤波,使用cv2.medianBlur()
函数进行中值滤波。
2.3 计算梯度值和方向
为了计算图像中每个像素点的梯度值和方向,我们需要使用Sobel算子。Sobel算子是一种用于计算图像梯度的离散差分算子,它包括水平方向和垂直方向两个算子。通过分别计算水平和垂直方向的梯度值,我们可以得到每个像素点的梯度向量。梯度向量的方向表示边缘的方向,梯度向量的大小表示边缘的强度。
在OpenCV中,可以使用cv2.Sobel()
函数计算图像的梯度值和方向。
2.4 非极大值抑制
非极大值抑制是一种用于细化边缘的方法,它可以有效地消除假边缘。非极大值抑制的基本思想是:在当前像素点的邻域内,如果存在一个梯度值更大的像素点,那么将当前像素点的梯度值设置为0。这样,我们就可以得到一个细化的边缘图。
2.5 双阈值法进行边缘连接
双阈值法是一种用于连接边缘的方法,它可以有效地消除孤立的边缘点。双阈值法的基本思想是:根据梯度值的大小设置两个阈值,将梯度值大于高阈值的像素点标记为强边缘,将梯度值小于低阈值的像素点标记为弱边缘。然后,只保留强边缘,将弱边缘连接到相邻的强边缘上。这样,我们就可以得到一个连续的边缘图。
在OpenCV中,可以使用cv2.threshold()
函数进行双阈值处理。
三、完整代码
from __future__ import print_function
import cv2 as cv
import argparse
max_lowThreshold = 100
window_name = 'Edge Map'
title_trackbar = 'Min Threshold:'
ratio = 3
kernel_size = 3
def CannyThreshold(val):
low_threshold = val
# 将图像使用3x3高斯核模糊平滑下
img_blur = cv.blur(src_gray, (3,3))
# canny边缘检测
detected_edges = cv.Canny(img_blur, low_threshold, low_threshold*ratio, kernel_size)
# detected_edges是边缘,二值图的形式
mask = detected_edges != 0
# 使用边缘二值图和原图相乘,目的是取出彩色的边缘
dst = src * (mask[:,:,None].astype(src.dtype))
cv.imshow(window_name, dst)
parser = argparse.ArgumentParser(description='Code for Canny Edge Detector tutorial.')
parser.add_argument('--input', help='Path to input image.', default='data/fruits.jpg')
args = parser.parse_args()
# 读取图片
src = cv.imread(cv.samples.findFile(args.input))
if src is None:
print('Could not open or find the image: ', args.input)
exit(0)
# 彩色图转灰度图
src_gray = cv.cvtColor(src, cv.COLOR_BGR2GRAY)
# 创建窗口
cv.namedWindow(window_name)
cv.createTrackbar(title_trackbar, window_name , 0, max_lowThreshold, CannyThreshold)
CannyThreshold(0)
cv.waitKey()