Bootstrap

【python】OpenCV—Tracking(10.2)

在这里插入图片描述

背景分割器介绍

在OpenCV中,背景分割器是处理视频或图像序列以区分前景(如移动物体)和背景的重要工具。以下是对OpenCV中几种常用背景分割器(MOG2、KNN、GMG)的使用场景、优缺点的详细解释:

一、Mixture of Gaussians (MOG2)

使用场景:

  • 适用于场景中存在很多变化和动态光照条件的情况。
  • 在处理光照变化和动态背景时表现良好

优点:

  • 对光照变化有较好的适应性。
  • 在动态背景环境下表现良好。

缺点:

  • 对于相对静态的背景可能效果不佳。

二、K-Nearest Neighbors (KNN)

使用场景:

  • 在处理运动目标和部分遮挡情况时可能更有效。

优点:

  • 根据像素的颜色特征和邻近像素的情况进行分类,因此在处理运动目标和部分遮挡时可能更有效。

缺点:

  • 在复杂动态背景下表现可能欠佳。

三、Geometric Multigrid (GMG)

使用场景:

  • 在动态背景和光照变化下表现较好。

优点:

  • 结合了几何学和统计学的方法,对动态背景和光照变化具有较好的鲁棒性。

缺点:

  • 对于较为静态的场景可能不够精确。

四、总结

MOG2 更适合光照变化和动态背景较多的场景。

KNN 在处理运动目标和部分遮挡时可能更有效,但在复杂动态背景下可能表现不佳。

GMG 在动态背景和光照变化下表现良好,但可能在静态场景下不够精确。

在选择背景分割器时,需要根据具体的应用场景和需求进行权衡。例如,如果场景中光照变化较大,那么MOG2可能是更好的选择;而如果主要目标是检测运动目标并处理部分遮挡,那么KNN可能更为合适。

opencv 中背景分割器可借助 BackgroundSubtractor 类,检测阴影,用阈值排除阴影,从而关注实际特征

cv2.createBackgroundSubtractorMOG2

OpenCV图像处理- 视频背景消除与前景ROI提取

createBackgroundSubtractorMOG2 是 OpenCV 库中的一个函数,用于创建基于混合高斯模型(Mixture of Gaussians, MOG2)的背景减除器。以下是对 createBackgroundSubtractorMOG2 的中文文档,清晰地分点表示和归纳了其主要内容:

一、函数概述

createBackgroundSubtractorMOG2 是 OpenCV 中用于背景/前景分割的算法之一,基于混合高斯模型(MOG2)进行背景建模和前景检测。该函数允许用户通过调整参数来适应不同的应用场景。

二、函数原型

retval = cv2.createBackgroundSubtractorMOG2([, history[, varThreshold[, detectShadows]]])

三、参数解释

history(可选,整型,默认值 200):

  • 表示用于训练背景模型的时间长度,单位是帧数。它决定了背景模型更新的速度,值越大,背景模型更新的速度就越慢——过往帧数,500帧,选择history = 1就变成两帧差

varThreshold(可选,浮点型,默认值 15):

  • 用于判断像素是否为背景的阈值。这个参数对结果有很大影响,值越小,检测到的运动物体就越多,但也可能增加误检——像素与模型之间的马氏距离,值越大,只有那些最新的像素会被归到前景,值越小前景对光照越敏感。

detectShadows(可选,布尔型,默认值 True):

  • 一个布尔值,用于指示算法是否检测阴影并对其进行标记。启用阴影检测会稍微降低速度,因此如果不需要此功能,建议将其设置为 False。

四、返回值

该函数返回一个背景减除器对象,该对象可以用于对视频帧或图像序列进行前景检测。

五、工作原理

模型初始化:在开始时,算法会对视频中的每个像素建立一个混合高斯模型。这个模型会学习并适应场景中的背景变化。

背景建模:随着新帧的到来,算法会更新每个像素的高斯分布。对于与现有高斯分布匹配良好的像素,这些分布会被更新以反映最新的像素值。对于不匹配任何现有分布的像素,会创建新的高斯分布或替换最不可能代表背景的高斯分布。

