Canny算法原理和应用
创始人
2024-05-31 08:05:39
0

Canny算法的原理

  • 使用高斯滤波器滤波

  • 使用 Sobel 滤波器滤波获得在 x 和 y 方向上的输出,在此基础上求出梯度的强度和梯度的角度

edge为边缘强度,tan为梯度方向

上图表示的是中心点的梯度向量、方位角以及边缘方向(任一点的边缘与梯度向量正交)
  • 对梯度角度进行量化处理

划重点:是沿着梯度方向对幅值进行非极大值抑制,而非边缘方向,这里初学者容易弄混。

例如:3*3区域内,边缘可以划分为垂直、水平、45°、135°4个方向,同样,梯度反向也为四个方向(与边缘方向正交)。因此为了进行非极大值,将所有可能的方向量化为4个方向,如下图:

量化后的情况可以总结为:

  • 根据梯度角度对边缘强度进行非极大值抑制(Non-maximum suppression),使图像边缘变得更细

非极大值抑制算法:0°时取(x,y)、(x+1,y)、(x-1,y) 中的最大值,其它角度类似

  • 使用滞后阈值对图像进行二值化处理,优化图像显示效果

  1. 选取系数TH和TL,比率为2:1或3:1。(一般取TH=0.3或0.2,TL=0.1);

b. 将小于低阈值的点抛弃,赋0;将大于高阈值的点立即标记(这些点为确定边缘点),赋1或255;

c. 将小于高阈值,大于低阈值的点使用8连通区域确定(即:只有与TH像素连接时才会被接受,成为边缘点,赋 1或255)

python算法实现

