当前位置:   article > 正文

【8】python-opencv3教程:边缘检测(Roberts算子边缘检测,Prewitt算子边缘检测,Sobel算子边缘检测)_45度的sobel核

45度的sobel核

第八节:边缘检测

         边缘检测:边缘检测指的是灰度值发生急剧变化的位置,边缘检测的目的是制作一个线图,在不会损害理解图像内容的情况下, 有大大减少了图像的数据量,提供了对图像数据的合适概述。

一:Roberts算子

代码实现:

  1. import cv2
  2. import numpy as np
  3. from scipy import signal
  4. def roberts(I, _boundary='fill', _fillvalue=0):
  5. # 图像的高,宽
  6. H1, W1 = I.shape[0:2]
  7. # 卷积核的尺寸
  8. H2, W2 = 2, 2
  9. # 卷积核1 和 锚点的位置
  10. R1 = np.array([[1, 0], [0, -1]], np.float32)
  11. kr1, kc1 = 0, 0
  12. # 计算full卷积
  13. IconR1 = signal.convolve2d(I, R1, mode='full', boundary=_boundary, fillvalue=_fillvalue)
  14. IconR1 = IconR1[H2-kr1-1:H1+H2-kr1-1, W2-kc1-1:W1+W2-kc1-1]
  15. # 卷积核2 和 锚点的位置
  16. R2 = np.array([[0, 1], [-1, 0]], np.float32)
  17. kr2, kc2 = 0, 1
  18. # 再计算full卷积
  19. IconR2 = signal.convolve2d(I, R2, mode='full', boundary=_boundary, fillvalue=_fillvalue)
  20. IconR2 = IconR2[H2-kr2-1:H1+H2-kr2-1, W2-kc2-1:W1+W2-kc2-1]
  21. return (IconR1, IconR2)
  22. if __name__ == '__main__':
  23. I = cv2.imread('img3.png', cv2.IMREAD_GRAYSCALE)
  24. # 显示原图
  25. cv2.imshow('origin', I)
  26. # 卷积,注意边界一般扩充采用的symm
  27. IconR1, IconR2 = roberts(I, 'symm')
  28. # 45度方向上的边缘强度的灰度级显示
  29. IconR1 = np.abs(IconR1)
  30. edge45 = IconR1.astype(np.uint8)
  31. cv2.imshow('edge45', edge45)
  32. # 135度方向上的边缘强度的灰度级显示
  33. IconR2 = np.abs(IconR2)
  34. edge135 = IconR2.astype(np.uint8)
  35. cv2.imshow('edge135', edge135)
  36. # 用平方和的开方来衡量最后输出的边缘
  37. edge = np.sqrt(np.power(IconR1, 2.0) + np.power(IconR2, 2.0))
  38. edge = np.round(edge)
  39. edge[edge > 255] = 255
  40. edge = edge.astype(np.uint8)
  41. # 显示边缘
  42. cv2.imshow('edge', edge)
  43. cv2.waitKey(0)
  44. cv2.destroyAllWindows()

输出结果:

二: Prewitt边缘检测

代码实现:

  1. import cv2
  2. import numpy as np
  3. from scipy import signal
  4. def prewitt(I, _boundary = 'symm', ):
  5. # prewitt算子是可分离的。 根据卷积运算的结合律,分两次小卷积核运算
  6. # 算子分为两部分,这是对第一部分操作
  7. # 1: 垂直方向上的均值平滑
  8. ones_y = np.array([[1], [1], [1]], np.float32)
  9. i_conv_pre_x = signal.convolve2d(I, ones_y, mode='same', boundary=_boundary)
  10. # 2: 水平方向上的差分
  11. diff_x = np.array([[1, 0, -1]], np.float32)
  12. i_conv_pre_x = signal.convolve2d(i_conv_pre_x, diff_x, mode='same', boundary=_boundary)
  13. # 算子分为两部分,这是对第二部分操作
  14. # 1: 水平方向上的均值平滑
  15. ones_x = np.array([[1, 1, 1]], np.float32)
  16. i_conv_pre_y = signal.convolve2d(I, ones_x, mode='same', boundary=_boundary)
  17. # 2: 垂直方向上的差分
  18. diff_y = np.array([[1], [0], [-1]], np.float32)
  19. i_conv_pre_y = signal.convolve2d(i_conv_pre_y, diff_y, mode='same', boundary=_boundary)
  20. return (i_conv_pre_x, i_conv_pre_y)
  21. if __name__ == '__main__':
  22. I = cv2.imread('img7.jpg', cv2.IMREAD_GRAYSCALE)
  23. cv2.imshow('origin', I)
  24. i_conv_pre_x, i_conv_pre_y = prewitt(I)
  25. # 取绝对值,分别得到水平方向和垂直方向的边缘强度
  26. abs_i_conv_pre_x = np.abs(i_conv_pre_x)
  27. abs_i_conv_pre_y = np.abs(i_conv_pre_y)
  28. # 水平方向和垂直方向上的边缘强度的灰度级显示
  29. edge_x = abs_i_conv_pre_x.copy()
  30. edge_y = abs_i_conv_pre_y.copy()
  31. # 将大于255的值截断为255
  32. edge_x[edge_x > 255] = 255
  33. edge_y[edge_y > 255] = 255
  34. # 数据类型转换
  35. edge_x = edge_x.astype(np.uint8)
  36. edge_y = edge_y.astype(np.uint8)
  37. # 显示
  38. cv2.imshow('edge_x', edge_x)
  39. cv2.imshow('edge_y', edge_y)
  40. # 利用abs_i_conv_pre_x 和 abs_i_conv_pre_y 求最终的边缘强度
  41. # 求边缘强度有多重方法, 这里使用的是插值法
  42. edge = 0.5 * abs_i_conv_pre_x + 0.5 * abs_i_conv_pre_y
  43. # 边缘强度灰度级显示
  44. edge[edge > 255] = 255
  45. edge = edge.astype(np.uint8)
  46. cv2.imshow('edge', edge)
  47. cv2.waitKey(0)
  48. cv2.destroyAllWindows()

