【python】OpenCV—Blur, Threshold, Gradient, Morphology(2)

系列文章

  • 【python】OpenCV—RGB, Rectangle, Circle, SS(1)
  • 【python】OpenCV—Blur, Threshold, Gradient, Morphology(2)
  • 【python】OpenCV—Edge, Corner, Face Detection(3)

文章目录

  • 0 import
  • 1 滤波
    • 1.1 统一的滤波器
    • 1.2 模糊(Blurring)
  • 2 阈值化(Thresholding)
    • 2.1 固定的 Threshold
    • 2.2 Adaptive thresholding
  • 3 梯度(Gradient)
  • 4 形态转换(Morpgological transformations)
    • 4.1 腐蚀(Erosion)
    • 4.2 膨胀(dilation)
    • 4.3 开(open)、闭(close)运算
  • 参考


0 import

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

%matplotlib inline

1 滤波

学习整理 Python下opencv使用笔记(五)(图像的平滑与滤波)

对于2D图像可以进行低通或者高通滤波操作,低通滤波(LPF)有利于去噪,模糊图像,高通滤波(HPF)有利于找到图像边界。

1.1 统一的滤波器

cv2.filter2D

1.2 模糊(Blurring)

  • 均值模糊(Averaging blurring):cv2.blur
  • 高斯模糊(Gaussian blurring):cv2.GaussianBlur
  • 中值模糊(median blurring):cv2.medianBlur
  • 双边滤波(bilateral filtering):cv2.bilateralFilter,是高斯模糊的一个高级版本。模糊化不仅可以溶解噪声,而且还会平滑边缘。而双边滤波器能在去除噪声的同时保持边缘锐化。这是由于它不仅使用高斯分布值,还同时考虑了距离和像素值的差异。因此,需要指定 sigmaSpace 和 sigmaColor 这两个参数。
img = cv2.imread('C://Users/13663//Desktop/1.jpg')
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
# Plot the image with different kernel sizes
kernels = [3, 5, 11, 17]
fig, axs = plt.subplots(nrows = 1, ncols = 4, figsize = (20, 20))
for ind, s in enumerate(kernels):
    img_blurred = cv2.blur(img, ksize = (s, s))
    ax = axs[ind]
    ax.set_title('kernel {i}'.format(i=s),
             fontsize =24, color = 'white')
    ax.imshow(img_blurred)
    ax.axis('off')
plt.show()

【python】OpenCV—Blur, Threshold, Gradient, Morphology(2)_第1张图片
逐渐模糊,一字排开这个看起来并不是很爽,2,2 看看

img = cv2.imread('C://Users/13663//Desktop/1.jpg')
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)

# Plot the image with different kernel sizes
kernels = [3, 5, 11, 17]
fig, axs = plt.subplots(nrows = 2, ncols = 2, figsize = (15, 9))
for ind, s in enumerate(kernels):
    img_blurred = cv2.blur(img, ksize = (s, s))
    ax = axs[ind//2][ind%2]
    ax.set_title('kernel {i}'.format(i=s),
             fontsize =24, color = 'white')
    ax.imshow(img_blurred)
    ax.axis('off')
plt.show()

【python】OpenCV—Blur, Threshold, Gradient, Morphology(2)_第2张图片
看看其它类型的 blurring

img = cv2.imread('C://Users/13663//Desktop/1.jpg')
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)

# Blur the image 
img_0 = cv2.blur(img, ksize = (7, 7))
img_1 = cv2.GaussianBlur(img, ksize = (7, 7), sigmaX = 0)   
img_2 = cv2.medianBlur(img, 7)
img_3 = cv2.bilateralFilter(img, 7, sigmaSpace = 75, sigmaColor =75)

