opencv中给出了canny边缘检测的接口,直接调用:

ret = cv2.canny(img,t1,t2)

即可得到边缘检测的结果ret。其中,t1,t2是需要人为设置的阈值。有不少论文研究了自动化的阈值设置方法,即算法在运行过程中能够自适应地找到较佳的分割阈值t1,t2,但是缺乏开源代码,特别是基于python3的实现几乎没有。

本文基于python3,复现一种自适应的阈值分割方法。

输入图片是:

输出结果对比如下:左图是直接用canny,右图是用本文程序自适应分割。

  

比较不足的是,由于自底向上重新编写,包括非最大抑制等过程。。可能耗时比较久。上面输入图像耗时27.38s,不知道其他学者研究的自适应阈值canny边缘检测方法的耗时情况如何。。程序中预处理过程中已经做了降采样,如果没有降采样的话,耗时会更长。

下面上代码:

主程序.py:

import numpy as np

import cv2, time, math

from scipy.signal import convolve2d as conv2

from matplotlib import pyplot as plt

from bilateralfilt import bilatfilt

from dog import deroGauss

import time

#...........................................................................................

def get_edges(I,sd):

dim = I.shape

Idog2d = np.zeros((nang,dim[0],dim[1]))

for i in range(nang):

dog2d = deroGauss(5,sd,angles[i])

Idog2dtemp = abs(conv2(I,dog2d,mode='same',boundary='fill'))

Idog2dtemp[Idog2dtemp<0]=0

Idog2d[i,:,:] = Idog2dtemp

return Idog2d

#...........................................................................................

def nonmaxsup(I,gradang):

dim = I.shape

Inms = np.zeros(dim)

xshift = int(np.round(math.cos(gradang*np.pi/180)))

yshift = int(np.round(math.sin(gradang*np.pi/180)))

Ipad = np.pad(I,(1,),'constant',constant_values = (0,0))

for r in range(1,dim[0]+1):

for c in range(1,dim[1]+1):

maggrad = [Ipad[r-xshift,c-yshift],Ipad[r,c],Ipad[r+xshift,c+yshift]]

if Ipad[r,c] == np.max(maggrad):

Inms[r-1,c-1] = Ipad[r,c]

return Inms

#...........................................................................................

def calc_sigt(I,threshval):

M,N = I.shape

ulim = np.uint8(np.max(I))

N1 = np.count_nonzero(I>threshval)

N2 = np.count_nonzero(I<=threshval)

w1 = np.float64(N1)/(M*N)

w2 = np.float64(N2)/(M*N)

#print N1,N2,w1,w2

try:

u1 = np.sum(i*np.count_nonzero(np.multiply(I>i-0.5,I<=i+0.5))/N1 for i in range(threshval+1,ulim))

u2 = np.sum(i*np.count_nonzero(np.multiply(I>i-0.5,I<=i+0.5))/N2 for i in range(threshval+1))

uT = u1*w1+u2*w2

sigt = w1*w2*(u1-u2)**2

#print u1,u2,uT,sigt

except:

return 0

return sigt

#...........................................................................................

def get_threshold(I):

max_sigt = 0

opt_t = 0

ulim = np.uint8(np.max(I))

print(ulim)

for t in range(ulim+1):

sigt = calc_sigt(I,t)

#print t, sigt

if sigt > max_sigt:

max_sigt = sigt

opt_t = t

print ('optimal high threshold: ',opt_t)

return opt_t

#...........................................................................................

def threshold(I,uth):

lth = uth/2.5

Ith = np.zeros(I.shape)

Ith[I>=uth] = 255

Ith[I=lth, I0:

Ipad[i,j] = 255

else:

Ipad[i,j] = 0

Ih = Ipad[1:r+1,1:c+1]

return Ih

#...........................................................................................

#Reading the image

img = cv2.imread('img0030.jpg')

while img.shape[0] > 1100 or img.shape[1] > 1100:

img = cv2.resize(img,None, fx=0.5,fy=0.5,interpolation = cv2.INTER_AREA)

#tic = time.time()

gimg = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)

dim = img.shape

#...........................................................................................

#Bilateral filtering

print ('Bilateral filtering...\n')

gimg = bilatfilt(gimg,5,3,10)

print ('after bilat: ',np.max(gimg),'\n')

#...........................................................................................

stime = time.time()

