opencv 形态变换

形态变换
在opencv之膨胀与腐蚀中介绍了Dilation/Erosion的原理.建议先读这一篇,搞懂原理. 这样就可以很轻松地理解为什么本文的这些形态变换可以取得相应的效果.
基于此,我们可以组合出更多的形态变换以达到不同的目的.
有以下几种:

Opening
Closing
Morphological Gradient
Top Hat
Black Hat
Opening
在这里插入图片描述

先腐蚀再膨胀,可以把较小的目标去除.比如:
在这里插入图片描述

Closing
在这里插入图片描述

可以把物体内的小黑洞消除.比如:

在这里插入图片描述

Morphological Gradient
在这里插入图片描述

可以提取出物体的轮廓.
比如下图,腐蚀和膨胀对物体内部的像素影响不大,(内部的局部最大值和最小值差不多),所以做完插值以后,边缘的像素值差比较大,内部像素差值变为0,从而提取出物体轮廓.

在这里插入图片描述

Top Hat
在这里插入图片描述

在这里插入图片描述

Black Hat
在这里插入图片描述

在这里插入图片描述

from __future__ import print_function
import cv2 as cv
import numpy as np
import argparse
morph_size = 0
max_operator = 4
max_elem = 2
max_kernel_size = 21
title_trackbar_operator_type = 'Operator:\n 0: Opening - 1: Closing  \n 2: Gradient - 3: Top Hat \n 4: Black Hat'
title_trackbar_element_type = 'Element:\n 0: Rect - 1: Cross - 2: Ellipse'
title_trackbar_kernel_size = 'Kernel size:\n 2n + 1'
title_window = 'Morphology Transformations Demo'
morph_op_dic = {0: cv.MORPH_OPEN, 1: cv.MORPH_CLOSE, 2: cv.MORPH_GRADIENT, 3: cv.MORPH_TOPHAT, 4: cv.MORPH_BLACKHAT}
def morphology_operations(val):
    morph_operator = cv.getTrackbarPos(title_trackbar_operator_type, title_window)
    morph_size = cv.getTrackbarPos(title_trackbar_kernel_size, title_window)
    morph_elem = 0
    val_type = cv.getTrackbarPos(title_trackbar_element_type, title_window)
    if val_type == 0:
        morph_elem = cv.MORPH_RECT
    elif val_type == 1:
        morph_elem = cv.MORPH_CROSS
    elif val_type == 2:
        morph_elem = cv.MORPH_ELLIPSE
    element = cv.getStructuringElement(morph_elem, (2*morph_size + 1, 2*morph_size+1), (morph_size, morph_size))
    operation = morph_op_dic[morph_operator]
    dst = cv.morphologyEx(src, operation, element)
    cv.imshow(title_window, dst)

src = cv.imread("/home/sc/disk/keepgoing/opencv_test/j.png")
if src is None:
    print('Could not open or find the image: ', args.input)
    exit(0)
    
cv.namedWindow(title_window)
cv.createTrackbar(title_trackbar_operator_type, title_window , 0, max_operator, morphology_operations)
cv.createTrackbar(title_trackbar_element_type, title_window , 0, max_elem, morphology_operations)
cv.createTrackbar(title_trackbar_kernel_size, title_window , 0, max_kernel_size, morphology_operations)
morphology_operations(0)
cv.waitKey()

可以用上述代码感受一下对不同图片,采用不同操作,不同参数,得到的结果是怎样的.

利用形态变换提取图像中的水平线
看一个具体的例子
我们想从下图中提取出水平线出来.
在这里插入图片描述

前面讲过,膨胀和腐蚀都是通过卷积核去定义一个要从什么样的区域去取局部极大值或局部极小值. 那为了完成水平线的提取,我们可以定义自己的特定形状的卷积核去完成这个功能.

形态变换实现水平线和音符提取

import cv2 as cv
import numpy as np

def test():
    src = cv.imread("/home/sc/disk/keepgoing/opencv_test/music.png",cv.IMREAD_COLOR)
    gray = cv.cvtColor(src, cv.COLOR_BGR2GRAY)
    gray = cv.bitwise_not(gray)
     cv.imshow("gray",gray)

    horizontal = np.copy(gray)
    vertical = np.copy(gray)
    
    ##设计特定形状卷积核
    cols = horizontal.shape[1]
    horizontal_size = cols // 30
    horizontalStructure = cv.getStructuringElement(cv.MORPH_RECT, (horizontal_size, 1))
    print(horizontalStructure)
    
    horizontal1 = cv.erode(horizontal, horizontalStructure)
    cv.imshow("h1",horizontal1)

    horizontal2 = cv.dilate(horizontal1, horizontalStructure)
    cv.imshow("h2",horizontal2)
    
    ##设计特定形状卷积核
    rows = vertical.shape[0]
    verticalsize = rows // 30
    verticalStructure = cv.getStructuringElement(cv.MORPH_RECT, (1, verticalsize))
    
    vertical = cv.erode(vertical, verticalStructure)
    vertical = cv.dilate(vertical, verticalStructure)
    cv.imshow("v",vertical)
    
test()
if 27 == cv.waitKey(0):
    cv.destroyAllWindows()

首先我们完成将图像的预处理.
在这里插入图片描述

这里用了cv.bitwise_not(gray)将我们关注的部分变为亮的.不关注的变为暗的. 因为膨胀和腐蚀都是针对亮的区域而言的.指亮的区域的扩张或收缩.

接下来就是如何定义我们的卷积核呢?
以音符的提取为例,我们希望把水平方向的白色横线去除,即我们更关注垂直方向的像素点. 水平方向的白色横线的上下位置基本是黑色的背景. 所以我们需要的卷积核是一个如下:
在这里插入图片描述

这样对白色横线上的像素点,通过取该像素点上下方若干个点的最小值,把该像素点灰度值变为0.从而达到去除白色横线的目的.
最终得到如下:
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值