react-native-rectangle-doc-scanner 0.44.0 → 0.45.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +35 -0
- package/dist/DocScanner.js +14 -12
- package/package.json +1 -1
- package/src/DocScanner.tsx +14 -12
package/README.md
CHANGED
|
@@ -5,6 +5,10 @@ VisionCamera + Fast-OpenCV powered document scanner template built for React Nat
|
|
|
5
5
|
## Features
|
|
6
6
|
- Real-time quad detection using `react-native-fast-opencv`
|
|
7
7
|
- Frame processor worklet executed on the UI thread via `react-native-vision-camera`
|
|
8
|
+
- High-resolution processing (1280p) for accurate corner detection
|
|
9
|
+
- Advanced anchor locking system maintains corner positions during camera movement
|
|
10
|
+
- Intelligent edge detection with optimized Canny parameters (50/150 thresholds)
|
|
11
|
+
- Adaptive smoothing with weighted averaging across multiple frames
|
|
8
12
|
- Resize plugin keeps frame processing fast on lower-end devices
|
|
9
13
|
- Skia overlay visualises detected document contours
|
|
10
14
|
- Stability tracker enables auto-capture once the document is steady
|
|
@@ -107,6 +111,37 @@ Passing `children` lets you render any UI on top of the camera preview, so you c
|
|
|
107
111
|
- The internal frame processor handles document detection; do not override `frameProcessor` in `cameraProps`.
|
|
108
112
|
- Adjust `minStableFrames` or tweak lighting conditions if auto capture is too sensitive or too slow.
|
|
109
113
|
|
|
114
|
+
## Detection Algorithm
|
|
115
|
+
|
|
116
|
+
The scanner uses a sophisticated multi-stage pipeline:
|
|
117
|
+
|
|
118
|
+
1. **Pre-processing** (1280p resolution for accuracy)
|
|
119
|
+
- Converts frame to grayscale
|
|
120
|
+
- Applies morphological opening to reduce noise
|
|
121
|
+
- Gaussian blur for smoother edges
|
|
122
|
+
- Canny edge detection with 50/150 thresholds
|
|
123
|
+
|
|
124
|
+
2. **Contour Detection**
|
|
125
|
+
- Finds external contours using CHAIN_APPROX_SIMPLE
|
|
126
|
+
- Applies convex hull for better corner detection
|
|
127
|
+
- Tests multiple epsilon values (0.1%-10%) for approxPolyDP
|
|
128
|
+
- Validates quadrilaterals for convexity
|
|
129
|
+
|
|
130
|
+
3. **Anchor Locking System**
|
|
131
|
+
- Once corners are detected, they "snap" to stable positions
|
|
132
|
+
- Maintains lock even when camera moves (up to 200px center delta)
|
|
133
|
+
- Holds anchor for up to 20 missed detections
|
|
134
|
+
- Adaptive blending between old and new positions for smooth transitions
|
|
135
|
+
- Builds confidence over time (max 30 frames) for stronger locking
|
|
136
|
+
|
|
137
|
+
4. **Quad Validation**
|
|
138
|
+
- Checks area ratio (0.02%-90% of frame)
|
|
139
|
+
- Validates minimum edge lengths
|
|
140
|
+
- Ensures reasonable aspect ratios
|
|
141
|
+
- Filters out non-convex shapes
|
|
142
|
+
|
|
143
|
+
This approach ensures corners remain locked once detected, allowing you to move the camera slightly without losing the document boundary.
|
|
144
|
+
|
|
110
145
|
## Build
|
|
111
146
|
```sh
|
|
112
147
|
yarn build
|
package/dist/DocScanner.js
CHANGED
|
@@ -100,19 +100,19 @@ const DocScanner = ({ onCapture, overlayColor = '#e7a649', autoCapture = true, m
|
|
|
100
100
|
const lastMeasurementRef = (0, react_1.useRef)(null);
|
|
101
101
|
const frameSizeRef = (0, react_1.useRef)(null);
|
|
102
102
|
const MAX_HISTORY = 5;
|
|
103
|
-
const SNAP_DISTANCE =
|
|
104
|
-
const SNAP_CENTER_DISTANCE =
|
|
105
|
-
const BLEND_DISTANCE =
|
|
106
|
-
const MAX_CENTER_DELTA =
|
|
107
|
-
const REJECT_CENTER_DELTA =
|
|
108
|
-
const MAX_AREA_SHIFT = 0.
|
|
109
|
-
const HISTORY_RESET_DISTANCE =
|
|
103
|
+
const SNAP_DISTANCE = 8; // pixels; keep corners locked when movement is tiny (increased for stronger lock)
|
|
104
|
+
const SNAP_CENTER_DISTANCE = 18;
|
|
105
|
+
const BLEND_DISTANCE = 80; // pixels; softly ease between similar shapes (increased)
|
|
106
|
+
const MAX_CENTER_DELTA = 120; // increased to allow more camera movement
|
|
107
|
+
const REJECT_CENTER_DELTA = 200; // increased to maintain lock during camera movement
|
|
108
|
+
const MAX_AREA_SHIFT = 0.55; // more tolerance for perspective changes
|
|
109
|
+
const HISTORY_RESET_DISTANCE = 90;
|
|
110
110
|
const MIN_AREA_RATIO = 0.0002;
|
|
111
111
|
const MAX_AREA_RATIO = 0.9;
|
|
112
112
|
const MIN_EDGE_RATIO = 0.015;
|
|
113
|
-
const MAX_ANCHOR_MISSES =
|
|
113
|
+
const MAX_ANCHOR_MISSES = 20; // increased to hold anchor longer when detection temporarily fails
|
|
114
114
|
const MIN_CONFIDENCE_TO_HOLD = 2;
|
|
115
|
-
const MAX_ANCHOR_CONFIDENCE =
|
|
115
|
+
const MAX_ANCHOR_CONFIDENCE = 30; // increased max confidence for stronger anchoring
|
|
116
116
|
const updateQuad = (0, react_native_worklets_core_1.useRunOnJS)((value) => {
|
|
117
117
|
if (__DEV__) {
|
|
118
118
|
console.log('[DocScanner] quad', value);
|
|
@@ -249,8 +249,8 @@ const DocScanner = ({ onCapture, overlayColor = '#e7a649', autoCapture = true, m
|
|
|
249
249
|
try {
|
|
250
250
|
// Report frame size for coordinate transformation
|
|
251
251
|
updateFrameSize(frame.width, frame.height);
|
|
252
|
-
// Use higher resolution for better accuracy -
|
|
253
|
-
const ratio =
|
|
252
|
+
// Use higher resolution for better accuracy - 1280p for improved corner detection
|
|
253
|
+
const ratio = 1280 / frame.width;
|
|
254
254
|
const width = Math.floor(frame.width * ratio);
|
|
255
255
|
const height = Math.floor(frame.height * ratio);
|
|
256
256
|
step = 'resize';
|
|
@@ -279,7 +279,9 @@ const DocScanner = ({ onCapture, overlayColor = '#e7a649', autoCapture = true, m
|
|
|
279
279
|
react_native_fast_opencv_1.OpenCV.invoke('GaussianBlur', mat, mat, gaussianKernel, 0);
|
|
280
280
|
step = 'Canny';
|
|
281
281
|
reportStage(step);
|
|
282
|
-
|
|
282
|
+
// Improved Canny parameters for better edge detection accuracy
|
|
283
|
+
// Lower threshold (50 -> more edges detected) and higher threshold (150 -> stronger edges kept)
|
|
284
|
+
react_native_fast_opencv_1.OpenCV.invoke('Canny', mat, mat, 50, 150);
|
|
283
285
|
step = 'createContours';
|
|
284
286
|
reportStage(step);
|
|
285
287
|
const contours = react_native_fast_opencv_1.OpenCV.createObject(react_native_fast_opencv_1.ObjectType.PointVectorOfVectors);
|
package/package.json
CHANGED
package/src/DocScanner.tsx
CHANGED
|
@@ -116,19 +116,19 @@ export const DocScanner: React.FC<Props> = ({
|
|
|
116
116
|
const frameSizeRef = useRef<{ width: number; height: number } | null>(null);
|
|
117
117
|
|
|
118
118
|
const MAX_HISTORY = 5;
|
|
119
|
-
const SNAP_DISTANCE =
|
|
120
|
-
const SNAP_CENTER_DISTANCE =
|
|
121
|
-
const BLEND_DISTANCE =
|
|
122
|
-
const MAX_CENTER_DELTA =
|
|
123
|
-
const REJECT_CENTER_DELTA =
|
|
124
|
-
const MAX_AREA_SHIFT = 0.
|
|
125
|
-
const HISTORY_RESET_DISTANCE =
|
|
119
|
+
const SNAP_DISTANCE = 8; // pixels; keep corners locked when movement is tiny (increased for stronger lock)
|
|
120
|
+
const SNAP_CENTER_DISTANCE = 18;
|
|
121
|
+
const BLEND_DISTANCE = 80; // pixels; softly ease between similar shapes (increased)
|
|
122
|
+
const MAX_CENTER_DELTA = 120; // increased to allow more camera movement
|
|
123
|
+
const REJECT_CENTER_DELTA = 200; // increased to maintain lock during camera movement
|
|
124
|
+
const MAX_AREA_SHIFT = 0.55; // more tolerance for perspective changes
|
|
125
|
+
const HISTORY_RESET_DISTANCE = 90;
|
|
126
126
|
const MIN_AREA_RATIO = 0.0002;
|
|
127
127
|
const MAX_AREA_RATIO = 0.9;
|
|
128
128
|
const MIN_EDGE_RATIO = 0.015;
|
|
129
|
-
const MAX_ANCHOR_MISSES =
|
|
129
|
+
const MAX_ANCHOR_MISSES = 20; // increased to hold anchor longer when detection temporarily fails
|
|
130
130
|
const MIN_CONFIDENCE_TO_HOLD = 2;
|
|
131
|
-
const MAX_ANCHOR_CONFIDENCE =
|
|
131
|
+
const MAX_ANCHOR_CONFIDENCE = 30; // increased max confidence for stronger anchoring
|
|
132
132
|
|
|
133
133
|
const updateQuad = useRunOnJS((value: Point[] | null) => {
|
|
134
134
|
if (__DEV__) {
|
|
@@ -290,8 +290,8 @@ export const DocScanner: React.FC<Props> = ({
|
|
|
290
290
|
// Report frame size for coordinate transformation
|
|
291
291
|
updateFrameSize(frame.width, frame.height);
|
|
292
292
|
|
|
293
|
-
// Use higher resolution for better accuracy -
|
|
294
|
-
const ratio =
|
|
293
|
+
// Use higher resolution for better accuracy - 1280p for improved corner detection
|
|
294
|
+
const ratio = 1280 / frame.width;
|
|
295
295
|
const width = Math.floor(frame.width * ratio);
|
|
296
296
|
const height = Math.floor(frame.height * ratio);
|
|
297
297
|
step = 'resize';
|
|
@@ -324,7 +324,9 @@ export const DocScanner: React.FC<Props> = ({
|
|
|
324
324
|
OpenCV.invoke('GaussianBlur', mat, mat, gaussianKernel, 0);
|
|
325
325
|
step = 'Canny';
|
|
326
326
|
reportStage(step);
|
|
327
|
-
|
|
327
|
+
// Improved Canny parameters for better edge detection accuracy
|
|
328
|
+
// Lower threshold (50 -> more edges detected) and higher threshold (150 -> stronger edges kept)
|
|
329
|
+
OpenCV.invoke('Canny', mat, mat, 50, 150);
|
|
328
330
|
|
|
329
331
|
step = 'createContours';
|
|
330
332
|
reportStage(step);
|