analyzeSkew static method
Analyzes document skew/tilt angle from edge pixel patterns.
Implementation
static SkewAnalysis analyzeSkew(
Uint8List imageBytes, {
required int width,
required int height,
}) {
if (imageBytes.isEmpty || width <= 2 || height <= 2) {
return const SkewAnalysis(
angleDegrees: 0.0,
isAligned: true,
correctionAngle: 0.0,
);
}
// Detect dominant edge direction using Sobel-like horizontal gradient
double sumAngle = 0;
int edgeCount = 0;
for (int y = 1; y < height - 1 && y * width < imageBytes.length; y++) {
for (int x = 1; x < width - 1; x++) {
final idx = y * width + x;
if (idx + width < imageBytes.length && idx - width >= 0) {
// Horizontal Sobel: [-1, 0, 1]
final gx = imageBytes[idx + 1] - imageBytes[idx - 1];
// Vertical Sobel: [-1, 0, 1]
final gy = imageBytes[idx + width] - imageBytes[idx - width];
final magnitude = math.sqrt(gx * gx + gy * gy);
if (magnitude > 30) {
// Strong edge detected
final angle = math.atan2(gy.toDouble(), gx.toDouble()) *
(180.0 / math.pi);
sumAngle += angle;
edgeCount++;
}
}
}
}
if (edgeCount == 0) {
return const SkewAnalysis(
angleDegrees: 0.0,
isAligned: true,
correctionAngle: 0.0,
);
}
final avgAngle = sumAngle / edgeCount;
// Normalize to deviation from horizontal/vertical
final skewAngle = (avgAngle % 90.0).abs();
final normalizedSkew =
skewAngle > 45.0 ? 90.0 - skewAngle : skewAngle;
return SkewAnalysis(
angleDegrees: normalizedSkew,
isAligned: normalizedSkew < 5.0,
correctionAngle: -normalizedSkew,
);
}