image-js
Version:
Image processing and manipulation in JavaScript
60 lines (48 loc) • 1.98 kB
text/typescript
import type { Image } from '../../../Image.js';
import { getRadius } from '../../../utils/getRadius.js';
import type { OrientedFastKeypoint } from '../../keypoints/getOrientedFastKeypoints.js';
import { checkBorderDistance } from '../../utils/checkBorderDistance.js';
import { extractSquareImage } from '../../utils/extractSquareImage.js';
export interface GetKeypointPatchOptions {
/**
* Size of the patch around the keypoint used to compute the descriptor.
* @default `31`
*/
patchSize?: number;
}
/**
* Get the patch around the keypoint with given size.
* @param image - Image from which to extract the patch.
* @param keypoint - Keypoint around which to extract the patch.
* @param options - Get keypoint patch options.
* @returns The patch around the keypoint.
*/
export function getKeypointPatch(
image: Image,
keypoint: OrientedFastKeypoint,
options: GetKeypointPatchOptions = {},
): Image {
const { patchSize = 31 } = options;
// crop smallest square surrounding the tilted patch of the keypoint
// we have to handle the fact that this square can have even dimensions
const radAngle = (keypoint.angle * Math.PI) / 180;
const rawWidth = Math.floor(
patchSize * (Math.abs(Math.cos(radAngle)) + Math.abs(Math.sin(radAngle))),
);
const cropWidth = rawWidth % 2 ? rawWidth : rawWidth + 1;
// we are not allowing keypoints that are too close to the border of the image
const borderDistance = getRadius(cropWidth);
if (!checkBorderDistance(image, keypoint.origin, borderDistance)) {
throw new RangeError(
'keypoint is too close to border for given patch size',
);
}
const cropped = extractSquareImage(image, keypoint.origin, cropWidth);
const rotated = cropped.transformRotate(-keypoint.angle, {
center: 'center',
interpolationType: 'nearest',
});
const cropOrigin = rotated.getCoordinates('center');
const result = extractSquareImage(rotated, cropOrigin, patchSize);
return result;
}