Canny算子的Python实现
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实现相关推荐
- canny算子的python实现以及pytorch实现
canny算子的python实现以及pytorch实现 canny的python实现 canny的pytorch实现 canny的python实现 参考Canny边缘检测算法(python 实现) i ...
- 图像处理:python实现canny算子
一.Canny边缘提取步骤 文中用python实现canny算子,Canny算子的步骤为: 1)图像灰度预处理 2)对每个像素求梯度 3)求每个点处最大梯度的编码 4)非极大值抑制,保证梯度编码的唯一 ...
- 【图像处理】——Python图像分割边缘检测算法之一阶梯度算子(Roberts、Prewitt、Sobel、 Kirsch、Canny算子)
目录 前言 一.边缘检测算法 1.一阶算子 2.二阶算子 二.一阶算子 原图像lena 1.Roberts算子 不同方向的算子模板 梯度的计算 系统代码: 自定义函数代码 结果 2.Prewitt 不 ...
- Python实现Canny算子
Canny算子 Canny算子是提取图像边缘的经典算法,在之前的基础学习过程中写过关于canny的python代码,最近的项目中需要用到才发现当初学的有所缺陷. Canny算子的基本步骤: 使用高斯滤 ...
- python的opencv操作记录12——Canny算子使用
文章目录 Canny算子 非极大值抑制 非极大值抑制中的插值 滞后阈值 实际应用 直接使用Canny算子 使用膨胀 先阈值分割 Canny算子 上一篇说到,我在一个小项目里需要在一幅图像中提取一根试管 ...
- python canny算子_Python - OpenCV 之Canny算子边缘提取
#!--*-- coding=utf-8 --*-- import cv2 import os import argparse ''' 基于OpenCV Canny 算子的提取图像边缘 ''' # d ...
- OpenCV(十七)边缘检测3 -- Canny算子(最优边缘检测)
目录 一.基础理论 1.作用及介绍 1.原理 2.过程 3.Canny函数 二.回调函数及总代码 效果 参考资料 一.基础理论 1.作用及介绍 Canny边缘检测是非常流行的边缘检测算 ...
- Canny边缘检测算法(python 实现)
文章目录 最优边缘准则 算法实现步骤 1. 应用高斯滤波来平滑(模糊)图像,目的是去除噪声 2. 计算梯度强度和方向 3. 应用非最大抑制技术NMS来消除边误检 4. 应用双阈值的方法来决定可能的(潜 ...
- 计算机视觉中Canny算子详解
文章目录 前言 一.Canny的实现步骤 二.具体实现 1.高斯平滑滤波 2.计算梯度大小和方向 3.非极大抑制 4.双阈值(Double Thresholding)和滞后边界跟踪 总结 前言 Can ...
最新文章
- python语言入门w-1Python开发——基础入门
- 学习笔记之-java8的新特性-函数式接口,lambda表达式,方法引用,Stream API,Optional类
- 病毒与木马大多作成 动态库形式的原因
- 嵌入式常见笔试题总结(3)
- python 取整_马克的Python学习笔记#数字,日期和时间
- Unity C# 反编译
- android 服务端 servlet webservice,Tomcat 上如何部署Servlet及Android中如何与服务器通信(12页)-原创力文档...
- aic值检验 p值_23. 假设检验的时候为什么常写p lt; 0.05,而不写具体的p值?
- WinForm 的定时器使用
- actor对自己不可见
- 独立看门狗及其实现的热启动
- linux 用户登陆全部记录,Linux—— 记录所有登陆用户的历史操作记录
- 床长人工智能教程 - 目录
- gitee.visualstudio.vsix 分享
- 魔方优化大师 v5.15 中文绿色版
- 【终极】文件夹隐藏方法,彻底隐藏文件夹的方法!显示隐藏的文件也看不到
- Android底部小白条的解决方法
- 计算一元二次方程(考虑实根虚根无解)
- Python编程之文本颜色设置
- 线性代数_4、行列式按行展开,异乘变零,拉普拉斯定理
热门文章
- “智慧教育·化繁为简” 迪普科技亮相第二十三届CERNET学术年会
- 一步步教你如何设置UEditor上传大视频文件
- 【单片机毕业设计】【mcuclub-cl-007】基于单片机的RFID高速收费的设计
- PowerDesigner16.5安装教程
- emui8.0Android系统,华为EMUI9.0国内首发,基于安卓P提供品质生活体验
- 在 Java 代码中来一段 JavaScript?聊聊 Flowable 中的脚本任务
- 浙江事业单位考不考计算机专业知识,浙江事业单位考试计算机相关综合知识,看哪些?...
- 2010上海工博会上的宜科展台
- GPU 核心和 CPU 核心
- futex同步机制分析之一应用