43 constexpr
unsigned int bresenham_radius = 3;
44 constexpr
unsigned int bresenham_count = 16;
58 const std::array<std::array<int, 2>, 16> circle_offsets =
84 const std::array<uint16_t, 16> fast9_masks =
106 inline bool in_range(
const uint8_t low,
const uint8_t high,
const uint8_t val)
108 return low <= val && val <= high;
111 template <
typename T,
typename F>
112 bool is_a_corner(
const Coordinates &candidate,
const SimpleTensor<T> &
src, uint8_t
threshold,
BorderMode border_mode, T constant_border_value, F intensity_at)
114 const auto intensity_p =
tensor_elem_at(src, candidate, border_mode, constant_border_value);
115 const auto thresh_bright = intensity_p +
threshold;
116 const auto thresh_dark = intensity_p -
threshold;
119 const auto p1 = intensity_at(candidate, 0);
120 const auto p9 = intensity_at(candidate, 8);
121 const auto p5 = intensity_at(candidate, 4);
122 const auto p13 = intensity_at(candidate, 12);
124 if((in_range(thresh_dark, thresh_bright, p1) && in_range(thresh_dark, thresh_bright, p9))
125 || (in_range(thresh_dark, thresh_bright, p5) && in_range(thresh_dark, thresh_bright, p13)))
130 uint16_t mask_bright = 0;
131 uint16_t mask_dark = 0;
134 for(
unsigned int n = 0; n < bresenham_count; ++n)
136 T intensity_n = intensity_at(candidate, n);
137 mask_bright |= (intensity_n > thresh_bright) << n;
138 mask_dark |= (intensity_n < thresh_dark) << n;
142 const auto found = std::find_if(fast9_masks.begin(), fast9_masks.end(), [&](decltype(fast9_masks[0]) mask)
144 return (mask_bright & mask) == mask || (mask_dark & mask) == mask;
147 return found != fast9_masks.end();
151 template <
typename T>
155 const auto intensity_at = [&](
const Coordinates & point,
const unsigned int idx)
157 const auto offset = circle_offsets[idx];
159 return tensor_elem_at(src, px, border_mode, constant_border_value);
162 const auto threshold =
static_cast<uint8_t
>(input_thresh);
163 std::vector<KeyPoint> corners;
166 std::vector<Coordinates> corner_candidates;
171 for(uint32_t i = 0; i < num_elements; ++i)
180 if(is_a_corner(candidate, src, threshold, border_mode, constant_border_value, intensity_at))
182 corner_candidates.emplace_back(candidate);
190 for(
const auto &candidate : corner_candidates)
192 const auto index =
coord2index(scores.shape(), candidate);
193 uint8_t thresh_max = UINT8_MAX;
195 uint8_t response = (thresh_min + thresh_max) / 2;
198 while(thresh_max - thresh_min > 1)
200 response = (thresh_min + thresh_max) / 2;
201 if(is_a_corner(candidate, src, response, border_mode, constant_border_value, intensity_at))
203 thresh_min = response;
207 thresh_max = response;
210 scores[index] = thresh_min;
217 for(
const auto &candidate : corner_candidates)
219 const auto index =
coord2index(scores.shape(), candidate);
223 corner.
x = candidate.x();
224 corner.
y = candidate.y();
230 corners.emplace_back(corner);
BorderMode
Methods available to handle borders.
__global uchar * offset(const Image *img, int x, int y)
Get the pointer position of a Image.
T tensor_elem_at(const SimpleTensor< T > &src, Coordinates coord, BorderMode border_mode, T constant_border_value)
float scale
Scale initialized to 0 by the corner detector.
Container for 2D border size.
float orientation
Orientation initialized to 0 by the corner detector.
1 channel, 1 U8 per channel
int32_t tracking_status
Status initialized to 1 by the corner detector, set to 0 when the point is lost.
TensorShape shape() const override
Shape of the tensor.
const ValidRegion valid_region
SimpleTensor< float > src
Copyright (c) 2017-2021 Arm Limited.
int coord2index(const TensorShape &shape, const Coordinates &coord)
Linearise the given coordinate.
float strength
Strength of the point.
T x() const
Alias to access the size of the first dimension.
float error
Tracking error initialized to 0 by the corner detector.
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.
std::vector< KeyPoint > fast_corners(const SimpleTensor< T > &src, float input_thresh, bool suppress_nonmax, BorderMode border_mode, T constant_border_value)
Simple tensor object that stores elements in a consecutive chunk of memory.
SimpleTensor< T > non_maxima_suppression(const SimpleTensor< T > &src, BorderMode border_mode, T constant_border_value)
Borders are left undefined.
int num_elements() const override
Number of elements of the tensor.
T y() const
Alias to access the size of the second dimension.
Container for valid region of a window.
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.