opencv-080-视频分析(背景消除与前景ROI提取)

知识点

通过视频中的背景进行建模,实现背景消除,生成mask图像,通过对mask二值图像分析实现对前景活动对象ROI区域的提取,是很多视频监控分析软件常用的手段之一,该方法很实时!整个步骤如下:

  1. 初始化背景建模对象GMM
  2. 读取视频一帧
  3. 使用背景建模消除生成mask
  4. 对mask进行轮廓分析提取ROI
  5. 绘制ROI对象

代码(c++,python)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
#include <iostream>
#include <opencv2/opencv.hpp>

using namespace std;
using namespace cv;

void process_frame(Mat &image);
Ptr<BackgroundSubtractor> pMOG2 = createBackgroundSubtractorMOG2(500, 100, false);

/*
* 视频分析(背景消除与前景ROI提取)
*/
int main() {
VideoCapture capture("../images/vtest.avi");
if (!capture.isOpened()) {
printf("could not open camera...\n");
return -1;
}

Mat frame;
while (true) {
bool ret = capture.read(frame);
if (!ret) break;
imshow("input", frame);
process_frame(frame);
imshow("result", frame);
char c = waitKey(50);
if (c == 27) {
break;
}
}
waitKey(0);
return 0;

waitKey(0);
return 0;
}

void process_frame(Mat &image) {
Mat mask;
pMOG2->apply(image, mask);

// 开操作
Mat se = getStructuringElement(MORPH_RECT, Size(1, 5));
morphologyEx(mask, mask, MORPH_OPEN, se);

// 寻找最大轮廓
vector<vector<Point>> contours;
vector<Vec4i> hierarchy;
findContours(mask, contours, hierarchy, RETR_EXTERNAL, CHAIN_APPROX_SIMPLE);
for (size_t t = 0; t < contours.size(); t++) {
double area = contourArea(contours[t]);
if (area < 100) {
continue;
}
RotatedRect rect = minAreaRect(contours[t]);
ellipse(image, rect, Scalar(0, 255, 0), 2);
circle(image, rect.center, 2, Scalar(255, 0, 0), 2);
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
import numpy as np
import cv2 as cv

cap = cv.VideoCapture('D:/images/video/vtest.avi')
fgbg = cv.createBackgroundSubtractorMOG2(
history=500, varThreshold=100, detectShadows=False)


def process(image, opt=1):
mask = fgbg.apply(frame)
line = cv.getStructuringElement(cv.MORPH_RECT, (1, 5), (-1, -1))
mask = cv.morphologyEx(mask, cv.MORPH_OPEN, line)
cv.imshow("mask", mask)
# 轮廓提取, 发现最大轮廓
out, contours, hierarchy = cv.findContours(mask, cv.RETR_EXTERNAL, cv.CHAIN_APPROX_SIMPLE)
for c in range(len(contours)):
area = cv.contourArea(contours[c])
if area < 100:
continue
rect = cv.minAreaRect(contours[c])
cv.ellipse(image, rect, (0, 255, 0), 2, 8)
cv.circle(image, (np.int32(rect[0][0]), np.int32(rect[0][1])), 2, (255, 0, 0), 2, 8, 0)
return image, mask


while True:
ret, frame = cap.read()
cv.imwrite("D:/input.png", frame)
cv.imshow('input', frame)
result, m_ = process(frame)
cv.imshow('result', result)
k = cv.waitKey(50)&0xff
if k == 27:
cv.imwrite("D:/result.png", result)
cv.imwrite("D:/mask.png", m_)

break
cap.release()
cv.destroyAllWindows()

结果

代码地址

github