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

2020-11-24 10:50:58 浏览数 (1)

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

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

5. 形态学变换

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

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

结构元素的形状

MORPH_RECT 矩形 MORPH_ELLIPSE 椭圆形 MORPH_CROSS 十字型

5.1 膨胀

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

膨胀的作用:

  1. 对象边缘增加一个像素
  2. 使对象边缘平滑
  3. 减少了对象与对象之间的距离
代码语言:javascript复制
dst = cv.dilate(src, kernel)

5.2 腐蚀

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

侵蚀的作用:

  1. 对象边缘减少一个像素
  2. 对象边缘平滑
  3. 弱化了对象与对象之间连接
代码语言:javascript复制
dst = cv.erode(src, kernel)

5.3 开操作

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

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

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

作用:

  1. 一般用于消除小的干扰或噪点(验证码图的干扰线)
  2. 可以通过此操作配合结构元素,提取图像的横线和竖线
代码语言:javascript复制
dst_open = cv.morphologyEx(src, cv.MORPH_OPEN, kernel)

5.4 闭操作

先膨胀,后侵蚀

一般用于填充内部缝隙

代码语言:javascript复制
dst_close = cv.morphologyEx(src2, cv.MORPH_CLOSE, kernel)

5.5 示例

代码语言:javascript复制
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两种方法来讲,越小的值就有着更高的匹配结果,而其余的方法则是数值越大匹配效果越好。

代码示例:

代码语言:javascript复制
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. 运动检测

代码示例:

代码语言:javascript复制
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()

0 人点赞