image-js
Version:
Image processing and manipulation in JavaScript
102 lines (94 loc) • 3.06 kB
text/typescript
import type { Image } from '../../Image.js';
import type { Point } from '../../geometry/index.js';
export interface IsFastKeypointOptions {
/**
* Number of contiguous pixels on the circle that should have an intensity difference with current pixel larger than threshold.
* This value is recommended to be 3/4 of the circle points.
* @default `3/4*circlePoints.length`
*/
nbContiguousPixels?: number;
/**
* Threshold for the intensity difference.
* @default `20`
*/
threshold?: number;
}
/**
* Determine wether a pixel in an image is a corner according to the FAST algorithm.
* @param origin - Pixel to process.
* @param image - Image to process.
* @param circlePoints - Coordinates of the points on the circle.
* @param compassPoints - Compass points for quick test.
* @param options - Is FAST keypoint options.
* @returns Whether the current pixel is a corner or not.
*/
export function isFastKeypoint(
origin: Point,
image: Image,
circlePoints: Point[],
compassPoints: Point[],
options: IsFastKeypointOptions = {},
): boolean {
const { nbContiguousPixels = 12, threshold = 20 } = options;
const currentIntensity = image.getValueByPoint(origin, 0);
let brighter = 0;
let darker = 0;
// quick test to exlude non corners
if (nbContiguousPixels >= 12) {
for (const point of compassPoints) {
const pointIntensity = image.getValue(
origin.column + point.column,
origin.row + point.row,
0,
);
if (currentIntensity - pointIntensity > threshold) {
darker++;
} else if (pointIntensity - currentIntensity > threshold) {
brighter++;
}
}
if (darker < 3 && brighter < 3) return false;
}
// determine whether points on circle are darker or brighter
const comparisonArray = [];
for (const point of circlePoints) {
const pointIntensity = image.getValue(
origin.column + point.column,
origin.row + point.row,
0,
);
if (currentIntensity + threshold <= pointIntensity) {
comparisonArray.push(-1); // circle point is lighter
} else if (pointIntensity <= currentIntensity - threshold) {
comparisonArray.push(1); // circle point is darker
} else {
comparisonArray.push(0); // circle point is similar
}
}
// compute number of repeating and touching values
let currentLength = 1;
const counterArray = [];
for (let i = 0; i < comparisonArray.length; i++) {
const currentValue = comparisonArray[i];
const nextValue = comparisonArray[(i + 1) % comparisonArray.length];
if (currentValue === nextValue) {
if (i === comparisonArray.length - 1) {
if (counterArray.length === 0) {
counterArray.push(currentLength);
} else {
counterArray[0] += currentLength;
}
} else {
currentLength++;
}
} else {
counterArray.push(currentLength);
currentLength = 1;
}
}
if (Math.max(...counterArray) >= nbContiguousPixels) {
return true;
} else {
return false;
}
}