# Plot the images
images = [img_0, img_1, img_2, img_3]
names = ['Mean Blur','Gaussian Blur','Median Blur','Bilateral Filter']
fig, axs = plt.subplots(nrows = 2, ncols = 2, figsize = (15, 9))
num = 0
for ind, p in enumerate(images):
    ax = axs[ind//2][ind%2]
    ax.set_title('{x}'.format(x=names[num]),
             fontsize =20, color = 'white')
    ax.imshow(p)
    ax.axis('off')
    num+=1
plt.show()

【python】OpenCV—Blur, Threshold, Gradient, Morphology(2)_第3张图片

2 阈值化(Thresholding)

2.1 固定的 Threshold

图像的阈值化就是利用图像像素点分布规律,设定阈值进行像素点分割,进而得到图像的二值图像。我们需要设置阈值和最大值,然后据此相应地进行像素值转换。核心函数如下:

ret, dst = cv2.threshold(src, thresh, maxval, type)

  • src: 输入图,只能输入单通道图像,通常来说为灰度图
  • dst: 输出图
  • thresh: 阈值
  • maxval: 当像素值超过了阈值(或者小于阈值,根据type来决定),所赋予的值
  • type:二值化操作的类型,包含以下5种类型:
    • 二进制阈值化:cv2.THRESH_BINARY
    • 反二进制阈值化:cv2.THRESH_BINARY_INV
    • 阈值化到零:cv2.THRESH_TOZERO
    • 反阈值化到零:cv2.THRESH_TOZERO_INV
    • 阈值截断:cv2.THRESH_TRUNC

也可以通过 BIF 查看,eg:help(cv2.threshold),返回的 ret 经测试发现同 thresh

【python】OpenCV—Blur, Threshold, Gradient, Morphology(2)_第4张图片
先看一个比较直接的例子

img = cv2.imread('C://Users/13663//Desktop/5.png')
#img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# Thresholding 
_, thresh_0 = cv2.threshold(img, 127, 255, cv2.THRESH_BINARY)
_, thresh_1 = cv2.threshold(img, 127, 255, cv2.THRESH_TOZERO)
_, thresh_2 = cv2.threshold(img, 127, _, cv2.THRESH_TRUNC)
_, thresh_3 = cv2.threshold(img, 127, 255, cv2.THRESH_BINARY_INV)
_, thresh_4 = cv2.threshold(img, 127, 255, cv2.THRESH_TOZERO_INV)

names = ['original image','binary T','zero T','trunc T','binary inv T','zero inv T']  
# Plot the images
images = [img, thresh_0, thresh_1, thresh_2, thresh_3, thresh_4]
fig, axs = plt.subplots(nrows = 2, ncols = 3, figsize = (13, 6))
for ind, p in enumerate(images):
    ax = axs[ind//3, ind%3]
    ax.set_title(names[ind],fontsize=14, color='white')
    ax.imshow(p,cmap='gray')
    ax.axis("off")
plt.show()

【python】OpenCV—Blur, Threshold, Gradient, Morphology(2)_第5张图片
看了一些关于 cv2.THRESH_TRUNC 的介绍,上面的公式也显示,如果大于 Threshold,像素值就会被赋值为 Threshold,可实验发现,大于 Threshold 会赋值为 255,不晓得是不是因为 opencv 版本的问题,或者是 coding 的问题!如果有水平较高的读者有幸看到了这篇博客,可以尝试回答一下这个问题!

下面看看比较轻松的例子

img = cv2.imread('C://Users/13663//Desktop/3.png')
img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

# Thresholding 
_, thresh_0 = cv2.threshold(img, 127, 255, cv2.THRESH_BINARY)
_, thresh_1 = cv2.threshold(img, 127, 255, cv2.THRESH_TOZERO)
_, thresh_2 = cv2.threshold(img, 127, 255, cv2.THRESH_TRUNC)
_, thresh_3 = cv2.threshold(img, 127, 255, cv2.THRESH_BINARY_INV)
_, thresh_4 = cv2.threshold(img, 127, 255, cv2.THRESH_TOZERO_INV)

names = ['original image','binary T','zero T','trunc T','binary inv T','zero inv T']  

# Plot the images
images = [img, thresh_0, thresh_1, thresh_2, thresh_3, thresh_4]
fig, axs = plt.subplots(nrows = 2, ncols = 3, figsize = (13, 6))
for ind, p in enumerate(images):
    ax = axs[ind//3, ind%3]
    ax.set_title(names[ind],fontsize=14, color='white')
    ax.imshow(p,cmap='gray')
    ax.axis("off")
plt.show()

【python】OpenCV—Blur, Threshold, Gradient, Morphology(2)_第6张图片

2.2 Adaptive thresholding

只取一个阈值并将其应用于图像的所有部分并不能满足我们的全部需求。如果我们有一张在多个不同区域亮度差异较多的图片这种情况,将一个值应用于整个图像一般不利于我们的图像处理任务。其对应更好的方法是对图像的每个部分使用不同的阈值。对应这种情况还有另外一种阈值化技术称为自适应阈值化(Adaptive thresholding)。通过对图像邻域内阈值的计算,可以得到不同光照条件下的较好结果。

核心函数 dst = cv2.adaptiveThreshold(src, maxval, thresh_type, type, Block Size, C)

  • src: 输入图,只能输入单通道图像,通常来说为灰度图
  • dst: 输出图
  • maxval: 当像素值超过了阈值(或者小于阈值,根据type来决定),所赋予的值
  • thresh_type: 阈值的计算方法,包含以下2种类型:
    • cv2.ADAPTIVE_THRESH_MEAN_C 领域内均值
    • cv2.ADAPTIVE_THRESH_GAUSSIAN_C 领域内像素点加权和,权重为一个高斯窗口
  • type:二值化操作的类型,与固定阈值函数相同,包含以下5种类型:
    • cv2.THRESH_BINARY
    • cv2.THRESH_BINARY_INV
    • cv2.THRESH_TRUNC
    • cv2.THRESH_TOZERO
    • cv2.THRESH_TOZERO_INV
  • Block Size: 图片中分块的大小
  • C :阈值计算方法中的常数项,代表从均值或加权均值中减去值的大小

for example

# Convert the image to grayscale
img = cv2.imread('C://Users/13663//Desktop/3.png')
img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# Adaptive Thresholding
_, thresh_binary = cv2.threshold(img, thresh = 127, maxval = 255, type = cv2.THRESH_BINARY)
adap_mean_2 = cv2.adaptiveThreshold(img, 255, 
                                    cv2.ADAPTIVE_THRESH_MEAN_C, 
                                    cv2.THRESH_BINARY, 7, 2)
adap_mean_2_inv = cv2.adaptiveThreshold(img, 255, 
                                        cv2.ADAPTIVE_THRESH_MEAN_C, 
                                        cv2.THRESH_BINARY_INV, 7, 2)
adap_mean_8 = cv2.adaptiveThreshold(img, 255, 
                                    cv2.ADAPTIVE_THRESH_MEAN_C, 
                                    cv2.THRESH_BINARY, 7, 8)
adap_gaussian_8 = cv2.adaptiveThreshold(img, 255, 
                                    cv2.ADAPTIVE_THRESH_GAUSSIAN_C, 
                                    cv2.THRESH_BINARY, 7, 8)
# Plot the images
images = [img, thresh_binary, adap_mean_2, adap_mean_2_inv, 
          adap_mean_8, adap_gaussian_8]
names = ['img', 'thresh_binary', 'adap_mean_2', 'adap_mean_2_inv', 
         'adap_mean_8', 'adap_gaussian_8']
fig, axs = plt.subplots(nrows = 2, ncols = 3, figsize = (15, 8))
for ind, p in enumerate(images):
    ax = axs[ind%2, ind//2]
    ax.set_title(names[ind],fontsize=18,color='white')
    ax.imshow(p, cmap = 'gray')
    ax.axis('off')
plt.show()

【python】OpenCV—Blur, Threshold, Gradient, Morphology(2)_第7张图片
当C值更大时,图像将变得更显式。

3 梯度(Gradient)

sobellaplace 为例

# Convert the image to grayscale
img = cv2.imread('C://Users/13663//Desktop/1.jpg')
img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# Apply gradient filtering
sobel_x = cv2.Sobel(img, cv2.CV_64F, dx = 1, dy = 0, ksize = 5)
sobel_y = cv2.Sobel(img, cv2.CV_64F, dx = 0, dy = 1, ksize = 5)
blended = cv2.addWeighted(src1=sobel_x, alpha=0.5, src2=sobel_y,
                          beta=0.5, gamma=0)
laplacian = cv2.Laplacian(img, cv2.CV_64F)
# Plot the images
images = [sobel_x, sobel_y, blended, laplacian]
names = ['sobel_x', 'sobel_y', 'blended', 'laplacian']
plt.figure(figsize = (14, 10))
for i in range(4):
    plt.subplot(2, 2, i+1)
    plt.imshow(images[i], cmap = 'gray')
    plt.title(names[i],fontsize=20,color='white')
    plt.axis('off')
plt.show()

【python】OpenCV—Blur, Threshold, Gradient, Morphology(2)_第8张图片
可以对比下 PIL 方法的效果(【python】PIL(下))

看看更多的例子
【python】OpenCV—Blur, Threshold, Gradient, Morphology(2)_第9张图片
【python】OpenCV—Blur, Threshold, Gradient, Morphology(2)_第10张图片


【python】OpenCV—Blur, Threshold, Gradient, Morphology(2)_第11张图片
【python】OpenCV—Blur, Threshold, Gradient, Morphology(2)_第12张图片

4 形态转换(Morpgological transformations)

涉及到腐蚀(erosion)、膨胀(dilation)、开(open)、闭(close)运算

4.1 腐蚀(Erosion)

【python】OpenCV—Blur, Threshold, Gradient, Morphology(2)_第13张图片
【python】OpenCV—Blur, Threshold, Gradient, Morphology(2)_第14张图片
原图
【python】OpenCV—Blur, Threshold, Gradient, Morphology(2)_第15张图片

img = cv2.imread('C://Users/13663//Desktop/6.png')
img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

# Create erosion kernels 
kernel_0 = np.ones((3, 3), np.uint8)
kernel_1 = cv2.getStructuringElement(cv2.MORPH_RECT, (3, 3))
kernel_2 = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (3, 3))
kernel_3 = cv2.getStructuringElement(cv2.MORPH_CROSS, (3, 3))

kernels = [kernel_0, kernel_1, kernel_2, kernel_3]
names = ['ones','rect','ellipse','cross']

# Plot the images
plt.figure(figsize = (10, 9))
for i in range(4):
    img_copy = img.copy()
    img_copy = cv2.erode(img_copy, kernels[i], iterations = 1)
    plt.subplot(2, 2, i+1)
    plt.title(names[i],fontsize=18,color='white')
    plt.imshow(img_copy,cmap='gray')
    plt.axis('off')
plt.show()

cv2.getStructuringElement 有三种

  • 矩形: cv2.MORPH_RECT
  • 椭圆形:cv2.MORPH_ELLIPSE
  • 交叉形:cv2.MORPH_CROSS

迭代一次后的效果,腐蚀,可以理解为把像素腐蚀掉了(变黑了——变0了),one 和 rect 效果一样
【python】OpenCV—Blur, Threshold, Gradient, Morphology(2)_第16张图片
迭代两次的结果,可以感受三者之间的不同了
【python】OpenCV—Blur, Threshold, Gradient, Morphology(2)_第17张图片
迭代三次的结果,总感觉椭圆和交叉形效果差不多,可能是示例的原因!
【python】OpenCV—Blur, Threshold, Gradient, Morphology(2)_第18张图片
参考文章中的例子如下,要典型一些,哈哈哈!
【python】OpenCV—Blur, Threshold, Gradient, Morphology(2)_第19张图片

4.2 膨胀(dilation)

img = cv2.imread('C://Users/13663//Desktop/6.png')
img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# Apply dilation
kernel = np.ones((3, 3), np.uint8)
img_dilate = cv2.dilate(img, kernel, iterations = 1)
plt.figure(figsize = (20, 10))
plt.subplot(1, 2, 1); plt.imshow(img, cmap="gray")
plt.axis('off')
plt.subplot(1, 2, 2); plt.imshow(img_dilate, cmap="gray")
plt.axis('off')
plt.show()

【python】OpenCV—Blur, Threshold, Gradient, Morphology(2)_第20张图片

4.3 开(open)、闭(close)运算

  • cv2.MORPH_OPEN:先腐蚀,后膨胀
  • cv2.MORPH_CLOSE:先膨胀,后腐蚀
  • cv2.MORPH_GRADIENT:计算膨胀结果图与腐蚀结果图之差
  • cv2.MORPH_TOPHAT:顶帽,开运算结果图与原始图像之差
  • cv2.MORPH_BLACKHAT:黑帽,闭运算结果图与原始图像之差
img = cv2.imread('C://Users/13663//Desktop/4.png')
img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# Apply the operations
kernel = np.ones((3, 3), np.uint8)
img_open = cv2.morphologyEx(img, op=cv2.MORPH_OPEN, kernel=kernel)
img_close = cv2.morphologyEx(img, op=cv2.MORPH_CLOSE, kernel=kernel)
img_grad = cv2.morphologyEx(img, op=cv2.MORPH_GRADIENT, kernel=kernel)
img_tophat = cv2.morphologyEx(img, op=cv2.MORPH_TOPHAT, kernel=kernel)
img_blackhat = cv2.morphologyEx(img, op=cv2.MORPH_BLACKHAT, kernel=kernel)
# Plot the images
images = [img, img_open, img_close, img_grad, 
          img_tophat, img_blackhat]
names = ['img', 'img_open', 'img_close', 'img_grad', 
         'img_tophat', 'img_blackhat']
fig, axs = plt.subplots(nrows = 2, ncols = 3, figsize = (15, 10))
for ind, p in enumerate(images):
    ax = axs[ind//3, ind%3]
    ax.set_title(names[ind],fontsize=18,color='white')
    ax.imshow(p, cmap = 'gray')
    ax.axis('off')
plt.show()

【python】OpenCV—Blur, Threshold, Gradient, Morphology(2)_第21张图片
【python】OpenCV—Blur, Threshold, Gradient, Morphology(2)_第22张图片


【python】OpenCV—Blur, Threshold, Gradient, Morphology(2)_第23张图片
【python】OpenCV—Blur, Threshold, Gradient, Morphology(2)_第24张图片


【python】OpenCV—Blur, Threshold, Gradient, Morphology(2)_第25张图片
【python】OpenCV—Blur, Threshold, Gradient, Morphology(2)_第26张图片


参考

  • 使用Python+OpenCV进行图像处理(二)| 视觉入门
  • python-opencv函数总结之(一)threshold、adaptiveThreshold、Otsu 二值化
  • 【python】PIL(下)

你可能感兴趣的:(Python,Digital,Image,Processing,Blurring,Threshold,Gradient,Morphology)