angles = [0,45,90,135]

nang = len(angles)

#...........................................................................................

#Gradient of Image

print ('Calculating Gradient...\n')

img_edges = get_edges(gimg,2)

print ('after gradient: ',np.max(img_edges),'\n')

#...........................................................................................

#Non-max suppression

print ('Suppressing Non-maximas...\n')

for n in range(nang):

img_edges[n,:,:] = nonmaxsup(img_edges[n,:,:],angles[n])

print ('after nms: ', np.max(img_edges))

img_edge = np.max(img_edges,axis=0)

lim = np.uint8(np.max(img_edge))

plt.imshow(img_edge)

plt.show()

#...........................................................................................

#Converting to uint8

#img_edges_uint8 = np.uint8(img_edges)

#...........................................................................................

#Thresholding

print ('Calculating Threshold...\n')

th = get_threshold(gimg)

the = get_threshold(img_edge)

#...........................................................................................

print ('\nThresholding...\n')

img_edge = threshold(img_edge, the*0.25)

#cv2.imshow('afterthe',img_edge)

#...........................................................................................

#Hysteresis

print ('Applying Hysteresis...\n')

#for i in xrange(nang):

img_edge = nonmaxsup(hysteresis(img_edge),90)

#...........................................................................................

#img_edge = np.max(img_edges,axis=0)

#...........................................................................................

#OpenCV Canny Function

img_canny = cv2.Canny(np.uint8(gimg),th/3,th)

#toc = time.time()

#print('自适应耗时:',toc-tic)

cv2.imshow('Uncanny',img_edge)

cv2.imshow('Canny',img_canny)

print( 'Time taken :: ', str(time.time()-stime)+' seconds...')

cv2.waitKey(0)

dog.py:

import numpy as np

import math

#Oriented Odd Symmetric Gaussian Filter :: First Derivative of Gaussian

def deroGauss(w=5,s=1,angle=0):

wlim = (w-1)/2

y,x = np.meshgrid(np.arange(-wlim,wlim+1),np.arange(-wlim,wlim+1))

G = np.exp(-np.sum((np.square(x),np.square(y)),axis=0)/(2*np.float64(s)**2))

G = G/np.sum(G)

dGdx = -np.multiply(x,G)/np.float64(s)**2

dGdy = -np.multiply(y,G)/np.float64(s)**2

angle = angle*math.pi/180 #converting to radians

dog = math.cos(angle)*dGdx + math.sin(angle)*dGdy

return dog

bilateralfilt.py:

import numpy as np

#import cv2, time

def bilatfilt(I,w,sd,sr):

dim = I.shape

Iout= np.zeros(dim)

#If the window is 5X5 then w = 5

wlim = (w-1)//2

y,x = np.meshgrid(np.arange(-wlim,wlim+1),np.arange(-wlim,wlim+1))

#Geometric closeness

g = np.exp(-np.sum((np.square(x),np.square(y)),axis=0)/(2*(np.float64(sd)**2)))

#Photometric Similarity

Ipad = np.pad(I,(wlim,),'edge')

for r in range(wlim,dim[0]+wlim):

for c in range(wlim,dim[1]+wlim):

Ix = Ipad[r-wlim:r+wlim+1,c-wlim:c+wlim+1]

s = np.exp(-np.square(Ix-Ipad[r,c])/(2*(np.float64(sr)**2)))

k = np.multiply(g,s)

Iout[r-wlim,c-wlim] = np.sum(np.multiply(k,Ix))/np.sum(k)

return Iout

参考资料:

https://github.com/sadimanna/canny(基于python2实现自适应阈值的canny,且个别地方会报错)

算法细节,可以网上搜索查看相关文献。

