目录
-
- 图像平滑处理(滤波操作)
-
- [1.均值滤波 blur()](#1.均值滤波 blur())
- [2.方框滤波 boxFilter()](#2.方框滤波 boxFilter())
- 3.高斯滤波GaussianBlur()
- 4.中值滤波medianBlur()
- 形态学操作morphology
- 计算图像梯度
图像平滑处理(滤波操作)
让有噪音点(图像上显得突兀的像素点)的图像变得更加自然顺眼
1.均值滤波 blur()
根据核的大小(rowcol),每个像素值就等于以此像素为中心的周围rowcol个像素的平均值。
核大一点,显然越平滑、模糊。
result = cv2.blur(img, (15, 15))
2.方框滤波 boxFilter()
normalize=true的时候,效果同均值滤波;normalize=false的时候,α=1,仅求和。
result1 = cv2.boxFilter(img, -1, (3,3), normalize=0)
result2 = cv2.boxFilter(img, -1, (6,6), normalize=1)
3.高斯滤波GaussianBlur()
原理为高斯分布(正态分布)
与均值滤波对比,其实还是利用周围的元素,不过周围每个元素的权重不同。
核宽度和高度必须是奇数。
让临近的像素具有更高的重要度,对周围像素计算加权平均值,较近的像素具有较大的权重值。
result = cv2.GaussianBlur(img, (15, 15), 0)
注:(15, 15)表示高斯滤波器的长和宽,0表示滤波器的标准差
4.中值滤波medianBlur()
非常适用于有椒盐点的图像
依据核大小,选取以某个像素为中心的那些像素的中位数作为本像素的值。
本滤波,核宽度核高度是相同的,只需要指明边长。
result = cv2.medianBlur(img, 3)
形态学操作morphology
使用卷积核
1.腐蚀操作
cv2.erode(img,kernel,iterations)
就像土壤侵蚀一样,这个操作会把前景物体的边界腐蚀掉(但是前景仍然是白色)。
卷积核沿着图像滑动,如果与卷积核对应的原图像的所有像素值都是1,
那么中心元素就保持原来的像素值,否则就变为零。
- 作用:去除白噪声、断开两个连在一块的物体...
python
img = cv2.imread('j.png',0)
kernel = np.ones((5,5),np.uint8)
erosion = cv2.erode(img,kernel,iterations = 1)
其中,
- img 指需要腐蚀的图
- kernel 指腐蚀操作的内核,默认是一个简单的3X3矩阵,
我们也可以利用getStructuringElement()函数指明它的形状 - iterations 指的是腐蚀次数,省略是默认为1
2.膨胀操作
python
cv2.dilate(img,kernel,iterations)
dilation = cv2.dilate(img,kernel,iterations = 1)
与腐蚀相反,与卷积核对应的原图像的像素值中只要有一个是1,中心元素的像素值就是1。
可以弥补腐蚀操作后的结果(填充被腐蚀的部分、连接两个被分开的物体...)
腐蚀是我们将"腐蚀"边缘。 它的工作方式是使用滑块(核)。
我们让滑块滑动,如果所有的像素是白色的,那么我们得到白色,否则是黑色。 这可能有助于消除一些白色噪音。
另一个版本是膨胀,它基本上是相反的:让滑块滑动,如果整个区域不是黑色的,就会转换成白色。
3.开运算 cv2.morphologyEx()
先进性腐蚀再进行膨胀就叫做开运算。它被用来去除噪声。
python
opening = cv2.morphologyEx(img, cv2.MORPH_OPEN, kernel)
4.闭运算 cv2.morphologyEx()
先膨胀再腐蚀。它经常被用来填充前景物体中的小洞,或者前景物体上的小黑点。
python
closing = cv2.morphologyEx(img, cv2.MORPH_CLOSE, kernel)
5.梯度运算
梯度 = 膨胀后的图像 - 腐蚀后的图像
python
gradient = cv2.morphologyEx(img, cv2.MORPH_GRADIENT, kernel)
6.礼帽与黑帽
礼帽 = 原始输入 - 开运算结果
python
tophat = cv2.morphologyEx(img, cv2.MORPH_TOPHAT, kernel)
黑帽 = 闭运算结果 - 原始输入
python
blackhat = cv2.morphologyEx(img, cv2.MORPH_BLACKHAT, kernel)
计算图像梯度
梯度
图像函数f(x,y)在点(x,y)的梯度是一个具有大小和方向的矢量,梯度的方向是函数f(x,y)变化最快的方向,当图像中存在边缘时,一定有较大的梯度值,相反,当图像中有比较平滑的部分时,灰度值变化较小,则相应的梯度也较小,图像处理中把梯度的模简称为梯度。
简单理解,一个图像是一个函数,梯度就是灰度值的变化率
图像的梯度是多少?哪些地方有梯度、找出来。
相当于边缘检测(在图像中物体的边缘像素点才有明显的数值变化,即梯度)
1.Sobel算子
从右到左,从下到上
右边减左边,下边减上边
得到边缘
python
dst = cv2.Sobel(src, ddepth, dx, dy, ksize)
其中,
- ddepth 图像的深度,通常为-1,或cv2.CV_64F表示负数
- dx、dy 表示水平和竖直方向
- ksize 是Sobel算子的大小,通常用33或55
注:cv2会默认进行截断,即像素点数值范围为0-255,小于0的全为0,大于255为255
白到黑是正数,黑到白就是负数了,所有的负数会被截断,为0,即都是黑的
故为了左右两侧边缘都能显示,需要加上绝对值cv2.convertScaleAbs(),即
python
sobelx = cv2.Sobel(img, cv2.CV_64F, 1, 0, ksize=3)
sobelx = cv2.convertScaleAbs(sobely)
以上为求Gx,即dx=1,dy=0,下面求Gy
python
sobely = cv2.Sobel(img, cv2.CV_64F, 0, 1, ksize=3)
sobely = cv2.convertScaleAbs(sobely)
分别计算x和y,再求和
python
sobleXY = cv2.addWeighted(sobelx, 0.5, sobely, 0.5, 0)
注:两个0.5是两个图像的比例权重,最后的0是偏置项,一般为0
以上为一般步骤,即x、y分开算再求和。若直接dx=1,dy=1一次算的话,效果不好。
2.Scharr算子
python
scharrx = cv2.Scharr(img,cv2.CV_64F, 1, 0)
scharry = cv2.Scharr(img,cv2.CV_64F, 0, 1)
scharrx = cv2.convertScaleAbs(scharrx)
scharry = cv2.convertScaleAbs(scharry)
scharrxy = cv.addWeighted(scharrx, 0.5, scharry, 0.5)
其中,
- scharrx = cv2.Scharr(img, cv2.CV_64F, 1, 0): 这一行对输入图像 img 沿着x轴应用Scharr算子。Scharr算子是一种用于边缘检测的卷积滤波器。
- scharry = cv2.Scharr(img, cv2.CV_64F, 0, 1): 这一行对输入图像 img 沿着y轴应用Scharr算子。
- scharrx = cv2.convertScaleAbs(scharrx): 将 scharrx 转换为无符号整数类型。这是因为Scharr算子的计算结果可能包含负值,而转换为无符号整数可以保留正数部分。
- scharry = cv2.convertScaleAbs(scharry): 将 scharry 转换为无符号整数类型。
- scharrxy = cv.addWeighted(scharrx, 0.5, scharry, 0.5): 使用 cv.addWeighted 函数将经过Scharr算子处理的x方向和y方向的图像叠加起来,创建一个新的图像 scharrxy。这里权重分别为0.5,表示对两个方向的处理结果进行平均。
3.laplacian算子
对像素点数值变化更敏感,也就意味着对图像上的噪音点敏感,容易认为是边缘。
单独使用效果不好。
python
Laplacian = cv2.Laplacian(img,cv2.CV_64F)
laplacian = cv2.convertScaleAbs(laplacian)
- scharr最深刻,然后soble,laplacian最浅。算子的核不同。
- 这里举一个简单的例子:
python
import cv2
import numpy as np
from matplotlib import pyplot as plt
# 读取图像
img = cv2.imread('./image/car1.jpg', cv2.IMREAD_GRAYSCALE)
# 进行形态学膨胀操作
kernel = np.ones((5,5), np.uint8) # 5x5 的卷积核
dilation = cv2.dilate(img, kernel, iterations=1)
# 进行形态学腐蚀操作
erosion = cv2.erode(img, kernel, iterations=1)
# 显示原始图像、膨胀和腐蚀的结果
plt.subplot(131), plt.imshow(img, cmap='gray'), plt.title('Original Image')
plt.subplot(132), plt.imshow(dilation, cmap='gray'), plt.title('Dilation')
plt.subplot(133), plt.imshow(erosion, cmap='gray'), plt.title('Erosion')
plt.show()
# 进行边缘检测(使用Sobel算子)
sobelx = cv2.Sobel(img, cv2.CV_64F, 1, 0, ksize=5)
sobely = cv2.Sobel(img, cv2.CV_64F, 0, 1, ksize=5)
edges = cv2.magnitude(sobelx, sobely)
# 显示边缘检测结果
plt.subplot(121), plt.imshow(img, cmap='gray'), plt.title('Original Image')
plt.subplot(122), plt.imshow(edges, cmap='gray'), plt.title('Edge Detection (Sobel)')
plt.show()
结果如下: