Commit 7ae74c55d8d8046c7e2c59d20763187656beb1ea

Authored by Josh Klontz
1 parent 3048ffa0

made LUT 1D

Showing 1 changed file with 52 additions and 28 deletions
openbr/plugins/quantize.cpp
... ... @@ -268,7 +268,14 @@ class ProductQuantizationDistance : public Distance
268 268  
269 269 const float *lut = (const float*)ProductQuantizationLUTs[index].data;
270 270 for (int j=0; j<elements; j++)
271   - distance += lut[j*256*256 + aData[j]*256+bData[j]];
  271 + {
  272 + const int aj = aData[j];
  273 + const int bj = bData[j];
  274 + // http://stackoverflow.com/questions/4803180/mapping-elements-in-2d-upper-triangle-and-lower-triangle-to-linear-structure
  275 + const int y = max(aj, bj);
  276 + const int x = min(aj, bj);
  277 + distance += lut[j*256*(256+1)/2 + x + (y+1)*y/2];
  278 + }
272 279 }
273 280 if (!bayesian) distance = -log(distance+1);
274 281 return distance;
... ... @@ -305,8 +312,14 @@ class RecursiveProductQuantizationDistance : public Distance
305 312 bData += sizeof(quint16);
306 313  
307 314 const float *lut = (const float*)ProductQuantizationLUTs[index].data;
308   - for (int j=0; j<elements; j++)
309   - similarity += lut[j*256*256 + aData[j]*256+bData[j]];
  315 + for (int j=0; j<elements; j++) {
  316 + const int aj = aData[j];
  317 + const int bj = bData[j];
  318 + // http://stackoverflow.com/questions/4803180/mapping-elements-in-2d-upper-triangle-and-lower-triangle-to-linear-structure
  319 + const int y = max(aj, bj);
  320 + const int x = min(aj, bj);
  321 + similarity += lut[j*256*(256+1)/2 + x + (y+1)*y/2];
  322 + }
310 323  
311 324 evidence += similarity;
312 325 const int subSize = (size-1)/4;
... ... @@ -395,35 +408,46 @@ private:
395 408 Mat clusterLabels;
396 409 kmeans(data, 256, clusterLabels, TermCriteria(TermCriteria::MAX_ITER, 10, 0), 3, KMEANS_PP_CENTERS, *center);
397 410  
  411 + Mat fullLUT(1, 256*256, CV_32FC1);
398 412 for (int i=0; i<256; i++)
399 413 for (int j=0; j<256; j++)
400   - lut->at<float>(0,i*256+j) = distance->compare(center->row(i), center->row(j));
401   -
402   - if (!bayesian) return;
403   -
404   - QList<int> indicies = OpenCVUtils::matrixToVector<int>(clusterLabels);
405   - QVector<float> genuineScores, impostorScores;
406   - genuineScores.reserve(indicies.size());
407   - impostorScores.reserve(indicies.size()*indicies.size()/2);
408   - for (int i=0; i<indicies.size(); i++)
409   - for (int j=i+1; j<indicies.size(); j++) {
410   - const float score = lut->at<float>(0, indicies[i]*256+indicies[j]);
411   - if (labels[i] == labels[j]) genuineScores.append(score);
412   - else impostorScores.append(score);
413   - }
414   -
415   - genuineScores = Common::Downsample(genuineScores, 256);
416   - impostorScores = Common::Downsample(impostorScores, 256);
417   - const double hGenuine = Common::KernelDensityBandwidth(genuineScores);
418   - const double hImpostor = Common::KernelDensityBandwidth(impostorScores);
  414 + fullLUT.at<float>(0,i*256+j) = distance->compare(center->row(i), center->row(j));
  415 +
  416 + if (bayesian) {
  417 + QList<int> indicies = OpenCVUtils::matrixToVector<int>(clusterLabels);
  418 + QVector<float> genuineScores, impostorScores;
  419 + genuineScores.reserve(indicies.size());
  420 + impostorScores.reserve(indicies.size()*indicies.size()/2);
  421 + for (int i=0; i<indicies.size(); i++)
  422 + for (int j=i+1; j<indicies.size(); j++) {
  423 + const float score = fullLUT.at<float>(0, indicies[i]*256+indicies[j]);
  424 + if (labels[i] == labels[j]) genuineScores.append(score);
  425 + else impostorScores.append(score);
  426 + }
  427 +
  428 + genuineScores = Common::Downsample(genuineScores, 256);
  429 + impostorScores = Common::Downsample(impostorScores, 256);
  430 + const double hGenuine = Common::KernelDensityBandwidth(genuineScores);
  431 + const double hImpostor = Common::KernelDensityBandwidth(impostorScores);
  432 +
  433 + for (int i=0; i<256; i++)
  434 + for (int j=i; j<256; j++) {
  435 + const float loglikelihood = log(Common::KernelDensityEstimation(genuineScores, fullLUT.at<float>(0,i*256+j), hGenuine) /
  436 + Common::KernelDensityEstimation(impostorScores, fullLUT.at<float>(0,i*256+j), hImpostor));
  437 + fullLUT.at<float>(0,i*256+j) = loglikelihood;
  438 + fullLUT.at<float>(0,j*256+i) = loglikelihood;
  439 + }
  440 + }
419 441  
  442 + // Compress LUT into one dimensional array
  443 + int index = 0;
420 444 for (int i=0; i<256; i++)
421   - for (int j=i; j<256; j++) {
422   - const float loglikelihood = log(Common::KernelDensityEstimation(genuineScores, lut->at<float>(0,i*256+j), hGenuine) /
423   - Common::KernelDensityEstimation(impostorScores, lut->at<float>(0,i*256+j), hImpostor));
424   - lut->at<float>(0,i*256+j) = loglikelihood;
425   - lut->at<float>(0,j*256+i) = loglikelihood;
  445 + for (int j=0; j<=i; j++) {
  446 + lut->at<float>(0,index) = fullLUT.at<float>(0,i*256+j);
  447 + index++;
426 448 }
  449 + if (index != lut->cols)
  450 + qFatal("Logic error.");
427 451 }
428 452  
429 453 int getStep(int cols) const
... ... @@ -454,7 +478,7 @@ private:
454 478 const QList<int> labels = src.labels<int>();
455 479  
456 480 Mat &lut = ProductQuantizationLUTs[index];
457   - lut = Mat(getDims(data.cols), 256*256, CV_32FC1);
  481 + lut = Mat(getDims(data.cols), 256*(256+1)/2, CV_32FC1);
458 482  
459 483 QList<Mat> subdata, subluts;
460 484 const int offset = getOffset(data.cols);
... ...