【数字图像分析】基于Python实现 Canny Edge Detection(Canny 边缘检测算法)
Canny 边缘检测算法
Steps:
- 高斯滤波平滑
- 计算梯度大小和方向
- 非极大值抑制
- 双阈值检测和连接
代码结构:
Canny Edge Detection
| Gaussian_Smoothing
| | convolution.py
| | | convolution()
| | gaussion_smoothing.py
| | | dnorm()
| | | gaussian_kernel()
| | | gaussian_blur()
| Sobel_Filter
| | sobel.py
| | | sobel_edge_detection()
| Canny.py
| | non_max_suppression()
| | threshold()
| | hysteresis()
| | main()
代码解读:
1. 高斯滤波平滑
创建一个高斯核(kernel_size=5):

执行卷积和平均操作(以下均以 lenna 图为例)

2. 计算梯度大小和方向
水平方向和竖直方向


梯度图:

3. 非极大值抑制

4. 双阈值检测和连接

以下是代码:
import numpy as np
import cv2
import argparse
from Computer_Vision.Canny_Edge_Detection.sobel import sobel_edge_detection
from Computer_Vision.Canny_Edge_Detection.gaussian_smoothing import gaussian_blur
import matplotlib.pyplot as plt
def non_max_suppression(gradient_magnitude, gradient_direction, verbose):
image_row, image_col = gradient_magnitude.shape
output = np.zeros(gradient_magnitude.shape)
PI = 180
for row in range(1, image_row - 1):
for col in range(1, image_col - 1):
direction = gradient_direction[row, col]
if (0 <= direction < PI / 8) or (15 * PI / 8 <= direction <= 2 * PI):
before_pixel = gradient_magnitude[row, col - 1]
after_pixel = gradient_magnitude[row, col + 1]
elif (PI / 8 <= direction < 3 * PI / 8) or (9 * PI / 8 <= direction < 11 * PI / 8):
before_pixel = gradient_magnitude[row + 1, col - 1]
after_pixel = gradient_magnitude[row - 1, col + 1]
elif (3 * PI / 8 <= direction < 5 * PI / 8) or (11 * PI / 8 <= direction < 13 * PI / 8):
before_pixel = gradient_magnitude[row - 1, col]
after_pixel = gradient_magnitude[row + 1, col]
else:
before_pixel = gradient_magnitude[row - 1, col - 1]
after_pixel = gradient_magnitude[row + 1, col + 1]
if gradient_magnitude[row, col] >= before_pixel and gradient_magnitude[row, col] >= after_pixel:
output[row, col] = gradient_magnitude[row, col]
if verbose:
plt.imshow(output, cmap='gray')
plt.title("Non Max Suppression")
plt.show()
return output
def threshold(image, low, high, weak, verbose=False):
output = np.zeros(image.shape)
strong = 255
strong_row, strong_col = np.where(image >= high)
weak_row, weak_col = np.where((image <= high) & (image >= low))
output[strong_row, strong_col] = strong
output[weak_row, weak_col] = weak
if verbose:
plt.imshow(output, cmap='gray')
plt.title("threshold")
plt.show()
return output
def hysteresis(image, weak):
image_row, image_col = image.shape
top_to_bottom = image.copy()
for row in range(1, image_row):
for col in range(1, image_col):
if top_to_bottom[row, col] == weak:
if top_to_bottom[row, col + 1] == 255 or top_to_bottom[row, col - 1] == 255 or top_to_bottom[row - 1, col] == 255 or top_to_bottom[
row + 1, col] == 255 or top_to_bottom[
row - 1, col - 1] == 255 or top_to_bottom[row + 1, col - 1] == 255 or top_to_bottom[row - 1, col + 1] == 255 or top_to_bottom[
row + 1, col + 1] == 255:
top_to_bottom[row, col] = 255
else:
top_to_bottom[row, col] = 0
bottom_to_top = image.copy()
for row in range(image_row - 1, 0, -1):
for col in range(image_col - 1, 0, -1):
if bottom_to_top[row, col] == weak:
if bottom_to_top[row, col + 1] == 255 or bottom_to_top[row, col - 1] == 255 or bottom_to_top[row - 1, col] == 255 or bottom_to_top[
row + 1, col] == 255 or bottom_to_top[
row - 1, col - 1] == 255 or bottom_to_top[row + 1, col - 1] == 255 or bottom_to_top[row - 1, col + 1] == 255 or bottom_to_top[
row + 1, col + 1] == 255:
bottom_to_top[row, col] = 255
else:
bottom_to_top[row, col] = 0
right_to_left = image.copy()
for row in range(1, image_row):
for col in range(image_col - 1, 0, -1):
if right_to_left[row, col] == weak:
if right_to_left[row, col + 1] == 255 or right_to_left[row, col - 1] == 255 or right_to_left[row - 1, col] == 255 or right_to_left[
row + 1, col] == 255 or right_to_left[
row - 1, col - 1] == 255 or right_to_left[row + 1, col - 1] == 255 or right_to_left[row - 1, col + 1] == 255 or right_to_left[
row + 1, col + 1] == 255:
right_to_left[row, col] = 255
else:
right_to_left[row, col] = 0
left_to_right = image.copy()
for row in range(image_row - 1, 0, -1):
for col in range(1, image_col):
if left_to_right[row, col] == weak:
if left_to_right[row, col + 1] == 255 or left_to_right[row, col - 1] == 255 or left_to_right[row - 1, col] == 255 or left_to_right[
row + 1, col] == 255 or left_to_right[
row - 1, col - 1] == 255 or left_to_right[row + 1, col - 1] == 255 or left_to_right[row - 1, col + 1] == 255 or left_to_right[
row + 1, col + 1] == 255:
left_to_right[row, col] = 255
else:
left_to_right[row, col] = 0
final_image = top_to_bottom + bottom_to_top + right_to_left + left_to_right
final_image[final_image > 255] = 255
return final_image
if __name__ == '__main__':
ap = argparse.ArgumentParser()
ap.add_argument("-i", "--image", required=True, help="Path to the image")
ap.add_argument("-v", "--verbose", type=bool, default=False, help="Path to the image")
args = vars(ap.parse_args())
image = cv2.imread(args["image"])
blurred_image = gaussian_blur(image, kernel_size=9, verbose=False)
edge_filter = np.array([[-1, 0, 1], [-2, 0, 2], [-1, 0, 1]])
gradient_magnitude, gradient_direction = sobel_edge_detection(blurred_image, edge_filter, convert_to_degree=True, verbose=args["verbose"])
new_image = non_max_suppression(gradient_magnitude, gradient_direction, verbose=args["verbose"])
weak = 50
new_image = threshold(new_image, 5, 20, weak=weak, verbose=args["verbose"])
new_image = hysteresis(new_image, weak)
plt.imshow(new_image, cmap='gray')
plt.title("Canny Edge Detector")
plt.show()
References
hahahha
【数字图像分析】基于Python实现 Canny Edge Detection(Canny 边缘检测算法)的更多相关文章
- 猜数字游戏--基于python
"""题目:练习使用python写一个猜数字的游戏,数字范围0-100,每次猜错,需要给出缩小后的范围,每个人只有10次的猜测机会,猜测机会用完游戏结束!"&q ...
- 【笔记】基于Python的数字图像处理
[博客导航] [Python相关] 前言 基于Python的数字图像处理,离不开相关处理的第三方库函数.搜索网络资源,列出如下资源链接. Python图像处理库到底用哪家 python计算机视觉编程— ...
- Image Processing and Analysis_8_Edge Detection:Scale-space and edge detection using anisotropic diffusion——1990
此主要讨论图像处理与分析.虽然计算机视觉部分的有些内容比如特 征提取等也可以归结到图像分析中来,但鉴于它们与计算机视觉的紧密联系,以 及它们的出处,没有把它们纳入到图像处理与分析中来.同样,这里面也有 ...
- Image Processing and Analysis_8_Edge Detection:A Computational Approach to Edge Detection——1986
此主要讨论图像处理与分析.虽然计算机视觉部分的有些内容比如特 征提取等也可以归结到图像分析中来,但鉴于它们与计算机视觉的紧密联系,以 及它们的出处,没有把它们纳入到图像处理与分析中来.同样,这里面也有 ...
- Image Processing and Analysis_8_Edge Detection:Theory of Edge Detection ——1980
此主要讨论图像处理与分析.虽然计算机视觉部分的有些内容比如特 征提取等也可以归结到图像分析中来,但鉴于它们与计算机视觉的紧密联系,以 及它们的出处,没有把它们纳入到图像处理与分析中来.同样,这里面也有 ...
- 计算机视觉中的边缘检测Edge Detection in Computer Vision
计算机视觉中的边缘检测 边缘检测是计算机视觉中最重要的概念之一.这是一个很直观的概念,在一个图像上运行图像检测应该只输出边缘,与素描比较相似.我的目标不仅是清晰地解释边缘检测是怎样工作的,同时也提 ...
- Image Processing and Analysis_8_Edge Detection:Edge Detection Revisited ——2004
此主要讨论图像处理与分析.虽然计算机视觉部分的有些内容比如特 征提取等也可以归结到图像分析中来,但鉴于它们与计算机视觉的紧密联系,以 及它们的出处,没有把它们纳入到图像处理与分析中来.同样,这里面也有 ...
- Image Processing and Analysis_8_Edge Detection:Local Scale Control for Edge Detection and Blur Estimation——1998
此主要讨论图像处理与分析.虽然计算机视觉部分的有些内容比如特 征提取等也可以归结到图像分析中来,但鉴于它们与计算机视觉的紧密联系,以 及它们的出处,没有把它们纳入到图像处理与分析中来.同样,这里面也有 ...
- Image Processing and Analysis_8_Edge Detection: Optimal edge detection in two-dimensional images ——1996
此主要讨论图像处理与分析.虽然计算机视觉部分的有些内容比如特 征提取等也可以归结到图像分析中来,但鉴于它们与计算机视觉的紧密联系,以 及它们的出处,没有把它们纳入到图像处理与分析中来.同样,这里面也有 ...
随机推荐
- C++ std::vector 基本用法2
#include <iostream> #include <vector> using namespace std; int main() { int ar[10] = { 1 ...
- EEPROM的概念接口类型及软件实例
基本概念 EEPROM的全称是“电可擦除可编程只读存储器”,即Electrically Erasable Programmable Read-Only Memory.是相对于紫外擦除的rom来讲的.但 ...
- Windows下使用virtualenv创建虚拟环境
操作系统 : windowns10_x64Python版本:3.6.8virtualenv版本:16.7.7virtualenvwrapper版本:1.2.5 方式一:直接使用virtualenv 1 ...
- go语言之map
go语言的map就相当于python的dict 1.map的初始化 //创建map //k的类型是int,v的类型是string var test25_1 map[int]string fmt.Pri ...
- 多线程六 同步容器&并发容器
同步容器(使用的是synchronized,并且不一定是百分百安全) 本篇续 -- 线程之间的通信 ,介绍java提供的并发集合,既然正确的使用wait和notify比较困难,java平台为我们提供了 ...
- ASP.NET MVC教程五:ASP.NET MVC中的路由
一.概述 在ASP.NET MVC架构中,控制器在3大核心构件中处于中心地位,通过控制器支配模型和视图,然而从浏览器发出的请求到控制器还需要路由的协助,路由将特定的请求和控制器的动作对应起来. 在AS ...
- 一起学Android之音频视频
概述 Android多媒体框架支持各种常见的媒体类型,可以很容易地将音频.视频和图像集成到App中.通过MediaPlayer Api,可以从应用程序资源(RAW).文件系统或网络上数据流资源来播放音 ...
- 发布方式一:发布.netcore流程
通过注册世纪互联,发布网站 注册需要上传身份证正反照片,以及打款一元,试用期一个月 https://www.azure.cn 注册完成后,进入主页面: 如图所示,创建完成后的效果: 点开详情, ...
- Vim 宏实战操作
宏的概念 什么是宏呢?英文名:macro,代表一串命令的集合. 示例操作文本 SELECT * FROM `edu_ocr_task` WHERE ((`userId`=284871) AND (`u ...
- System.InvalidOperationException:This.NpgsqlTransaction has completed;it is no longer usable. at Npgsql.NpgsqlTransaction.CheckCompleted() in ...
关于报此异常,原因是事务不能循环提交,一个方法中事务只能提交一次. System.InvalidOperationException:This.NpgsqlTransaction has comple ...