opencv的sobel算子(自己实现与官方比较)

本文通过实现Sobel算子并对比标准函数效果,探讨了Sobel算子的细节,如梯度计算中除数的选择及图像处理过程中的常见问题解决方法。

做了sobel的实现,比较现有函数,发现自己的问题。

3*3的sobel为:[[1,2,1],[0,0,0],[-1,-2,-1]]/8和它的转置矩阵。

为什么除以8不是4呢,我猜是因为隐含了(求导1+求导2)/2的变换。比如3*3的图形,求正中间像素的梯度,有[(A[0][1]-A[1][1])+(A[1][1]-A[2][1])]/2。

所以得出整体除以8作为梯度值。

视线中的问题和学到的:1、cv2.filter2D做的其实是相关,不是卷积

    2、用astype做负浮点数的变换(到np.uint8),会做类似缩放,把整个二维数组映射到(-255,255)

    3、导致cv2.Sobel是灰的,我的图是黑白。。。

所以,我把sobel算子和原图做了相关后,加了128,这样和官方的效果差不多了。不过y图的好像反了,不过关系不大。

代码:

import cv2
import numpy as np
import matplotlib.pyplot as plt
pic=cv2.imread("C:\\Users\\acer\\Pictures\\book.jpg")
pic_float=pic.astype(np.float)
pic1=cv2.cvtColor(pic, cv2.COLOR_RGB2GRAY)

edge=cv2.Canny(pic1,80,170)
#cv2.imshow("GRAY",pic1)
#cv2.imshow("EDGE",edge)
pic1=pic1.astype(np.float)
sobelx=cv2.Sobel(pic1,cv2.CV_64F,1,0,ksize=3)
sobely=cv2.Sobel(pic1,cv2.CV_64F,0,1,ksize=3)

kernel=np.array([[1.0,2.0,1.0],[2.0,4.0,2.0],[1.0,2.0,1.0]])/16
kernelx=np.array([[-1.0,0.0,1.0],[-2.0,0.0,2.0],[-1.0,0.0,1.0]])/8
kernely=np.array([[1.0,2.0,1.0],[0.0,0.0,0.0],[-1.0,-2.0,-1.0]])/8
pic1=cv2.filter2D(pic1,-1,kernel)
my_sobelx=cv2.filter2D(pic1,-1,kernelx)+128
my_sobely=cv2.filter2D(pic1,-1,kernely)+128

my_sobelx=my_sobelx.astype(np.uint8)
my_sobely=my_sobely.astype(np.uint8)

plt.subplot(2,2,1)
plt.imshow(sobelx,cmap='gray')
plt.title('X'),plt.xticks([1,2]),plt.yticks([3,4])
plt.subplot(2,2,2)
plt.imshow(sobely,cmap='gray')
plt.title('Y'),plt.xticks([]),plt.yticks([])
plt.subplot(2,2,3)
plt.imshow(my_sobelx,cmap='gray')
plt.title('MY_X'),plt.xticks([1,2]),plt.yticks([3,4])
plt.subplot(2,2,4)
plt.imshow(my_sobely,cmap='gray')
plt.title('MY_Y'),plt.xticks([]),plt.yticks([])


plt.show()


错的图(没加128)


改正后的图(放大一部分,清楚点,y图是反的)


以上。



### OpenCVSobel算子的使用实现 #### Sobel算子简介 Sobel算子是一种用于计算数字图像梯度的重要工具,在计算机视觉领域广泛应用。它通过两个 \(3 \times 3\) 的卷积核分别计算水平方向 (\(G_x\)) 垂直方向 (\(G_y\)) 的一阶偏导数,从而提取图像边缘信息[^4]。 #### 实现函数 `cv::Sobel` 在OpenCV库中,`cv::Sobel` 函数提供了便捷的方式来应用Sobel算子。以下是其基本语法: ```cpp void cv::Sobel( InputArray src, // 输入图像 OutputArray dst, // 输出图像 int ddepth, // 输出图像的深度 int dx, // x 方向上的导数阶数 int dy, // y 方向上的导数阶数 int ksize = 3, // 卷积核大小,默认为3 double scale = 1, // 缩放因子 double delta = 0, // 可选增量值 int borderType = BORDER_DEFAULT // 边界填充方式 ); ``` 其中,参数 `dx` `dy` 分别表示沿x轴y轴的方向导数阶次;当两者均为1时,则实现了标准的一阶Sobel算子操作[^2]。 #### Python代码示例 下面是一个简单的Python脚本,展示了如何使用OpenCV中的Sobel算子来检测灰度图的边缘: ```python import cv2 import numpy as np from matplotlib import pyplot as plt # 加载原始图片并转换成灰度模式 img = cv2.imread('image.jpg', cv2.IMREAD_GRAYSCALE) # 应用Sobel算子 sobelx = cv2.Sobel(img, cv2.CV_64F, 1, 0, ksize=5) # 计算X方向梯度 sobely = cv2.Sobel(img, cv2.CV_64F, 0, 1, ksize=5) # 计算Y方向梯度 # 显示结果 plt.subplot(2,2,1), plt.imshow(img,cmap='gray') plt.title('Original'), plt.xticks([]), plt.yticks([]) plt.subplot(2,2,2), plt.imshow(sobelx,cmap='gray') plt.title('Sobel X'), plt.xticks([]), plt.yticks([]) plt.subplot(2,2,3), plt.imshow(sobely,cmap='gray') plt.title('Sobel Y'), plt.xticks([]), plt.yticks([]) plt.show() ``` 上述代码加载了一张名为 'image.jpg' 的图像文件,并对其执行了基于Sobel算子的边缘增强处理[^1]。 #### 结果解释 运行以上程序后可以看到原图以及经过Sobel滤波器处理后的效果对比图。这些效果图能够清晰显示出物体轮廓其他显著变化区域的位置信息[^3]。 #### 注意事项 为了防止数据溢出或者精度损失问题,在调用 `cv::Sobel()` 方法之前通常会指定较高的目标位深(如 CV_16S 或者 CV_64F)。另外还需要注意的是如果输入源是彩色RGB格式的话则需先转为单通道灰度形式再做进一步分析。 ---
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值