Program Listing for File xf_bfmatcher.hpp
↰ Return to documentation for file (/tmp/ws/src/vitis_common/include/imgproc/xf_bfmatcher.hpp
)
/*
* Copyright 2020 Xilinx, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef __XF_VITIS_BFMATCHER_HPP__
#define __XF_VITIS_BFMATCHER_HPP__
#include "ap_int.h"
#include "../common/xf_utility.hpp"
namespace xf {
namespace cv {
// Some macros related to template (for easiness of coding)
const int DESC_SIZE = 256;
const ap_int<16> POOR_MATCH = -1;
using DESC_TYPE = ap_uint<DESC_SIZE>;
using DIST_TYPE = ap_uint<9>;
using MATCH_TYPE = ap_int<16>;
#define _GENERIC_BF_TPLT template <int PU = 1, int MAX_KEYPOINTS = 10000>
#define _GENERIC_BF GenericBF<PU, MAX_KEYPOINTS>
// ======================================================================================
// Top bfMatcher API
// --------------------------------------------------------------------------------------
// Template Args:-
// ......................................................................................
_GENERIC_BF_TPLT class GenericBF {
public:
DESC_TYPE stack_t[MAX_KEYPOINTS];
void copyTrainingSet(DESC_TYPE desc_train[MAX_KEYPOINTS], ap_uint<32> keypoints_t) {
READ_LOOP_DESC_TRAIN:
for (ap_uint<32> i = 0; i < keypoints_t; i++) {
// clang-format off
#pragma HLS LOOP_TRIPCOUNT min=MAX_KEYPOINTS max=MAX_KEYPOINTS
#pragma HLS PIPELINE II=1
// clang-format on
stack_t[i] = desc_train[i];
}
}
DIST_TYPE computeHamming(DESC_TYPE desc_val_q, DESC_TYPE desc_val_t) {
// clang-format off
#pragma HLS INLINE OFF
// clang-format on
DIST_TYPE dist = 0;
for (int i = 0; i < DESC_SIZE; i++) {
// clang-format off
#pragma HLS UNROLL
// clang-format on
dist += desc_val_q.range(i, i) == desc_val_t.range(i, i) ? 0 : 1;
}
return dist;
}
void process(DESC_TYPE data_q,
DESC_TYPE data_t,
int idx_t,
DIST_TYPE& dist_min_1,
DIST_TYPE& dist_min_2,
MATCH_TYPE& match_idx_1) {
// clang-format off
#pragma HLS INLINE
// clang-format on
DIST_TYPE local_dist = computeHamming(data_q, data_t);
if (local_dist < dist_min_1) {
dist_min_2 = dist_min_1;
dist_min_1 = local_dist;
match_idx_1 = idx_t;
} else if (local_dist < dist_min_2) {
dist_min_2 = local_dist;
}
}
};
_GENERIC_BF_TPLT
void bfMatcher(DESC_TYPE desc_list_q[MAX_KEYPOINTS],
DESC_TYPE desc_list_t[MAX_KEYPOINTS],
MATCH_TYPE match_list[MAX_KEYPOINTS],
ap_uint<32> num_keypoints_q,
ap_uint<32> num_keypoints_t,
float ratio_thresh) {
// clang-format off
#pragma HLS INLINE OFF
// clang-format on
#ifndef __SYNTHESIS__
assert((num_keypoints_q <= MAX_KEYPOINTS) &&
"Number of keypoints in the descriptor query set must be less than the MAX_KEYPOINTS parameter");
assert((num_keypoints_t <= MAX_KEYPOINTS) &&
"Number of keypoints in the descriptor training set must be less than the MAX_KEYPOINTS parameter");
#endif
const int MAX_KEYPOINTS_PU = MAX_KEYPOINTS / PU;
int proc_loop_kp1 = (num_keypoints_q / PU);
MATCH_TYPE match_1[PU];
// clang-format off
#pragma HLS ARRAY_PARTITION variable=match_1 complete dim=1
// clang-format on
DIST_TYPE dist_min_1[PU], dist_min_2[PU];
// clang-format off
#pragma HLS ARRAY_PARTITION variable=dist_min_1 complete dim=1
#pragma HLS ARRAY_PARTITION variable=dist_min_2 complete dim=1
// clang-format on
_GENERIC_BF bf;
bf.copyTrainingSet(desc_list_t, num_keypoints_t);
PROCESS_LOOP_DESC_1:
for (int i = 0; i < proc_loop_kp1; i++) {
// clang-format off
#pragma HLS LOOP_TRIPCOUNT min=MAX_KEYPOINTS_PU max=MAX_KEYPOINTS_PU
// clang-format on
DESC_TYPE query_set[PU];
// clang-format off
#pragma HLS ARRAY_PARTITION variable=query_set complete dim=1
// clang-format on
INIT_LOOP_1:
for (int init_idx = 0; init_idx < PU; init_idx++) {
// clang-format off
#pragma HLS PIPELINE II=1
// clang-format on
query_set[init_idx] = desc_list_q[i * PU + init_idx];
dist_min_1[init_idx] = 511;
dist_min_2[init_idx] = 511;
match_1[init_idx] = 0;
}
PROCESS_LOOP_DESC_2:
for (int j = 0; j < num_keypoints_t; j++) {
// clang-format off
#pragma HLS LOOP_TRIPCOUNT min=MAX_KEYPOINTS max=MAX_KEYPOINTS
#pragma HLS PIPELINE II=1
// clang-format on
DESC_TYPE train_data = bf.stack_t[j];
PROCESS_LOOP_DESC_3:
for (int k = 0; k < PU; k++) {
// clang-format off
#pragma HLS UNROLL
// clang-format on
bf.process(query_set[k], train_data, j, dist_min_1[k], dist_min_2[k], match_1[k]);
}
}
WRITE_LOOP_1:
for (int w_pu_idx = 0; w_pu_idx < PU; w_pu_idx++) {
// clang-format off
#pragma HLS PIPELINE II=1
// clang-format on
// Lowe's ratio test
if ((float)dist_min_1[w_pu_idx] < (ratio_thresh * (float)dist_min_2[w_pu_idx]))
match_list[i * PU + w_pu_idx] = match_1[w_pu_idx];
else
match_list[i * PU + w_pu_idx] = POOR_MATCH;
}
}
const int REM_KEYPOINTS = PU - 1;
int proc_loop_kp1_trunc = (num_keypoints_q / PU) * PU;
int rem_extra = num_keypoints_q - proc_loop_kp1_trunc;
PROCESS_LOOP_EXTRA:
for (int rem = 0; rem < rem_extra; rem++) {
// clang-format off
#pragma HLS LOOP_TRIPCOUNT min=REM_KEYPOINTS max=REM_KEYPOINTS
// clang-format on
dist_min_1[0] = 511;
dist_min_2[0] = 511;
PROCESS_LOOP_REM_DESC_2:
for (int j = 0; j < num_keypoints_t; j++) {
// clang-format off
#pragma HLS LOOP_TRIPCOUNT min=MAX_KEYPOINTS max=MAX_KEYPOINTS
#pragma HLS PIPELINE II=1
// clang-format on
bf.process(desc_list_q[proc_loop_kp1_trunc + rem], bf.stack_t[j], j, dist_min_1[0], dist_min_2[0],
match_1[0]);
}
if ((float)dist_min_1[0] < (ratio_thresh * (float)dist_min_2[0]))
match_list[proc_loop_kp1_trunc + rem] = match_1[0];
else
match_list[proc_loop_kp1_trunc + rem] = POOR_MATCH;
}
return;
}
// ======================================================================================
// Some clean up for macros used
#undef DESC_SIZE
#undef DESC_TYPE
} // end of cv
} // end of xf
#endif // end of __XF_VITIS_BFMATCHER_HPP__