Canny算子

Canny算子是提取图像边缘的经典算法,在之前的基础学习过程中写过关于canny的python代码,最近的项目中需要用到才发现当初学的有所缺陷。

Canny算子的基本步骤:

  1. 使用高斯滤波器对图像进行处理,消除噪点对边缘提取的影响
  2. 使用两个对称核(sobel)计算出图像的梯度和梯度方向
  3. 将梯度方向归纳为0,45,90,135四个梯度方向(之前实现的,有缺陷)
  4. 对边缘强度进行非极大值抑制,比较四个梯度方向上三个像素梯度的大小,如果最大值不是中间梯度,则抑制为0
  5. 使用滞后阈值对图像进行二值化处理,介于高低阈值之间的值,使用8领域判断法(如果8领域有一个大于高阈值,则设置为255)

具体实现代码如下:

在之前的复现中犯了一个明显的错误,将梯度方向做了处理(四个方向),最好的处理方-处理成4个区间(0-45,45-90,09-135,135-180)用插值的方式进行梯度比较,插值的大小根据角度不同取权重乘以两个相邻像素。参考:Python实现Canny算子边缘检测 | Z Blog (yueyue200830.github.io)

此代码来源于(自己实现的有瑕疵就不记录了):(145条消息) Canny边缘检测算法(python 实现)_Master_miao的博客-CSDN博客_canny python

import numpy as np
import cv2 as cv
from matplotlib import pyplot as pltdef smooth(image, sigma = 1.4, length = 5):""" Smooth the imageCompute a gaussian filter with sigma = sigma and kernal_length = length.Each element in the kernal can be computed as below:G[i, j] = (1/(2*pi*sigma**2))*exp(-((i-k-1)**2 + (j-k-1)**2)/2*sigma**2)Then, use the gaussian filter to smooth the input image.Args:image: array of grey imagesigma: the sigma of gaussian filter, default to be 1.4length: the kernal length, default to be 5Returns:the smoothed image"""# Compute gaussian filterk = length // 2gaussian = np.zeros([length, length])for i in range(length):for j in range(length):gaussian[i, j] = np.exp(-((i-k) ** 2 + (j-k) ** 2) / (2 * sigma ** 2))gaussian /= 2 * np.pi * sigma ** 2# Batch Normalizationgaussian = gaussian / np.sum(gaussian)# Use Gaussian FilterW, H = image.shapenew_image = np.zeros([W - k * 2, H - k * 2])for i in range(W - 2 * k):for j in range(H - 2 * k):# 卷积运算new_image[i, j] = np.sum(image[i:i+length, j:j+length] * gaussian)new_image = np.uint8(new_image)return new_imagedef get_gradient_and_direction(image):""" Compute gradients and its directionUse Sobel filter to compute gradients and direction.-1 0 1        -1 -2 -1Gx = -2 0 2   Gy =  0  0  0-1 0 1         1  2  1Args:image: array of grey imageReturns:gradients: the gradients of each pixeldirection: the direction of the gradients of each pixel"""Gx = np.array([[-1, 0, 1], [-2, 0, 2], [-1, 0, 1]])Gy = np.array([[-1, -2, -1], [0, 0, 0], [1, 2, 1]])W, H = image.shapegradients = np.zeros([W - 2, H - 2])direction = np.zeros([W - 2, H - 2])for i in range(W - 2):for j in range(H - 2):dx = np.sum(image[i:i+3, j:j+3] * Gx)dy = np.sum(image[i:i+3, j:j+3] * Gy)gradients[i, j] = np.sqrt(dx ** 2 + dy ** 2)if dx == 0:direction[i, j] = np.pi / 2else:direction[i, j] = np.arctan(dy / dx)gradients = np.uint8(gradients)return gradients, directiondef NMS(gradients, direction):""" Non-maxima suppressionArgs:gradients: the gradients of each pixeldirection: the direction of the gradients of each pixelReturns:the output image"""W, H = gradients.shapenms = np.copy(gradients[1:-1, 1:-1])for i in range(1, W - 1):for j in range(1, H - 1):theta = direction[i, j]weight = np.tan(theta)if theta > np.pi / 4:d1 = [0, 1]d2 = [1, 1]weight = 1 / weightelif theta >= 0:d1 = [1, 0]d2 = [1, 1]elif theta >= - np.pi / 4:d1 = [1, 0]d2 = [1, -1]weight *= -1else:d1 = [0, -1]d2 = [1, -1]weight = -1 / weightg1 = gradients[i + d1[0], j + d1[1]]g2 = gradients[i + d2[0], j + d2[1]]g3 = gradients[i - d1[0], j - d1[1]]g4 = gradients[i - d2[0], j - d2[1]]grade_count1 = g1 * weight + g2 * (1 - weight)grade_count2 = g3 * weight + g4 * (1 - weight)if grade_count1 > gradients[i, j] or grade_count2 > gradients[i, j]:nms[i - 1, j - 1] = 0return nmsdef double_threshold(nms, threshold1, threshold2):""" Double ThresholdUse two thresholds to compute the edge.Args:nms: the input imagethreshold1: the low thresholdthreshold2: the high thresholdReturns:The binary image."""visited = np.zeros_like(nms)output_image = nms.copy()W, H = output_image.shapedef dfs(i, j):if i >= W or i < 0 or j >= H or j < 0 or visited[i, j] == 1:returnvisited[i, j] = 1if output_image[i, j] > threshold1:output_image[i, j] = 255dfs(i-1, j-1)dfs(i-1, j)dfs(i-1, j+1)dfs(i, j-1)dfs(i, j+1)dfs(i+1, j-1)dfs(i+1, j)dfs(i+1, j+1)else:output_image[i, j] = 0for w in range(W):for h in range(H):if visited[w, h] == 1:continueif output_image[w, h] >= threshold2:dfs(w, h)elif output_image[w, h] <= threshold1:output_image[w, h] = 0visited[w, h] = 1for w in range(W):for h in range(H):if visited[w, h] == 0:output_image[w, h] = 0return output_imageif __name__ == "__main__":# code to read imageimage = cv.imread('test.jpg',0)cv.imshow("Original",image)smoothed_image = smooth(image)cv.imshow("GaussinSmooth(5*5)",smoothed_image)gradients, direction = get_gradient_and_direction(smoothed_image)# print(gradients)# print(direction)nms = NMS(gradients, direction)output_image = double_threshold(nms, 40, 100)cv.imshow("outputImage",output_image)cv.waitKey(0)

Python实现Canny算子相关推荐

  1. 图像处理:python实现canny算子

    一.Canny边缘提取步骤 文中用python实现canny算子,Canny算子的步骤为: 1)图像灰度预处理 2)对每个像素求梯度 3)求每个点处最大梯度的编码 4)非极大值抑制,保证梯度编码的唯一 ...

  2. 【图像处理】——Python图像分割边缘检测算法之一阶梯度算子(Roberts、Prewitt、Sobel、 Kirsch、Canny算子)

    目录 前言 一.边缘检测算法 1.一阶算子 2.二阶算子 二.一阶算子 原图像lena 1.Roberts算子 不同方向的算子模板 梯度的计算 系统代码: 自定义函数代码 结果 2.Prewitt 不 ...

  3. canny算子的python实现以及pytorch实现

    canny算子的python实现以及pytorch实现 canny的python实现 canny的pytorch实现 canny的python实现 参考Canny边缘检测算法(python 实现) i ...

  4. Canny算子的Python实现

    1.引言 Canny算子是一种较为好用的边缘检测算子,边缘检测效果良好.利用Python实现,原速度约为5分钟以上,不能够满足使用需要. 本文利用Python实现,并注意使用numba支持的数据类型及 ...

  5. python的opencv操作记录12——Canny算子使用

    文章目录 Canny算子 非极大值抑制 非极大值抑制中的插值 滞后阈值 实际应用 直接使用Canny算子 使用膨胀 先阈值分割 Canny算子 上一篇说到,我在一个小项目里需要在一幅图像中提取一根试管 ...

  6. python canny算子_Python - OpenCV 之Canny算子边缘提取

    #!--*-- coding=utf-8 --*-- import cv2 import os import argparse ''' 基于OpenCV Canny 算子的提取图像边缘 ''' # d ...

  7. OpenCV(十七)边缘检测3 -- Canny算子(最优边缘检测)

    目录 一.基础理论 1.作用及介绍 1.原理 2.过程 3.Canny函数 二.回调函数及总代码 效果 参考资料 ​​​​​​​ 一.基础理论 1.作用及介绍 Canny边缘检测是非常流行的边缘检测算 ...

  8. 计算机视觉中Canny算子详解

    文章目录 前言 一.Canny的实现步骤 二.具体实现 1.高斯平滑滤波 2.计算梯度大小和方向 3.非极大抑制 4.双阈值(Double Thresholding)和滞后边界跟踪 总结 前言 Can ...

  9. Python OpenCV -- Canny 边缘检测 (十一)

    Canny 边缘检测 原理 Canny 边缘检测算法 是 John F. Canny 于 1986年开发出来的一个多级边缘检测算法,也被很多人认为是边缘检测的 最优算法, 最优边缘检测的三个主要评价标 ...

最新文章

  1. R语言curve绘图函数
  2. LeetCode Construct Quad Tree(dfs)
  3. 【BZOJ3518】点组计数 [欧拉函数]
  4. sgolayfilt函数_Matlab中Savitzky-Golay filtering(最小二乘平滑滤波)函数sgolayfilt的使用方法...
  5. python 使用文本注解绘制树节点_实用篇 | 34 个最火的 Python 开源框架
  6. WPF 2D绘图(2)Geometry
  7. pixel 解锁_如何在Google Pixel 4和Pixel 4 XL上禁用面部解锁
  8. Golang 退出chroot环境的方法
  9. gradle脚本源码查看环境搭建
  10. python有关数据结构问题
  11. 处理得怎么样填空词语_武都网络推广软件效果怎么样【易商网络】
  12. 【AI视野·今日Robot 机器人论文速览 第二十三期】Tue, 28 Sep 2021
  13. 眼睛又干又痒,到底是干眼症还是结膜炎?
  14. win10计算机图片,Win10使用系统自带的电子相册整理电脑中照片方法图解
  15. 微软的学术可视化搜索
  16. 如何用循环执行玩转自定义企业微信机器人?
  17. Echarts绘制地图,且可以下钻到省区
  18. 技术人员如何提升自己的价值
  19. 鸿合一体机触屏没反应怎么办_电脑一体机触摸屏没反应 触摸屏电脑一体机常见故障解决方法...
  20. stay hungary stay foolish

热门文章

  1. sql的 聚合函数汇总
  2. SQL_聚合函数使用总结
  3. JAVA计算机毕业设计ipq管理系统Mybatis+系统+数据库+调试部署
  4. 线性回归中成本函数的由来
  5. python学习 - time()函数使用
  6. sql 如何定位慢查询
  7. 【前端面试知识点】- 大厂面试(二)
  8. 网易公开课《计算机科学导论》简评
  9. python 元组_python 元组操作总结
  10. 售价高达2.5万,苹果首款MR头显“炸场”,眼睛、手和语音都能控制,WWDC23开启科技革命