前景检测:如果某个像素的值与所有高斯分布都不匹配,或者只与表示前景的高斯分布匹配,则该像素被视为前景像素。

阴影检测(如果启用):算法还可以检测并标记出由于前景对象遮挡而产生的阴影区域。

六、使用场景

动态背景:在背景经常变化的情况下,如光照变化、树叶摇动等,MOG2 表现出较好的鲁棒性。

视频监控:在视频监控系统中,用于检测运动物体或行人。

实时分析:由于 MOG2 的计算效率较高,因此适用于需要实时处理的应用场景。

七、注意事项

参数调整:根据具体的应用场景和需求,可能需要调整 history、varThreshold 和 detectShadows 等参数以获得最佳效果。

性能考虑:虽然 MOG2 在大多数情况下都能提供较好的性能,但在某些极端情况下(如快速变化的光照条件),可能需要考虑使用其他更复杂的背景减除算法。

import cv2
import os
# bs = cv2.createBackgroundSubtractorKNN(detectShadows=True)
bs = cv2.createBackgroundSubtractorMOG2(detectShadows=True)
os.makedirs("frame1", exist_ok=True)
os.makedirs("frame2", exist_ok=True)
os.makedirs("frame3", exist_ok=True)

camera = cv2.VideoCapture('car.mkv')
index = 0
while True:
    ret, frame = camera.read()
    index += 1
    frame_h, frame_w, _ = frame.shape
    fgmask = bs.apply(frame)
    th = cv2.threshold(fgmask.copy(), 244, 255, cv2.THRESH_BINARY)[1]
    dilated = cv2.dilate(th, cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (3, 3)),
                         iterations=2)
    contours, _ = cv2.findContours(dilated, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)

    for c in contours:
        # if cv2.contourArea(c) > frame_w*0.075 * frame_h*0.075:
        if cv2.contourArea(c) > 1000:
            (x, y, w, h) = cv2.boundingRect(c)
            cv2.rectangle(frame, (x,y), (x+w, y+h), (0, 0, 255), 5)
    cv2.imshow("mog", fgmask)
    cv2.imwrite("./frame1/{}.jpg".format(index), fgmask)
    cv2.imshow("thresh", th)
    cv2.imwrite("./frame2/{}.jpg".format(index), th)
    cv2.imshow("detection", frame)
    cv2.imwrite("./frame3/{}.jpg".format(index), frame)

    if cv2.waitKey(30) & 0xff == ord("q"):
        break

camera.release()
cv2.destroyAllWindows()

请添加图片描述

请添加图片描述

请添加图片描述
做 gif 的时候只设置了播放一次,重复播放需要刷新该页面

cv2.createBackgroundSubtractorKNN

用法基本和 cv2.createBackgroundSubtractorMOG2 一致,工作原理如下

模型初始化:在开始时,KNN 算法会收集一系列初始帧来构建背景模型。

背景建模:对于每个新的帧,KNN 算法会计算当前像素与背景模型中所有样本之间的距离,并基于这些距离来决定该像素是前景还是背景。

前景检测:如果当前像素与所有背景模型中的样本距离都大于 dist2Threshold,则该像素被视为前景。

阴影检测(如果启用):如果 detectShadows 设置为 True,KNN 算法会尝试检测并标记出前景中的阴影区域。

import cv2
import numpy as np
bs = cv2.createBackgroundSubtractorKNN(detectShadows=True)
camera = cv2.VideoCapture('car.mkv')
index = 0
while True:
    ret, frame = camera.read()
    index += 1
    frame_h, frame_w, _ = frame.shape
    fgmask = bs.apply(frame)
    th = cv2.threshold(fgmask.copy(), 244, 255, cv2.THRESH_BINARY)[1]
    dilated = cv2.dilate(th, cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (3, 3)),
                         iterations=2)
    contours, _ = cv2.findContours(dilated, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)

    for c in contours:
        # if cv2.contourArea(c) > frame_w*0.075 * frame_h*0.075:
        if cv2.contourArea(c) > 1000:
            (x, y, w, h) = cv2.boundingRect(c)
            cv2.rectangle(frame, (x,y), (x+w, y+h), (0, 0, 255), 5)
    cv2.imshow("mog", fgmask)
    cv2.imwrite("./frame1/{}.jpg".format(index), fgmask)
    cv2.imshow("thresh", th)
    cv2.imwrite("./frame2/{}.jpg".format(index), th)
    cv2.imshow("detection", frame)
    cv2.imwrite("./frame3/{}.jpg".format(index), frame)

    if cv2.waitKey(30) & 0xff == ord("q"):
        break

