-
Notifications
You must be signed in to change notification settings - Fork 0
API‐Feature‐Detection
Namespace: acl::feature (CPP) / acl::neon::feature (NEON)
Common data structures (in the acl:: namespace):
struct KeyPoint { int x, y; float response; };
struct KeyPointORB { float x, y, response, scale, angle; uint8_t descriptor[32]; };
struct KeyPointExt { float x, y, response, scale, angle; float descriptor[128]; };
struct Point2f { float x, y; };
struct DMatch { int queryIdx, trainIdx; float distance; };
struct Vec2f { float val[2]; }; // (rho, theta)
struct Vec3f { float val[3]; }; // (cx, cy, radius)
struct Vec4i { int val[4]; }; // (x1, y1, x2, y2)FAST corner detection (Bresenham 16-pixel circle comparison).
Tier: Pro+
Channels: 1ch
Inplace: not supported
Types:
| Template parameter | Allowed types | Constraint |
|---|---|---|
T |
uint8_t |
— |
int fastCornerDetect(
const uint8_t* srcImage, int width, int height, int srcStride,
std::vector<KeyPoint>& keypoints,
int threshold = 20,
bool nonmaxSuppress = true,
int type = 9);| Parameter | Type | Meaning | Default |
|---|---|---|---|
srcImage |
const uint8_t* |
Input grayscale image | non-null |
srcStride |
int |
Bytes per row |
0 = width
|
keypoints |
vector<KeyPoint>& |
Output corners | — |
threshold |
int |
Grayscale difference threshold | 20 |
nonmaxSuppress |
bool |
Whether to perform NMS | true |
type |
int |
FAST-N (9 or 12; N is the number of consecutive pixels) |
9 |
Harris corner detection. Response R = det(M) - k * trace(M)^2, where M is the structure tensor.
Tier: Pro+
Channels: 1ch
Inplace: not supported
Types:
| Template parameter | Allowed types | Constraint |
|---|---|---|
T |
uint8_t |
— |
// Detect corners (including NMS)
int harrisCornerDetect(
const uint8_t* srcImage, int width, int height, int srcStride,
std::vector<KeyPoint>& keypoints,
int blockSize = 2,
float k = 0.04f,
float threshold = 1e6f);
// Emit the Harris response map only (caller does the threshold / NMS) — CPP only
int harrisResponse(
const uint8_t* srcImage, float* dstImage,
int width, int height, int srcStride,
int blockSize = 2, float k = 0.04f);| Parameter | Type | Meaning | Default |
|---|---|---|---|
blockSize |
int |
Structure-tensor neighborhood radius | 2 |
k |
float |
Harris free parameter | 0.04 |
threshold |
float |
Minimum response threshold | 1e6 |
Shi-Tomasi corners (Good Features to Track): response = min(λ1, λ2) (the structure tensor's eigenvalues).
Tier: Pro+
Channels: 1ch
Inplace: not supported
Types:
| Template parameter | Allowed types | Constraint |
|---|---|---|
T |
uint8_t |
— |
int shiTomasiCornerDetect(
const uint8_t* srcImage, int width, int height, int srcStride,
std::vector<KeyPoint>& keypoints,
int maxCorners = 500,
float qualityLevel = 0.01f,
float minDistance = 10.0f,
int blockSize = 2);
// Alias (same semantics as shiTomasiCornerDetect)
int shiTomasiDetect(
const uint8_t* srcImage, int width, int height, int srcStride,
std::vector<KeyPoint>& corners,
int maxCorners = 500,
float qualityLevel = 0.01f,
float minDistance = 10.0f,
int blockSize = 2);
// Emit the min-eigenvalue response map only — CPP only
int minEigenValResponse(
const uint8_t* srcImage, float* dstImage,
int width, int height, int srcStride,
int blockSize = 2);| Parameter | Type | Meaning | Default |
|---|---|---|---|
maxCorners |
int |
Upper bound on returned corners (0 = no limit) |
500 |
qualityLevel |
float |
Minimum quality ratio relative to the strongest response | 0.01 |
minDistance |
float |
Minimum Euclidean distance between adjacent corners | 10.0 |
blockSize |
int |
Structure-tensor neighborhood radius | 2 |
ORB detection + 256-bit rBRIEF descriptors.
Tier: Pro+
Channels: 1ch
Inplace: not supported
Types:
| Template parameter | Allowed types | Constraint |
|---|---|---|
T |
uint8_t |
— |
// Detect + compute descriptors
int orbDetectAndCompute(
const uint8_t* srcImage, int width, int height, int srcStride,
std::vector<KeyPointORB>& keypoints,
int maxKeypoints = 500,
float scaleFactor = 1.2f,
int nLevels = 8,
int fastThreshold = 20);
// Detection only (discard descriptors, output KeyPoint)
int orbDetect(
const uint8_t* srcImage, int width, int height, int srcStride,
std::vector<KeyPoint>& keypoints,
int maxKeypoints = 500,
float scaleFactor = 1.2f,
int nLevels = 8,
int fastThreshold = 20);
// Hamming distance between two 256-bit descriptors (0-256)
int orbHammingDistance(const uint8_t desc1[32], const uint8_t desc2[32]);| Parameter | Type | Meaning | Default |
|---|---|---|---|
maxKeypoints |
int |
Target keypoint count | 500 |
scaleFactor |
float |
Inter-level pyramid scale factor (> 1.0) |
1.2 |
nLevels |
int |
Number of pyramid levels | 8 |
fastThreshold |
int |
FAST internal threshold | 20 |
srcWidth / srcHeightmust be ≥32.
SIFT scale-invariant features + 128-D descriptors.
Tier: Business
Channels: 1ch
Inplace: not supported
Types:
| Template parameter | Allowed types | Constraint |
|---|---|---|
T |
uint8_t |
— |
int siftDetectAndCompute(
const uint8_t* srcImage, int width, int height, int srcStride,
std::vector<KeyPointExt>& keypoints,
int nOctaves = 0,
int nScalesPerOctave = 3,
float contrastThresh = 0.04f,
float edgeThresh = 10.0f,
float sigma = 1.6f);
// Detection only
int siftDetect(
const uint8_t* srcImage, int width, int height, int srcStride,
std::vector<KeyPoint>& keypoints,
int nOctaves = 0, int nScalesPerOctave = 3,
float contrastThresh = 0.04f, float edgeThresh = 10.0f,
float sigma = 1.6f);| Parameter | Type | Meaning | Default |
|---|---|---|---|
nOctaves |
int |
Number of pyramid octaves (0 = auto log2(min(w,h)) - 2) |
0 |
nScalesPerOctave |
int |
Scales per octave | 3 |
contrastThresh |
float |
DoG extremum contrast threshold | 0.04 |
edgeThresh |
float |
Edge-response rejection threshold | 10.0 |
sigma |
float |
Initial Gaussian sigma | 1.6 |
srcWidth / srcHeightmust be ≥16.
SURF accelerated features. Integral image + Hessian determinant; outputs 128-D descriptors (the first 64 dimensions of keypoints.descriptor are used).
Tier: Business
Channels: 1ch
Inplace: not supported
Types:
| Template parameter | Allowed types | Constraint |
|---|---|---|
T |
uint8_t |
— |
int surfDetectAndCompute(
const uint8_t* srcImage, int width, int height, int srcStride,
std::vector<KeyPointExt>& keypoints,
float hessianThresh = 100.0f,
int nOctaves = 4,
int nOctaveLayers = 3);
// Detection only
int surfDetect(
const uint8_t* srcImage, int width, int height, int srcStride,
std::vector<KeyPoint>& keypoints,
float hessianThresh = 100.0f,
int nOctaves = 4, int nOctaveLayers = 3);
srcWidth / srcHeightmust be ≥24.
HOG descriptor — histogram of gradient orientations; commonly used for pedestrian detection and classification features.
Tier: Pro+
Channels: 1ch
Inplace: not supported
Types:
| Template parameter | Allowed types | Constraint |
|---|---|---|
T |
uint8_t |
— |
struct HOGParams {
int cellSize; // default 8
int blockSize; // default 2 (block = blockSize × blockSize cells)
int nbins; // default 9
int blockStride; // default 1 (in units of cells)
};
int computeHOG(
const uint8_t* srcImage, int width, int height, int srcStride,
float* descriptors, int& descriptorSize,
const HOGParams& params = HOGParams());| Parameter | Type | Meaning | Default |
|---|---|---|---|
descriptors |
float* |
Output descriptor array (pre-allocated by the caller) | non-null |
descriptorSize |
int& |
Returns the actual number of floats written | — |
params |
const HOGParams& |
HOG parameters | default-constructed |
Output size =
blocksX * blocksY * (blockSize * blockSize * nbins). You can estimate this in advance using the default parameters or by calling once to readdescriptorSize.
Standard Hough line detection (houghLines outputs (rho, theta)) and probabilistic Hough (houghLinesP outputs line-segment endpoints).
Tier: Pro+
Channels: 1ch binary edge map (typically produced by canny)
Inplace: not supported
Types:
| Template parameter | Allowed types | Constraint |
|---|---|---|
T |
uint8_t |
— |
// Standard Hough
int houghLines(
const uint8_t* edgeImage, int width, int height, int stride,
std::vector<acl::Vec2f>& lines,
float rho,
float theta,
int threshold);
// Probabilistic Hough (returns line segments)
int houghLinesP(
const uint8_t* edgeImage, int width, int height, int stride,
std::vector<acl::Vec4i>& lines,
float rho,
float theta,
int threshold,
double minLineLength,
double maxLineGap);| Parameter | Type | Meaning | Recommended |
|---|---|---|---|
edgeImage |
const uint8_t* |
Input binary edge image (non-zero = edge) | non-null |
rho |
float |
Distance resolution (pixels) | 1.0 |
theta |
float |
Angle resolution (radians) | M_PI/180 |
threshold |
int |
Accumulator vote threshold | standard 100 / probabilistic 50
|
minLineLength |
double |
(probabilistic only) minimum line length | 0 |
maxLineGap |
double |
(probabilistic only) maximum gap between two points on the same line | 10 |
Output:
-
houghLines→Vec2f(rho, theta) -
houghLinesP→Vec4i(x1, y1, x2, y2)
Hough circle detection (21HT gradient method).
Tier: Pro+
Channels: 1ch grayscale image (internally performs Canny + gradient, no pre-binarization needed)
Inplace: not supported
Types:
| Template parameter | Allowed types | Constraint |
|---|---|---|
T |
uint8_t |
— |
int houghCircles(
const uint8_t* grayImage, int width, int height, int stride,
std::vector<acl::Vec3f>& circles,
float dp = 1.0f,
float minDist = 20.0f,
float param1 = 100.0f,
float param2 = 100.0f,
int minRadius = 0,
int maxRadius = 0);| Parameter | Type | Meaning | Default |
|---|---|---|---|
grayImage |
const uint8_t* |
Input grayscale image | non-null |
circles |
vector<Vec3f>& |
Output circles (cx, cy, radius)
|
— |
dp |
float |
Accumulator-to-image resolution ratio | 1.0 |
minDist |
float |
Minimum distance between adjacent circle centers | 20.0 |
param1 |
float |
Canny upper threshold (lower threshold auto = param1 / 2) |
100.0 |
param2 |
float |
Accumulator threshold for circle-center detection | 100.0 |
minRadius |
int |
Minimum radius | 0 |
maxRadius |
int |
Maximum radius (0 = max(width, height)) |
0 |
Sparse pyramid Lucas-Kanade optical flow.
Tier: Pro+
Channels: 1ch
Inplace: not supported
Types:
| Template parameter | Allowed types | Constraint |
|---|---|---|
T |
uint8_t |
— |
int opticalFlowLK(
const uint8_t* prevImage, const uint8_t* nextImage,
int width, int height, int stride,
const acl::Point2f* prevPts, acl::Point2f* nextPts,
uint8_t* status, float* error,
int numPoints,
int winSize = 21,
int maxLevel = 3,
int maxIter = 30,
float epsilon = 0.01f);| Parameter | Type | Meaning | Default |
|---|---|---|---|
prevImage, nextImage
|
const uint8_t* |
Previous / next frames | non-null |
prevPts |
const Point2f* |
Points in the previous frame to be tracked | non-null |
nextPts |
Point2f* |
Tracked points in the next frame (caller pre-allocates numPoints) |
non-null |
status |
uint8_t* |
Per-point status (1 = tracking succeeded, 0 = lost; pre-allocated for numPoints) |
non-null |
error |
float* |
Per-point tracking error (may be nullptr; when non-null, pre-allocated for numPoints) |
nullable |
numPoints |
int |
Number of tracked points | — |
winSize |
int |
Search window size | 21 |
maxLevel |
int |
Maximum pyramid level | 3 |
maxIter |
int |
Max iterations per level | 30 |
epsilon |
float |
Convergence threshold | 0.01 |
Brute-force descriptor matching: bfMatch* returns 1 nearest neighbor per query; bfKnn* returns K nearest neighbors. The float version uses L2 distance; the Binary version uses Hamming distance.
Tier: Pro+
Channels: N/A (descriptor vectors)
Inplace: not supported
Types:
| Template parameter | Allowed types | Constraint |
|---|---|---|
T |
uint8_t |
binary descriptors (e.g. ORB) |
T |
float |
real-valued descriptors (e.g. SIFT/SURF) |
// float descriptors, L2 distance, 1-NN
int bfMatch(
const float* queryDescs, int queryCount, int descDim,
const float* trainDescs, int trainCount,
std::vector<acl::DMatch>& matches);
// Binary descriptors (e.g. ORB), Hamming distance, 1-NN
int bfMatchBinary(
const uint8_t* queryDescs, int queryCount, int descBytes,
const uint8_t* trainDescs, int trainCount,
std::vector<acl::DMatch>& matches);
// float descriptors, L2, K-NN
int bfKnnMatch(
const float* queryDescs, int queryCount, int descDim,
const float* trainDescs, int trainCount,
std::vector<std::vector<acl::DMatch>>& matches,
int k = 2);
// Binary descriptors, Hamming, K-NN
int bfKnnMatchBinary(
const uint8_t* queryDescs, int queryCount, int descBytes,
const uint8_t* trainDescs, int trainCount,
std::vector<std::vector<acl::DMatch>>& matches,
int k = 2);| Parameter | Type | Meaning |
|---|---|---|
queryDescs, trainDescs
|
const float* / const uint8_t*
|
Row-major descriptors, length Count × (descDim or descBytes)
|
descDim |
int |
float descriptor dimension (SIFT 128; the SURF implementation uses 64) |
descBytes |
int |
Binary descriptor byte count (ORB 32) |
matches |
vector<DMatch>& or vector<vector<DMatch>>&
|
Output matches; each DMatch contains queryIdx, trainIdx, distance
|
k |
int |
K for K-NN (actually returns min(k, trainCount)) |
uint8_t srcImage[1920*1080];
std::vector<acl::KeyPointORB> kps;
// 1) ORB detection + description
acl::neon::feature::orbDetectAndCompute(
srcImage, 1920, 1080, 0, kps);
// 2) ORB matching between two images (Binary + Hamming)
std::vector<uint8_t> qDescs(kps.size() * 32), tDescs(/*...*/);
for (size_t i = 0; i < kps.size(); ++i)
memcpy(qDescs.data() + i*32, kps[i].descriptor, 32);
std::vector<acl::DMatch> matches;
acl::neon::feature::bfMatchBinary(
qDescs.data(), (int)kps.size(), 32,
tDescs.data(), /*trainCount=*/200,
matches);