1 /*M/////////////////////////////////////////////////////////////////////////////////////// 2 // 3 // IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. 4 // 5 // By downloading, copying, installing or using the software you agree to this license. 6 // If you do not agree to this license, do not download, install, 7 // copy or use the software. 8 // 9 // 10 // License Agreement 11 // For Open Source Computer Vision Library 12 // 13 // Copyright (C) 2013, OpenCV Foundation, all rights reserved. 14 // Third party copyrights are property of their respective owners. 15 // 16 // Redistribution and use in source and binary forms, with or without modification, 17 // are permitted provided that the following conditions are met: 18 // 19 // * Redistribution's of source code must retain the above copyright notice, 20 // this list of conditions and the following disclaimer. 21 // 22 // * Redistribution's in binary form must reproduce the above copyright notice, 23 // this list of conditions and the following disclaimer in the documentation 24 // and/or other materials provided with the distribution. 25 // 26 // * The name of the copyright holders may not be used to endorse or promote products 27 // derived from this software without specific prior written permission. 28 // 29 // This software is provided by the copyright holders and contributors "as is" and 30 // any express or implied warranties, including, but not limited to, the implied 31 // warranties of merchantability and fitness for a particular purpose are disclaimed. 32 // In no event shall the Intel Corporation or contributors be liable for any direct, 33 // indirect, incidental, special, exemplary, or consequential damages 34 // (including, but not limited to, procurement of substitute goods or services; 35 // loss of use, data, or profits; or business interruption) however caused 36 // and on any theory of liability, whether in contract, strict liability, 37 // or tort (including negligence or otherwise) arising in any way out of 38 // the use of this software, even if advised of the possibility of such damage. 39 // 40 //M*/ 41 42 #include "precomp.hpp" 43 44 #include "tldDetector.hpp" 45 #include "tracking_utils.hpp" 46 47 namespace cv { 48 inline namespace tracking { 49 namespace impl { 50 namespace tld { 51 // Calculate offsets for classifiers prepareClassifiers(int rowstep)52 void TLDDetector::prepareClassifiers(int rowstep) 53 { 54 for (int i = 0; i < (int)classifiers.size(); i++) 55 classifiers[i].prepareClassifier(rowstep); 56 } 57 58 // Calculate posterior probability, that the patch belongs to the current EC model ensembleClassifierNum(const uchar * data)59 double TLDDetector::ensembleClassifierNum(const uchar* data) 60 { 61 double p = 0; 62 for (int k = 0; k < (int)classifiers.size(); k++) 63 p += classifiers[k].posteriorProbabilityFast(data); 64 p /= classifiers.size(); 65 return p; 66 } 67 computeSminus(const Mat_<uchar> & patch) const68 double TLDDetector::computeSminus(const Mat_<uchar>& patch) const 69 { 70 double sminus = 0.0; 71 Mat_<uchar> modelSample(STANDARD_PATCH_SIZE, STANDARD_PATCH_SIZE); 72 for (int i = 0; i < *negNum; i++) 73 { 74 modelSample.data = &(negExp->data[i * 225]); 75 sminus = std::max(sminus, 0.5 * (tracking_internal::computeNCC(modelSample, patch) + 1.0)); 76 } 77 return sminus; 78 } 79 80 // Calculate Relative similarity of the patch (NN-Model) Sr(const Mat_<uchar> & patch) const81 double TLDDetector::Sr(const Mat_<uchar>& patch) const 82 { 83 double splus = 0.0, sminus = 0.0; 84 Mat_<uchar> modelSample(STANDARD_PATCH_SIZE, STANDARD_PATCH_SIZE); 85 for (int i = 0; i < *posNum; i++) 86 { 87 modelSample.data = &(posExp->data[i * 225]); 88 splus = std::max(splus, 0.5 * (tracking_internal::computeNCC(modelSample, patch) + 1.0)); 89 } 90 sminus = computeSminus(patch); 91 92 if (splus + sminus == 0.0) 93 return 0.0; 94 return splus / (sminus + splus); 95 } 96 SrAndSc(const Mat_<uchar> & patch) const97 std::pair<double, double> TLDDetector::SrAndSc(const Mat_<uchar>& patch) const 98 { 99 double splusC = 0.0, sminus = 0.0, splus = 0.0; 100 Mat_<uchar> modelSample(STANDARD_PATCH_SIZE, STANDARD_PATCH_SIZE); 101 int med = tracking_internal::getMedian((*timeStampsPositive)); 102 for (int i = 0; i < *posNum; i++) 103 { 104 modelSample.data = &(posExp->data[i * 225]); 105 double s = 0.5 * (tracking_internal::computeNCC(modelSample, patch) + 1.0); 106 107 if ((int)(*timeStampsPositive)[i] <= med) 108 splusC = std::max(splusC, s); 109 110 splus = std::max(splus, s); 111 } 112 sminus = computeSminus(patch); 113 114 double sr = (splus + sminus == 0.0) ? 0. : splus / (sminus + splus); 115 double sc = (splusC + sminus == 0.0) ? 0. : splusC / (sminus + splusC); 116 117 return std::pair<double, double>(sr, sc); 118 } 119 120 #ifdef HAVE_OPENCL ocl_Sr(const Mat_<uchar> & patch)121 double TLDDetector::ocl_Sr(const Mat_<uchar>& patch) 122 { 123 double splus = 0.0, sminus = 0.0; 124 125 126 UMat devPatch = patch.getUMat(ACCESS_READ, USAGE_ALLOCATE_DEVICE_MEMORY); 127 UMat devPositiveSamples = posExp->getUMat(ACCESS_READ, USAGE_ALLOCATE_DEVICE_MEMORY); 128 UMat devNegativeSamples = negExp->getUMat(ACCESS_READ, USAGE_ALLOCATE_DEVICE_MEMORY); 129 UMat devNCC(1, 2*MAX_EXAMPLES_IN_MODEL, CV_32FC1, ACCESS_RW, USAGE_ALLOCATE_DEVICE_MEMORY); 130 131 132 ocl::Kernel k; 133 ocl::ProgramSource src = ocl::tracking::tldDetector_oclsrc; 134 String error; 135 ocl::Program prog(src, String(), error); 136 k.create("NCC", prog); 137 if (k.empty()) 138 printf("Kernel create failed!!!\n"); 139 k.args( 140 ocl::KernelArg::PtrReadOnly(devPatch), 141 ocl::KernelArg::PtrReadOnly(devPositiveSamples), 142 ocl::KernelArg::PtrReadOnly(devNegativeSamples), 143 ocl::KernelArg::PtrWriteOnly(devNCC), 144 *posNum, 145 *negNum); 146 147 size_t globSize = 1000; 148 149 if (!k.run(1, &globSize, NULL, false)) 150 printf("Kernel Run Error!!!"); 151 152 Mat resNCC = devNCC.getMat(ACCESS_READ); 153 154 for (int i = 0; i < *posNum; i++) 155 splus = std::max(splus, 0.5 * (resNCC.at<float>(i) + 1.0)); 156 157 for (int i = 0; i < *negNum; i++) 158 sminus = std::max(sminus, 0.5 * (resNCC.at<float>(i+500) +1.0)); 159 160 if (splus + sminus == 0.0) 161 return 0.0; 162 return splus / (sminus + splus); 163 } 164 ocl_batchSrSc(const Mat_<uchar> & patches,double * resultSr,double * resultSc,int numOfPatches)165 void TLDDetector::ocl_batchSrSc(const Mat_<uchar>& patches, double *resultSr, double *resultSc, int numOfPatches) 166 { 167 UMat devPatches = patches.getUMat(ACCESS_READ, USAGE_ALLOCATE_DEVICE_MEMORY); 168 UMat devPositiveSamples = posExp->getUMat(ACCESS_READ, USAGE_ALLOCATE_DEVICE_MEMORY); 169 UMat devNegativeSamples = negExp->getUMat(ACCESS_READ, USAGE_ALLOCATE_DEVICE_MEMORY); 170 UMat devPosNCC(MAX_EXAMPLES_IN_MODEL, numOfPatches, CV_32FC1, ACCESS_RW, USAGE_ALLOCATE_DEVICE_MEMORY); 171 UMat devNegNCC(MAX_EXAMPLES_IN_MODEL, numOfPatches, CV_32FC1, ACCESS_RW, USAGE_ALLOCATE_DEVICE_MEMORY); 172 173 ocl::Kernel k; 174 ocl::ProgramSource src = ocl::tracking::tldDetector_oclsrc; 175 String error; 176 ocl::Program prog(src, String(), error); 177 k.create("batchNCC", prog); 178 if (k.empty()) 179 printf("Kernel create failed!!!\n"); 180 k.args( 181 ocl::KernelArg::PtrReadOnly(devPatches), 182 ocl::KernelArg::PtrReadOnly(devPositiveSamples), 183 ocl::KernelArg::PtrReadOnly(devNegativeSamples), 184 ocl::KernelArg::PtrWriteOnly(devPosNCC), 185 ocl::KernelArg::PtrWriteOnly(devNegNCC), 186 *posNum, 187 *negNum, 188 numOfPatches); 189 190 size_t globSize = 2 * numOfPatches*MAX_EXAMPLES_IN_MODEL; 191 192 if (!k.run(1, &globSize, NULL, true)) 193 printf("Kernel Run Error!!!"); 194 195 Mat posNCC = devPosNCC.getMat(ACCESS_READ); 196 Mat negNCC = devNegNCC.getMat(ACCESS_READ); 197 198 //Calculate Srs 199 for (int id = 0; id < numOfPatches; id++) 200 { 201 double spr = 0.0, smr = 0.0, spc = 0.0, smc = 0; 202 int med = tracking_internal::getMedian((*timeStampsPositive)); 203 for (int i = 0; i < *posNum; i++) 204 { 205 spr = std::max(spr, 0.5 * (posNCC.at<float>(id * 500 + i) + 1.0)); 206 if ((int)(*timeStampsPositive)[i] <= med) 207 spc = std::max(spr, 0.5 * (posNCC.at<float>(id * 500 + i) + 1.0)); 208 } 209 for (int i = 0; i < *negNum; i++) 210 smc = smr = std::max(smr, 0.5 * (negNCC.at<float>(id * 500 + i) + 1.0)); 211 212 if (spr + smr == 0.0) 213 resultSr[id] = 0.0; 214 else 215 resultSr[id] = spr / (smr + spr); 216 217 if (spc + smc == 0.0) 218 resultSc[id] = 0.0; 219 else 220 resultSc[id] = spc / (smc + spc); 221 } 222 } 223 #endif 224 225 // Calculate Conservative similarity of the patch (NN-Model) Sc(const Mat_<uchar> & patch) const226 double TLDDetector::Sc(const Mat_<uchar>& patch) const 227 { 228 double splus = 0.0, sminus = 0.0; 229 Mat_<uchar> modelSample(STANDARD_PATCH_SIZE, STANDARD_PATCH_SIZE); 230 int med = tracking_internal::getMedian((*timeStampsPositive)); 231 for (int i = 0; i < *posNum; i++) 232 { 233 if ((int)(*timeStampsPositive)[i] <= med) 234 { 235 modelSample.data = &(posExp->data[i * 225]); 236 splus = std::max(splus, 0.5 * (tracking_internal::computeNCC(modelSample, patch) + 1.0)); 237 } 238 } 239 sminus = computeSminus(patch); 240 241 if (splus + sminus == 0.0) 242 return 0.0; 243 244 return splus / (sminus + splus); 245 } 246 247 #ifdef HAVE_OPENCL ocl_Sc(const Mat_<uchar> & patch)248 double TLDDetector::ocl_Sc(const Mat_<uchar>& patch) 249 { 250 double splus = 0.0, sminus = 0.0; 251 252 UMat devPatch = patch.getUMat(ACCESS_READ, USAGE_ALLOCATE_DEVICE_MEMORY); 253 UMat devPositiveSamples = posExp->getUMat(ACCESS_READ, USAGE_ALLOCATE_DEVICE_MEMORY); 254 UMat devNegativeSamples = negExp->getUMat(ACCESS_READ, USAGE_ALLOCATE_DEVICE_MEMORY); 255 UMat devNCC(1, 2 * MAX_EXAMPLES_IN_MODEL, CV_32FC1, ACCESS_RW, USAGE_ALLOCATE_DEVICE_MEMORY); 256 257 258 ocl::Kernel k; 259 ocl::ProgramSource src = ocl::tracking::tldDetector_oclsrc; 260 String error; 261 ocl::Program prog(src, String(), error); 262 k.create("NCC", prog); 263 if (k.empty()) 264 printf("Kernel create failed!!!\n"); 265 k.args( 266 ocl::KernelArg::PtrReadOnly(devPatch), 267 ocl::KernelArg::PtrReadOnly(devPositiveSamples), 268 ocl::KernelArg::PtrReadOnly(devNegativeSamples), 269 ocl::KernelArg::PtrWriteOnly(devNCC), 270 *posNum, 271 *negNum); 272 273 size_t globSize = 1000; 274 275 if (!k.run(1, &globSize, NULL, false)) 276 printf("Kernel Run Error!!!"); 277 278 Mat resNCC = devNCC.getMat(ACCESS_READ); 279 280 int med = tracking_internal::getMedian((*timeStampsPositive)); 281 for (int i = 0; i < *posNum; i++) 282 if ((int)(*timeStampsPositive)[i] <= med) 283 splus = std::max(splus, 0.5 * (resNCC.at<float>(i) +1.0)); 284 285 for (int i = 0; i < *negNum; i++) 286 sminus = std::max(sminus, 0.5 * (resNCC.at<float>(i + 500) + 1.0)); 287 288 if (splus + sminus == 0.0) 289 return 0.0; 290 return splus / (sminus + splus); 291 } 292 #endif // HAVE_OPENCL 293 294 // Generate Search Windows for detector from aspect ratio of initial BBs generateScanGrid(int rows,int cols,Size initBox,std::vector<Rect2d> & res,bool withScaling)295 void TLDDetector::generateScanGrid(int rows, int cols, Size initBox, std::vector<Rect2d>& res, bool withScaling) 296 { 297 res.clear(); 298 //Scales step: SCALE_STEP; Translation steps: 10% of width & 10% of height; minSize: 20pix 299 for (double h = initBox.height, w = initBox.width; h < cols && w < rows;) 300 { 301 for (double x = 0; (x + w + 1.0) <= cols; x += (0.1 * w)) 302 { 303 for (double y = 0; (y + h + 1.0) <= rows; y += (0.1 * h)) 304 res.push_back(Rect2d(x, y, w, h)); 305 } 306 if (withScaling) 307 { 308 if (h <= initBox.height) 309 { 310 h /= SCALE_STEP; w /= SCALE_STEP; 311 if (h < 20 || w < 20) 312 { 313 h = initBox.height * SCALE_STEP; w = initBox.width * SCALE_STEP; 314 CV_Assert(h > initBox.height || w > initBox.width); 315 } 316 } 317 else 318 { 319 h *= SCALE_STEP; w *= SCALE_STEP; 320 } 321 } 322 else 323 { 324 break; 325 } 326 } 327 } 328 329 //Detection - returns most probable new target location (Max Sc) 330 331 class CalcScSrParallelLoopBody: public cv::ParallelLoopBody 332 { 333 public: CalcScSrParallelLoopBody(TLDDetector * detector,Size initSize)334 explicit CalcScSrParallelLoopBody (TLDDetector * detector, Size initSize): 335 detectorF (detector), 336 initSizeF (initSize) 337 { 338 } 339 operator ()(const cv::Range & r) const340 virtual void operator () (const cv::Range & r) const CV_OVERRIDE 341 { 342 for (int ind = r.start; ind < r.end; ++ind) 343 { 344 resample(detectorF->resized_imgs[detectorF->ensScaleIDs[ind]], 345 Rect2d(detectorF->ensBuffer[ind], initSizeF), 346 detectorF->standardPatches[ind]); 347 std::pair<double, double> values = detectorF->SrAndSc(detectorF->standardPatches[ind]); 348 detectorF->scValues[ind] = values.second; 349 detectorF->srValues[ind] = values.first; 350 } 351 } 352 353 TLDDetector * detectorF; 354 const Size initSizeF; 355 private: 356 CalcScSrParallelLoopBody (const CalcScSrParallelLoopBody&); 357 CalcScSrParallelLoopBody& operator= (const CalcScSrParallelLoopBody&); 358 }; 359 detect(const Mat & img,const Mat & imgBlurred,Rect2d & res,std::vector<LabeledPatch> & patches,Size initSize)360 bool TLDDetector::detect(const Mat& img, const Mat& imgBlurred, Rect2d& res, std::vector<LabeledPatch>& patches, Size initSize) 361 { 362 patches.clear(); 363 Mat tmp; 364 int dx = initSize.width / 10, dy = initSize.height / 10; 365 Size2d size = img.size(); 366 double scale = 1.0; 367 int npos = 0, nneg = 0; 368 double maxSc = -5.0; 369 Rect2d maxScRect; 370 int scaleID; 371 372 resized_imgs.clear (); 373 blurred_imgs.clear (); 374 varBuffer.clear (); 375 ensBuffer.clear (); 376 varScaleIDs.clear (); 377 ensScaleIDs.clear (); 378 379 //Detection part 380 //Generate windows and filter by variance 381 scaleID = 0; 382 resized_imgs.push_back(img); 383 blurred_imgs.push_back(imgBlurred); 384 do 385 { 386 Mat_<double> intImgP, intImgP2; 387 computeIntegralImages(resized_imgs[scaleID], intImgP, intImgP2); 388 for (int i = 0, imax = cvFloor((0.0 + resized_imgs[scaleID].cols - initSize.width) / dx); i < imax; i++) 389 { 390 for (int j = 0, jmax = cvFloor((0.0 + resized_imgs[scaleID].rows - initSize.height) / dy); j < jmax; j++) 391 { 392 if (!patchVariance(intImgP, intImgP2, originalVariancePtr, Point(dx * i, dy * j), initSize)) 393 continue; 394 varBuffer.push_back(Point(dx * i, dy * j)); 395 varScaleIDs.push_back(scaleID); 396 } 397 } 398 scaleID++; 399 size.width /= SCALE_STEP; 400 size.height /= SCALE_STEP; 401 scale *= SCALE_STEP; 402 resize(img, tmp, size, 0, 0, DOWNSCALE_MODE); 403 resized_imgs.push_back(tmp); 404 GaussianBlur(resized_imgs[scaleID], tmp, GaussBlurKernelSize, 0.0f); 405 blurred_imgs.push_back(tmp); 406 } while (size.width >= initSize.width && size.height >= initSize.height); 407 408 //Encsemble classification 409 for (int i = 0; i < (int)varBuffer.size(); i++) 410 { 411 prepareClassifiers(static_cast<int> (blurred_imgs[varScaleIDs[i]].step[0])); 412 if (ensembleClassifierNum(&blurred_imgs[varScaleIDs[i]].at<uchar>(varBuffer[i].y, varBuffer[i].x)) <= ENSEMBLE_THRESHOLD) 413 continue; 414 ensBuffer.push_back(varBuffer[i]); 415 ensScaleIDs.push_back(varScaleIDs[i]); 416 } 417 418 //Batch preparation 419 srValues.resize (ensBuffer.size()); 420 scValues.resize (ensBuffer.size()); 421 422 //Carefully resize standard patches with reference-counted Mat members 423 const int oldPatchesSize = (int)standardPatches.size(); 424 standardPatches.resize (ensBuffer.size()); 425 if ((int)ensBuffer.size() > oldPatchesSize) 426 { 427 Mat_<uchar> standardPatch(STANDARD_PATCH_SIZE, STANDARD_PATCH_SIZE); 428 for (int i = oldPatchesSize; i < (int)ensBuffer.size(); ++i) 429 { 430 standardPatches[i] = standardPatch.clone(); 431 } 432 } 433 434 //Batch calculation 435 cv::parallel_for_ (cv::Range (0, (int)ensBuffer.size ()), CalcScSrParallelLoopBody (this, initSize)); 436 437 //NN classification 438 for (int i = 0; i < (int)ensBuffer.size(); i++) 439 { 440 LabeledPatch labPatch; 441 double curScale = pow(SCALE_STEP, ensScaleIDs[i]); 442 labPatch.rect = Rect2d(ensBuffer[i].x*curScale, ensBuffer[i].y*curScale, initSize.width * curScale, initSize.height * curScale); 443 444 const double srValue = srValues[i]; 445 const double scValue = scValues[i]; 446 447 ////To fix: Check the paper, probably this cause wrong learning 448 // 449 labPatch.isObject = srValue > THETA_NN; 450 labPatch.shouldBeIntegrated = abs(srValue - THETA_NN) < CLASSIFIER_MARGIN; 451 patches.push_back(labPatch); 452 // 453 454 if (!labPatch.isObject) 455 { 456 nneg++; 457 continue; 458 } 459 else 460 { 461 npos++; 462 } 463 464 if (scValue > maxSc) 465 { 466 maxSc = scValue; 467 maxScRect = labPatch.rect; 468 } 469 } 470 471 if (maxSc < 0) 472 return false; 473 else 474 { 475 res = maxScRect; 476 return true; 477 } 478 } 479 480 #ifdef HAVE_OPENCL ocl_detect(const Mat & img,const Mat & imgBlurred,Rect2d & res,std::vector<LabeledPatch> & patches,Size initSize)481 bool TLDDetector::ocl_detect(const Mat& img, const Mat& imgBlurred, Rect2d& res, std::vector<LabeledPatch>& patches, Size initSize) 482 { 483 patches.clear(); 484 Mat_<uchar> standardPatch(STANDARD_PATCH_SIZE, STANDARD_PATCH_SIZE); 485 Mat tmp; 486 int dx = initSize.width / 10, dy = initSize.height / 10; 487 Size2d size = img.size(); 488 double scale = 1.0; 489 int npos = 0, nneg = 0; 490 double maxSc = -5.0; 491 Rect2d maxScRect; 492 int scaleID; 493 std::vector <Mat> resized_imgs, blurred_imgs; 494 std::vector <Point> varBuffer, ensBuffer; 495 std::vector <int> varScaleIDs, ensScaleIDs; 496 497 //Detection part 498 //Generate windows and filter by variance 499 scaleID = 0; 500 resized_imgs.push_back(img); 501 blurred_imgs.push_back(imgBlurred); 502 do 503 { 504 Mat_<double> intImgP, intImgP2; 505 computeIntegralImages(resized_imgs[scaleID], intImgP, intImgP2); 506 for (int i = 0, imax = cvFloor((0.0 + resized_imgs[scaleID].cols - initSize.width) / dx); i < imax; i++) 507 { 508 for (int j = 0, jmax = cvFloor((0.0 + resized_imgs[scaleID].rows - initSize.height) / dy); j < jmax; j++) 509 { 510 if (!patchVariance(intImgP, intImgP2, originalVariancePtr, Point(dx * i, dy * j), initSize)) 511 continue; 512 varBuffer.push_back(Point(dx * i, dy * j)); 513 varScaleIDs.push_back(scaleID); 514 } 515 } 516 scaleID++; 517 size.width /= SCALE_STEP; 518 size.height /= SCALE_STEP; 519 scale *= SCALE_STEP; 520 resize(img, tmp, size, 0, 0, DOWNSCALE_MODE); 521 resized_imgs.push_back(tmp); 522 GaussianBlur(resized_imgs[scaleID], tmp, GaussBlurKernelSize, 0.0f); 523 blurred_imgs.push_back(tmp); 524 } while (size.width >= initSize.width && size.height >= initSize.height); 525 526 //Encsemble classification 527 for (int i = 0; i < (int)varBuffer.size(); i++) 528 { 529 prepareClassifiers((int)blurred_imgs[varScaleIDs[i]].step[0]); 530 if (ensembleClassifierNum(&blurred_imgs[varScaleIDs[i]].at<uchar>(varBuffer[i].y, varBuffer[i].x)) <= ENSEMBLE_THRESHOLD) 531 continue; 532 ensBuffer.push_back(varBuffer[i]); 533 ensScaleIDs.push_back(varScaleIDs[i]); 534 } 535 536 //NN classification 537 //Prepare batch of patches 538 int numOfPatches = (int)ensBuffer.size(); 539 Mat_<uchar> stdPatches(numOfPatches, 225); 540 double *resultSr = new double[numOfPatches]; 541 double *resultSc = new double[numOfPatches]; 542 543 uchar *patchesData = stdPatches.data; 544 for (int i = 0; i < (int)ensBuffer.size(); i++) 545 { 546 resample(resized_imgs[ensScaleIDs[i]], Rect2d(ensBuffer[i], initSize), standardPatch); 547 uchar *stdPatchData = standardPatch.data; 548 for (int j = 0; j < 225; j++) 549 patchesData[225*i+j] = stdPatchData[j]; 550 } 551 //Calculate Sr and Sc batches 552 ocl_batchSrSc(stdPatches, resultSr, resultSc, numOfPatches); 553 554 555 for (int i = 0; i < (int)ensBuffer.size(); i++) 556 { 557 LabeledPatch labPatch; 558 standardPatch.data = &stdPatches.data[225 * i]; 559 double curScale = pow(SCALE_STEP, ensScaleIDs[i]); 560 labPatch.rect = Rect2d(ensBuffer[i].x*curScale, ensBuffer[i].y*curScale, initSize.width * curScale, initSize.height * curScale); 561 562 double srValue, scValue; 563 564 srValue = resultSr[i]; 565 566 ////To fix: Check the paper, probably this cause wrong learning 567 // 568 labPatch.isObject = srValue > THETA_NN; 569 labPatch.shouldBeIntegrated = abs(srValue - THETA_NN) < CLASSIFIER_MARGIN; 570 patches.push_back(labPatch); 571 // 572 573 if (!labPatch.isObject) 574 { 575 nneg++; 576 continue; 577 } 578 else 579 { 580 npos++; 581 } 582 scValue = resultSc[i]; 583 if (scValue > maxSc) 584 { 585 maxSc = scValue; 586 maxScRect = labPatch.rect; 587 } 588 } 589 590 if (maxSc < 0) 591 return false; 592 res = maxScRect; 593 return true; 594 } 595 #endif // HAVE_OPENCL 596 597 // Computes the variance of subimage given by box, with the help of two integral 598 // images intImgP and intImgP2 (sum of squares), which should be also provided. patchVariance(Mat_<double> & intImgP,Mat_<double> & intImgP2,double * originalVariance,Point pt,Size size)599 bool TLDDetector::patchVariance(Mat_<double>& intImgP, Mat_<double>& intImgP2, double *originalVariance, Point pt, Size size) 600 { 601 int x = (pt.x), y = (pt.y), width = (size.width), height = (size.height); 602 CV_Assert(0 <= x && (x + width) < intImgP.cols && (x + width) < intImgP2.cols); 603 CV_Assert(0 <= y && (y + height) < intImgP.rows && (y + height) < intImgP2.rows); 604 double p = 0, p2 = 0; 605 double A, B, C, D; 606 607 A = intImgP(y, x); 608 B = intImgP(y, x + width); 609 C = intImgP(y + height, x); 610 D = intImgP(y + height, x + width); 611 p = (A + D - B - C) / (width * height); 612 613 A = intImgP2(y, x); 614 B = intImgP2(y, x + width); 615 C = intImgP2(y + height, x); 616 D = intImgP2(y + height, x + width); 617 p2 = (A + D - B - C) / (width * height); 618 619 return ((p2 - p * p) > VARIANCE_THRESHOLD * *originalVariance); 620 } 621 622 }}}} // namespace 623