camera.release()
cv2.destroyAllWindows()

请添加图片描述

请添加图片描述

请添加图片描述

附录

cv2.threshold

cv2.threshold 是 OpenCV 库中的一个重要函数,用于对图像进行阈值化处理。阈值化处理是数字图像处理中常用的一种方法,可以将图像转换为二值图像,即图像中每个像素只有黑白两种颜色。以下是 cv2.threshold 函数的详细中文文档:

一、函数原型

retval, dst = cv2.threshold(src, thresh, maxval, type[, dst])

二、参数说明

src:输入图像,必须是单通道灰度图像。

thresh:阈值,用于对像素值进行比较的界限值。可以是一个固定的数值,也可以是一个自适应阈值算法。

maxval:当像素值大于阈值时,赋予的新像素值。在二值化处理中,通常设置为 255(即白色)。

type:阈值类型,决定了对像素值大于或小于阈值的像素进行何种操作。常见的阈值类型包括:

  • cv2.THRESH_BINARY:大于阈值的像素设置为 maxval,小于等于阈值的像素设置为 0。
  • cv2.THRESH_BINARY_INV:大于阈值的像素设置为 0,小于等于阈值的像素设置为 maxval。
  • cv2.THRESH_TRUNC:大于阈值的像素设置为阈值,小于等于阈值的像素保持不变。
  • cv2.THRESH_TOZERO:大于阈值的像素保持不变,小于等于阈值的像素设置为 0。
  • cv2.THRESH_TOZERO_INV:大于阈值的像素设置为 0,小于等于阈值的像素保持不变。

dst:输出图像,可选参数。如果未提供,将创建一个新的图像来存储结果。

三、返回值

retval:选取的阈值。在某些情况下,如果使用了自适应阈值算法,这个值可能有所不同。

dst:输出图像,与输入图像具有相同的大小和类型。

四、应用场景

阈值处理在图像处理中有广泛的应用,包括但不限于:

  • 图像分割:将图像中的目标物体与背景进行分离。
  • 目标检测:使用轮廓提取等方法进行目标检测和识别。
  • 图像增强:改善图像的对比度和清晰度。
  • 文字识别:更容易地提取出文字区域。
  • 图像压缩:减小图像文件的大小,实现图像的压缩和存储。

cv2.dilate

cv2.dilate 是 OpenCV 库中的一个函数,用于对图像进行膨胀操作。膨胀是一种形态学操作,它可以用来增加图像中物体的大小,填充图像中的空洞,连接相邻的物体等。以下是 cv2.dilate 函数的详细中文文档:

一、函数原型

dst = cv2.dilate(src, kernel[, dst[, anchor[, iterations[, borderType[, borderValue]]]]])

二、参数说明

src:输入图像,可以是灰度图像或彩色图像。

kernel:

  • 用于膨胀操作的结构元素,控制膨胀的形状和大小。
  • 可以使用 cv2.getStructuringElement() 函数来创建结构元素,该函数接受形状、大小等参数。
  • 常见的形状有:MORPH_RECT(矩形)、MORPH_CROSS(交叉形)、MORPH_ELLIPSE(椭圆形)。

dst:

  • 输出图像,与输入图像具有相同的尺寸和深度。
  • 可选参数,如果未提供,将创建一个新的图像来存储结果。

anchor:

  • 结构元素的锚点位置,决定了结构元素在图像上的位置。
  • 默认为 (-1, -1),表示锚点位于结构元素的中心。

iterations:

  • 膨胀操作的迭代次数。
  • 默认为 1,表示只进行一次膨胀操作。

