今天的简单,利用canny算法实现边缘检测,再opencv内已经内置,只需一行代码即可实现。具体代码如下:
代码运行环境为jupyter notebook

#-*- coding: utf-8 -*-
import time
import cv2cap = cv2.VideoCapture(0)
#设置图像的高
cap.set(3,240)
#设置图像的宽,这里虽然设置的是240但是实际上是320,
cap.set(4,240)
#写入指定设备
f = open('/dev/fb0','wb')while True:st = time.time()ret,img = cap.read()if ret:#截取240*240的图像,lcd最大能显示的是240*240个16位像素img = img[:,0:240]#将捕获的一帧图像灰度化处理img = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)#将灰度图顺时针旋转180度img = cv2.rotate(img,cv2.ROTATE_180)#canny边缘检测img = cv2.Canny(img, 200, 300)#转换为16位色彩,(因为lcd是16位显示)img = cv2.cvtColor(img,cv2.COLOR_GRAY2BGR565)cv2.putText(img, "{0}" .format(str(1 / (time.time() - st))), (0, 30), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255, 0, 255), 1)#写入图像的二进制数据f.seek(0)f.write(bytearray(img))

canny边缘检测算法非常复杂,但是也很有趣,他有五个步骤,即使用高斯滤波器对图像进行去噪,计算梯度,在边缘上使用非最大抑制(NMS),在检测到边缘上使用双阈值去除假阳性,最后还会分析所有边缘及其之间的连接,以保留真正的边缘并不消除不明显的边缘。我这里给出张平老师写的《opencv算法 基于python和c++》精讲里的代码
main.py

 # -*- coding: utf-8 -*-import numpy as npimport sysimport mathimport cv2import sobel #注意sobel边缘检测#边缘检测#非极大值抑制def non_maximum_suppression_default(dx,dy):#边缘强度edgeMag = np.sqrt(np.power(dx,2.0) + np.power(dy,2.0))#宽、高rows,cols = dx.shape#梯度方向gradientDirection = np.zeros(dx.shape)#边缘强度非极大值抑制edgeMag_nonMaxSup = np.zeros(dx.shape)for r in range(1,rows-1):for c in range(1,cols-1):#angle 的范围 [0,180] [-180,0]angle = math.atan2(dy[r][c],dx[r][c])/math.pi*180gradientDirection[r][c] = angle#左 / 右方向if(abs(angle)<22.5 or abs(angle) >157.5):if(edgeMag[r][c]>edgeMag[r][c-1] and edgeMag[r][c] > edgeMag[r][c+1]):edgeMag_nonMaxSup[r][c] = edgeMag[r][c]#左上 / 右下方向  if(angle>=22.5 and angle < 67.5 or(-angle > 112.5 and -angle <= 157.5)):if(edgeMag[r][c] > edgeMag[r-1][c-1] and edgeMag[r][c]>edgeMag[r+1][c+1]):edgeMag_nonMaxSup[r][c] = edgeMag[r][c]#上 / 下方向if((angle>=67.5 and angle<=112.5) or (angle>=-112.5 and angle<=-67.5)):if(edgeMag[r][c] > edgeMag[r-1][c] and edgeMag[r][c] > edgeMag[r+1][c]):edgeMag_nonMaxSup[r][c] = edgeMag[r][c]#右上 / 左下方向if((angle>112.5 and angle<=157.5) or(-angle>=22.5 and -angle< 67.5 )):if(edgeMag[r][c]>edgeMag[r-1][c+1] and edgeMag[r][c] > edgeMag[r+1][c-1]):edgeMag_nonMaxSup[r][c] = edgeMag[r][c]return edgeMag_nonMaxSup#非极大值抑制:插值比较def non_maximum_suppression_Inter(dx,dy):#边缘强度edgeMag = np.sqrt(np.power(dx,2.0)+np.power(dy,2.0))#宽、高rows,cols = dx.shape#梯度方向gradientDirection = np.zeros(dx.shape)#边缘强度的非极大值抑制edgeMag_nonMaxSup = np.zeros(dx.shape)for r in range(1,rows-1):for c in range(1,cols-1):if dy[r][c] ==0 and dx[r][c] == 0:continue#angle的范围 [0,180],[-180,0]angle = math.atan2(dy[r][c],dx[r][c])/math.pi*180gradientDirection[r][c] = angle#左上方和上方的插值 右下方和下方的插值if (angle > 45 and angle <=90) or (angle > -135 and angle <=-90):ratio = dx[r][c]/dy[r][c]leftTop_top = ratio*edgeMag[r-1][c-1]+(1-ratio)*edgeMag[r-1][c]rightBottom_bottom = (1-ratio)*edgeMag[r+1][c] + ratio*edgeMag[r+1][c+1]if edgeMag[r][c] >  leftTop_top and edgeMag[r][c] > rightBottom_bottom:edgeMag_nonMaxSup[r][c]  = edgeMag[r][c]#右上方和上方的插值 左下方和下方的插值if (angle>90 and angle<=135) or (angle>-90 and angle <= -45):ratio = abs(dx[r][c]/dy[r][c])rightTop_top = ratio*edgeMag[r-1][c+1] + (1-ratio)*edgeMag[r-1][c]leftBottom_bottom = ratio*edgeMag[r+1][c-1] + (1-ratio)*edgeMag[r+1][c]if edgeMag[r][c] > rightTop_top and edgeMag[r][c] > leftBottom_bottom:edgeMag_nonMaxSup[r][c]  = edgeMag[r][c]#左上方和左方的插值 右下方和右方的插值if (angle>=0 and angle <=45) or (angle>-180 and angle <= -135):ratio = dy[r][c]/dx[r][c]rightBottom_right = ratio*edgeMag[r+1][c+1]+(1-ratio)*edgeMag[r][c+1]leftTop_left = ratio*edgeMag[r-1][c-1]+(1-ratio)*edgeMag[r][c-1]if edgeMag[r][c] > rightBottom_right and edgeMag[r][c] > leftTop_left:edgeMag_nonMaxSup[r][c]  = edgeMag[r][c]#右上方和右方的插值 左下方和左方的插值if(angle>135 and angle<=180) or (angle>-45 and angle <=0):ratio = abs(dy[r][c]/dx[r][c])rightTop_right = ratio*edgeMag[r-1][c+1]+(1-ratio)*edgeMag[r][c+1]leftBottom_left = ratio*edgeMag[r+1][c-1]+(1-ratio)*edgeMag[r][c-1]if edgeMag[r][c] > rightTop_right and edgeMag[r][c] > leftBottom_left:edgeMag_nonMaxSup[r][c]  = edgeMag[r][c]return edgeMag_nonMaxSup#判断一个点的坐标是否在图像范围内def checkInRange(r,c,rows,cols):if r>=0 and r<rows and c>=0 and c<cols:return Trueelse:return Falsedef trace(edgeMag_nonMaxSup,edge,lowerThresh,r,c,rows,cols):#大于阈值为确定边缘点if edge[r][c] == 0:edge[r][c]=255for i in range(-1,2):for j in range(-1,2):if checkInRange(r+i,c+j,rows,cols) and edgeMag_nonMaxSup[r+i][c+j] >= lowerThresh:trace(edgeMag_nonMaxSup,edge,lowerThresh,r+i,c+j,rows,cols)#滞后阈值def hysteresisThreshold(edge_nonMaxSup,lowerThresh,upperThresh):#宽高rows,cols = edge_nonMaxSup.shapeedge = np.zeros(edge_nonMaxSup.shape,np.uint8)for r in range(1,rows-1):for c in range(1,cols-1):#大于高阈值,设置为确定边缘点,而且以该点为起始点延长边缘if edge_nonMaxSup[r][c] >= upperThresh:trace(edgeMag_nonMaxSup,edge,lowerThresh,r,c,rows,cols)#小于低阈值,被剔除if edge_nonMaxSup[r][c]< lowerThresh:edge[r][c] = 0return edge#主函数if __name__ =="__main__":if len(sys.argv)>1:image = cv2.imread(sys.argv[1],cv2.CV_LOAD_IMAGE_GRAYSCALE)else:print("Usge:python canny.py imageFile")# ------- canny 边缘检测 -----------#第一步: 基于 sobel 核的卷积image_sobel_x,image_sobel_y = sobel.sobel(image,3)#边缘强度:两个卷积结果对应位置的平方和edge = np.sqrt(np.power(image_sobel_x,2.0) + np.power(image_sobel_y,2.0))#边缘强度的灰度级显示edge[edge>255] = 255edge = edge.astype(np.uint8)cv2.imshow("sobel edge",edge)#第二步:非极大值抑制edgeMag_nonMaxSup = non_maximum_suppression_default(image_sobel_x,image_sobel_y)edgeMag_nonMaxSup[edgeMag_nonMaxSup>255] =255edgeMag_nonMaxSup = edgeMag_nonMaxSup.astype(np.uint8)cv2.imshow("edgeMag_nonMaxSup",edgeMag_nonMaxSup)#第三步:双阈值滞后阈值处理,得到 canny 边缘#滞后阈值的目的就是最后决定处于高阈值和低阈值之间的是否为边缘点edge = hysteresisThreshold(edgeMag_nonMaxSup,60,180)lowerThresh = 40upperThresh = 150cv2.imshow("canny",edge)cv2.imwrite("canny.jpg",edge)# -------以下是为了单阈值与滞后阈值的结果比较 ------#大于高阈值 设置为白色 为确定边缘EDGE = 255#小于低阈值的设置为黑色 表示不是边缘,被剔除NOEDGE = 0#而大于等于低阈值 小于高阈值的设置为灰色,标记为可能的边缘POSSIBLE_EDGE = 128tempEdge = np.copy(edgeMag_nonMaxSup)rows,cols = tempEdge.shapefor r in xrange(rows):for c in xrange(cols):if tempEdge[r][c]>=upperThresh:tempEdge[r][c] = EDGEelif tempEdge[r][c]<lowerThresh:tempEdge[r][c] = NOEDGEelse:tempEdge[r][c] = POSSIBLE_EDGEcv2.imshow("tempEdge",tempEdge)lowEdge = np.copy(edgeMag_nonMaxSup)lowEdge[lowEdge>60] = 255lowEdge[lowEdge<60] = 0cv2.imshow("lowEdge",lowEdge)upperEdge = np.copy(edgeMag_nonMaxSup)upperEdge[upperEdge>180]=255upperEdge[upperEdge<=180]=0cv2.imshow("upperEdge",upperEdge)cv2.waitKey(0)cv2.destroyAllWindows()

