博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

OpenCV 计算机视觉之图像基本操作(三)

Posted on 2021-04-26 21:44  通宵的达旦  阅读(255)  评论(0)    收藏  举报

形态学

形态学的基本思想是利用一种特殊的结构元(个人认为也可以当做一个卷积核)来测量或提取输入图像中相应的形状或特征,以便进一步进行图像分析和目标识别。形态学方法的基础是集合论。将数学形态学作为工具,从图像中提取用于表达和描绘区域形状的图像成分,如边界、骨架等。
形态学的基本操作有腐蚀操作、膨胀操作、开操作、闭操作
形态学提取边界


腐蚀操作

用下图的B作为结构元,以黑点为中心,在A图上扫一遍,如果B中完全落在A上,则中心位置(也就是黑点位置的像素保留),否则腐蚀掉(也就是舍去)。如图C所示,当B运算在A上的第一个位置时,因为B没有全部落在A上,所以1这个位置就被腐蚀掉。
在数学上,其实也就是如果B与A的交集仍然是A,则保留,否则为0。最后保留的这些点构成了被腐蚀操作后的结果(也就是图D)。

image
image
我们可以使用OpenCv中的以下函数来实现:
cv2.erode(src, kernel,dst,anchor,iterations,borderType,borderValue)
其中:
src: 输入图像(二值图像)
kernel: 结构元,用np.ones()去生成,默认是一个3×3的矩阵。也可以用CV2.getStructuringElement()去生成,这个函数的第一个参数是内核的形状,有三种选择,分别是矩形MORPH_RECT、交叉形MORPH_CROSS、椭圆形MORPH_ELLIPSE。第二个参数是内核大小。

kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (3, 3))  # 椭圆结构
kernel = cv2.getStructuringElement(cv2.MORPH_CROSS, (3, 3))  # 十字结构
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (3, 3))  # 矩形结构

iteration: 指的是腐蚀次数。默认为1

实例演示

具体代码:

import numpy as np
import cv2
img_original = cv2.imread("uuuu.jpg")
# kernal = np.ones((5,5),np.uint8)       这也是一种设置核的方式
kernal= cv2.getStructuringElement(cv2.MORPH_RECT,(7,7))
esions = cv2.erode(img_original,kernal,iterations=1)
img = np.hstack((img_original,esions))
cv2.imshow("esions",img)
cv2.waitKey(0)

image

不仅毛刺没有了,而且发现圆圈的线条也变细致了,这就是腐蚀操作。

膨胀操作

在输入图像A和结构元B做运算的时候,B只要保证和A有接触就可以了,和A一点也不接触就不行,比如F图这个位置就不可以,E图就可以。最后将B中和A接触的部分加入到A中,A就会比运算之前的A变得更“胖”,这就是膨胀。比如下图:
image

实例

由于之前腐蚀操作,所以原来的圆圈线条变得更细了,而且出现了断点,所以我们再利用腐蚀后的图去实际操作以下膨胀操作,具体代码如下:

import numpy as np
import cv2
img_original = cv2.imread("uuuu.jpg")
#kernal = np.ones((5,5),np.uint8)
kernal= cv2.getStructuringElement(cv2.MORPH_RECT,(8,8))
esions = cv2.erode(img_original,kernal,iterations=1)
kernal1 = cv2.getStructuringElement(cv2.MORPH_RECT,(8,8))
dilate = cv2.dilate(esions,kernal1)
img = np.hstack((img_original,esions,dilate))
cv2.imshow("dilate",img)
cv2.waitKey(0)

效果(发现圆圈又比操作之前变得胖了):
image

开操作

开操作就是先来个腐蚀操作,然后再继续做个膨胀操作。
它的作用就是具有消除细小物体,在纤细处分离物体和平滑较大物体边界
opening = cv2.morphologyEx(img, cv2.MORPH_OPEN, kernel)

闭操作

闭操作就是先来个膨胀操作,然后再继续做个腐蚀操作。
它的作用就是填充物体内细小空洞,连接邻近物体和平滑边界的作用,也可以消除前景物体上面的小黑点。
closing = cv2.morphologyEx(img, cv2.MORPH_CLOSE, kernel)

实际运用:

比如对于带有噪点的指纹图,我们可以先利用腐蚀操作去除噪点,然后再利用膨胀操作去填充由于腐蚀操作带来的新的断点。就如下图做过开操作的指纹图一样。
image

梯度运算

图像形态学中的梯度运算是一个组合函数,就像前面涉及到的开运算和闭运算一样。梯度运算是膨胀减去腐蚀的运算,我们会得到一个轮廓的结果。(想像一下从膨胀后的图像减去腐蚀过的图像,其实也就是将大家共有的部分都剔除出去,那么最后剩下的也就只有轮廓了)。

  1. 先不用库中的梯度运算函数去实验,我们用膨胀减去腐蚀进行操作。代码如下:
import numpy as np
import cv2
img_original = cv2.imread("uuuu.jpg")
kernal = cv2.getStructuringElement(cv2.MORPH_ELLIPSE,(3,3))
img_dilate = cv2.dilate(img_original,kernal)
img_erode = cv2.erode(img_original,kernal)
img_gradient  = img_dilate - img_erode
img = np.hstack((img_original,img_dilate,img_erode,img_gradient))
cv2.imshow("gradient",img)
cv2.waitKey(0)

结果:(依次为原图、膨胀、腐蚀、膨胀-腐蚀)
image

2.现在我们用cv2中的梯度运算的函数去实现

img_gradient = cv2.morphologyEx(img_original,cv2.MORPH_GRADIENT,kernal)
函数原型:morphologyEx(src, op, kernel, dst=None, anchor=None, iterations=None, borderType=None, borderValue=None)

结果(左边:原图,右边:梯度运算的结果):
image

礼帽运算

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

import cv2
import matplotlib.pyplot as plt
from matplotlib.font_manager import FontProperties
#解决中文乱码
font_set = FontProperties(fname=r"c:\windows\fonts\simsun.ttc", size=15)
img_original = cv2.imread("uuuu.jpg")
kernal = cv2.getStructuringElement(cv2.MORPH_RECT,(5,5))
img_dilate = cv2.dilate(img_original,kernal)
img_erode = cv2.erode(img_original,kernal)
img_open = cv2.morphologyEx(img_original,cv2.MORPH_OPEN,kernal)
tophat = img_original - img_open
tophat_func = cv2.morphologyEx(img_original,cv2.MORPH_TOPHAT,kernal)
titles = ["原始图像","开运算","组合","函数"]
imgs = [img_original,img_open,tophat,tophat_func]
for i in range(4):
    plt.subplot(1,4,i+1)
    plt.imshow(imgs[i])
    plt.title(titles[i],fontproperties=font_set)
    plt.xticks([])
    plt.yticks([])
plt.show()

结果:
image

黑帽运算

黑帽运算 = 闭运算 - 原始输入
代码:

import numpy as np
import cv2
import matplotlib.pyplot as plt
from matplotlib.font_manager import FontProperties
#解决中文乱码
font_set = FontProperties(fname=r"c:\windows\fonts\simsun.ttc", size=15)
img_original = cv2.imread("uuuu.jpg")

img_close = cv2.morphologyEx(img_original,cv2.MORPH_CLOSE,(3,3))
tophat = img_close - img_original
tophat_func = cv2.morphologyEx(img_original,cv2.MORPH_BLACKHAT,(3,3))
titles = ["闭运算","原始输入","组合","函数"]
imgs = [img_close,img_original,tophat,tophat_func]
for i in range(4):
    plt.subplot(1,4,i+1)
    plt.imshow(imgs[i])
    plt.title(titles[i],fontproperties=font_set)
    plt.xticks([])
    plt.yticks([])
plt.show()

结果:
image