| 154 | } |
| 155 | |
| 156 | bool Extract(const Bitmap& bitmap, |
| 157 | FeatureKeypoints* keypoints, |
| 158 | FeatureDescriptors* descriptors) { |
| 159 | THROW_CHECK(bitmap.IsGrey()); |
| 160 | THROW_CHECK_NOTNULL(keypoints); |
| 161 | |
| 162 | if (sift_ == nullptr || sift_->width != bitmap.Width() || |
| 163 | sift_->height != bitmap.Height()) { |
| 164 | sift_ = VlSiftType(vl_sift_new(bitmap.Width(), |
| 165 | bitmap.Height(), |
| 166 | options_.sift->num_octaves, |
| 167 | options_.sift->octave_resolution, |
| 168 | options_.sift->first_octave), |
| 169 | &vl_sift_delete); |
| 170 | if (!sift_) { |
| 171 | return false; |
| 172 | } |
| 173 | } |
| 174 | |
| 175 | vl_sift_set_peak_thresh(sift_.get(), options_.sift->peak_threshold); |
| 176 | vl_sift_set_edge_thresh(sift_.get(), options_.sift->edge_threshold); |
| 177 | |
| 178 | // Iterate through octaves. |
| 179 | std::vector<size_t> level_num_features; |
| 180 | std::vector<FeatureKeypoints> level_keypoints; |
| 181 | std::vector<FeatureDescriptorsData> level_descriptors; |
| 182 | bool first_octave = true; |
| 183 | while (true) { |
| 184 | if (first_octave) { |
| 185 | const std::vector<uint8_t>& data_uint8 = bitmap.RowMajorData(); |
| 186 | std::vector<float> data_float(data_uint8.size()); |
| 187 | for (size_t i = 0; i < data_uint8.size(); ++i) { |
| 188 | data_float[i] = static_cast<float>(data_uint8[i]) / 255.0f; |
| 189 | } |
| 190 | if (vl_sift_process_first_octave(sift_.get(), data_float.data())) { |
| 191 | break; |
| 192 | } |
| 193 | first_octave = false; |
| 194 | } else { |
| 195 | if (vl_sift_process_next_octave(sift_.get())) { |
| 196 | break; |
| 197 | } |
| 198 | } |
| 199 | |
| 200 | // Detect keypoints. |
| 201 | vl_sift_detect(sift_.get()); |
| 202 | |
| 203 | // Extract detected keypoints. |
| 204 | const VlSiftKeypoint* vl_keypoints = vl_sift_get_keypoints(sift_.get()); |
| 205 | const int num_keypoints = vl_sift_get_nkeypoints(sift_.get()); |
| 206 | if (num_keypoints == 0) { |
| 207 | continue; |
| 208 | } |
| 209 | |
| 210 | // Extract features with different orientations per DOG level. |
| 211 | size_t level_idx = 0; |
| 212 | int prev_level = -1; |
| 213 | FeatureDescriptorsFloatData desc(1, kSiftDescriptorDim); |