sobel.py

# -*- coding: utf-8 -*-
import numpy as np
import sys
import math
import cv2
from scipy import signal
#二项式展开式的系数,即平滑系数
def pascalSmooth(n):pascalSmooth = np.zeros([1,n],np.float32)for i in range(n):pascalSmooth[0][i] = math.factorial(n -1)/(math.factorial(i)*math.factorial(n-1-i))return pascalSmooth
#计算差分
def pascalDiff(n):pascalDiff = np.zeros([1,n],np.float32)pascalSmooth_previous = pascalSmooth(n-1)for i in range(n):if i ==0:#恒等于 1pascalDiff[0][i] = pascalSmooth_previous[0][i]elif i == n-1:#恒等于 -1pascalDiff[0][i] = -pascalSmooth_previous[0][i-1]else:pascalDiff[0][i] = pascalSmooth_previous[0][i] - pascalSmooth_previous[0][i-1]return pascalDiff
#通过平滑系数和差分系数的卷积运算计算卷积核
def getSobelKernel(winSize):pascalSmoothKernel = pascalSmooth(winSize)pascalDiffKernel = pascalDiff(winSize)#水平方向上的卷积核sobelKernel_x = signal.convolve2d(pascalSmoothKernel.transpose(),pascalDiffKernel,mode='full')#垂直方向上的卷积核sobelKernel_y = signal.convolve2d(pascalSmoothKernel,pascalDiffKernel.transpose(),mode='full')return (sobelKernel_x,sobelKernel_y)
# sobel 边缘检测
def sobel(image,winSize):rows,cols = image.shapepascalSmoothKernel = pascalSmooth(winSize)pascalDiffKernel = pascalDiff(winSize)# --- 与水平方向的卷积核卷积 ----image_sobel_x = np.zeros(image.shape,np.float32)#垂直方向上的平滑image_sobel_x = signal.convolve2d(image,pascalSmoothKernel.transpose(),mode='same')#水平方向上的差分image_sobel_x = signal.convolve2d(image_sobel_x,pascalDiffKernel,mode='same')# --- 与垂直方向上的卷积核卷积 --- image_sobel_y = np.zeros(image.shape,np.float32)#水平方向上的平滑image_sobel_y = signal.convolve2d(image,pascalSmoothKernel,mode='same')#垂直方向上的差分image_sobel_y = signal.convolve2d(image_sobel_y,pascalDiffKernel.transpose(),mode='same')return (image_sobel_x,image_sobel_y)
#主函数
if __name__ =="__main__":if len(sys.argv)>1:image = cv2.imread(sys.argv[1],cv2.CV_LOAD_IMAGE_GRAYSCALE)else:print "Usge:python Sobel.py imageFile"#得到卷积核sobelKernel3 = getSobelKernel(3)sobelKernel5 = getSobelKernel(5)print(sobelKernel3)print(sobelKernel5)#卷积image_sobel_x,image_sobel_y = sobel(image,3)edge_x = np.abs(image_sobel_x)edge_x[ edge_x>255]=255edge_x=edge_x.astype(np.uint8)edge_y = np.abs(image_sobel_y)edge_y[ edge_y>255]=255edge_y=edge_y.astype(np.uint8)cv2.imwrite("img7_sobel_x_3_3.jpg",edge_x)cv2.imwrite("img7_sobel_y_3_3.jpg",edge_y)#边缘强度:两个卷积结果对应位置的平方和edge = np.sqrt(np.power(image_sobel_x,2.0) + np.power(image_sobel_y,2.0))#边缘强度的灰度级显示edge[edge>255] = 255edge = np.round(edge)edge = edge.astype(np.uint8)cv2.imshow("sobel edge",edge)cv2.imwrite("sobel.jpg",edge)#模拟素描pencilSketch = edge.copy()pencilSketch = 255 - pencilSketchpencilSketch[pencilSketch < 80] = 80cv2.imshow("pencilSketch",pencilSketch)cv2.imwrite("pencilSketch.jpg",pencilSketch)cv2.waitKey(0)cv2.destroyAllWindows()

