
在OpenCV中,背景分割器是处理视频或图像序列以区分前景(如移动物体)和背景的重要工具。以下是对OpenCV中几种常用背景分割器(MOG2、KNN、GMG)的使用场景、优缺点的详细解释:
一、Mixture of Gaussians (MOG2)
使用场景:
优点:
缺点:
二、K-Nearest Neighbors (KNN)
使用场景:
优点:
缺点:
三、Geometric Multigrid (GMG)
使用场景:
优点:
缺点:
四、总结
MOG2 更适合光照变化和动态背景较多的场景。
KNN 在处理运动目标和部分遮挡时可能更有效,但在复杂动态背景下可能表现不佳。
GMG 在动态背景和光照变化下表现良好,但可能在静态场景下不够精确。
在选择背景分割器时,需要根据具体的应用场景和需求进行权衡。例如,如果场景中光照变化较大,那么MOG2可能是更好的选择;而如果主要目标是检测运动目标并处理部分遮挡,那么KNN可能更为合适。
opencv 中背景分割器可借助 BackgroundSubtractor 类,检测阴影,用阈值排除阴影,从而关注实际特征
createBackgroundSubtractorMOG2 是 OpenCV 库中的一个函数,用于创建基于混合高斯模型(Mixture of Gaussians, MOG2)的背景减除器。以下是对 createBackgroundSubtractorMOG2 的中文文档,清晰地分点表示和归纳了其主要内容:
一、函数概述
createBackgroundSubtractorMOG2 是 OpenCV 中用于背景/前景分割的算法之一,基于混合高斯模型(MOG2)进行背景建模和前景检测。该函数允许用户通过调整参数来适应不同的应用场景。
二、函数原型
retval = cv2.createBackgroundSubtractorMOG2([, history[, varThreshold[, detectShadows]]])
三、参数解释
history(可选,整型,默认值 200):
varThreshold(可选,浮点型,默认值 15):
detectShadows(可选,布尔型,默认值 True):
四、返回值
该函数返回一个背景减除器对象,该对象可以用于对视频帧或图像序列进行前景检测。
五、工作原理
模型初始化:在开始时,算法会对视频中的每个像素建立一个混合高斯模型。这个模型会学习并适应场景中的背景变化。
背景建模:随着新帧的到来,算法会更新每个像素的高斯分布。对于与现有高斯分布匹配良好的像素,这些分布会被更新以反映最新的像素值。对于不匹配任何现有分布的像素,会创建新的高斯分布或替换最不可能代表背景的高斯分布。
前景检测:如果某个像素的值与所有高斯分布都不匹配,或者只与表示前景的高斯分布匹配,则该像素被视为前景像素。
阴影检测(如果启用):算法还可以检测并标记出由于前景对象遮挡而产生的阴影区域。
六、使用场景
动态背景:在背景经常变化的情况下,如光照变化、树叶摇动等,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.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 是 OpenCV 库中的一个重要函数,用于对图像进行阈值化处理。阈值化处理是数字图像处理中常用的一种方法,可以将图像转换为二值图像,即图像中每个像素只有黑白两种颜色。以下是 cv2.threshold 函数的详细中文文档:
一、函数原型
retval, dst = cv2.threshold(src, thresh, maxval, type[, dst])
二、参数说明
src:输入图像,必须是单通道灰度图像。
thresh:阈值,用于对像素值进行比较的界限值。可以是一个固定的数值,也可以是一个自适应阈值算法。
maxval:当像素值大于阈值时,赋予的新像素值。在二值化处理中,通常设置为 255(即白色)。
type:阈值类型,决定了对像素值大于或小于阈值的像素进行何种操作。常见的阈值类型包括:
dst:输出图像,可选参数。如果未提供,将创建一个新的图像来存储结果。
三、返回值
retval:选取的阈值。在某些情况下,如果使用了自适应阈值算法,这个值可能有所不同。
dst:输出图像,与输入图像具有相同的大小和类型。
四、应用场景
阈值处理在图像处理中有广泛的应用,包括但不限于:
cv2.dilate 是 OpenCV 库中的一个函数,用于对图像进行膨胀操作。膨胀是一种形态学操作,它可以用来增加图像中物体的大小,填充图像中的空洞,连接相邻的物体等。以下是 cv2.dilate 函数的详细中文文档:
一、函数原型
dst = cv2.dilate(src, kernel[, dst[, anchor[, iterations[, borderType[, borderValue]]]]])
二、参数说明
src:输入图像,可以是灰度图像或彩色图像。
kernel:
dst:
anchor:
iterations:
borderType:
borderValue:
三、返回值
dst:膨胀后的输出图像。
四、用法解释
cv2.dilate 函数的作用是将图像中的物体进行膨胀操作,使其变大。膨胀操作的效果取决于所使用的结构元素的形状和大小。通常情况下,结构元素可以是矩形、圆形或者自定义形状。膨胀操作会将结构元素覆盖区域内的像素值取最大值(对于灰度图像)或进行逻辑运算(对于二值图像),从而使目标物体的边界变得更加平滑,填充空洞,连接相邻的物体。
cv2.findContours 是 OpenCV 库中用于在二值图像中查找轮廓的函数。以下是对 cv2.findContours 函数的详细中文文档,包括函数原型、参数说明、返回值以及示例代码。
一、函数原型
contours, hierarchy = cv2.findContours(image, mode, method[, contours[, hierarchy[, offset]]])
二、参数说明
image:
mode:轮廓检索模式,指定轮廓的层级关系。
method:轮廓逼近方法,指定轮廓的表示方式。
contours(可选):
hierarchy(可选):
offset(可选):
三、返回值
contours:
轮廓列表,其中每个轮廓都是一个 NumPy 数组,包含该轮廓上所有点的坐标。
hierarchy:
轮廓的层次关系信息的 NumPy 数组,其中每个轮廓的层次关系由四个整数 [next, previous, first child, parent] 组成。
cv2.boundingRect 是 OpenCV 库中的一个函数,用于计算点集或灰度图像中非零像素的最小外接矩形(边界框)。以下是关于 cv2.boundingRect 函数的详细中文文档:
一、函数原型
rect = cv2.boundingRect(points)
或者
x, y, w, h = cv2.boundingRect(points)
二、参数说明
points:
三、返回值
rect(或者 x, y, w, h):
四、细节解析
坐标系统:在 OpenCV 中,坐标系的原点 (0, 0) 位于图像的左上角,x 轴向右为正方向,y 轴向下为正方向。
边界框属性:
与 cv2.findContours 的关系: