运动物体检测以及追踪

概括:运动物体检测是应用差分法实现,运动物体追踪是利用基于时间序列预测模型实现。
##运动物体检测
常用的检测方法为背景减除法和帧差法,这两种方法原理基本上都是图片相减。两种方法各有优缺点:

帧差法适用于更多场景,如:摄像头移动以及多目标运动场景,缺点就是检测的人物之间容易出现空洞。
背景减除法,适用场景局限,只适用于第一帧是背景图的视频,但检测人物没有空洞。
以上这两种方法均不能很好的处理光照过强以及阴影的运动物体视频。

物体检测方法还有许多,有基于图像相减的三帧差法,还有对于电脑性能要求较高的光流法。


效果

背景减除法:(人物没有出现空洞现象,但对于光照过强区域效果不好)
这里写图片描述
帧差法:(人物出现空洞,对下一步处理造成影响)
这里写图片描述

运动物体追踪

之前一直对每一帧检测的运动物体进行标志就以为达到了追踪,但实时检测标志并不是追踪,若在多目标运动物体中没有做到区分不同的目标,就不算是追踪。

追踪思路

这里写图片描述
1.对每一帧进行运动目标检测
2.对检测到的物体进行判断,判断是否是存在的运动目标,是则添加运动轨迹,不是则当作新的目标。
3.画出运动轨迹等
如何判断当前已检测到的目标是否是已经存在的运动目标?
这里我刚开始选取的是简单的轮廓面积已经轮廓外接矩形等特征,因为轮廓获得的不稳定,显然效果不是很好。这里采用的是预测模型,在上一篇鼠标运动的预测中。简单来说就是用检测到的运动目标与预测的位置进行比较,若在一定误差内就算追踪成功。

运动视频下载

网上有很多的视频库,我下载视频库的链接

代码

头文件

#pragma once
#ifndef TrackObject
#define TrackObject
#include<opencv2\opencv.hpp>
#include<iostream>
using namespace std;
using namespace cv;
class Blob {
public:
	vector<Point>_contour;
	vector<Point>centerPos;
	Point preditNextCenter;
	Point currentCenter;//first
	Rect currentRect;//first
	double currentArea;//first
	double currentRate;//first
	//bool isStillBeTracked;//是否还在被跟踪
	//int FramesWithoutMatched;
	Blob(vector<Point>con);
	void Predit();
	
};
#endif // !TrackObject

Main

//问题:由于光照的影响很不稳定(对于寻找的轮廓),光照补偿(解决阴影)和去除光照



