1.引言

Canny算子是一种较为好用的边缘检测算子,边缘检测效果良好。利用Python实现,原速度约为5分钟以上,不能够满足使用需要。

本文利用Python实现,并注意使用numba支持的数据类型及写法进行,故而可以利用numba进行加速,对5000*3000像素图像提取边缘,整体流程用时13秒,满足使用需要。

2.预备功能函数

1.卷积函数

def convolution(image, kernel):"""This function is used for convolution.Args:image: image input.kerbel: the filter."""kernel_height, kernel_width = kernel.shapeheight, width = image.shapekernel_size = kernel_heighthalf_size = np.floor(kernel_size/2)@numba.jit(nopython = True)def conv(image, kernel, half_size, height, width):result = np.zeros((height, width), dtype = np.float32)for row in range(half_size, height - half_size):for col in range(half_size, width - half_size):sum_var = 0for v_row in range(-1*half_size, half_size+1):for v_col in range(-1*half_size, half_size+1):sum_var = sum_var + image[row+v_row, col+v_col] * kernel[v_row, v_col]result[row, col] = sum_varreturn resultresult = conv(image, kernel, half_size, height, width)return result

2.高斯模板函数

用于提供一个高斯滤波核

def generate_Guassian_template(kernel_size = 3, sigma = 1):template = np.zeros((kernel_size, kernel_size), \dtype = np.float32)halfsize = np.floor(kernel_size/2).astype(np.int16)@numba.jit(nopython = True)def gaussian2d(x, y, sigma):result = np.exp(-(np.power(x, 2)+np.power(y, 2))/(2*np.power(sigma, 2)))return result@numba.jit(nopython = True)def generate(template, halfsize, sigma):for v_row in range(-1*halfsize, halfsize+1):for v_col in range(-1*halfsize, halfsize+1):template[v_row+halfsize, v_col+halfsize] = gaussian2d(v_row, v_col, sigma)element_sum = np.sum(template)template = template/element_sumreturn templatere = generate(template, halfsize, sigma)return re

3. 梯度类

暂时只实现了两种梯度,后面可能会增加Sobel梯度。

# -*- coding: utf-8 -*-
# @author: Dasheng Fan
# @email: fandasheng1999@163.comimport numpy as np
import numba
import syssys.path.append('../')
from utils.gray_processing import gray_processingclass RobertsGradient(object):"""Roberts is a kind of gradient of the image."""def __init__(self):""""""def calculate(self, image):"""Culculate the Roberts gradient gx and gy.Args:image: image to input.Return:gx, gy"""if len(image.shape) != 2:image = gray_processing(image)@numba.jit(nopython = True)def run(image):height, width = image.shapegradient_gy_img = np.zeros((height, width), dtype = np.float32)gradient_gx_img = np.zeros((height, width), dtype = np.float32)for row in range(1, height-1):for col in range(1, width-1):gradient_gx_img[row, col] = image[row, col] - image[row+1, col+1]gradient_gy_img[row, col] = image[row+1, col] - image[row, col+1]return gradient_gx_img, gradient_gy_imggx, gy = run(image)return gx, gyclass Gradient(object):def __init__(self):passdef calculate(self, image):@numba.jit(nopython=True)def run(image):height, width = image.shapegx = np.zeros((height, width), dtype = np.float32)gy = np.zeros((height, width), dtype = np.float32)for row in range(1, height-1):for col in range(1, width-1):gx[row, col] = image[row, col+1] - image[row, col]gy[row, col] = image[row+1, col] - image[row, col]return gx, gygx, gy = run(image)return gx, gy

4.灰度化函数

