Commit 7ae74c55d8d8046c7e2c59d20763187656beb1ea
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,7 +268,14 @@ class ProductQuantizationDistance : public Distance | ||
| 268 | 268 | ||
| 269 | const float *lut = (const float*)ProductQuantizationLUTs[index].data; | 269 | const float *lut = (const float*)ProductQuantizationLUTs[index].data; |
| 270 | for (int j=0; j<elements; j++) | 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 | if (!bayesian) distance = -log(distance+1); | 280 | if (!bayesian) distance = -log(distance+1); |
| 274 | return distance; | 281 | return distance; |
| @@ -305,8 +312,14 @@ class RecursiveProductQuantizationDistance : public Distance | @@ -305,8 +312,14 @@ class RecursiveProductQuantizationDistance : public Distance | ||
| 305 | bData += sizeof(quint16); | 312 | bData += sizeof(quint16); |
| 306 | 313 | ||
| 307 | const float *lut = (const float*)ProductQuantizationLUTs[index].data; | 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 | evidence += similarity; | 324 | evidence += similarity; |
| 312 | const int subSize = (size-1)/4; | 325 | const int subSize = (size-1)/4; |
| @@ -395,35 +408,46 @@ private: | @@ -395,35 +408,46 @@ private: | ||
| 395 | Mat clusterLabels; | 408 | Mat clusterLabels; |
| 396 | kmeans(data, 256, clusterLabels, TermCriteria(TermCriteria::MAX_ITER, 10, 0), 3, KMEANS_PP_CENTERS, *center); | 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 | for (int i=0; i<256; i++) | 412 | for (int i=0; i<256; i++) |
| 399 | for (int j=0; j<256; j++) | 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 | for (int i=0; i<256; i++) | 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 | int getStep(int cols) const | 453 | int getStep(int cols) const |
| @@ -454,7 +478,7 @@ private: | @@ -454,7 +478,7 @@ private: | ||
| 454 | const QList<int> labels = src.labels<int>(); | 478 | const QList<int> labels = src.labels<int>(); |
| 455 | 479 | ||
| 456 | Mat &lut = ProductQuantizationLUTs[index]; | 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 | QList<Mat> subdata, subluts; | 483 | QList<Mat> subdata, subluts; |
| 460 | const int offset = getOffset(data.cols); | 484 | const int offset = getOffset(data.cols); |