import cv2
import numpy as np
import matplotlib.pyplot as pltdef Canny(img):# Gray scaledef BGR2GRAY(img):b = img[:, :, 0].copy()g = img[:, :, 1].copy()r = img[:, :, 2].copy()# Gray scaleout = 0.2126 * r + 0.7152 * g + 0.0722 * bout = out.astype(np.uint8)return out# Gaussian filter for grayscaledef gaussian_filter(img, K_size=3, sigma=1.4):if len(img.shape) == 3:H, W, C = img.shapegray = Falseelse:img = np.expand_dims(img, axis=-1)H, W, C = img.shapegray = True## Zero paddingpad = K_size // 2out = np.zeros([H + pad * 2, W + pad * 2, C], dtype=np.float)out[pad : pad + H, pad : pad + W] = img.copy().astype(np.float)## prepare KernelK = np.zeros((K_size, K_size), dtype=np.float)for x in range(-pad, -pad + K_size):for y in range(-pad, -pad + K_size):K[y + pad, x + pad] = np.exp( - (x ** 2 + y ** 2) / (2 * sigma * sigma))#K /= (sigma * np.sqrt(2 * np.pi))K /= (2 * np.pi * sigma * sigma)K /= K.sum()tmp = out.copy()# filteringfor y in range(H):for x in range(W):for c in range(C):out[pad + y, pad + x, c] = np.sum(K * tmp[y : y + K_size, x : x + K_size, c])out = np.clip(out, 0, 255)out = out[pad : pad + H, pad : pad + W]out = out.astype(np.uint8)if gray:out = out[..., 0]return out# sobel filterdef sobel_filter(img, K_size=3):if len(img.shape) == 3:H, W, C = img.shapeelse:H, W = img.shape# Zero paddingpad = K_size // 2out = np.zeros((H + pad * 2, W + pad * 2), dtype=np.float)out[pad : pad + H, pad : pad + W] = img.copy().astype(np.float)tmp = out.copy()out_v = out.copy()out_h = out.copy()## Sobel verticalKv = [[1., 2., 1.],[0., 0., 0.], [-1., -2., -1.]]## Sobel horizontalKh = [[1., 0., -1.],[2., 0., -2.],[1., 0., -1.]]# filteringfor y in range(H):for x in range(W):out_v[pad + y, pad + x] = np.sum(Kv * (tmp[y : y + K_size, x : x + K_size]))out_h[pad + y, pad + x] = np.sum(Kh * (tmp[y : y + K_size, x : x + K_size]))out_v = np.clip(out_v, 0, 255)out_h = np.clip(out_h, 0, 255)out_v = out_v[pad : pad + H, pad : pad + W]out_v = out_v.astype(np.uint8)out_h = out_h[pad : pad + H, pad : pad + W]out_h = out_h.astype(np.uint8)return out_v, out_h# get edge strength and edge angledef get_edge_angle(fx, fy):# get edge strengthedge = np.sqrt(np.power(fx.astype(np.float32), 2) + np.power(fy.astype(np.float32), 2))edge = np.clip(edge, 0, 255)# make sure the denominator is not 0fx = np.maximum(fx, 1e-10)#fx[np.abs(fx) <= 1e-5] = 1e-5# get edge angleangle = np.arctan(fy / fx)return edge, angle# 将角度量化为0°、45°、90°、135°def angle_quantization(angle):angle = angle / np.pi * 180angle[angle < -22.5] = 180 + angle[angle < -22.5]_angle = np.zeros_like(angle, dtype=np.uint8)_angle[np.where((angle <= 22.5) | (angle > 157.5))] = 0_angle[np.where((angle > 22.5) & (angle <= 67.5))] = 45_angle[np.where((angle > 67.5) & (angle <= 112.5))] = 90_angle[np.where((angle > 112.5) & (angle <= 157.5))] = 135return _angledef non_maximum_suppression(angle, edge):H, W = angle.shape_edge = edge.copy()for y in range(H):for x in range(W):if angle[y, x] == 0:dx1, dy1, dx2, dy2 = -1, 0, 1, 0elif angle[y, x] == 45:dx1, dy1, dx2, dy2 = -1, 1, 1, -1elif angle[y, x] == 90:dx1, dy1, dx2, dy2 = 0, -1, 0, 1elif angle[y, x] == 135:dx1, dy1, dx2, dy2 = -1, -1, 1, 1# 边界处理if x == 0:dx1 = max(dx1, 0)dx2 = max(dx2, 0)if x == W-1:dx1 = min(dx1, 0)dx2 = min(dx2, 0)if y == 0:dy1 = max(dy1, 0)dy2 = max(dy2, 0)if y == H-1:dy1 = min(dy1, 0)dy2 = min(dy2, 0)# 如果不是最大值,则将这个位置像素值置为0if max(max(edge[y, x], edge[y + dy1, x + dx1]), edge[y + dy2, x + dx2]) != edge[y, x]:_edge[y, x] = 0return _edge# 滞后阈值处理二值化图像# > HT 的设为255,< LT 的设置0,介于它们两个中间的值,使用8邻域判断法def hysterisis(edge, HT=100, LT=30):H, W = edge.shape# Histeresis thresholdedge[edge >= HT] = 255edge[edge <= LT] = 0_edge = np.zeros((H + 2, W + 2), dtype=np.float32)_edge[1 : H + 1, 1 : W + 1] = edge## 8 - Nearest neighbornn = np.array(((1., 1., 1.), (1., 0., 1.), (1., 1., 1.)), dtype=np.float32)for y in range(1, H+2):for x in range(1, W+2):if _edge[y, x] < LT or _edge[y, x] > HT:continueif np.max(_edge[y-1:y+2, x-1:x+2] * nn) >= HT:_edge[y, x] = 255else:_edge[y, x] = 0edge = _edge[1:H+1, 1:W+1]return edge# grayscalegray = BGR2GRAY(img)# gaussian filteringgaussian = gaussian_filter(gray, K_size=5, sigma=1.4)# sobel filteringfy, fx = sobel_filter(gaussian, K_size=3)# get edge strength, angleedge, angle = get_edge_angle(fx, fy)# angle quantizationangle = angle_quantization(angle)# non maximum suppressionedge = non_maximum_suppression(angle, edge)# hysterisis thresholdout = hysterisis(edge, 80, 20)return outif __name__ == '__main__':# Read imageimg = cv2.imread("../paojie.jpg").astype(np.float32)image = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY).astype(np.uint8)# Cannyedge = Canny(img)out = edge.astype(np.uint8)# Save resultcv2.imshow('src and canny', np.hstack((image, out)))cv2.waitKey(0)cv2.destroyAllWindows()

