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检测_【数字图像分析】基于Python实现 Canny Edge Detection(Canny 边缘检测算法)...相关推荐

  1. python登录系统账号检测_一种基于python的惠普打印机默认用户名密码检测方法与流程...

    本发明涉及打印机检测技术领域,特别是一种基于python的惠普打印机默认用户名密码检测方法. 背景技术: 网络打印机是当前各大中小型企业正常办公比不可少的办公网络设备,但对于大中型企业而言,不同部门或 ...

  2. python 文件格式转换_数据分析:基于Python的自定义文件格式转换系统

    ( 白宁超 2018年7月16日14:47:41 ) 导读:随着大数据的快速发展,自然语言处理.数据挖掘.机器学习技术应用愈加广泛.针对大数据的预处理工作是一项庞杂.棘手的工作.首先数据采集和存储,尤 ...

  3. python人工智能计算器_招募:基于python的召唤师全时段全技能(含均值AI)计算器全程测试...

    该楼层疑似违规已被系统折叠 隐藏此楼查看此楼 √ 功能简介 借助Python跨平台.轻量化的优点,解决常规excel无法完成的准确AI.速度量化.CD量化.前后摇量化的问题,制作可以自动最优选择技能连 ...

  4. python selenium爬虫_详解基于python +Selenium的爬虫

    详解基于python +Selenium的爬虫 一.背景 1. Selenium Selenium 是一个用于web应用程序自动化测试的工具,直接运行在浏览器当中,支持chrome.firefox等主 ...

  5. python检索论文_一种基于Python的音乐检索方法的研究

    应用技术 0 前言 最近两年,人们对于流行音乐的追求与需求量日益增 加,但如何保证用户能在不知歌名只知歌词的情况下,完成 自己的全方面多种类的听歌需求呢?于是,电脑工程师就推 出了"听歌识曲 ...

  6. python椭圆形骨料_一种基于python再生混凝土三维随机球形骨料模型的构建方法与流程...

    本发明涉及建筑技术领域,尤其涉一种基于python再生混凝土三维随机球形骨料模型的构建方法. 背景技术: 再生混凝土是指利用再生粗骨料部分或者全部代替天然骨料配置而成的混凝土,再生混凝土技术的开发和利 ...

  7. python 人脸检测_借助摄像头在Python中实现人脸检测

    Python部落(www.freelycode.com)组织翻译, 禁止转载 本文作者是Shantnu Tiwari--曾多年在C/C++的魔爪中饱受折磨,直到他发现了Python--使用起来感觉如呼 ...

  8. python 椭圆检测_使用OpenCV和Python检测触摸/重叠圆/椭圆

    这是我检测圈子的尝试.综上所述 >执行BGR-> HSV转换,并使用V通道进行处理 V通道: >阈值,应用形态关闭,然后进行距离转换(我会称之为dist) 分区形象: >创建一 ...

  9. python 仪表盘监控_做一个基于python的树莓派MCU性能-温度监控仪表盘

    前段时间,需要比较树莓派MCU发热情况,因为没有找到合适工具,故使用python在画一个曲线图,完成图如下: 这个图完全由树莓派的Raspbian操作系统自带的python完成,现在我和大家一步步来介 ...

  10. python 图像拼接 检测_图像处理之图像拼接(python)

    一.算法目的 在同一位置拍摄两张以上图片,这些图片是单应性相关的,即图片之间有相同的拍摄区域.基于此将图片进行缝补,拼成一个大的图像来创建全景图像. 二.基本原理 要实现两张图片的简单拼接,其实只需找 ...

最新文章

  1. 中信银行总行信息科技部笔试面试以及最后拿offer经历
  2. 变步长龙格库塔法matlab代码,matlab 龙格库塔法 变步长龙格库塔法.doc
  3. Apache Spark源码走读之3 -- Task运行期之函数调用关系分析
  4. 动态调整canvas时的问题
  5. textarea支持a标签_微慕小程序开源版A标签优化说明
  6. more指令和less指令使用的区别
  7. 修改IP4属性时,针对闪退问题的解决方法
  8. 百度和知乎哪个引流效果好?知乎和百度的有什么区别?
  9. android极光推送设置消息类型,详解极光推送的 4 种消息形式—— Android 篇
  10. postgresql批量插入数据脚本_asp.net实现Postgresql快速写入/读取大量数据实例
  11. 乒乓球:浅析业余高手从输球中总结的10条心得!
  12. wincc 脚本 实现计算机重启,安装WINCC过程中提示需要重启电脑,请问如何解决?-工业支持中心-西门子中国...
  13. 使用PIE-Engine探寻地球灯光蕴藏的秘密
  14. 两个int类型数据交换的神级操作
  15. 《C程序员:从校园到职场》出版预告(3):从“阳春白雪”到“下里巴人”
  16. 专业技能热门配方大全
  17. ubuntu10.10下ESPON v350扫描仪的安装
  18. html命名锚记链接失败,命名锚记(设置命名锚记超级链接)
  19. Python经典例题:跑马灯文字效应
  20. mysql存储过程临时表_mysql存储过程中使用临时表

热门文章

  1. 前端学习(3234):react生命周期1
  2. [vue] vue的属性名称与method的方法名称一样时会发生什么问题?
  3. [css] 什么是脱离文档流?有什么办法可以让元素脱离标准的文档流?
  4. “约见”面试官系列之常见面试题第二十五篇之对vue-router的理解(建议收藏)
  5. 前端学习(1939)vue之电商管理系统电商系统之完成全部功能
  6. 前端学习(1930)vue之电商管理系统电商系统之美化一层循环的UI结构删除业务逻辑实现
  7. 前端学习(1290):nodejs模块化的开发导出另一种方式
  8. mybatis学习(27):获取自增id方式一(在mapper中insert配置节点的属性)
  9. 断路器操作机构分合闸线圈电流特征曲线特点
  10. Vue-Router的路由实例构造配置