doc_scan_lite 0.0.1
doc_scan_lite: ^0.0.1 copied to clipboard
Lightweight classical-CV document edge detection and perspective-crop FFI plugin — no ML models, no Play Services.
doc_scan_lite #
A lightweight Flutter FFI plugin for live document edge detection and perspective-crop. Classical computer vision only — no ML models, no Google Play Services / ML Kit dependency — targeting a native binary in the hundreds-of-KB range per ABI.
How it works #
src/ implements the detection pipeline from scratch in C:
- YUV420 Y-plane extraction (grayscale, no RGB conversion)
- 5x5 Gaussian blur
- Canny edge detection (Sobel + non-max suppression + hysteresis)
- Morphological dilate
- Contour tracing (Moore-neighbor border following)
- Douglas-Peucker polygon simplification
- Quad filtering (4 points, convex, area > 20% of frame)
- Corner ordering (TL/TR/BR/BL)
- Homography solve + perspective warp
Exposed via two C functions (src/doc_scan_lite.h):
bool detect_quad(const uint8_t* frame, int width, int height, Quad* out);
bool warp_perspective(const uint8_t* frame, int width, int height, Quad quad,
uint8_t* out_buffer, int out_width, int out_height);
lib/ wraps these with an isolate-based Dart API so detection never blocks
the UI thread:
DocScanController— owns a persistent background isolate, throttles incoming camera frames to a target detection fps independent of the camera's preview rate, smooths corners with a moving average, and exposescurrentQuad/isLocked.DocScannerPreview— camera preview widget with a live quad overlay.QuadCornerEditor— manual drag-adjustment widget for correcting a bad auto-detection, pure Dart/Flutter with no native cost.captureAndCrop()re-runs detection on a full-resolution frame and returns the warped/cropped image as aCapturedDocument.
Testing #
test/run_tests.shbuilds and runs the C pipeline unit tests standalone (no Flutter/FFI toolchain involved) — corner ordering, Douglas-Peucker, homography, and a full synthetic detect+warp smoke test.example/demonstrates live camera detection end-to-end. Camera streams on emulators are unreliable for this — test on a real device.
Regenerating FFI bindings #
dart run ffigen --config ffigen.yaml
If ffigen's bundled libclang can't find stdbool.h on Linux, point CPATH
at your system clang's resource include dir first:
CPATH="$(clang -print-resource-dir)/include" dart run ffigen --config ffigen.yaml
Non-goals #
No OCR, no multi-page PDF assembly, no ML models or trained weights, no Google Play Services / ML Kit dependency anywhere in the tree.