pythoncanny边缘检测自适应阈值_基于python实现自适应阈值的canny边缘检测相关推荐

  1. python canny优化_基于python的自适应阈值的Canny边缘检测

    canny边缘检测的接口在opencv中给出,直接调用: ret = cv2.canny(img,t1,t2) 您可以获取边缘检测结果. 其中,t1,t2是需要手动设置的阈值. 许多文献研究了自动阈值 ...

  2. python 英语分词_基于Python NLTK库进行英文文本预处理

    文本预处理是要文本处理成计算机能识别的格式,是文本分类.文本可视化.文本分析等研究的重要步骤.具体流程包括文本分词.去除停用词.词干抽取(词形还原).文本向量表征.特征选择等步骤,以消除脏数据对挖掘分 ...

  3. cv2 python 获取斑马线_基于python的opencv图像处理实现对斑马线的检测示例

    基本思路 斑马线检测通过opencv图像处理来进行灰度值转换.高斯滤波去噪.阈值处理.腐蚀和膨胀后对图像进行轮廓检测,通过判断车辆和行人的位置,以及他们之间的距离信息,当车速到超过一定阈值时并且与行人 ...

  4. python 按需加载_基于python的opcode优化和模块按需加载机制研究(学习与个人思路)(原创)...

    基于python的opcode优化和模块按需加载机制研究(学习与思考) 姓名:XXX 学校信息:XXX 主用编程语言:python3.5 文档转换为PDF有些图片无法完全显示,请移步我的博客查看 完成 ...

  5. python基于水色图像的水质评价_基于Python和遥感图像的膨胀与腐蚀操作

    引言 膨胀与腐蚀是图像形态学中的基本操作,本文将从两个角度实现python的膨胀与腐蚀算法,分别是特征提取与分割后处理.目前,在RGB图像领域,这两种形态学算法经常用于分割结果的处理,例如连通区处理. ...

  6. 大学计算机基础python学多久_基于Python 的“大学计算机基础”课程教学设计

    基于Python 的"大学计算机基础"课程教学设计 日期:2018-04-11 04:32 摘要 培养非计算机专业大学生的计算思维能力,在"大学计算机基础"课程 ...

  7. 基于python的微信公众号开发教程_基于python的微信公众号开发教程

    应广大python学员的期盼,九宝老师精心制作的"基于python的微信公众号开发"视频教程即将上线. 该课程秉承九宝培训一贯的"简单.高效.快速"的讲课原则, ...

  8. python中numpy数组的合并_基于Python中numpy数组的合并实例讲解

    基于Python中numpy数组的合并实例讲解 Python中numpy数组的合并有很多方法,如 - np.append() - np.concatenate() - np.stack() - np. ...

  9. python人脸识别库_基于Python的face_recognition库实现人脸识别

    Python Python开发 Python语言 基于Python的face_recognition库实现人脸识别 一.face_recognition库简介 face_recognition是Pyt ...

最新文章

  1. 4.二叉树的先序、中序以及后序遍历的递归写法与非递归写法(LeetCode第94、144、145题)
  2. spring--(4)级联属性赋值
  3. Boost:测试bind <void>
  4. 【Android】dip、dp、sp、pt和px的区别
  5. python中isinstance用法_Python内置isinstance函数详细介绍
  6. Xamarin 跨移动端开发系列(01) -- 搭建环境、编译、调试、部署、运行
  7. C语言试题七十六之请编写函实现百钱买百鸡
  8. csv格式清洗与转换python_实例详解Python中 CSV格式清洗与转换
  9. centos mysql无法启动 sock_linux 下mysql无法启动 mysql.sock
  10. modelsim和matlab联合仿真,Modelsim与Matlab联合仿真
  11. TCP: SYN ACK FIN RST PSH URG 详解【转】
  12. java将图片灰度化
  13. 我需要一个足够大的桌子
  14. java核心技术卷1 2 英文版pdf/epub+源代码 Core Java, 11th Edition
  15. 目前数据可视化工具软件的排名
  16. 学c语言前要了解什么软件,学习c语言需要什么软件?
  17. abbot_release
  18. Delphi的日期时间格式
  19. 如何使用Pandas进行数据分析!最详细的数据分析教程!
  20. 重电计算机学院李明建,【i小T有话说 | 第8期】风里雨里,我在上电计算机学院等你!...

热门文章

  1. POJ 3585 Accumulation Degree 树形dp
  2. Linux下使用ftp上传压缩文件,windows下载打开损坏问题
  3. 书单推荐 | web前端好书推荐(一)
  4. 机考怎么作弊_电脑上考试如何作弊 电脑上考试不能复制粘贴怎么办
  5. 将 Jar 包打成一个 Jar 包
  6. 电阻 电容 并联电路
  7. 大数据开发之常用软件
  8. 感悟+北京and新疆知识点
  9. GL音乐播放器1.0.0版-- 总结帖
  10. FCPX:600种VHS Studio转场效果合集