opencv常用的形态学操作

导读

在使用opencv做图像处理的时候,我们经常会需要用到一些基础的图像形态学操作腐蚀膨胀。通过这些基本的形态学操作我们可以实现去噪以及图像的切割等。

形态学变换是基于图像形状的基础变换,它只能在二值图像上做处理。形态学操作需要两个输入,输入图像structuring elementkernelstructuring elementkernel决定我们做何种形态学处理的操作。腐蚀膨胀是形态学处理的基础操作,而开运算闭运算是基于腐蚀膨胀的变种操作。下面我们就介绍一下如何在实际中应用这些操作

注意:在做图像的形态学处理的时候,需要对图像做二值化,且需要将处理的像素值改为255,因为图像的形态学处理操作都是基于白色像素上处理的。
opencv常用的形态学操作_第1张图片
后面我们基于上面这张图片来做处理

腐蚀

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

img_path = "img/demo.jpg"
#读取图片
img = cv2.imread(img_path)
#将图片转为灰度图
gray_img = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
#二值化图片,这里需要注意的时候我们需要选择THRESH_BINARY_INV模式
_,binary_img = cv2.threshold(gray_img,128,255,cv2.THRESH_BINARY_INV)

#定义腐蚀操作的kernel
erode_kernel = np.ones((3,3),np.uint8)
erode_img =cv2.erode(binary_img,erode_kernel)

plt.figure()
plt.subplot(1,2,1)
plt.imshow(cv2.cvtColor(binary_img,cv2.COLOR_BGR2RGB))
plt.title("binary_img")
plt.subplot(1,2,2)
plt.imshow(cv2.cvtColor(erode_img,cv2.COLOR_BGR2RGB))
plt.title("erode_img")
plt.show()

opencv常用的形态学操作_第2张图片
通过上面图片的腐蚀操作可以发现,白色的文字都完全被侵蚀了,除此之外我们还发现图片右下角白色区域周围的白色噪点也被侵蚀了。

下面我们来分析一下图像的腐蚀操作究竟发生了什么,下面我们看看这个例子

binary_img = np.array([ [0, 0, 0, 0, 0],
                        [0,255,255,255,0],
                        [0,255,255,255,0],
                        [0,255,255,255,0],
                        [0, 0, 0, 0, 0]],np.uint8)
erode_kernel = np.ones((3,3),np.uint8)
erode_img =cv2.erode(binary_img,erode_kernel)
print(erode_img)
"""
[[  0   0   0   0   0]
 [  0   0   0   0   0]
 [  0   0 255   0   0]
 [  0   0   0   0   0]
 [  0   0   0   0   0]]
"""

通过上面的例子发现,经过3x3的kernel之后,最终只保留了中心的255像素,周边的255都变成了0。在进行腐蚀操作的时候,就是通过kernel大小的卷积在原图像上滑动,只有当kernel范围内的像素全为255时输出才为255,否则输出为0,所以kernel越大最终白色像素保留的会越少。

膨胀

#定义膨胀操作的kernel
dilate_kernel = np.ones((3,3),np.uint8)
dilate_img =cv2.dilate(binary_img,dilate_kernel)

plt.figure()
plt.subplot(1,2,1)
plt.imshow(cv2.cvtColor(binary_img,cv2.COLOR_BGR2RGB))
plt.title("binary_img")
plt.subplot(1,2,2)
plt.imshow(cv2.cvtColor(dilate_img,cv2.COLOR_BGR2RGB))
plt.title("dilate_img")
plt.show()

opencv常用的形态学操作_第3张图片
图像经过膨胀之后,白色像素的范围变大了。在做膨胀的时候,只要当kernel范围内的像素有255时输出就为255,只有kernel范围内全为0时才输出0

开闭运算

开运算其实就是先通过腐蚀操作后面再进行膨胀,闭运算和开运算恰好相反先通过膨胀操作后面再进行腐蚀

#定义kernel
kernel = np.ones((3,3),np.uint8)
#开运算
open_img =cv2.morphologyEx(binary_img,cv2.MORPH_OPEN,kernel)
#闭运算
close_img = cv2.morphologyEx(binary_img,cv2.MORPH_CLOSE,kernel)

opencv常用的形态学操作_第4张图片
通过结合腐蚀膨胀运算我们可以去除图像上的白色噪点

梯度运算

梯度运算等价于膨胀运算-腐蚀运算

#定义kernel
kernel = np.ones((3,3),np.uint8)
gradient_img = cv2.morphologyEx(binary_img,cv2.MORPH_GRADIENT,kernel)

opencv常用的形态学操作_第5张图片
梯度运算主要是用来保留图像的轮廓

Top Hat和Black Hat运算

Top Hat运算等价于原始图像 - 开运算,Black Hat运算等价于闭运算 - 原始图像

#定义kernel
kernel = np.ones((3,3),np.uint8)
tophat_img = cv2.morphologyEx(binary_img,cv2.MORPH_TOPHAT,kernel)
blackhat_img = cv2.morphologyEx(binary_img,cv2.MORPH_BLACKHAT,kernel)

opencv常用的形态学操作_第6张图片

Structuring Element

前面我们使用的都是方形的kernel,除此之外我们也可以使用矩形的kernel来实现我们的目的,例如在做文本的行分割时,我们需要将文字的行连在一起以检测出文本行的位置,此时我们就可以采用矩形的kernel来达到我们的目的。
opencv库还提供了椭圆的kernel以及圆形的kernel

#椭圆形的kernel
ellipse_kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE,(5,5))
print(ellipse_kernel)
"""
[[0 0 1 0 0]
 [1 1 1 1 1]
 [1 1 1 1 1]
 [1 1 1 1 1]
 [0 0 1 0 0]]
"""
#圆形kernel
cross_kernel = cv2.getStructuringElement(cv2.MORPH_CROSS,(5,5))
print(cross_kernel)
"""
[[0 0 1 0 0]
 [0 0 1 0 0]
 [1 1 1 1 1]
 [0 0 1 0 0]
 [0 0 1 0 0]]
"""

你可能感兴趣的:(opencv修炼之路,opencv,计算机视觉,图像处理)