参考链接:

https://www.cnblogs.com/wojianxin/p/12533526.html

https://blog.csdn.net/weixin_40647819/article/details/91411424

相关内容

热门资讯

同学聚会祝酒词 同学聚会祝酒词高中同学聚会祝酒词(1):斗转星移,岁月如歌,转眼我们从古龙中学毕业已经9多年了。9年...
台词经典语录 台词经典语录15篇  无论是在学校还是在社会中,许多人对一些广为流传的语录都不陌生吧,语录具有短小简...
幼儿园元旦晚会园长的经典致辞 幼儿园元旦晚会园长的经典致辞(精选5篇)  在平时的学习、工作或生活中,大家或多或少都用到过致辞吧,...
婚礼男方家长致辞 婚礼男方家长致辞通用15篇  无论在学习、工作或是生活中,大家都不可避免地会接触到致辞吧,致辞具有“...
学校班级元旦晚会主持稿 学校班级元旦晚会主持稿  导语:在学校召开元旦晚会的时候,通常要用到主持词的。接下来小编整理了学校班...
新郎迎娶新娘主持词 新郎迎娶新娘是一生中最浪漫的事情之一,那么都有什么好的主持词呢?以下是PINCAI小编整理的关于主持...
公司员工大会主持稿 公司员工大会主持稿  在现在的社会生活中,需要使用主持稿的情况越来越多,主持稿一般是由主持人根据场景...
开业的致辞 开业的致辞15篇  在日常的学习、工作、生活中,大家都对致辞很是熟悉吧,致辞是指在举行会议或某种仪式...
毕业聚餐主持词 毕业聚餐主持词  主持词是主持人在节目进行过程中用于串联节目的串联词。在当今中国社会,主持人在活动中...
女娲传说之灵珠经典台词 女娲传说之灵珠经典台词15句  你们根本不懂爱,你们的爱太过自私,不择手段。——仙乐  你放心,我不...
青春演讲比赛主持词 青春演讲比赛主持词  主持:  男——李勇  女——张雨  女:我与祖国共奋进男:我为崛起献青春。 ...
年会赞助商致辞 年会赞助商致辞(精选5篇)  在日常的学习、工作、生活中,要用到致辞的情况还是蛮多的,致辞具有很强的...
培训会主持词 培训会主持词(精选10篇)  在日常中,大家总免不了要培训及会议吧,那么你知道主持词怎么写吗?下面是...
电影《三少爷的剑》经典台词 电影《三少爷的剑》经典台词精选  1. 冷风如刀,大地荒漠,苍天无情。  2. 这世上永远有两种人,...
《十六个夏天》的经典台词 《十六个夏天》的经典台词大全  1.就说我不是他的收藏品,乱说什么啊!  2.说话冲的人,心里都是软...
80岁生日宴会致辞 80岁生日宴会致辞(精选11篇)  在学习、工作或生活中,大家都不可避免地会接触到致辞吧,致辞具有有...
婚宴长辈证婚人致辞 婚宴长辈证婚人致辞  在平日的学习、工作和生活里,大家总少不了要接触或使用致辞吧,致辞受场合、事件的...
元旦舞会主持词 元旦舞会主持词(精选7篇)  主持词要尽量增加文化内涵、寓教于乐,不断提高观众的文化知识和素养。在人...
圣诞联欢会主持词 圣诞联欢会主持词  活动对象的不同,主持词的写作风格也会大不一样。时代不断在进步,主持成为很多活动不...
美好童年—庆“六一”大型活动... 美好童年—庆“六一”大型活动主持词  利用在中国拥有几千年文化的诗词能够有效提高主持词的感染力。随着...