OpenCV学习+常用函数记录④:形态学、模板匹配和运动检测

213
0
2020年12月9日 09时23分

OpenCV 形态学、模板匹配和运动检测

 

  • 5. 形态学变换
    • 5.1 膨胀
    • 5.2 腐蚀
    • 5.3 开操作
    • 5.4 闭操作
    • 5.5 示例
  • 6. 模板匹配
  • 7. 运动检测

 

5. 形态学变换

 

首先放上形态学变换的官方文档:[官网文档]

 

形态学变化是基于图像形状的一些简单操作。操作对象一般是二值图像,需要两个输入,一个是输入图像,另一个是3×3的结构元素(内核),决定了膨胀操作的本质。常见的操作是图像的膨胀和腐蚀。以及他们的进阶操作注入Opening、Closing、Gradient等等。

 

结构元素的形状

 

MORPH_RECT 矩形
MORPH_ELLIPSE 椭圆形
MORPH_CROSS 十字型

 

5.1 膨胀

 

跟卷积操作非常类似,有图像A和3×3的结构元素,结构元素在A上进行滑动。计算结构元素在A上覆盖的最大像素值来替换当前结构元素对应的正中间的元素

 

膨胀的作用:

 

  1. 对象边缘增加一个像素
  2. 使对象边缘平滑
  3. 减少了对象与对象之间的距离

 

dst = cv.dilate(src, kernel)

 

5.2 腐蚀

 

腐蚀和膨胀过程类似,唯一不同的是以覆盖的最小值替换当前的像素值

 

侵蚀的作用:

 

  1. 对象边缘减少一个像素
  2. 对象边缘平滑
  3. 弱化了对象与对象之间连接

 

dst = cv.erode(src, kernel)

 

5.3 开操作

 

先腐蚀,后膨胀,主要应用在二值图像或灰度图像

先腐蚀: 让当前窗口中最小的颜色值替换当前颜色值

后膨胀: 让当前窗口中最大的颜色值替换当前颜色值

 

作用:

 

  1. 一般用于消除小的干扰或噪点(验证码图的干扰线)
  2. 可以通过此操作配合结构元素,提取图像的横线和竖线

 

dst_open = cv.morphologyEx(src, cv.MORPH_OPEN, kernel)

 

5.4 闭操作

 

先膨胀,后侵蚀

 

一般用于填充内部缝隙

 

dst_close = cv.morphologyEx(src2, cv.MORPH_CLOSE, kernel)

 

5.5 示例

 

import cv2 as cv

src = cv.imread("../img/morph-opening.jpg")
src2 = cv.imread("../img/morph-closing.jpg")

# 定义结构元素
kernel = cv.getStructuringElement(cv.MORPH_RECT, (3, 3))
print kernel

# 腐蚀操作
dst_erode = cv.erode(src, kernel)
# 膨胀操作
dst_dilate = cv.dilate(dst_erode, kernel)
# 开操作:先腐蚀再膨胀
dst_open = cv.morphologyEx(src, cv.MORPH_OPEN, kernel)
# 闭操作:先膨胀再腐蚀
dst_close = cv.morphologyEx(src2, cv.MORPH_CLOSE, kernel)

cv.imshow("j", src)
cv.imshow("dst_erode", dst_erode)
cv.imshow("dst_dilate", dst_dilate)
cv.imshow("dst_open", dst_open)
cv.imshow("j", src2)
cv.imshow("dst_close", dst_close)
cv.waitKey()

 

6. 模板匹配

 

模板匹配就是在整个图像区域发现与给定子图像匹配的小块区域。

 

在OpenCV中提供了6种匹配度量方法。

 

  1. 平方差匹配法CV_TM_SQDIFF
  2. 归一化平方差匹配法CV_TM_SQDIFF_NORMED
  3. 相关匹配法CV_TM_CCORR
  4. 归一化相关匹配法CV_TM_CCORR_NORMED
  5. 系数匹配法CV_TM_CCOEFF
  6. 化相关系数匹配法CV_TMCCOEFF_NORMED

 

通常来讲,随着从简单测量方法(平方差)到更复杂的测量方法(相关系数法),我们可以获得越来越准确的匹配。然而这同时也会以越来越大的计算量为代价。对于选取何种方法,针对不同的匹配情况进行对此分析比较,选取更适合自己应用场景同时兼顾速度和精度的最佳方案。 注意 :对于方法SQDIFF和SQDIFF_NORMED两种方法来讲,越小的值就有着更高的匹配结果,而其余的方法则是数值越大匹配效果越好。

 

代码示例:

 

import cv2 as cv
# 加载原图
src = cv.imread("../img/zhaonimei.jpg")
cv.imshow("src", src)
# 加载模板
temp = cv.imread("../img/mei.jpg")
cv.imshow("template", temp)
# 输入参数:原图,模板,匹配度量方法
result = cv.matchTemplate(src, temp, cv.TM_SQDIFF)
# 将结果进行归一化处理
cv.normalize(result, result, 0, 1, cv.NORM_MINMAX)
print(result)
# 求最大值最小值
m_min, m_max, minLoc, maxLoc = cv.minMaxLoc(result)
print(minLoc, maxLoc, m_min, m_max)
cv.rectangle(src, (minLoc[0], minLoc[1]), (minLoc[0] + temp.shape[1], minLoc[1] + temp.shape[0]), (0, 0, 255), 2)
cv.imshow("dst", src)
cv.waitKey()

 

7. 运动检测

 

代码示例:

 

import cv2 as cv
capture = cv.VideoCapture("../img/vtest.avi")
flag = capture.isOpened()
print(flag)
flag, frame = capture.read()
# 初始化BS模型
mog2 = cv.createBackgroundSubtractorMOG2(detectShadows=True)
# 形态学变换去掉噪声
kernel = cv.getStructuringElement(cv.MORPH_RECT, (3, 3))
# frame = None
# Mask = None
while flag:
    flag, frame = capture.read()
    if not flag:
        break
    cv.imshow("frame", frame)
    Mask = mog2.apply(frame)
    #  thresh, mogMask = cv.threshold(Mask, 120, 255, cv.THRESH_BINARY)
    Mask = cv.morphologyEx(Mask, cv.MORPH_OPEN, kernel)
    _, contours, _ = cv.findContours(Mask, cv.RETR_EXTERNAL, cv.CHAIN_APPROX_SIMPLE)
    for i, contour in enumerate(contours):
        area = cv.contourArea(contour)
        if area > 500:
            cv.drawContours(frame, contours, i, (0, 0, 255), 2, cv.LINE_AA)
            rect = cv.boundingRect(contour)
            print(rect)
            cv.rectangle(frame, (rect[0], rect[1]), (rect[0] + rect[2], rect[1] + rect[3]), (255, 0, 0), 2)
    cv.imshow("frame", frame)
    cv.imshow("mog2", Mask)
    key = cv.waitKey(100)
    if key == 27:
        break
capture.release()
cv.destroyAllWindows()

发表评论

后才能评论