extractAlignedSquare function

Mat? extractAlignedSquare(
  1. Mat src,
  2. double cx,
  3. double cy,
  4. double size,
  5. double theta, {
  6. int? outSize,
})

Extracts a rotated square region from a cv.Mat using OpenCV's warpAffine.

This function uses SIMD-accelerated warpAffine which is 10-50x faster than pure Dart bilinear interpolation.

Parameters:

  • src: Source cv.Mat image
  • cx: Center X coordinate in pixels
  • cy: Center Y coordinate in pixels
  • size: Side length of the square region in source pixels
  • theta: Rotation angle in radians (positive = counter-clockwise)
  • outSize: Optional output side length in pixels. When set, the warp scales the size-by-size source region directly to outSize-by-outSize in a single resample, equivalent to cropping at size and then cv.resize-ing to outSize (the scaled matrix uses the same pixel-center alignment as cv.resize). Use this to extract crops at a model's input resolution without paying for a full-size warp plus a second resample.

Returns the cropped and rotated cv.Mat. Caller must dispose. Returns null if size is invalid.

Implementation

cv.Mat? extractAlignedSquare(
  cv.Mat src,
  double cx,
  double cy,
  double size,
  double theta, {
  int? outSize,
}) {
  final int sizeInt = size.round();
  if (sizeInt <= 0) return null;
  final int dstSize = outSize ?? sizeInt;
  final double scale = dstSize / sizeInt;

  final double angleDegrees = -theta * 180.0 / math.pi;

  final cv.Mat rotMat = cv.getRotationMatrix2D(
    cv.Point2f(cx, cy),
    angleDegrees,
    scale,
  );

  // Pixel-center alignment matching crop-then-cv.resize: a resize by factor
  // s samples src((x + 0.5) / s - 0.5), so the source center must land at
  // dstSize / 2 + 0.5 * (s - 1) rather than dstSize / 2. Reduces to the
  // plain crop placement when outSize is null (s == 1).
  final double outCenter = dstSize / 2.0 + 0.5 * (scale - 1.0);

  final double tx = rotMat.at<double>(0, 2) + outCenter - cx;
  final double ty = rotMat.at<double>(1, 2) + outCenter - cy;
  rotMat.set<double>(0, 2, tx);
  rotMat.set<double>(1, 2, ty);

  final cv.Mat output = cv.warpAffine(
    src,
    rotMat,
    (dstSize, dstSize),
    borderMode: cv.BORDER_CONSTANT,
    borderValue: cv.Scalar.black,
  );

  rotMat.dispose();
  return output;
}