欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

OpenCV基于背景减除实现行人计数

程序员文章站 2022-03-03 08:05:23
目录前言一、图像预处理二、对象计数1.轮廓提取2.效果显示三、源码总结前言本文将使用opencv c++ 对视频中的人流量进行统计。一、图像预处理原图如图所示。本案例的需求是想要统计画面中的人流量。画...

前言

本文将使用opencv c++ 对视频中的人流量进行统计。

一、图像预处理

OpenCV基于背景减除实现行人计数

原图如图所示。本案例的需求是想要统计画面中的人流量。画面中走动的行人可以看作是前景,那么我们就需要将前景、背景分割出来。我们可以使用opencv提供的backgroundsubtractormog2 高斯混合模型,将行人从画面中分割出来,然后提取轮廓就可以统计人流量了。

ptr<backgroundsubtractormog2>mog = createbackgroundsubtractormog2();
mog->apply(frame, mask);

OpenCV基于背景减除实现行人计数

使用上面两行代码就可以创建高斯混合背景提取器。传入原图,返回背景减除结果。如上图所示。接下来只需对上图进行一些简单操作,再提取轮廓就可以进行人流统计了。

threshold(mask, mask, 200, 255, thresh_binary );

morphologyex(mask, mask, morph_open, kernel);

dilate(mask, mask, kernel1);

进行二值化、形态学等操作可以将行人作为一个独立个体分割出来。效果如图。

OpenCV基于背景减除实现行人计数

二、对象计数

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);
	}

OpenCV基于背景减除实现行人计数

最终效果如图所示。

三、源码

#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、将分割出来的前景进行轮廓提取,从而统计出人流量。

到此这篇关于opencv基于背景减除实现行人计数的文章就介绍到这了,更多相关opencv行人计数内容请搜索以前的文章或继续浏览下面的相关文章希望大家以后多多支持!