| 672 | } |
| 673 | |
| 674 | bool Extract(const Bitmap& bitmap, |
| 675 | FeatureKeypoints* keypoints, |
| 676 | FeatureDescriptors* descriptors) override { |
| 677 | THROW_CHECK(bitmap.IsGrey()); |
| 678 | THROW_CHECK_NOTNULL(keypoints); |
| 679 | THROW_CHECK_NOTNULL(descriptors); |
| 680 | |
| 681 | // Note the max dimension of SiftGPU is the maximum dimension of the |
| 682 | // first octave in the pyramid (which is the 'first_octave'). |
| 683 | const int compensation_factor = |
| 684 | 1 << -std::min(0, options_.sift->first_octave); |
| 685 | THROW_CHECK_EQ(options_.EffMaxImageSize() * compensation_factor, |
| 686 | sift_gpu_.GetMaxDimension()); |
| 687 | |
| 688 | std::lock_guard<std::mutex> lock(*sift_gpu_mutexes_[sift_gpu_.gpu_index]); |
| 689 | |
| 690 | // Note, that this produces slightly different results than using SiftGPU |
| 691 | // directly for RGB->GRAY conversion, since it uses different weights. |
| 692 | const int code = sift_gpu_.RunSIFT(bitmap.Pitch(), |
| 693 | bitmap.Height(), |
| 694 | bitmap.RowMajorData().data(), |
| 695 | GL_LUMINANCE, |
| 696 | GL_UNSIGNED_BYTE); |
| 697 | |
| 698 | const int kSuccessCode = 1; |
| 699 | if (code != kSuccessCode) { |
| 700 | return false; |
| 701 | } |
| 702 | |
| 703 | const size_t num_features = static_cast<size_t>(sift_gpu_.GetFeatureNum()); |
| 704 | |
| 705 | keypoints_buffer_.resize(num_features); |
| 706 | |
| 707 | FeatureDescriptorsFloatData descriptors_float(num_features, |
| 708 | kSiftDescriptorDim); |
| 709 | |
| 710 | // Download the extracted keypoints and descriptors. |
| 711 | sift_gpu_.GetFeatureVector(keypoints_buffer_.data(), |
| 712 | descriptors_float.data()); |
| 713 | |
| 714 | keypoints->resize(num_features); |
| 715 | for (size_t i = 0; i < num_features; ++i) { |
| 716 | (*keypoints)[i] = FeatureKeypoint(keypoints_buffer_[i].x, |
| 717 | keypoints_buffer_[i].y, |
| 718 | keypoints_buffer_[i].s, |
| 719 | keypoints_buffer_[i].o); |
| 720 | } |
| 721 | |
| 722 | // Save and normalize the descriptors. |
| 723 | if (options_.sift->normalization == |
| 724 | SiftExtractionOptions::Normalization::L2) { |
| 725 | L2NormalizeFeatureDescriptors(&descriptors_float); |
| 726 | } else if (options_.sift->normalization == |
| 727 | SiftExtractionOptions::Normalization::L1_ROOT) { |
| 728 | L1RootNormalizeFeatureDescriptors(&descriptors_float); |
| 729 | } else { |
| 730 | LOG(FATAL_THROW) << "Normalization type not supported"; |
| 731 | } |
nothing calls this directly
no test coverage detected