react-native-rectangle-doc-scanner 0.27.0 → 0.29.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/dist/DocScanner.js +32 -20
- package/package.json +1 -1
- package/src/DocScanner.tsx +34 -23
package/dist/DocScanner.js
CHANGED
|
@@ -150,30 +150,17 @@ const DocScanner = ({ onCapture, overlayColor = '#e7a649', autoCapture = true, m
|
|
|
150
150
|
step = 'cvtColor';
|
|
151
151
|
reportStage(step);
|
|
152
152
|
react_native_fast_opencv_1.OpenCV.invoke('cvtColor', mat, mat, react_native_fast_opencv_1.ColorConversionCodes.COLOR_BGR2GRAY);
|
|
153
|
-
|
|
154
|
-
step = 'bilateralFilter';
|
|
155
|
-
reportStage(step);
|
|
156
|
-
const filtered = react_native_fast_opencv_1.OpenCV.createObject(react_native_fast_opencv_1.ObjectType.Mat);
|
|
157
|
-
react_native_fast_opencv_1.OpenCV.invoke('bilateralFilter', mat, filtered, 9, 75, 75);
|
|
158
|
-
// Use adaptive threshold for better contrast in varying lighting
|
|
159
|
-
step = 'adaptiveThreshold';
|
|
160
|
-
reportStage(step);
|
|
161
|
-
const thresh = react_native_fast_opencv_1.OpenCV.createObject(react_native_fast_opencv_1.ObjectType.Mat);
|
|
162
|
-
react_native_fast_opencv_1.OpenCV.invoke('adaptiveThreshold', filtered, thresh, 255, 1, 1, 11, 2);
|
|
163
|
-
// Morphological operations to clean up noise
|
|
164
|
-
const morphologyKernel = react_native_fast_opencv_1.OpenCV.createObject(react_native_fast_opencv_1.ObjectType.Size, 3, 3);
|
|
153
|
+
const morphologyKernel = react_native_fast_opencv_1.OpenCV.createObject(react_native_fast_opencv_1.ObjectType.Size, 5, 5);
|
|
165
154
|
step = 'getStructuringElement';
|
|
166
155
|
reportStage(step);
|
|
167
156
|
const element = react_native_fast_opencv_1.OpenCV.invoke('getStructuringElement', react_native_fast_opencv_1.MorphShapes.MORPH_RECT, morphologyKernel);
|
|
168
157
|
step = 'morphologyEx';
|
|
169
158
|
reportStage(step);
|
|
170
|
-
react_native_fast_opencv_1.OpenCV.invoke('morphologyEx',
|
|
171
|
-
// Apply Gaussian blur before Canny for smoother edges
|
|
159
|
+
react_native_fast_opencv_1.OpenCV.invoke('morphologyEx', mat, mat, react_native_fast_opencv_1.MorphTypes.MORPH_OPEN, element);
|
|
172
160
|
const gaussianKernel = react_native_fast_opencv_1.OpenCV.createObject(react_native_fast_opencv_1.ObjectType.Size, 5, 5);
|
|
173
161
|
step = 'GaussianBlur';
|
|
174
162
|
reportStage(step);
|
|
175
163
|
react_native_fast_opencv_1.OpenCV.invoke('GaussianBlur', mat, mat, gaussianKernel, 0);
|
|
176
|
-
// Use higher Canny thresholds for cleaner edges
|
|
177
164
|
step = 'Canny';
|
|
178
165
|
reportStage(step);
|
|
179
166
|
react_native_fast_opencv_1.OpenCV.invoke('Canny', mat, mat, 50, 150);
|
|
@@ -199,9 +186,9 @@ const DocScanner = ({ onCapture, overlayColor = '#e7a649', autoCapture = true, m
|
|
|
199
186
|
if (__DEV__) {
|
|
200
187
|
console.log('[DocScanner] area ratio', areaRatio);
|
|
201
188
|
}
|
|
202
|
-
// Filter by area: document should be at least
|
|
189
|
+
// Filter by area: document should be at least 0.1% and at most 98% of frame
|
|
203
190
|
// This prevents detecting tiny noise or the entire frame
|
|
204
|
-
if (areaRatio < 0.
|
|
191
|
+
if (areaRatio < 0.001 || areaRatio > 0.98) {
|
|
205
192
|
continue;
|
|
206
193
|
}
|
|
207
194
|
step = `contour_${i}_arcLength`;
|
|
@@ -210,8 +197,8 @@ const DocScanner = ({ onCapture, overlayColor = '#e7a649', autoCapture = true, m
|
|
|
210
197
|
const approx = react_native_fast_opencv_1.OpenCV.createObject(react_native_fast_opencv_1.ObjectType.PointVector);
|
|
211
198
|
let approxArray = [];
|
|
212
199
|
// Start with smaller epsilon for more accurate corner detection
|
|
213
|
-
// Try epsilon values from 0.
|
|
214
|
-
const epsilonValues = [0.
|
|
200
|
+
// Try epsilon values from 0.4% up to 6% of perimeter
|
|
201
|
+
const epsilonValues = [0.004, 0.006, 0.008, 0.01, 0.012, 0.015, 0.02, 0.03, 0.04, 0.05, 0.06];
|
|
215
202
|
for (let attempt = 0; attempt < epsilonValues.length; attempt += 1) {
|
|
216
203
|
const epsilon = epsilonValues[attempt] * perimeter;
|
|
217
204
|
step = `contour_${i}_approxPolyDP_attempt_${attempt}`;
|
|
@@ -229,7 +216,32 @@ const DocScanner = ({ onCapture, overlayColor = '#e7a649', autoCapture = true, m
|
|
|
229
216
|
break;
|
|
230
217
|
}
|
|
231
218
|
}
|
|
232
|
-
|
|
219
|
+
if (approxArray.length !== 4) {
|
|
220
|
+
// fallback: boundingRect (axis-aligned) so we always have 4 points
|
|
221
|
+
try {
|
|
222
|
+
const rect = react_native_fast_opencv_1.OpenCV.invoke('boundingRect', contour);
|
|
223
|
+
const rectValue = rect?.value ?? rect;
|
|
224
|
+
const rectX = rectValue.x ?? rectValue?.topLeft?.x ?? 0;
|
|
225
|
+
const rectY = rectValue.y ?? rectValue?.topLeft?.y ?? 0;
|
|
226
|
+
const rectW = rectValue.width ?? rectValue?.size?.width ?? 0;
|
|
227
|
+
const rectH = rectValue.height ?? rectValue?.size?.height ?? 0;
|
|
228
|
+
approxArray = [
|
|
229
|
+
{ x: rectX, y: rectY },
|
|
230
|
+
{ x: rectX + rectW, y: rectY },
|
|
231
|
+
{ x: rectX + rectW, y: rectY + rectH },
|
|
232
|
+
{ x: rectX, y: rectY + rectH },
|
|
233
|
+
];
|
|
234
|
+
if (__DEV__) {
|
|
235
|
+
console.log('[DocScanner] boundingRect fallback', approxArray);
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
catch (err) {
|
|
239
|
+
if (__DEV__) {
|
|
240
|
+
console.warn('[DocScanner] boundingRect fallback failed', err);
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
// Only proceed if we found exactly 4 corners after fallback
|
|
233
245
|
if (approxArray.length !== 4) {
|
|
234
246
|
continue;
|
|
235
247
|
}
|
package/package.json
CHANGED
package/src/DocScanner.tsx
CHANGED
|
@@ -167,34 +167,18 @@ export const DocScanner: React.FC<Props> = ({
|
|
|
167
167
|
reportStage(step);
|
|
168
168
|
OpenCV.invoke('cvtColor', mat, mat, ColorConversionCodes.COLOR_BGR2GRAY);
|
|
169
169
|
|
|
170
|
-
|
|
171
|
-
step = 'bilateralFilter';
|
|
172
|
-
reportStage(step);
|
|
173
|
-
const filtered = OpenCV.createObject(ObjectType.Mat);
|
|
174
|
-
OpenCV.invoke('bilateralFilter', mat, filtered, 9, 75, 75);
|
|
175
|
-
|
|
176
|
-
// Use adaptive threshold for better contrast in varying lighting
|
|
177
|
-
step = 'adaptiveThreshold';
|
|
178
|
-
reportStage(step);
|
|
179
|
-
const thresh = OpenCV.createObject(ObjectType.Mat);
|
|
180
|
-
OpenCV.invoke('adaptiveThreshold', filtered, thresh, 255, 1, 1, 11, 2);
|
|
181
|
-
|
|
182
|
-
// Morphological operations to clean up noise
|
|
183
|
-
const morphologyKernel = OpenCV.createObject(ObjectType.Size, 3, 3);
|
|
170
|
+
const morphologyKernel = OpenCV.createObject(ObjectType.Size, 5, 5);
|
|
184
171
|
step = 'getStructuringElement';
|
|
185
172
|
reportStage(step);
|
|
186
173
|
const element = OpenCV.invoke('getStructuringElement', MorphShapes.MORPH_RECT, morphologyKernel);
|
|
187
174
|
step = 'morphologyEx';
|
|
188
175
|
reportStage(step);
|
|
189
|
-
OpenCV.invoke('morphologyEx',
|
|
176
|
+
OpenCV.invoke('morphologyEx', mat, mat, MorphTypes.MORPH_OPEN, element);
|
|
190
177
|
|
|
191
|
-
// Apply Gaussian blur before Canny for smoother edges
|
|
192
178
|
const gaussianKernel = OpenCV.createObject(ObjectType.Size, 5, 5);
|
|
193
179
|
step = 'GaussianBlur';
|
|
194
180
|
reportStage(step);
|
|
195
181
|
OpenCV.invoke('GaussianBlur', mat, mat, gaussianKernel, 0);
|
|
196
|
-
|
|
197
|
-
// Use higher Canny thresholds for cleaner edges
|
|
198
182
|
step = 'Canny';
|
|
199
183
|
reportStage(step);
|
|
200
184
|
OpenCV.invoke('Canny', mat, mat, 50, 150);
|
|
@@ -227,9 +211,9 @@ export const DocScanner: React.FC<Props> = ({
|
|
|
227
211
|
console.log('[DocScanner] area ratio', areaRatio);
|
|
228
212
|
}
|
|
229
213
|
|
|
230
|
-
// Filter by area: document should be at least
|
|
214
|
+
// Filter by area: document should be at least 0.1% and at most 98% of frame
|
|
231
215
|
// This prevents detecting tiny noise or the entire frame
|
|
232
|
-
if (areaRatio < 0.
|
|
216
|
+
if (areaRatio < 0.001 || areaRatio > 0.98) {
|
|
233
217
|
continue;
|
|
234
218
|
}
|
|
235
219
|
|
|
@@ -241,8 +225,8 @@ export const DocScanner: React.FC<Props> = ({
|
|
|
241
225
|
let approxArray: Array<{ x: number; y: number }> = [];
|
|
242
226
|
|
|
243
227
|
// Start with smaller epsilon for more accurate corner detection
|
|
244
|
-
// Try epsilon values from 0.
|
|
245
|
-
const epsilonValues = [0.
|
|
228
|
+
// Try epsilon values from 0.4% up to 6% of perimeter
|
|
229
|
+
const epsilonValues = [0.004, 0.006, 0.008, 0.01, 0.012, 0.015, 0.02, 0.03, 0.04, 0.05, 0.06];
|
|
246
230
|
|
|
247
231
|
for (let attempt = 0; attempt < epsilonValues.length; attempt += 1) {
|
|
248
232
|
const epsilon = epsilonValues[attempt] * perimeter;
|
|
@@ -265,7 +249,34 @@ export const DocScanner: React.FC<Props> = ({
|
|
|
265
249
|
}
|
|
266
250
|
}
|
|
267
251
|
|
|
268
|
-
|
|
252
|
+
if (approxArray.length !== 4) {
|
|
253
|
+
// fallback: boundingRect (axis-aligned) so we always have 4 points
|
|
254
|
+
try {
|
|
255
|
+
const rect = OpenCV.invoke('boundingRect', contour);
|
|
256
|
+
const rectValue = rect?.value ?? rect;
|
|
257
|
+
const rectX = rectValue.x ?? rectValue?.topLeft?.x ?? 0;
|
|
258
|
+
const rectY = rectValue.y ?? rectValue?.topLeft?.y ?? 0;
|
|
259
|
+
const rectW = rectValue.width ?? rectValue?.size?.width ?? 0;
|
|
260
|
+
const rectH = rectValue.height ?? rectValue?.size?.height ?? 0;
|
|
261
|
+
|
|
262
|
+
approxArray = [
|
|
263
|
+
{ x: rectX, y: rectY },
|
|
264
|
+
{ x: rectX + rectW, y: rectY },
|
|
265
|
+
{ x: rectX + rectW, y: rectY + rectH },
|
|
266
|
+
{ x: rectX, y: rectY + rectH },
|
|
267
|
+
];
|
|
268
|
+
|
|
269
|
+
if (__DEV__) {
|
|
270
|
+
console.log('[DocScanner] boundingRect fallback', approxArray);
|
|
271
|
+
}
|
|
272
|
+
} catch (err) {
|
|
273
|
+
if (__DEV__) {
|
|
274
|
+
console.warn('[DocScanner] boundingRect fallback failed', err);
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
// Only proceed if we found exactly 4 corners after fallback
|
|
269
280
|
if (approxArray.length !== 4) {
|
|
270
281
|
continue;
|
|
271
282
|
}
|