#include "ObjectTrack.h"
double DistanceBetwwenPoint(Point p1,Point p2)
{
	int x =abs(p1.x - p2.x);
	int y = abs(p1.y - p2.y);
	double res = sqrt(pow(x, 2)) + sqrt(pow(y, 2));
	//cout << "距离为:" << res << endl;
	return res;
	//sqrt(里面参数接受为double型)
}
vector<Blob>Blobs;
int main()
{
	VideoCapture  cap("Walk1.mpeg");//这个视频有轻微抖动现象,利用高斯滤波
	//int framenum = cap.get(CAP_PROP_POS_FRAMES);
	
	if (!cap.isOpened()) { cout << "读取视频错误" << endl; return 0; }
	Mat cur, pre;
	cap >> pre;
	GaussianBlur(pre,pre,Size(3,3),0.8);
	cvtColor(pre,pre,CV_BGR2GRAY);

	while (1)
	{
		cap >> cur;

		if (cur.empty()) { break; }//作用相当于判断是否到达视频最后一帧

		GaussianBlur(cur,cur,Size(3,3),0.8);
		cvtColor(cur,cur,CV_BGR2GRAY);

		/*具体实现步骤*/
		//1.背景减除法检测运动物体
		Mat df;//difference frame
		absdiff(cur, pre,df );
		threshold(df,df,70,255,CV_THRESH_BINARY);
		vector<vector<Point>>contours;//找到的轮廓均存在contours
		findContours(df,contours,CV_RETR_EXTERNAL,CV_CHAIN_APPROX_SIMPLE);

		vector<Blob>possibleBlobs;
		
		for (size_t i = 0; i < contours.size(); i++)
		{//筛选出可能的目标对象,根据视频中的背景设置筛选条件
			Blob tem(contours[i]);
			//if (tem.currentArea > 60&&tem.currentRate<1.0) {
			if (tem.currentArea > 100) {
				possibleBlobs.push_back(tem);
				
			}
		}
		cout << "每次检测出来的possible个数" << possibleBlobs.size() << endl;

		/*
		2.跟踪队列为空则直接把possibleBlob全部放入跟踪队列
		其他则进行判断,判断是已有的跟踪对象,则把中心点推入已有的跟踪对象,
		若是新的跟踪对象直接放入跟踪队列里
		*/
		if (Blobs.size()==0) {//跟踪队列为空
			for (auto &c : possibleBlobs)
			{
				Blobs.push_back(c);
			}
			cout << "目标队列为空时第一次加入目标队列追踪的个数"<<Blobs.size() << endl;
		}
		else {
			for (auto &tem : Blobs)
			{
				tem.Predit();
			}
			/*
			3.选作什么作为不同的跟踪目标之间的区分呢
			首先尝试过直接利用已找到的轮廓作为区分,例如轮廓的面积和轮廓外界矩形特征等,但是区分效果很不好
			这里利用的是鼠标运动检测中的预测目标点,若预测的目标点小于规定值则认为是同一个目标。

			*/
			for (auto &tem : possibleBlobs)
			{
				int flag = false;
				for (auto &target : Blobs)
				{
					if (DistanceBetwwenPoint(tem.currentCenter, target.preditNextCenter) <50.0 )
					{
						target.centerPos.push_back(tem.currentCenter);
						flag = true;
						break;
					}
				}

				if (flag == false)Blobs.push_back(tem);//作为新目标被跟踪
			}
		}
		/*for (auto &tem : possibleBlobs)
		{//不正确的写法
		int flag = false;//匹配标志
		for (auto &exist : Blobs)
		{
		if (abs(tem.currentArea - exist.currentArea) <= scale && abs(tem.currentRate - exist.currentRate) <= scale)
		{
		exist.centerPos.push_back(tem.currentCenter);
		flag = true;
		break;
		}
		}
		if (flag == false)Blobs.push_back(tem);
		}*/

		
		
		cout <<"追踪对象有:"<< Blobs.size() << endl;
		for (int i = 0; i < Blobs.size(); i++)
		{
			int size = Blobs[i].centerPos.size();
			cout << "第" << i << "个追踪对象内的centerPos点数:" << size << endl;
			
			for (int k= 0;k < size; k++)
			{
				circle(cur, Blobs[i].centerPos[k],1,Scalar(255,0,0),1,8);
			}
			
			if (size == 1)
			{
				rectangle(cur, Blobs[i].currentRect, Scalar(255, 0, 0), 1, 8);
			}
			else
			{
				Point p1;
				p1.x = Blobs[i].centerPos[size - 1].x - Blobs[i].currentRect.width*0.5;
				p1.y= Blobs[i].centerPos[size - 1].y - Blobs[i].currentRect.height*0.5;
				Rect rect(p1.x,p1.y,Blobs[i].currentRect.width,Blobs[i].currentRect.height);
				rectangle(cur, rect, Scalar(255, 0, 0), 1, 8);
			}
			
		}
		//drawContours(cur,contours,-1,Scalar(255,0,0),1,8);
		imshow("df",df);
		imshow("cur",cur);
		//pre=cur;//加上这一句就是帧差法
		if (waitKey(100) == 27)break;//或者当前的帧数是最后一帧,采用判断当前读取的帧数是否非空即可
	}
	cap.release();
	destroyAllWindows();
	system("pause");
	return 0;
}



其中cpp文件里有初始化和预测函数,预测方法与鼠标移动预测类似,所以就不贴了。

效果

这里写图片描述

  • 15
    点赞
  • 161
    收藏
    觉得还不错? 一键收藏
  • 15
    评论
Python爬虫实训主要涉及以下几个方面的内容: 1. 爬虫基础知识:了解什么是爬虫,爬虫的工作原理,以及常用的爬虫框架和库,如Scrapy、BeautifulSoup等。 2. 网络请求:学习如何使用Python发送HTTP请求,获取网页内容。可以使用Python的requests库来实现。 3. 数据解析:学习如何解析网页内容,提取所需的数据。可以使用正则表达式、XPath、CSS选择器等方法进行数据解析。 4. 数据存储:学习如何将爬取到的数据存储到本地文件或数据库中。可以使用Python的文件操作或数据库操作来实现。 5. 反爬虫策略:了解常见的反爬虫策略,如验证码、IP封禁等,并学习如何应对这些策略,提高爬虫的稳定性和效率。 6. 爬虫实战:通过实际案例来进行爬虫实训,例如爬取某个网站的新闻、图片等内容,并进行数据分析和可视化展示。 以下是一个简单的示例代码,演示如何使用Python进行简单的网页爬取和数据解析: ```python import requests from bs4 import BeautifulSoup # 发送HTTP请求,获取网页内容 url = 'https://www.example.com' response = requests.get(url) html = response.text # 解析网页内容,提取所需数据 soup = BeautifulSoup(html, 'html.parser') title = soup.title.text links = soup.find_all('a') for link in links: href = link.get('href') text = link.text print(href, text) # 存储数据到本地文件 with open('data.txt', 'w', encoding='utf-8') as f: f.write(title) f.write('\n') for link in links: f.write(link.get('href')) f.write('\n') print('爬取完成!') ```
评论 15
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值