OpenCV C++案例實戰十一《基于背景減除---行人計數》
- 前言
- 一、影像預處理
- 二、物件計數
- 1.輪廓提取
- 2.效果顯示
- 三、原始碼
- 總結
前言
本文將使用OpenCV C++ 對視頻中的人流量進行統計,
一、影像預處理

原圖如圖所示,本案例的需求是想要統計畫面中的人流量,畫面中走動的行人可以看作是前景,那么我們就需要將前景、背景分割出來,我們可以使用OpenCV提供的BackgroundSubtractorMOG2 高斯混合模型,將行人從畫面中分割出來,然后提取輪廓就可以統計人流量了,
Ptr<BackgroundSubtractorMOG2>MOG = createBackgroundSubtractorMOG2();
MOG->apply(frame, mask);

使用上面兩行代碼就可以創建高斯混合背景提取器,傳入原圖,回傳背景減除結果,如上圖所示,接下來只需對上圖進行一些簡單操作,再提取輪廓就可以進行人流統計了,
threshold(mask, mask, 200, 255, THRESH_BINARY );
morphologyEx(mask, mask, MORPH_OPEN, kernel);
dilate(mask, mask, kernel1);
進行二值化、形態學等操作可以將行人作為一個獨立個體分割出來,效果如圖,

二、物件計數
1.輪廓提取
將上面的二值影像進行輪廓檢測,然后統計有效輪廓就可以完成物件計數了,
vector<vector<Point>>contours;
vector<vector<Point>>EffectiveContours;
findContours(mask, contours, RETR_EXTERNAL, CHAIN_APPROX_SIMPLE);
for (int i = 0; i < contours.size(); i++)
{
double area = contourArea(contours[i]);
if (area > 300)
{
EffectiveContours.push_back(contours[i]);
}
}
2.效果顯示
char text[10];
for (int i = 0; i < EffectiveContours.size(); i++)
{
RotatedRect rect = minAreaRect(EffectiveContours[i]);
Rect box = rect.boundingRect();
rectangle(frame, Rect(box.x, box.y, box.width, box.height), Scalar(0, 255, 0), 2);
sprintf_s(text, "%s%d", "Current:", EffectiveContours.size());
putText(frame, text, Point(10, 30), FONT_HERSHEY_SIMPLEX, 1, Scalar(0, 255, 0), 2);
}
最終效果如圖所示,
三、原始碼
#include<iostream>
#include<opencv2/opencv.hpp>
using namespace std;
using namespace cv;
int main()
{
VideoCapture capture;
capture.open("1.avi");
if (!capture.isOpened())
{
cout << "Can not open video source!" << endl;
system("pause");
return -1;
}
Ptr<BackgroundSubtractorMOG2>MOG = createBackgroundSubtractorMOG2();
Mat kernel = getStructuringElement(MORPH_RECT, Size(3, 5));
Mat kernel1 = getStructuringElement(MORPH_RECT, Size(7, 3));
Mat frame, mask;
while (capture.read(frame))
{
MOG->apply(frame, mask);
threshold(mask, mask, 200, 255, THRESH_BINARY );
morphologyEx(mask, mask, MORPH_OPEN, kernel);
dilate(mask, mask, kernel1);
vector<vector<Point>>contours;
vector<vector<Point>>EffectiveContours;
findContours(mask, contours, RETR_EXTERNAL, CHAIN_APPROX_SIMPLE);
for (int i = 0; i < contours.size(); i++)
{
double area = contourArea(contours[i]);
if (area > 300)
{
EffectiveContours.push_back(contours[i]);
}
}
char text[10];
for (int i = 0; i < EffectiveContours.size(); i++)
{
RotatedRect rect = minAreaRect(EffectiveContours[i]);
Rect box = rect.boundingRect();
rectangle(frame, Rect(box.x, box.y, box.width, box.height), Scalar(0, 255, 0), 2);
sprintf_s(text, "%s%d", "Current:", EffectiveContours.size());
putText(frame, text, Point(10, 30), FONT_HERSHEY_SIMPLEX, 1, Scalar(0, 255, 0), 2);
}
imshow("frame", frame);
imshow("mask", mask);
char key = waitKey(10);
if (key == 27)
{
break;
}
}
destroyAllWindows();
capture.release();
system("pause");
return 0;
}
總結
本文使用OpenCV C++ 基于背景減除進行人流計數,關鍵步驟有以下幾點,
1、使用BackgroundSubtractorMOG2 將前景從背景中分割出來,
2、將分割出來的前景進行輪廓提取,從而統計出人流量,
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/401500.html
標籤:其他
下一篇:003-OpenCV簡單讀取視頻
