4.5、classifier.prepare(scales);准备分类器,scales(size类型)容器里是所有扫描窗口(21个)的尺度,由上面的buildGrid()函数初始化;
TLD的分类器有三部分:方差分类器模块、集合分类器模块和最近邻分类器模块;这三个分类器是级联的,每一个扫描窗口依次全部通过上面三个分类器,才被认为含有前景目标。这里prepare这个函数主要是初始化集合分类器模块;
集合分类器(随机森林)基于n个基本分类器(共10棵树),每个分类器(树)都是基于一个pixelcomparisons(共13个像素比较集)的,也就是说每棵树有13个判断节点(组成一个pixelcomparisons),输入的图像片与每一个判断节点(相应像素点)进行比较,产生0或者1,然后将这13个0或者1连成一个13位的二进制码x(有2^13种可能),每一个x对应一个后验概率P(y|x)= #p/(#p+#n) (也有2^13种可能),#p和#n分别是正和负图像片的数目。那么整一个集合分类器(共10个基本分类器)就有10个后验概率了,将10个后验概率进行平均,如果大于阈值(一开始设经验值0.65,后面再训练优化)的话,就认为该图像片含有前景目标;
后验概率P(y|x)= #p/(#p+#n)的产生方法:初始化时,每个后验概率都得初始化为0;运行时候以下面方式更新:将已知类别标签的样本(训练样本)通过n个分类器进行分类,如果分类结果错误,那么相应的#p和#n就会更新,这样P(y|x)也相应更新了。
pixelcomparisons的产生方法:先用一个归一化的patch去离散化像素空间,产生所有可能的垂直和水平的pixelcomparisons,然后我们把这些pixelcomparisons随机分配给n个分类器,每个分类器得到完全不同的pixelcomparisons(特征集合),这样,所有分类器的特征组统一起来就可以覆盖整个patch了。
特征(FernFeaturestd::vector for each scale)是相对于一种尺度的矩形框而言的,TLD中第s种尺度的第i个特征features[s]= Feature(x1, y1, x2, y2);是两个随机分配的(scales*rng())像素点坐标(就是由这两个像素点比较得到0或者1的)。每一种尺度的扫描窗口都含有totalFeatures = nstructs* structSize个特征;nstructs为树木(由一个特征组构建,每组特征代表图像块的不同视图表示)的个数;structSize为每棵树的特征个数,也即每棵树的判断节点个数;树上每一个特征都作为一个决策节点;
prepare函数的工作就是先给每一个扫描窗口初始化了对应的pixelcomparisons(两个随机分配的像素点坐标);然后初始化后验概率为0;
posteriors、 pCounter、 nCounter数量为n行(10个基本分类器)的值,每维8192(2.^13)个值
4.6、generatePositiveData(frame1, num_warps_init);此函数通过对第一帧图像的目标框box(用户指定的要跟踪的目标)进行仿射变换来合成训练初始分类器的正样本集。具体方法如下:先在距离初始的目标框最近的扫描窗口内选择10个boundingbox(已经由上面的getOverlappingBoxes函数得到,存于good_boxes里面了),然后在每个boundingbox的内部,进行±1%范围的偏移,±1%范围的尺度变化,±10%范围的平面内旋转,并且在每个像素上增加方差为5的高斯噪声(确切的大小是在指定的范围内随机选择的),那么每个box都进行20次这种几何变换,那么10个box将产生200个仿射变换的boundingbox,作为正样本。具体实现如下:
getPattern(frame(best_box),pEx, mean, stdev);此函数将frame图像best_box区域的图像片归一化为均值为0的15*15大小的patch,存于pEx(用于最近邻分类器的正样本)正样本中(最近邻的box的Pattern),该正样本只有一个。同时还获取当前box内的均值与方差,分别存于mean和stdev中。
generator(frame,pt, warped, bbhull.size(), rng);此函数属于PatchGenerator类的构造函数,用来对图像区域进行仿射变换,先RNG一个随机因子,再调用()运算符产生一个变换后的正样本。
classifier.getFeatures(patch,grid[idx].sidx, fern);函数得到输入的patch的特征fern(13位的二进制代码);(前面已经说了如何获取:prepare函数的工作就是先给每一个扫描窗口初始化了对应的pixelcomparisons(两个随机分配的像素点坐标),就是计算这两个点对应的Patch像素值的大小)
pX.push_back(make_pair(fern,1)); //positive ferns <features, labels=1>然后标记为正样本,存入pX(用于集合分类器的正样本)正样本库;
以上的操作会循环 num_warps * good_boxes.size()即20 * 10次,这样,pEx就有了一个正样本,而pX有了200个正样本了;
得到的pEx为均值为0的一个Mat(15*15),而pX为200个,每个为10个的二进制码转换后的数 |