@thi.ng/pixel-flow
Version:
Naive, lightweight CPU-based dense optical flow implementation
165 lines • 5.18 kB
TypeScript
import type { ICopy, Predicate2 } from "@thi.ng/api";
import type { IPixelBuffer } from "@thi.ng/pixel";
/**
* Configuration options. See {@link OpticalFlow} for algorithm details.
*
* @remarks
* The resulting flow field will have a resolution of:
*
* ```text
* [
* ceil((imgWidth - 2 * margin) / step),
* ceil((imgHeight - 2 * margin) / step)
* ]
* ```
*
* Where `step` is {@link OpticalFlowOpts.step} and `margin` is the sum of
* {@link OpticalFlowOpts.windowSize} and {@link OpticalFlowOpts.displace}.
*/
export interface OpticalFlowOpts {
/**
* Number of pixels to skip between samples (in both X/Y direction).
*
* @defaultValue 6
*/
step: number;
/**
* Maximum per-axis displacement distance in pixels used for computing the
* frame differences. MUST be a multiple of
* {@link OpticalFlowOpts.displaceStep}.
*
* @remarks
* Both this value and `displaceStep` indirectly control the granularity of
* flow directions. See {@link OpticalFlow} for algorithm details.
*
* @defaultValue 9
*/
displace: number;
/**
* Pixel step size to iterate the `[-displace,displace]` interval in each
* direction.
*
* @remarks
* Both this value and {@link OpticalFlowOpts.displace} indirectly control
* the granularity of flow directions. See {@link OpticalFlow} for algorithm
* details.
*
* @defaultValue 3
*/
displaceStep: number;
/**
* Half the kernel window size, used to compute summed frame difference for
* a displace region. MUST be a multiple of
* {@link OpticalFlowOpts.windowStep}.
*
* @remarks
* See {@link OpticalFlow} for algorithm details.
*
* @defaultValue 12
*/
windowSize: number;
/**
* Pixel step size to iterate a single kernel window. Also see
* {@link OpticalFlowOpts.windowSize}.
*
* @defaultValue 3
*/
windowStep: number;
/**
* Amplitude/scale factor of flow vectors.
*
* @defaultValue 1
*/
amp: number;
/**
* Temporal smoothing linear interpolation factor for flow vectors.
*
* @defaultValue 0.25
*/
smooth: number;
/**
* Minimum summed difference threshold for a kernel window to be considered
* as candidate. Values < 0 mean all deltas are considered.
*
* @remarks
* The summed window difference is computed as:
*
* ```text
* sum(pow(abs(a[i]-b[i])/range,2)) / windowSize
* ```
*
* Therefore, the thresold also is to be specified in the [0,1] interval.
*
* @defaultValue 0.001
*/
threshold: number;
/**
* Pixel value range (default: 255). If processing float buffers, this
* option likely will have to be set to 1.0.
*
* @defaultValue 255
*/
range: number;
/**
* Displacement window selection mode (see {@link OpticalFlow} for more details).
*
* @defaultValue "min"
*/
mode: "min" | "max";
}
/**
* Naive dense Optical Flow extraction. See {@link OpticalFlowOpts} for
* configuration options and details.
*
* @remarks
* The algorithm requires a previous and current frame. The flow field is
* obtained by sampling the current frame at a given
* {@link OpticalFlowOpts.step} distance. For each of these sample/grid
* positions a kernel window (of `2*windowSize+1` pixels) is being swept/applied
* to compute the differences to the previous frame. To compute these
* differences, the previous frame is offset multiple times in both X/Y
* directions within the `[-displace, +displace)` interval. The kernel computes
* the summed difference for each of these displaced window regions and selects
* the window with the minimum or maximum change (depending on
* {@link OpticalFlowOpts.mode}). The relative (displacement) position of that
* selected window is then used as the flow vector for that cell, which will
* then be linearly interpolated to apply temporal smoothing of the field
* (configurable via {@link OpticalFlowOpts.smooth}) and minimize jittering.
*/
export declare class OpticalFlow<T extends IPixelBuffer & ICopy<T>> {
prev: T;
flow: Float64Array;
step: number;
displace: number;
displaceStep: number;
windowSize: number;
windowStep: number;
amp: number;
smooth: number;
width: number;
height: number;
margin: number;
threshold: number;
invRange: number;
mode: "min" | "max";
pred: Predicate2<number>;
constructor(startFrame: T, opts: Partial<OpticalFlowOpts>);
/**
* Computes optical flow between given frame and (stored) previous frame,
* according to configured options. Returns updated flowfield in a format
* compatible with thi.ng/tensors `asTensor()`.
*
* @remarks
* See {@link OpticalFlow} class docs for more details.
*
* @param curr
*/
update(curr: T): {
type: "f64";
data: Float64Array<ArrayBufferLike>;
shape: [number, number, number];
stride: [number, number, number];
dir: number[];
};
}
//# sourceMappingURL=index.d.ts.map