42 std::tuple<SimpleTensor<T>, SimpleTensor<T>,
float> compute_sobel(
const SimpleTensor<uint8_t> &
src,
int gradient_size,
int block_size,
BorderMode border_mode, uint8_t constant_border_value)
44 SimpleTensor<T> grad_x;
45 SimpleTensor<T> grad_y;
46 float norm_factor = 0.f;
53 norm_factor = 1.f / (4 * 255 * block_size);
56 norm_factor = 1.f / (16 * 255 * block_size);
59 norm_factor = 1.f / (64 * 255 * block_size);
65 return std::make_tuple(grad_x, grad_y, norm_factor);
68 template <
typename T,
typename U>
69 std::vector<KeyPoint> harris_corner_detector_impl(
const SimpleTensor<U> &src,
float threshold,
float min_dist,
float sensitivity,
int gradient_size,
int block_size,
BorderMode border_mode,
70 U constant_border_value)
74 SimpleTensor<T> grad_x;
75 SimpleTensor<T> grad_y;
76 float norm_factor = 0.f;
79 std::tie(grad_x, grad_y, norm_factor) = compute_sobel<T>(
src, gradient_size, block_size, border_mode, constant_border_value);
85 for(
int i = 0; i < scores.num_elements(); ++i)
87 Coordinates src_coord =
index2coord(src.shape(), i);
88 Coordinates block_top_left{ src_coord.
x() - block_size / 2, src_coord.y() - block_size / 2 };
89 Coordinates block_bottom_right{ src_coord.x() + block_size / 2, src_coord.y() + block_size / 2 };
102 for(
int y = block_top_left.y(); y <= block_bottom_right.y(); ++y)
104 for(
int x = block_top_left.x(); x <= block_bottom_right.x(); ++x)
106 Coordinates block_coord(x, y);
108 const float norm_x =
tensor_elem_at(grad_x, block_coord, border_mode, static_cast<T>(constant_border_value)) * norm_factor;
109 const float norm_y =
tensor_elem_at(grad_y, block_coord, border_mode, static_cast<T>(constant_border_value)) * norm_factor;
111 Gx2 += std::pow(norm_x, 2);
112 Gy2 += std::pow(norm_y, 2);
113 Gxy += norm_x * norm_y;
117 const float trace2 = std::pow(Gx2 + Gy2, 2);
118 const float det = Gx2 * Gy2 - std::pow(Gxy, 2);
119 const float response = det - sensitivity * trace2;
121 if(response > threshold)
123 scores[i] = response;
136 std::vector<KeyPoint> corner_candidates;
138 for(
int i = 0; i < suppressed_scores.num_elements(); ++i)
140 Coordinates coord =
index2coord(suppressed_scores.shape(), i);
142 if(
is_in_valid_region(suppressed_scores_region, coord) && suppressed_scores[i] != 0.f)
145 corner.
x = coord.x();
146 corner.y = coord.y();
147 corner.tracking_status = 1;
148 corner.strength = suppressed_scores[i];
150 corner.orientation = 0.f;
153 corner_candidates.emplace_back(corner);
158 std::sort(corner_candidates.begin(), corner_candidates.end(), [](
const KeyPoint & a,
const KeyPoint &
b)
160 return a.strength >
b.strength;
163 std::vector<KeyPoint> corners;
164 corners.reserve(corner_candidates.size());
167 for(
const KeyPoint &point : corner_candidates)
169 const auto strongest = std::find_if(corners.begin(), corners.end(), [&](
const KeyPoint & other)
171 return std::sqrt((std::pow(point.x - other.x, 2) + std::pow(point.y - other.y, 2))) < min_dist;
174 if(strongest == corners.end())
176 corners.emplace_back(point);
180 corners.shrink_to_fit();
186 template <
typename T>
187 std::vector<KeyPoint>
harris_corner_detector(
const SimpleTensor<T> &src,
float threshold,
float min_dist,
float sensitivity,
int gradient_size,
int block_size,
BorderMode border_mode,
188 T constant_border_value)
190 if(gradient_size < 7)
192 return harris_corner_detector_impl<int16_t>(
src,
threshold, min_dist, sensitivity, gradient_size, block_size, border_mode, constant_border_value);
196 return harris_corner_detector_impl<int32_t>(
src,
threshold, min_dist, sensitivity, gradient_size, block_size, border_mode, constant_border_value);
201 uint8_t constant_border_value);
BorderMode
Methods available to handle borders.
T tensor_elem_at(const SimpleTensor< T > &src, Coordinates coord, BorderMode border_mode, T constant_border_value)
#define ARM_COMPUTE_ERROR(msg)
Print the given message then throw an std::runtime_error.
1 channel, 1 F32 per channel
#define ARM_COMPUTE_ERROR_ON(cond)
If the condition is true then an error message is printed and an exception thrown.
SimpleTensor< float > src
Copyright (c) 2017-2021 Arm Limited.
T x() const
Alias to access the size of the first dimension.
bool is_in_valid_region(const ValidRegion &valid_region, Coordinates coord)
Check if a coordinate is within a valid region.
Coordinates index2coord(const TensorShape &shape, int index)
Convert a linear index into n-dimensional coordinates.
x and y gradient dimension
std::vector< KeyPoint > harris_corner_detector(const SimpleTensor< T > &src, float threshold, float min_dist, float sensitivity, int gradient_size, int block_size, BorderMode border_mode, T constant_border_value)
SimpleTensor< T > non_maxima_suppression(const SimpleTensor< T > &src, BorderMode border_mode, T constant_border_value)
Borders are left undefined.
SimpleTensor< T > threshold(const SimpleTensor< T > &src, T threshold, T false_value, T true_value, ThresholdType type, T upper)
ValidRegion shape_to_valid_region(const TensorShape &a_shape, bool border_undefined=false, BorderSize border_size=BorderSize(0))
Create a valid region based on tensor shape, border mode and border size.