python数字图像处理基础(四)——图像平滑处理、形态学操作、图像梯度

目录

    • 图像平滑处理(滤波操作)
      • 1.均值滤波 blur()
      • 2.方框滤波 boxFilter()
      • 3.高斯滤波GaussianBlur()
      • 4.中值滤波medianBlur()
    • 形态学操作morphology
      • 1.腐蚀操作
        • 2.膨胀操作
      • 3.开运算 cv2.morphologyEx()
      • 4.闭运算 cv2.morphologyEx()
      • 5.梯度运算
      • 6.礼帽与黑帽
    • 计算图像梯度
      • 1.Sobel算子
      • 2.Scharr算子
      • 3.laplacian算子

图像平滑处理(滤波操作)

让有噪音点(图像上显得突兀的像素点)的图像变得更加自然顺眼

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,
那么中心元素就保持原来的像素值,否则就变为零。

  • 作用:去除白噪声、断开两个连在一块的物体…
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.膨胀操作
cv2.dilate(img,kernel,iterations)
dilation = cv2.dilate(img,kernel,iterations = 1)

与腐蚀相反,与卷积核对应的原图像的像素值中只要有一个是1,中心元素的像素值就是1。
可以弥补腐蚀操作后的结果(填充被腐蚀的部分、连接两个被分开的物体…)

腐蚀是我们将“腐蚀”边缘。 它的工作方式是使用滑块(核)。
我们让滑块滑动,如果所有的像素是白色的,那么我们得到白色,否则是黑色。 这可能有助于消除一些白色噪音。
另一个版本是膨胀,它基本上是相反的:让滑块滑动,如果整个区域不是黑色的,就会转换成白色。

3.开运算 cv2.morphologyEx()

先进性腐蚀再进行膨胀就叫做开运算。它被用来去除噪声。

opening = cv2.morphologyEx(img, cv2.MORPH_OPEN, kernel)

4.闭运算 cv2.morphologyEx()

先膨胀再腐蚀。它经常被用来填充前景物体中的小洞,或者前景物体上的小黑点。

closing = cv2.morphologyEx(img, cv2.MORPH_CLOSE, kernel)

5.梯度运算

梯度 = 膨胀后的图像 - 腐蚀后的图像

gradient = cv2.morphologyEx(img, cv2.MORPH_GRADIENT, kernel)

6.礼帽与黑帽

礼帽 = 原始输入 - 开运算结果

tophat = cv2.morphologyEx(img, cv2.MORPH_TOPHAT, kernel)

黑帽 = 闭运算结果 - 原始输入

blackhat = cv2.morphologyEx(img, cv2.MORPH_BLACKHAT, kernel)

计算图像梯度

梯度

图像函数f(x,y)在点(x,y)的梯度是一个具有大小和方向的矢量,梯度的方向是函数f(x,y)变化最快的方向,当图像中存在边缘时,一定有较大的梯度值,相反,当图像中有比较平滑的部分时,灰度值变化较小,则相应的梯度也较小,图像处理中把梯度的模简称为梯度。

简单理解,一个图像是一个函数,梯度就是灰度值的变化率

图像的梯度是多少?哪些地方有梯度、找出来。
相当于边缘检测(在图像中物体的边缘像素点才有明显的数值变化,即梯度)

1.Sobel算子

从右到左,从下到上
右边减左边,下边减上边
得到边缘

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(),即

sobelx = cv2.Sobel(img, cv2.CV_64F, 1, 0, ksize=3)
sobelx = cv2.convertScaleAbs(sobely)

以上为求Gx,即dx=1,dy=0,下面求Gy

sobely = cv2.Sobel(img, cv2.CV_64F, 0, 1, ksize=3)
sobely = cv2.convertScaleAbs(sobely)

分别计算x和y,再求和

sobleXY = cv2.addWeighted(sobelx, 0.5, sobely, 0.5, 0)

注:两个0.5是两个图像的比例权重,最后的0是偏置项,一般为0

以上为一般步骤,即x、y分开算再求和。若直接dx=1,dy=1一次算的话,效果不好。

2.Scharr算子

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算子

对像素点数值变化更敏感,也就意味着对图像上的噪音点敏感,容易认为是边缘。
单独使用效果不好。

Laplacian = cv2.Laplacian(img,cv2.CV_64F)
laplacian = cv2.convertScaleAbs(laplacian)
  • scharr最深刻,然后soble,laplacian最浅。算子的核不同。

  • 这里举一个简单的例子:
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()

结果如下:

python数字图像处理基础(四)——图像平滑处理、形态学操作、图像梯度_第1张图片
python数字图像处理基础(四)——图像平滑处理、形态学操作、图像梯度_第2张图片


你可能感兴趣的:(数字图像处理,python,计算机视觉,opencv)