# -*- coding: utf-8 -*-
# @author: Dasheng Fan
# @email: fandasheng1999@163.com"""
Gray processing.
"""import numpy as np
from matplotlib import pyplot as plt
import sys
import osdef gray_processing(image):"""For gray processing.Args:image: A 3 channels image.Reture:A gray image.Reference:"https://baike.baidu.com/item/%E7%81%B0%E5%BA%A6%E5%8C%96/3206969?fr=aladdin""""if len(image.shape) != 3:raise Exception("The channel is wrong.")u = np.power(image[:, :, 0], 2.2) + np.power(1.5*image[:, :, 1], 2.2) + \np.power(0.6*image[:, :, 2], 2.2)d = 1 + np.power(1.5, 2.2) + np.power(0.6, 2.2)gray = np.power(u/d, 1/2.2)return grayif __name__ == '__main__':pass

3.实现

1.高斯滤波,参考:
https://www.jianshu.com/p/73e6ccbd8f3f
2.梯度计算:无参考
3.极大值抑制(Canny的很复杂)
主要参考:https://blog.csdn.net/kezunhai/article/details/11620357
4.双阈值检测,抑制孤立低阈值点
参考:https://www.cnblogs.com/techyan1990/p/7291771.html

代码

# -*- coding: utf-8 -*-
# @author: Dasheng Fan
# @email: fandasheng1999@163.com"""
Canny operator.
"""
import numpy as np
import numba
from operators.diptools import generate_Guassian_template, convolution
from operators.gradient import RobertsGradient,Gradient
from utils.gray_processing import gray_processing
from utils.display import display, doubledisplayclass Canny(object):"""Canny operator is used for line detecting."""def __init__(self, Guassian_kernel_size = 3, Guassian_sigma = 1, high_threshhold_ratio = 0.15,low_threshhold_ratio = 0.08):self._G_kernel_size = Guassian_kernel_sizeself._G_sigma = Guassian_sigmaself._h_thresh_r = high_threshhold_ratioself._l_thresh_r = low_threshhold_ratiodef detect(self, image):if len(image.shape) != 2:image = gray_processing(image)height, width = image.shapeg_template = generate_Guassian_template()image = convolution(image, g_template)gradient = Gradient()gx, gy = gradient.calculate(image)@numba.jit(nopython = True)def nonmaxsuppress(gx,gy):"""Reference:https://blog.csdn.net/kezunhai/article/details/11620357"""g = np.sqrt(np.add(np.power(gx, 2), np.power(gy, 2)))angle = np.arctan(gy/gx)height, width = g.shapeflags = np.zeros((height, width), dtype = np.float32)for row in range(1, height-1):for col in range(1, width - 1):local_g = g[row, col]if np.abs(gy[row, col])>np.abs(gx[row, col]):if gy[row, col] == 0:weight = 1else:weight = np.abs(gx[row,col]/gy[row, col])g2 = g[row-1, col]g4 = g[row+1, col]if np.multiply(gx[row,col], gy[row, col])>0:g1 = g[row-1, col-1]g3 = g[row+1, col+1]else:g1 = g[row-1, col+1]g3 = g[row+1, col-1]else:if gx[row, col] == 0:weight = 1else:weight = np.abs(gy[row, col]/gx[row, col])g2 = g[row, col-1]g4 = g[row, col+1]if np.multiply(gx[row, col],gy[row,col])>0:g1 = g[row-1, col-1]g3 = g[row+1, col+1]else:g1 = g[row+1, col-1]g3 = g[row-1, col+1]inter_g1 = weight*g1 + (1-weight)*g2inter_g2 = weight*g3 + (1-weight)*g4 local_g = g[row, col]if local_g >=inter_g1 and local_g>=inter_g2:flags[row, col] = 1return flagsflags1 = nonmaxsuppress(gx, gy)@numba.jit(nopython = True)def _double_threshhold_suppress(high_threshhold_ratio, low_threshhold_ratio, gx, gy):"""The theory can be found here:https://www.cnblogs.com/techyan1990/p/7291771.htmlOnly the theory is refered, the codes are different."""g = np.sqrt(np.add(np.power(gx, 2), np.power(gy, 2)))height, width = g.shapemax_g = np.max(g)high_thresh = max_g * high_threshhold_ratiolow_thresh = max_g * low_threshhold_ratioflags = np.zeros((height, width), dtype = np.float32)for row in range(1, height-1):for col in range(1, width - 1):if g[row, col] >= high_thresh:flags[row, col] = 1elif g[row, col] > low_thresh and g[row, col] < high_thresh:# 不洋嚯了,写汉语# 这里检查一下八邻域, 如果有强边缘就认为弱边缘是边缘点for var_y in range(-1, 2):for var_x in range(-1, 2):if g[row+var_y, row+var_x] > high_thresh:flags[row, col] = 1breakelse:flags[row, col] = 0return flagsflags2 = _double_threshhold_suppress(self._h_thresh_r, self._l_thresh_r, gx, gy)flags = np.multiply(flags1, flags2)return flags

返回的flags是标志矩阵,矩阵中为1的元素对应的点是边缘点,为0则不是。

4.效果

校医院还是要检测一个的。

Canny算子的Python实现相关推荐

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

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

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

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

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

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

  4. Python实现Canny算子

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

  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边缘检测算法(python 实现)

    文章目录 最优边缘准则 算法实现步骤 1. 应用高斯滤波来平滑(模糊)图像,目的是去除噪声 2. 计算梯度强度和方向 3. 应用非最大抑制技术NMS来消除边误检 4. 应用双阈值的方法来决定可能的(潜 ...

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

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

最新文章

  1. python语言入门w-1Python开发——基础入门
  2. 学习笔记之-java8的新特性-函数式接口,lambda表达式,方法引用,Stream API,Optional类
  3. 病毒与木马大多作成 动态库形式的原因
  4. 嵌入式常见笔试题总结(3)
  5. python 取整_马克的Python学习笔记#数字,日期和时间
  6. Unity C# 反编译
  7. android 服务端 servlet webservice,Tomcat 上如何部署Servlet及Android中如何与服务器通信(12页)-原创力文档...
  8. aic值检验 p值_23. 假设检验的时候为什么常写p lt; 0.05,而不写具体的p值?
  9. WinForm 的定时器使用
  10. actor对自己不可见
  11. 独立看门狗及其实现的热启动
  12. linux 用户登陆全部记录,Linux—— 记录所有登陆用户的历史操作记录
  13. 床长人工智能教程 - 目录
  14. gitee.visualstudio.vsix 分享
  15. 魔方优化大师 v5.15 中文绿色版
  16. 【终极】文件夹隐藏方法,彻底隐藏文件夹的方法!显示隐藏的文件也看不到
  17. Android底部小白条的解决方法
  18. 计算一元二次方程(考虑实根虚根无解)
  19. Python编程之文本颜色设置
  20. 线性代数_4、行列式按行展开,异乘变零,拉普拉斯定理

热门文章

  1. “智慧教育·化繁为简” 迪普科技亮相第二十三届CERNET学术年会
  2. 一步步教你如何设置UEditor上传大视频文件
  3. 【单片机毕业设计】【mcuclub-cl-007】基于单片机的RFID高速收费的设计
  4. PowerDesigner16.5安装教程
  5. emui8.0Android系统,华为EMUI9.0国内首发,基于安卓P提供品质生活体验
  6. 在 Java 代码中来一段 JavaScript?聊聊 Flowable 中的脚本任务
  7. 浙江事业单位考不考计算机专业知识,浙江事业单位考试计算机相关综合知识,看哪些?...
  8. 2010上海工博会上的宜科展台
  9. GPU 核心和 CPU 核心
  10. futex同步机制分析之一应用