Opencv實戰(一) 視頻人數統計(C++ & Opencv)前后背景分離方法


在博客《視頻人數統計(opencv)》中,作者使用的Absdiff幀差法降低背景影響,進而通過二值化,邊緣化,濾波器,形態學變化,查找輪廓,輪廓面積控制,繪制輪廓等一系列方法完成了對樣例圖片的處理,並實現了人數統計的功能。同樣的,筆者最初也是和這位作者采用了同樣的方法來做,但是在筆者的樣例視頻中統計的效果並不是很理性。之后筆者使用了前后背景分離的方法來代替Absdiff幀差法,最后得到了較為理想的效果。閑話不多說,直接上代碼了。

using namespace std;
using namespace cv;

int main(int argc, const char** argv)
{
VideoCapture cap;
bool update_bg_model = true;

//cap.open(0);
cap.open("People.mp4");

if( !cap.isOpened() )
{
printf("can not open camera or video file\n");
return -1;
}

namedWindow("image", WINDOW_AUTOSIZE);
namedWindow("foreground mask", WINDOW_AUTOSIZE);
namedWindow("foreground image", WINDOW_AUTOSIZE);
namedWindow("mean background image", WINDOW_AUTOSIZE);

BackgroundSubtractorMOG2 bg_model;//(100, 3, 0.3, 5);建立背景模型

Mat img, fgmask, fgimg;
int i = 0;

for(;;)
{
i++;
cap >> img;

if( img.empty() )
break;

img = img(Rect(40, 0, 300, img.rows));

if( fgimg.empty() )
fgimg.create(img.size(), img.type());

//更新模型
bg_model(img, fgmask, update_bg_model ? -1 : 0);
medianBlur(fgmask, fgmask, 13);
threshold(fgmask, fgmask, 150, 255, THRESH_BINARY);

Mat element = getStructuringElement(MORPH_RECT, Size(3, 3));

/*erode(fgmask, fgmask, element, Point(0, 0), 3);
dilate(fgmask, fgmask, element, Point(0, 0), 3);*/


Mat srcGrayImage = fgmask.clone();
vector<vector<Point>> vContours;
vector<Vec4i> vHierarchy;
findContours(srcGrayImage, vContours, vHierarchy, RETR_CCOMP, CHAIN_APPROX_SIMPLE, Point(0, 0));

int count = 0;
RNG rng(12345);

for (int i = 0; i < vContours.size(); i++)
{
double area = contourArea(vContours[i], false);

RotatedRect smallRect = minAreaRect(vContours[i]);
Point2f smallRect_center = smallRect.center;
float smallRect_width = smallRect.size.width;
float smallRect_height = smallRect.size.height;
float smallRect_angle = 0;

smallRect = RotatedRect(smallRect_center, Size2f(smallRect_height, smallRect_width), smallRect_angle);
Point2f P[4];
smallRect.points(P);

if (area>1000 && area < 4200)
{
count++;
for (int j = 0; j <= 3; j++)
{
line(img, P[j], P[(j + 1) % 4], Scalar(255, 0, 0), 2);
}
}
if (area>4200 && area < 6000)
{
count+=2;
for (int j = 0; j <= 3; j++)
{
line(img, P[j], P[(j + 1) % 4], Scalar(255, 0, 0), 2);
}
}

}

Scalar color = Scalar(rng.uniform(0, 255), rng.uniform(0, 255), rng.uniform(0, 255));//任意值
putText(img, int2str(count), Point(220, 40), FONT_HERSHEY_TRIPLEX, 1, color, 2);

fgimg = Scalar::all(0);
img.copyTo(fgimg, fgmask);

Mat bgimg;
bg_model.getBackgroundImage(bgimg);

imshow("image", img);

/*string windows_name = "Video/image_" + int2str(i);
string windows_name_ext = windows_name + ".jpg";
imwrite(windows_name_ext, img);*/


imshow("foreground mask", fgmask);


imshow("foreground image", fgimg);
if(!bgimg.empty())
imshow("mean background image", bgimg );

char k = (char)waitKey(1);
if( k == 27 ) break;
if( k == ' ' )
{
update_bg_model = !update_bg_model;
if(update_bg_model)
printf("\t>背景更新(Background update)已打開\n");
else
printf("\t>背景更新(Background update)已關閉\n");
}
}

return 0;
}

最后,讓我們來看看運行結果:

1個人

這里寫圖片描述

2個人

這里寫圖片描述

3個人

這里寫圖片描述

4個人

這里寫圖片描述

附加個人視頻人數統計展示地址:
http://www.bilibili.com/video/av11568593/
http://www.bilibili.com/video/av11593676/

參考:
【1】http://blog.csdn.net/u013812682/article/details/51980765
【2】 @淺墨_毛星雲《OpenCV3編程入門》OpenCV2版書本附贈示例程序20


注意!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系我们删除。



 
粤ICP备14056181号  © 2014-2020 ITdaan.com