R329-canny边缘检测相关推荐

  1. OpenCV 笔记(03)— 读取视频、通过摄像头采集视频、采集视频 canny 边缘检测

    我们本节学习如何利用 OpenCV 中的 VideoCapture 类,来对视频进行读取显示,以及调用摄像头. VideoCapture 它提供了从摄像机或视频文件捕获视频的 C++ 接口, 作用是从 ...

  2. OpenCV 笔记(02)— 图像显示、保存、腐蚀、模糊、canny 边缘检测(imread、imshow、namedWindow、imwrite)

    OpenCV 提供两种用户界面选项: 基于原生用户界面的基本界面,适用于 Mac OS X 的 cocoa 或 carbon,以及适用于 Linux 或 Windows 用户界面的 GTK ,这些界面 ...

  3. OpenCV+python:Canny边缘检测算法

    1,边缘处理 图像边缘信息主要集中在高频段,通常说图像锐化或检测边缘,实质就是高频滤波.我们知道微分运算是求信号的变化率,具有加强高频分量的作用. 在空域运算中来说,对图像的锐化就是计算微分.由于数字 ...

  4. Python,Opencv cv2.Canny()边缘检测

    Python,Opencv的Canny边缘检测 1. 效果图 2. 源码 参考 这篇博客将介绍Canny边缘检测的概念,并利用cv2.Canny()实现边缘检测: Canny边缘检测是一种流行的边缘检 ...

  5. 【OpenCV 】Sobel 导数/Laplace 算子/Canny 边缘检测

    canny边缘检测见OpenCV [七]----边缘提取算子(图像边缘提取)--canny算法的原理及实现 1 Sobel 导数 1.1.1 原因 上面两节我们已经学习了卷积操作.一个最重要的卷积运算 ...

  6. python边缘检测代码_python Canny边缘检测算法的实现

    图像边缘信息主要集中在高频段,通常说图像锐化或检测边缘,实质就是高频滤波.我们知道微分运算是求信号的变化率,具有加强高频分量的作用.在空域运算中来说,对图像的锐化就是计算微分.对于数字图像的离散信号, ...

  7. opencv Canny边缘检测用法

    <span style="color:#000080">1. cv2.Canny(image, threshold1, threshold2[, edges[, ape ...

  8. python opencv 边缘检测_opencv-python-学习笔记十四(Canny边缘检测)

    原理 Canny边缘检测是一种常用的边缘检测算法.由 John F. Canny提出 这是一个多阶段的算法,我们将经历每个阶段. 1.降低噪音 由于边缘检测容易受到图像中噪声的影响,第一步是用5x5高 ...

  9. 利用Canny边缘检测算子进行边缘检测的原理及OpenCV代码实现

    图像处理开发需求.图像处理接私活挣零花钱,请加微信/QQ 2487872782 图像处理开发资料.图像处理技术交流请加QQ群,群号 271891601 Canny算子是John Canny在1986年 ...

  10. Canny边缘检测原理及C#程序实现

    原文:Canny边缘检测原理及C#程序实现 Canny边缘检测是被公认的检测效果最好的边缘检测方法,是由John F. Canny于1986年提出,算法目标是找出一个最优的边缘检测的方法,所谓最优即: ...

最新文章

  1. Linux Java Web 服务器搭建之tomcat安装
  2. Python 正则表达式(分组)
  3. 高效的沟通方式-会议
  4. AtCoder AGC029E Wandering TKHS
  5. 飞畅科技-工业以太网交换机组网方式介绍
  6. nagios的实时监控
  7. 全球信息数据量陡增 大数据应用前景广阔
  8. python语言程序设计实践教程答案实验五_Python程序设计实验五
  9. 机顶盒ttl无法输入_请教大神,机顶盒接TTL进不了uboot模式
  10. mysql分页查询非常慢_MySQL分页查询慢的原因及解决方案
  11. msm8953 usb记录
  12. 我爱淘冲刺阶段站立会议每天任务1
  13. 我是ASML,除了技术,还有故事
  14. Matlab save colormap
  15. 编译google test 源码
  16. 薇诺娜如何以创新战略在新消费浪潮中屹立不倒
  17. android 播放多个音频文件,android – 如何同时播放多个ogg或mp3 ..?
  18. 当代年轻人到底怎么跨越阶层?
  19. 2021年跨境电商还值得做吗,怎么选择适合自己的电商平台
  20. 计算机理论如何指导实践,计算机专业教学中理论与实践的结合

热门文章

  1. python turtle什么意思_python模块turtle简单用法
  2. Mac和XCode技巧
  3. HFC(光纤同轴电缆混合网)
  4. 何苦做游戏 — 一位网游制作人的成长故事
  5. 二、openwrt自定义编译包的过程
  6. MinGW CygWin、mingw64-gcc cygwin-gcc区别
  7. 2021入职培训有感:站在新的起点,迎接新的挑战
  8. 科目二 如何侧方位停车
  9. 统计信号处理:(估计二) 最小方差无偏估计
  10. 培训机构大众点评微信小程序