borderType:

  • 边界扩充的类型。
  • 默认为 BORDER_CONSTANT。

borderValue:

  • 边界扩充的数值。
  • 默认为 0。

三、返回值

dst:膨胀后的输出图像。

四、用法解释

cv2.dilate 函数的作用是将图像中的物体进行膨胀操作,使其变大。膨胀操作的效果取决于所使用的结构元素的形状和大小。通常情况下,结构元素可以是矩形、圆形或者自定义形状。膨胀操作会将结构元素覆盖区域内的像素值取最大值(对于灰度图像)或进行逻辑运算(对于二值图像),从而使目标物体的边界变得更加平滑,填充空洞,连接相邻的物体。

cv2.findContours

cv2.findContours 是 OpenCV 库中用于在二值图像中查找轮廓的函数。以下是对 cv2.findContours 函数的详细中文文档,包括函数原型、参数说明、返回值以及示例代码。

一、函数原型

contours, hierarchy = cv2.findContours(image, mode, method[, contours[, hierarchy[, offset]]])

二、参数说明
image:

  • 输入的二值化图像,一般为灰度图像或二值图像。

mode:轮廓检索模式,指定轮廓的层级关系。

  • cv2.RETR_EXTERNAL:只返回最外层的轮廓。
  • cv2.RETR_LIST:返回所有轮廓,不建立轮廓间的层级关系。
  • cv2.RETR_TREE:返回所有轮廓,并建立完整的层级关系。
  • cv2.RETR_CCOMP:返回所有轮廓,并重建嵌套轮廓的完整层次结构(二级)。

method:轮廓逼近方法,指定轮廓的表示方式。

  • cv2.CHAIN_APPROX_NONE:保存所有的轮廓点。
  • cv2.CHAIN_APPROX_SIMPLE:仅保存轮廓的端点。
  • cv2.CHAIN_APPROX_TC89_L1 和 cv2.CHAIN_APPROX_TC89_KCOS:应用 Teh-Chin 链逼近算法。

contours(可选):

  • 用于存储检测到的轮廓的变量,如果传递了该参数,则不会返回此值。

hierarchy(可选):

  • 用于存储轮廓的层次关系信息的变量,如果传递了该参数,则不会返回此值。

offset(可选):

  • 可选的偏移量,用于在输出轮廓坐标中移动每个点。默认为 Point()。

三、返回值
contours:
轮廓列表,其中每个轮廓都是一个 NumPy 数组,包含该轮廓上所有点的坐标。
hierarchy:
轮廓的层次关系信息的 NumPy 数组,其中每个轮廓的层次关系由四个整数 [next, previous, first child, parent] 组成。

cv2.boundingRect

cv2.boundingRect 是 OpenCV 库中的一个函数,用于计算点集或灰度图像中非零像素的最小外接矩形(边界框)。以下是关于 cv2.boundingRect 函数的详细中文文档:

一、函数原型

rect = cv2.boundingRect(points)

或者
x, y, w, h = cv2.boundingRect(points)

二、参数说明

points:

  • 输入的轮廓点集合,可以是 numpy.ndarray 类型,通常通过 cv2.findContours 函数获取。

三、返回值

rect(或者 x, y, w, h):

  • 返回一个矩形边界框的信息。
  • 如果返回单个变量 rect,它是一个包含四个整数值的元组,即 (x, y, w, h)。
  • 如果返回四个单独的变量,则 x 和 y 是矩形左上角的坐标(通常是整数),w 是矩形的宽度,h 是矩形的高度。

四、细节解析

坐标系统:在 OpenCV 中,坐标系的原点 (0, 0) 位于图像的左上角,x 轴向右为正方向,y 轴向下为正方向。

边界框属性:

  • (x, y):矩形左上角的坐标。
  • w:矩形的宽度(水平方向上的像素数)
  • h:矩形的高度(垂直方向上的像素数)

与 cv2.findContours 的关系:

  • 通常,cv2.boundingRect 函数用于处理 cv2.findContours 函数返回的轮廓数据。cv2.findContours 可以从二值图像中检测出轮廓,并返回轮廓的点集信息。
;