输出结果:

三:Sobel边缘检测

代码实现:

  1. import math
  2. import cv2
  3. import numpy as np
  4. from scipy import signal
  5. def pascalSmooth(n):
  6. # 返回n阶的非归一化的高斯平滑算子
  7. pascalSmooth = np.zeros([1, n], np.float32)
  8. for i in range(n):
  9. pascalSmooth[0][i] = math.factorial(n - 1) / (math.factorial(i) * math.factorial(n-1-i))
  10. return pascalSmooth
  11. def pascalDiff(n): # 在一半之前是逐差法。。后半部分的值和前半部分对应
  12. # 返回n阶差分算子
  13. pascalDiff = np.zeros([1, n], np.float32)
  14. pascalSmooth_previous = pascalSmooth(n - 1)
  15. for i in range(n):
  16. if i == 0:
  17. # 恒等于1
  18. pascalDiff[0][i] = pascalSmooth_previous[0][i]
  19. elif i == n-1:
  20. pascalDiff[0][i] = pascalSmooth_previous[0][i-1]
  21. else:
  22. pascalDiff[0][i] = pascalSmooth_previous[0][i] - pascalSmooth_previous[0][i-1]
  23. return pascalDiff
  24. def getSmoothKernel(n):
  25. # 返回两个sobel算子
  26. pascalSmoothKernel = pascalSmooth(n)
  27. pascalDiffKernel = pascalDiff(n)
  28. # 水平方向上的卷积核
  29. sobelKernel_x = signal.convolve2d(pascalSmoothKernel.transpose(), pascalDiffKernel, mode='full')
  30. # 垂直方向上的卷积核
  31. sobelKernel_y = signal.convolve2d(pascalSmoothKernel, pascalDiffKernel.transpose(), mode='full')
  32. return (sobelKernel_x, sobelKernel_y)
  33. def sobel(image, n):
  34. rows, cols = image.shape
  35. # 得到平滑算子
  36. pascalSmoothKernel = pascalSmooth(n)
  37. # 得到差分算子
  38. pascalDiffKernel = pascalDiff(n)
  39. # 与水平方向的sobel核卷积
  40. # 先进行垂直方向的平滑
  41. image_sobel_x = signal.convolve2d(image, pascalSmoothKernel.transpose(), mode='same')
  42. # 再进行水平方向的差分
  43. image_sobel_x = signal.convolve2d(image_sobel_x, pascalDiffKernel, mode='same')
  44. # 与垂直方向的sobel核卷积
  45. # 先进行水平方向的平滑
  46. image_sobel_y = signal.convolve2d(image, pascalSmoothKernel, mode='same')
  47. image_sobel_y = signal.convolve2d(image_sobel_y, pascalDiffKernel.transpose(), mode='same')
  48. return (image_sobel_x, image_sobel_y)
  49. if __name__ == '__main__':
  50. I = cv2.imread('img7.jpg', cv2.IMREAD_GRAYSCALE)
  51. cv2.imshow('origin', I)
  52. # 卷积
  53. image_sobel_x, image_sobel_y = sobel(I, 7)
  54. # cv2.imshow('image_sobel_x', image_sobel_x)
  55. # cv2.imshow('image_sobel_y', image_sobel_y)
  56. # 平方和的方式展开
  57. edge = np.sqrt(np.power(image_sobel_x, 2.0) + np.power(image_sobel_y, 2.0))
  58. # 边缘强度的灰度级显示
  59. edge = edge / np.max(edge)
  60. edge = np.power(edge, 1)
  61. edge = edge * 255
  62. edge = edge.astype(np.uint8)
  63. cv2.imshow('edge', edge)
  64. cv2.waitKey(0)
  65. cv2.destroyAllWindows()

 输出结果:
 

    后面出一节,狂调API。。。无需实现这些算法,只需知道在opencv中怎么调用。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/花生_TL007/article/detail/69780
推荐阅读
相关标签
  

闽ICP备14008679号