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/

鉴于很多朋友求数据源,现公开下载地址

https://download.csdn.net/download/lgh0824/10382739

参考:
【1】http://blog.csdn.net/u013812682/article/details/51980765
【2】 @浅墨_毛星云《OpenCV3编程入门》OpenCV2版书本附赠示例程序20

评论 27
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

二十四桥下一句

您的鼓励是我最大的创作动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值