基于OpenCV高斯模型的公共场景人流量统计

关注我,并留言,不定期送各种c++资料
代码全部在下面,就一个文件,随便添加一个空项目后就可以将下面代码替换到工程中。具体操作步骤没时间过多的写,可以看注释。代码运行没有问题,我用的是opencv344和vs2017。需要源代码和资料的请在这里下载,在我的工程里面环境已经配置好https://download.csdn.net/download/qq_41476542/12305236
代码如下:

#include
#include
#include 
using namespace std;//命名空间std
using namespace cv;//命名空间cvv b  
string int2str(const int &int_temp)//数据流之间的转换
{
	stringstream stream;//通过流来实现字符串和数字的转换
	string string_temp;//有不限长度的优点
	stream << int_temp; //将int输入流,向左移4位
	string_temp = stream.str();  //此处也可以用 stream>>string_temp//从stream中抽取前面插入的int值
	
	return string_temp;
} int main(int argc, const char** argv)
{
	VideoCapture cap;//打开摄像头对象
	bool update_bg_model = true;
    cap.open(0);
   // cap.open("http://113.57.246.23:8080/shot.jpg");
    cap.open("C:\\Users\\Administrator\\Desktop\\acvis09-5950.avi");
	//cap.open("D:\\qq\\demo\\vtest.avi");	
	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);//原图大小
	
	Ptr bg_model = createBackgroundSubtractorMOG2();//(100, 3, 0.3, 5);建立背景模型
	Mat img, fgmask, fgimg;//定义矩阵
	int i = 0;
	for (;;)//死循环
	{
		i++;
		cap >> img;//由capture类输出图像
		if (img.empty())
			break;
		img = img(Rect(40, 0, 300, img.rows));
		if (fgimg.empty())
			fgimg.create(img.size(), img.type());
		//更新模型
		bg_model->apply(img, fgmask, update_bg_model ? -1 : 0);//背景模型的跟新
		medianBlur(fgmask, fgmask, 13);//有效抑制噪声的中值滤波函数,基本思想是用像素点邻域灰度值的中值来代替该像素点的灰度值。输入图像输出图像尺寸大小,必须是大于1的奇数,如3、5、7……
		threshold(fgmask, fgmask, 150, 255, THRESH_BINARY);//# 阈值化,将非纯白色(244~255)的所有像素设为0
		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> vContours;
		vector 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该类表示平面上的旋转矩形,该类对象有三个重要属性:
			//矩形中心点(质心),边长(长和宽),旋转角度。三种构造函数和三种成员操作函数
			RotatedRect smallRect = minAreaRect(vContours[i]);
		/*	RotatedRect该类表示平面上的旋转矩形,有三个属性:
				矩形中心点(质心)
				边长(长和宽)
				旋转角度
*/
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,这里就使用flow1_at_point.x形式存取像素值
			Point2f P[4];
			//points()函数用于求矩形的4个顶点,
			smallRect.points(P);
			if (area>600 && area < 3000)
			{
				count++;
				for (int j = 0; j <= 3; j++)
				{
					//划线,绘制在img上
					line(img, P[j], P[(j + 1) % 4], Scalar(255, 0, 0), 2);
				}
			}
			if (area>3000&& area < 5000)
			{
				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));
		//写字参数1:, Mat& img,待写字的图片,我们写在img图上
		/*参数2:,const string& text,待写入的字,我们下面写入Hello
			参数3:, Point org, 第一个字符左下角坐标,我们设定在图片的Point(50, 60)坐标。表示x = 50, y = 60。
			参数4:,int fontFace,字体类型,FONT_HERSHEY_SIMPLEX ,FONT_HERSHEY_PLAIN ,FONT_HERSHEY_DUPLEX 等等等。
			参数5:,double fontScale,字体大小,我们设置为2号
			参数6:,Scalar color,字体颜色,颜色用Scalar()表示,不懂得去百度。
			参数7:, int thickness,字体粗细,我们下面代码使用的是4号
			参数8:, int lineType,线型,我们使用默认值8.*/
		
		putText(img, int2str(count), Point(220, 40), FONT_HERSHEY_TRIPLEX, 1, color, 2);
		//设定所有的值为0.
		得到前景
		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;
}

你可能感兴趣的:(对于初学者的教学)