首页 > 代码库 > 压缩跟踪(CT)代码详细学习_模块1(样本的采集和扩充)

压缩跟踪(CT)代码详细学习_模块1(样本的采集和扩充)

    本章主要详解的是compressive tracking框架中的第一部分:样本的采集和扩充部分。

    在开始代码学习的前面,你需要知道的理论知识参见论文:Real-time Compressive Tracking。理论理解可以参见我的博客:http://blog.csdn.net/ikerpeng/article/details/19826409 。

    这个模块中你需要知道一个基本的概念:代码里面几个变量指的是什么。上一张图:


也许你现在还不知道他们是什么,直接贴代码了。相信有我的注释你一定会懂的。


头文件 sampleRect.h 

#pragma once
#include <opencv2\opencv.hpp>
#include <vector>
using namespace cv;
using namespace std;

class sampleRect
{
public:
	 sampleRect(void);//构造函数,初始化下面的rOuterpositive
	 ~sampleRect(void);

private:
	int rOuterpositive;//这个设定的是正负样本的边界,在这个边界里面的就是正样本,外面的就是负样本。
	void sampleRect0(Mat& _image, Rect& _objectPatch, float _rInner, float _rOuter, int _maxSampleNum, vector<Rect>& _sampleRect );
	//这个函数最重要,它是用来扩充正负样本的。他通过设定_rInner,_rOuter两个边界,选出的样本是_rInner里面的,_rOuter外面的。也就是说_rInner>_rOuter.
	//在进行正样本扩充的时候_rOuter=0._rInner=上面那个边界rOuterpositive;产生负样本的时候_rOuter=rOuterpositive。里面的参数在实现的时候说明
	void sampleRect1(Mat& _image, Rect& _objectPatch, float _srw,  vector<Rect>& _sampleRect );//这个函数是要扩充待检测的样本的

};



#include "sampleRect.h"
#include <math.h>
#include<iostream>


sampleRect::sampleRect()
{
	int rOuterpositive=4;//这里我们都是以矩形框的左上角的点为参照的,若是要扩充的样本的这个点离目标位置的这个点的距离在4个像素以内则定义为正样本,否则为负。
}
sampleRect::~sampleRect()
{

}
void sampleRect::sampleRect0(Mat& _image, Rect& _objectPatch, float _rInner, float _rOuter, int _maxSampleNum, vector<Rect>& _sampleRect )
{
	/*
	Arguments: 
   -_image:        processing frame 
   -_objectBox:    recent object position  
   -_rInner:       inner sampling radius 
   -_rOuter:       Outer sampling radius 
   -_maxSampleNum: maximal number of sampled images 
   -_sampleRect:    Storing the rectangle coordinates of the sampled images.
	*/
	int rowsz=_image.rows-_objectPatch.height-1;//y方向上取值的最大范围
	int colsz= _image.cols- _objectPatch.width-1;
	float rInnerSq=_rInner*_rInner;//这个相当于是外圆的距离的平方,为的是和后面的dist作比较的,小于这个值就在圆里面
	float rOuterSq=_rOuter*_rOuter;//同上,大于这个值就在选择的范围里面了。具体参见示意图1。
	int dist;
	RNG rng;

	//下面这个是为了要确定选出来的patch快的范围(其实是左上角点的坐标的范围)
	int minrow = max(0,(int)_objectPatch.y-(int)_rInner);//计算出的结果是y坐标的最小取值,相当于一个圆外接矩形的最上面的那个点。具体参见示意图1
	int maxrow = min(rowsz-1, (int)_objectPatch.y+(int)_rInner);//计算出的结果是y坐标的最大取值,相当于一个圆外接矩形的最下面的那个点。
	int mincol = max(0,(int)_objectPatch.x-(int)_rInner);//计算出的结果是x坐标的最小取值,相当于一个圆外接矩形的最左边的那个点。
	int maxcol = min(colsz,(int)_objectPatch.x+(int)_rInner);//计算出的结果是x坐标的最大取值,相当于一个圆外接矩形的最右边的那个点。

	float prob=_maxSampleNum/(maxrow-minrow+1)/(maxcol-mincol+1);//这个值的设定是为了将扩充正负样本的函数统一到一个函数里面
	// 因为负样本的扩充时设定的最外面的边界_rInner是比较大的。那就很产生很多的样本,这个时候我们就通过这个值的判断随机的选择一些
	//_maxSampleNum设置是很大的。上面的式子是相当于除以后面两个的乘积啦。

	int r,c; //横纵坐标
	int i=0; //记住vector的尺寸
	_sampleRect.clear();// 很重要,开始的时候一定清空样本存储的地方
	Rect rect(0,0,0,0); //用来记录每一个被选到的样本块

	for ( r=minrow; r<=maxrow; r++)
	{
		for( c=mincol; c<=maxcol; c++)
		{
			dist=(_objectPatch.y-r)*(_objectPatch.y-r)+(_objectPatch.x-c)*(_objectPatch.x-c);//到目标点的距离
			if((rng.uniform(0., 1.)<prob)&&(dist<=rInnerSq)&&(dist>=rOuterSq))
				//这里就是将正负样本的扩充统一起来了。对于正样本,因为满足的范围小,prob一定>1,所以满足条件的都要。
				//对于负样本来说,rng.uniform(0., 1.)<prob)就不一定成立,所以是随机的保存所产生的满足要求的负样本。
				//(附加说明一点,_maxSampleNum这里设置的是10000.一般一个图像至少320*240,所以prob=1/6左右,也就是保存了全部负样本的1/6左右)
			{
				rect.x=c;//满足上面的条件以后就采集样本并存储到_sampleRect中
				rect.y=r;
				rect.height=_objectPatch.height;
				rect.width=_objectPatch.width;
				_sampleRect.push_back(rect);
				i++;
			}
			
		}
	}
	_sampleRect.resize(i);//这个操作是要确定这个vector的尺寸。因为vector给你分配的空间往往是大于你所要的。
}

//下面的操作基本上是一样的了,其作用是在上一帧的位置附近生成一些待检测的样本。这被认为是可能的目标出现的位置。
void sampleRect::sampleRect1(Mat& _image, Rect& _objectPatch, float _srw,  vector<Rect>& _sampleRect )
{
	int rowsz=_image.rows-_objectPatch.height-1;
	int colsz =_image.cols -_objectPatch.width-1;
	int radSq= _srw*_srw;

	int dist;
	Rect rect;

	int minrow=max(0,(int)_objectPatch.y-(int)_srw);
	int maxrow=min(rowsz,(int)_objectPatch.y+(int)_srw);
	int mincol =max(0,(int)_objectPatch.x-(int)_srw);
	int maxcol =max(colsz,(int)_objectPatch.x+(int)_srw);

	int r,c;
	int i=0;

	for( r=minrow; r<=maxrow;r++)
	{
		for ( c=mincol; c<=maxcol; c++)
		{
			dist=(_objectPatch.y-r)*(_objectPatch.y-r)+(_objectPatch.x-c)*(_objectPatch.x-c);
			if(dist<=radSq )//不在需要prob来限制量了,下面都是一样的了。
			{
				rect.x=c;
				rect.y=r;
				rect.height=_objectPatch.height;
				rect.width=_objectPatch.width;
				_sampleRect.push_back(rect);
				i++;

			}
			
		}
	}
	_sampleRect.resize(i);
}
//本节搞定。

我是实实在在的初学者,发现问题请指正啊!谢谢!