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 | 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); | ... | ... |