图像处理-梯度计算

1.概述

2.Laplacian算子

下面我们用最后得出梯度的幅值为G(x,y)=(gx2+gy2)方向为: θ=arctangygx现在我们用程序来实现这个过程。

拉普拉斯算子,在数学上的表达式为:

L(x,y)=f(x)x(2)+f(y)y(2)

这个是对图像xy方向两次求导,然后相加。我门先看x方向的一阶导数,gx=f(x,y)f(x1,y),再对以一阶导数求导便是二阶导数,最终结果为:

gxx=gx(x+1)gx(x)=f(x+1,y)f(x,y)(f(x,y)f(x1,y))=f(x+1,y)2f(x,y)+f(x1,y)

最后同理可得:

gyy=f(x,y+1)2f(x,y)+f(x,y1)

最后可得:

L(x,y)=f(x)x(2)+f(y)y(2)=f(x+1,y)4f(x,y)+f(x1,y)+f(x,y+1)+f(x,y1)

用3x的模板可以表示为:

010141010

点击查看代码

import numpy as np
import cv2
import matplotlib.pyplot as plt

img = cv2.imread('lena.jpg', cv2.IMREAD_UNCHANGED)
img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

laplace = np.array([[0, -1, 0], [-1, 4, -1], [0, -1, 0]])

img_laplace = cv2.filter2D(img, -1, laplace)

img_opencv_laplacian = cv2.Laplacian(img, cv2.CV_64F, ksize=3)

plt.figure(figsize=(30, 10))  # 定义编号为1 大小为(8,5)
plt.subplot(1, 3, 1), plt.imshow(img, cmap='gray'), plt.title('source'), plt.xticks([]), plt.yticks([])
plt.subplot(1, 3, 2), plt.imshow(img_laplace, cmap='gray'), plt.title('Laplace by self code'), plt.xticks(
    []), plt.yticks([])
plt.subplot(1, 3, 3), plt.imshow(img_opencv_laplacian, cmap='gray'), plt.title('Laplace by Api'), plt.xticks(
    []), plt.yticks([])
plt.show()




这张图更加明显,拉普拉斯算子对差异较大的更加明显点,api感觉像是加上了一定偏移量

3.Sobel算子

(101202101)×(P1P2P3P4P5P6P7P8P9)

P5x:P5x=(P3P2)+2(P6P4)+(P9P7)
y,(121000121)
025500255255
0255255cv2.convertScaleAbs

总梯度

G=Gx2+Gy2,

简化版

G=|Gx|+|Gy|

点击查看代码

dst = cv2.Sobel(src,ddepth,dx,dy,[ksize])

ddepth: 不要取负数 cv2.CV_64F 扩展到负数,dst = cv2.convertScaleAbs(dst) 转为绝对值
ksize:核大小,必须是奇数
dx=1,dy=0:计算x轴方向,反之就是y方向

计算综合

用右边的,左边的边界不明显


不用手工计算,用api相加
dst=cv2.addWeighted

4.Scharr算子

为什么用scharr算子?
sobel算子不太精确
(30310010303)

(31030003103)

两个算子运算强度一样
scharr算子更加精确,这是为什么呢?

注意opencv计算的过程中可能会出现负值,所以要对负值取绝对值

点击查看代码

dst = Scharr(src,cv2.CV_64F,dx,dy) # ddpeth不能用-1,默认8位的int如果是负数就强制变成0了,所以要用cv2.CV_64F 扩大范围,允许负数,然后用下面的函数转为绝对值
dst = cv2.convertScaleAbs(dst)

其他和Sobel算子一样

Scharr算子和Sobel算子的关系

Scharr算子和Sobel算子的比较


大小一样,故计算量一样。
scharr算子临近像素的权重更大,故精确度更高。
对比两种算子的处理效果。发现scharr算子能计算出更小的梯度变化
虽然网上是这么说的,但是个人感觉从下面的比较来看,Sobel算子对图像的分割更加明显,我个人理解泛化性能更好一些,感觉Scharr还是加入了一些细小的噪声


5.自定义卷积核

这里把scharr卷积核中的邻近像素的权重加大了,更加加入了一些噪声

点击查看代码

import numpy as np
import cv2
import matplotlib.pyplot as plt

img = cv2.imread('lena.jpg')
img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
g_x = np.array([[-3, 0, 3], [-20, 0, 20], [-3, 0, 3]])

img_g_x = cv2.filter2D(img, -1, g_x)

plt.subplot(2, 3, 1), plt.imshow(img, cmap='gray'), plt.title('source'), plt.xticks([]), plt.yticks([])
plt.subplot(2, 3, 2), plt.imshow(img_g_x, cmap='gray'), plt.title('x gradient'), plt.xticks([]), plt.yticks([])
plt.show()


6.腐蚀+膨胀

腐蚀+膨胀 也能算出梯度,但是不精准

posted @   筷点雪糕侠  阅读(687)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· .NET10 - 预览版1新功能体验(一)
点击右上角即可分享
微信分享提示