一、Sobel函数
- 在 OpenCV 内,使用函数 cv2.Sobel()实现 Sobel 算子运算,其语法形式为:
dst = cv2.Sobel( src, ddepth, dx, dy[,ksize[, scale[, delta[, borderType]]]] )-
ddepth 代表输出图像的深度。其具体对应关系如表9-1 所示。
- dx 代表 x 方向上的求导阶数。
- dy 代表 y 方向上的求导阶数。
- ksize 代表 Sobel 核的大小。该值为-1 时,则会使用 Scharr 算子进行运算。
- scale 代表计算导数值时所采用的缩放因子,默认情况下该值是 1,是没有缩放的。
- delta 代表加在目标图像 dst 上的值,该值是可选的,默认为 0。
-
borderType 代表边界样式。该参数的具体类型及值如表 9-2 所示。
-
二、使用
- 计算x方向边缘(梯度):dx=1,dy=0
- 计算 y 方向边缘(梯度):dx=0, dy=1。
- 参数 dx 与参数 dy 的值均为 1:dx=1, dy=1。
- 计算 x 方向和 y 方向的边缘叠加:通过组合方式实现。
三、一半不到的圆形轮廓
import cv2
import numpy as np
# 读取图像
image = cv2.imread(r'D:\OpenCVpic\yuan.png', 0)
cv2.imshow('image', image)
yuan_x=cv2.Sobel(image,-1,dx=1,dy=0)
cv2.imshow('yuan_x', yuan_x)
# 窗口等待命令 0表示无限等待
cv2.waitKey(0)
cv2.destroyAllWindows()
-
Gx矩阵的计算本质上是该像素点的右侧减左侧。
在该处的Sobel函数中,-1表示与原图像相同的深度,即默认的uint8。
对于处于左侧边缘的像素来说,右边是白色(255)左边是黑色(0),那么右减左就是255(白色),但是对于图像左边来说,右边是黑色(0),左边是白色(255),右减左等于-255,然而由于0penCV中图像矩阵是uint8类型的,取值范围是0-255,那么对于-255他会默认赋予0(黑色)。
如果想得到更为完整的圆形轮廓,则可以改用以下代码
四、接近完整的圆形轮廓
import cv2
import numpy as np
# 读取图像
image = cv2.imread(r'D:\OpenCVpic\yuan.png', 0)
cv2.imshow('image', image)
yuan_x_64=cv2.Sobel(image,cv2.CV_64F,dx=1,dy=0)
yuan_x_full = cv2.convertScaleAbs(yuan_x_64)
cv2.imshow('yuan_x_full', yuan_x_full)
# 窗口等待命令 0表示无限等待
cv2.waitKey(0)
cv2.destroyAllWindows()
- 对比两次运行的第5行代码可以发现,该处将Sobel的第5个变量-1更改为cv2.CV 64F,即将默认的int8改为fioat64,因此可保存负数。
之后通过第6行的绝对值变换成功将右侧保留下来的-255更换为255,成功被检测.
五、完整的圆形轮廓
- 从上面的结果可以发现,虽然左右都被成功检测,但上下方的轮廓依旧不完整,这很好理解,因为上下方的像素点左右都为黑0,通过Gx肯定无法得到结果,因此此出我们可以转换思路,通过Gy检测竖直方向的轮廓,然后将两个最终的轮廓图进行叠加,即可得到完整的圆形轮廓
# -*- coding: utf-8 -*-
"""
Created on Thu Sep 5 15:56:03 2024
@author: Administrator
"""
import cv2
import numpy as np
# 读取图像
image = cv2.imread(r'D:\OpenCVpic\yuan.png', 0)
cv2.imshow('image', image)
yuan_x_64=cv2.Sobel(image,cv2.CV_64F,dx=1,dy=0)
yuan_x_full = cv2.convertScaleAbs(yuan_x_64)
yuan_y_64=cv2.Sobel(image,cv2.CV_64F,dx=0,dy=1)
yuan_y_full = cv2.convertScaleAbs(yuan_y_64)
yuan_xy_full = cv2.addWeighted(yuan_x_full,1,yuan_y_full,1,0)
cv2.imshow('yuan_xy_full', yuan_xy_full)
# 窗口等待命令 0表示无限等待
cv2.waitKey(0)
cv2.destroyAllWindows()
六、资料
[51cto]mob6454cc7b8169的博客
https://blog.51cto.com/u_16099349/11371871