// 初始化 -------------------------------------------------------- // 参数1帧宽,参数2帧高,参数3初始第一帧,参数4初始边框盒 void BpTld_Init(int Width,int Height,IplImage * firstImage,double * firstbb) { // 获取图像参数 frameWidth = Width; frameHeight = Height; frameSize = (CvSize *)malloc(sizeof(CvSize)); *frameSize = cvSize(frameWidth, frameHeight); IntegralImage *firstFrame = new IntegralImage(); firstFrame->createFromIplImage(firstImage); IplImage *firstFrameIplImage = firstImage; double *bb = firstbb; initBBWidth = (float)bb[2]; initBBHeight = (float)bb[3]; //初始化信任度 confidence = 1.0f; // 初始化分类器,跟踪器和探测器 srand((unsigned int)time(0)); classifier = new Classifier(TOTAL_FERNS, TOTAL_NODES, MIN_FEATURE_SCALE, MAX_FEATURE_SCALE); tracker = new Tracker(frameWidth, frameHeight, frameSize, firstFrameIplImage, classifier); detector = new Detector(frameWidth, frameHeight, bb, classifier); // 用初始图像小块和它的仿射变形来训练分类器 classifier->train(firstFrame, (int)bb[0], (int)bb[1], (int)initBBWidth, (int)initBBHeight, 1); bbWarpPatch(firstFrame, bb); trainNegative(firstFrame, bb); // 释放内存 delete firstFrame; // 设置bool值initialised initialised = true; return; }
/* MEX入口点. 两种使用方法: 初始化: TLD(帧宽, 帧高, 第一帧, 选择出的边框盒) 处理每一帧: 新的轨迹边框盒 = TLD(当前帧, 轨迹边框盒) */ void BpTld_Process(IplImage * NewImage,double * ttbb,double * outPut) { // 获得输入 ------------------------------------------------------------- // 当前帧 IplImage *nextFrame = NewImage; IntegralImage *nextFrameIntImg = new IntegralImage(); nextFrameIntImg->createFromIplImage(NewImage); // 轨迹边框盒[x, y, width, height] double *bb = ttbb; // 跟踪 + 探测 ------------------------------------------------------ // 只有在上个迭代中我们足够自信的时候,才跟踪 // 从这开始,跟踪器处理下一帧内存 double *tbb; vector<double *> *dbbs; if (confidence > MIN_TRACKING_CONF) { tbb = tracker->track(nextFrame, nextFrameIntImg, bb); if (tbb[4] > MIN_TRACKING_CONF) { dbbs = detector->detect(nextFrameIntImg, tbb); } else { dbbs = detector->detect(nextFrameIntImg, NULL); } } else { dbbs = detector->detect(nextFrameIntImg, NULL); tracker->setPrevFrame(nextFrame); tbb = new double[5]; tbb[0] = 0; tbb[1] = 0; tbb[2] = 0; tbb[3] = 0; tbb[4] = MIN_TRACKING_CONF; } // 学习 ----------------------------------------------------------------- // 获得最好的探测出的小块的信任度 double dbbMaxConf = 0.0f; int dbbMaxConfIndex = -1; for (int i = 0; i < dbbs->size(); i++) { double dbbConf = dbbs->at(i)[4]; if (dbbConf > dbbMaxConf) { dbbMaxConf = dbbConf; dbbMaxConfIndex = i; } } // // //if (dbbMaxConfIndex >= 0) //{ testDetector.x = dbbs->at(dbbMaxConfIndex)[0]; //testDetector.y = dbbs->at(dbbMaxConfIndex)[1]; //testDetector.width = dbbs->at(dbbMaxConfIndex)[2]; //testDetector.height = dbbs->at(dbbMaxConfIndex)[3]; //} //// // 如果探测出的小块中有一个信任度最高,并且大于MIN_REINIT_CONF // 那么就重置跟踪器的边框盒 if (dbbMaxConf > tbb[4] && dbbMaxConf > MIN_REINIT_CONF) { delete tbb; tbb = new double[5]; double *dbb = dbbs->at(dbbMaxConfIndex); tbb[0] = dbb[0]; tbb[1] = dbb[1]; tbb[2] = dbb[2]; tbb[3] = dbb[3]; tbb[4] = dbb[4]; } // 如果跟踪出的小块的信任度最高并且最后一帧时足够自信,那么就启动约束。 else if (tbb[4] > dbbMaxConf && confidence > MIN_LEARNING_CONF) { for (int i = 0; i < dbbs->size(); i++) { // 用正向和负向小块训练分类器 // 正向-与被跟踪的小块重合 // 负向-被分类为正向但与被跟踪的小块不重合 double *dbb = dbbs->at(i); if (dbb[5] == 1) { classifier->train(nextFrameIntImg, (int)dbb[0], (int)dbb[1], (int)dbb[2], (int)dbb[3], 1); } else if (dbb[5] == 0) { classifier->train(nextFrameIntImg, (int)dbb[0], (int)dbb[1], (int)dbb[2], (int)dbb[3], 0); } } } // 为下个迭代设置信任度 confidence = tbb[4]; //设置输出 outPut[0] = tbb[0]; outPut[1] = tbb[1]; outPut[2] = tbb[2]; outPut[3] = tbb[3]; ////////////////////////////////////////////////////////////////////////// //此处tbb[0],tbb[1],tbb[2],tbb[3]即是最终的边框盒 //如果tbb[2],tbb[3]全都大于0,,就表明估算出物体位置 ////////////////////////////////////////////////////////////////////////// // 设置输出 ------------------------------------------------------------ // 我们输出一系列边框盒;第一个是跟踪出的小块,剩下的是探测出的小块 // Rows correspond to individual bounding boxes // Columns correspond to [x, y, width, height, confidence, overlapping] // 释放内存 free(tbb); dbbs->clear(); delete nextFrameIntImg; }