相关API:createBackgroundSubtractorMOG2
所属领域及用途
createBackgroundSubtractorMOG2 通常属于计算机视觉库中的函数,常见于 OpenCV 这类广泛应用于图像和视频处理的库。它的主要用途是进行背景减除操作,也就是从包含动态目标(比如视频里运动的人、车等物体)的图像序列(通常是视频帧)中,把相对静态的背景提取出来,进而分离出前景中的目标物体,方便后续对这些目标做识别、跟踪等进一步处理。
参数含义
1. 第一个参数(例如这里的 500):
• 在多数实现中,这个参数一般表示历史帧数(history)。它决定了构建背景模型时参考的过去图像帧的数量。较大的值意味着模型能基于更多的过往信息来学习背景的特征,使得对背景的估计更准确和稳定,但同时也会增加计算量和内存占用。例如设置为 500 ,就是利用过去 500 帧的图像数据来不断更新和完善背景模型,以适应背景可能存在的缓慢变化(像光照渐变等情况)。
2. 第二个参数(例如这里的 100):
• 常对应着方差阈值(varThreshold)。这个阈值用于判定像素点是否属于背景或者前景。对于每个像素点,在背景模型中会有相应的高斯分布来描述其颜色特征及变化情况。当新的一帧图像中某个像素点的颜色值与对应高斯分布的均值的偏差大于这个方差阈值时,该像素点就会被判定为前景,反之则属于背景。不同的场景下,需要根据图像中前景和背景颜色差异等实际情况合理调整该阈值,比如在复杂多变且前景与背景区分度不是特别大的场景下,可能需要适当调小这个值来更精准地分离前景和背景。
3. 第三个参数(例如这里的 false):
• 通常是一个布尔值,用于控制是否检测阴影(detectShadows)。如果设置为 true,算法在进行背景减除时,除了区分前景和背景,还会尝试标记出那些可能是前景物体投射的阴影区域,将其作为一种特殊的分类来处理,这在某些需要精细区分目标和阴影的应用场景中有用;而设置为 false,就像这里的情况,算法不会去专门检测阴影,直接简单地将图像分为前景和背景两部分,这样能减少一些额外的计算开销,在一些对阴影不关注的场景下更适用。
MOG2->apply
apply 方法主要用于将背景减除算法应用到输入的图像帧上,目的是通过已构建好的背景模型(基于之前设定的历史帧数等参数学习得到的背景特征信息),来区分当前输入图像帧中的前景物体和背景区域,进而输出一个能够表示这种区分结果的图像数据,通常是以掩模(mask)的形式呈现。
参数与返回值
• 参数:它接收一个参数,就是要进行背景减除处理的单帧图像(比如视频中的某一帧画面,图像格式通常是符合对应库要求的,像 OpenCV 里一般是 Mat 类型等表示的图像数据结构)。
• 返回值:返回值通常是一个图像掩模,其数据类型同样取决于具体的库实现,在 OpenCV 中一般也是 Mat 类型。这个掩模图像中每个像素点的像素值有着特定含义,比如常见的是以 0 表示被判定为背景的像素点,以 255 表示被判定为前景的像素点(当然也可能存在其他灰度值用于表示不同情况,例如若开启阴影检测,可能还有中间值表示阴影区域等)。后续就可以利用这个掩模图像,结合其他图像处理操作(例如寻找轮廓、做形态学运算等)来进一步处理和分析检测出的前景目标,像提取前景目标的形状、位置等信息,或者去除一些噪点等,以便更好地服务于诸如目标跟踪、目标识别等更复杂的计算机视觉任务。pMOG2->apply (或相应语言下对应的正确调用方式)是实现背景减除并获取前景掩模的关键步骤,是整个基于背景建模进行目标检测等流程中的核心环节之一。
pMOG2->getBackgroundImage
这个方法的主要作用是获取当前所构建的背景模型对应的图像表示。也就是说,基于之前设定的参数(如历史帧数等)学习和更新后,模型所认为的当前场景下的背景画面会以图像的形式被提取出来。它在调试或者一些需要直观查看背景模型学习效果的场景中很有用,比如想确认背景减除器是否准确地学习到了场景中的静态背景部分,有没有受到前景物体的干扰等情况。
返回值
通常会返回一个图像对象(例如在 OpenCV 中会返回 Mat 类型的图像数据结构),该图像展示的就是背景模型所对应的背景图像内容,其图像的尺寸、通道数等属性和之前输入到背景减除器进行处理的原始图像帧是对应的(一般是在不断学习过程中适配了输入图像的相关属性)。返回的这个背景图像可以像普通图像一样进行展示、保存或者进一步分析等操作,比如通过可视化的方式展示在界面上,对比查看其与实际场景中期望的背景是否一致,或者将其保存下来用于后续其他分析用途等。
#include <opencv2/opencv.hpp>
#include <iostream>
using namespace cv;
using namespace std;
void process_frame(Mat &image);
void process2(Mat &image);
auto pMOG2 = createBackgroundSubtractorMOG2(500, 100, false);
int main(int argc, char** argv) {
VideoCapture capture("D:/images/video/vtest.avi");
if (!capture.isOpened()) {
printf("could not open the camera...\n");
}
namedWindow("frame", WINDOW_AUTOSIZE);
Mat frame;
while (true) {
bool ret = capture.read(frame);
if (!ret) break;
imshow("frame", frame);
process2(frame);
char c = waitKey(1);
if (c == 27) { // ESC
break;
}
}
capture.release();
waitKey(0);
destroyAllWindows();
}
void process2(Mat &image) {
Mat mask, bg_image;
pMOG2->apply(image, mask);
// 形态学操作
Mat se = getStructuringElement(MORPH_RECT, Size(1, 5), Point(-1, -1));
morphologyEx(mask, mask, MORPH_OPEN, se);
imshow("mask", mask);
vector<vector<Point>> contours;
vector<Vec4i> hirearchy;
findContours(mask, contours, hirearchy, RETR_EXTERNAL, CHAIN_APPROX_SIMPLE, Point());
for (size_t t = 0; t < contours.size(); t++) {
double area = contourArea(contours[t]);
if (area < 100) {
continue;
}
Rect box = boundingRect(contours[t]);
RotatedRect rrt = minAreaRect(contours[t]);
// rectangle(image, box, Scalar(0, 0, 255), 2, 8, 0);
circle(image, rrt.center, 2, Scalar(255, 0, 0), 2, 8, 0);
ellipse(image, rrt, Scalar(0, 0, 255), 2, 8);
}
imshow("result", image);
}