react-native-rectangle-doc-scanner 0.28.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 +36 -20
- package/package.json +1 -1
- package/src/DocScanner.tsx +38 -22
package/dist/DocScanner.js
CHANGED
|
@@ -150,29 +150,20 @@ 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
|
-
const gaussianKernel = react_native_fast_opencv_1.OpenCV.createObject(react_native_fast_opencv_1.ObjectType.Size, 5, 5);
|
|
155
|
-
step = 'GaussianBlur';
|
|
156
|
-
reportStage(step);
|
|
157
|
-
react_native_fast_opencv_1.OpenCV.invoke('GaussianBlur', mat, mat, gaussianKernel, 0);
|
|
158
|
-
// Morphological operations to enhance edges
|
|
159
|
-
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);
|
|
160
154
|
step = 'getStructuringElement';
|
|
161
155
|
reportStage(step);
|
|
162
156
|
const element = react_native_fast_opencv_1.OpenCV.invoke('getStructuringElement', react_native_fast_opencv_1.MorphShapes.MORPH_RECT, morphologyKernel);
|
|
163
157
|
step = 'morphologyEx';
|
|
164
158
|
reportStage(step);
|
|
165
|
-
react_native_fast_opencv_1.OpenCV.invoke('morphologyEx', mat, mat, react_native_fast_opencv_1.MorphTypes.
|
|
166
|
-
|
|
159
|
+
react_native_fast_opencv_1.OpenCV.invoke('morphologyEx', mat, mat, react_native_fast_opencv_1.MorphTypes.MORPH_OPEN, element);
|
|
160
|
+
const gaussianKernel = react_native_fast_opencv_1.OpenCV.createObject(react_native_fast_opencv_1.ObjectType.Size, 5, 5);
|
|
161
|
+
step = 'GaussianBlur';
|
|
162
|
+
reportStage(step);
|
|
163
|
+
react_native_fast_opencv_1.OpenCV.invoke('GaussianBlur', mat, mat, gaussianKernel, 0);
|
|
167
164
|
step = 'Canny';
|
|
168
165
|
reportStage(step);
|
|
169
166
|
react_native_fast_opencv_1.OpenCV.invoke('Canny', mat, mat, 50, 150);
|
|
170
|
-
// Dilate edges slightly to connect nearby contours
|
|
171
|
-
step = 'dilate';
|
|
172
|
-
reportStage(step);
|
|
173
|
-
const dilateKernel = react_native_fast_opencv_1.OpenCV.createObject(react_native_fast_opencv_1.ObjectType.Size, 2, 2);
|
|
174
|
-
const dilateElement = react_native_fast_opencv_1.OpenCV.invoke('getStructuringElement', react_native_fast_opencv_1.MorphShapes.MORPH_RECT, dilateKernel);
|
|
175
|
-
react_native_fast_opencv_1.OpenCV.invoke('dilate', mat, mat, dilateElement);
|
|
176
167
|
step = 'createContours';
|
|
177
168
|
reportStage(step);
|
|
178
169
|
const contours = react_native_fast_opencv_1.OpenCV.createObject(react_native_fast_opencv_1.ObjectType.PointVectorOfVectors);
|
|
@@ -195,9 +186,9 @@ const DocScanner = ({ onCapture, overlayColor = '#e7a649', autoCapture = true, m
|
|
|
195
186
|
if (__DEV__) {
|
|
196
187
|
console.log('[DocScanner] area ratio', areaRatio);
|
|
197
188
|
}
|
|
198
|
-
// 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
|
|
199
190
|
// This prevents detecting tiny noise or the entire frame
|
|
200
|
-
if (areaRatio < 0.
|
|
191
|
+
if (areaRatio < 0.001 || areaRatio > 0.98) {
|
|
201
192
|
continue;
|
|
202
193
|
}
|
|
203
194
|
step = `contour_${i}_arcLength`;
|
|
@@ -206,8 +197,8 @@ const DocScanner = ({ onCapture, overlayColor = '#e7a649', autoCapture = true, m
|
|
|
206
197
|
const approx = react_native_fast_opencv_1.OpenCV.createObject(react_native_fast_opencv_1.ObjectType.PointVector);
|
|
207
198
|
let approxArray = [];
|
|
208
199
|
// Start with smaller epsilon for more accurate corner detection
|
|
209
|
-
// Try epsilon values from 0.
|
|
210
|
-
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];
|
|
211
202
|
for (let attempt = 0; attempt < epsilonValues.length; attempt += 1) {
|
|
212
203
|
const epsilon = epsilonValues[attempt] * perimeter;
|
|
213
204
|
step = `contour_${i}_approxPolyDP_attempt_${attempt}`;
|
|
@@ -225,7 +216,32 @@ const DocScanner = ({ onCapture, overlayColor = '#e7a649', autoCapture = true, m
|
|
|
225
216
|
break;
|
|
226
217
|
}
|
|
227
218
|
}
|
|
228
|
-
|
|
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
|
|
229
245
|
if (approxArray.length !== 4) {
|
|
230
246
|
continue;
|
|
231
247
|
}
|
package/package.json
CHANGED
package/src/DocScanner.tsx
CHANGED
|
@@ -167,33 +167,22 @@ export const DocScanner: React.FC<Props> = ({
|
|
|
167
167
|
reportStage(step);
|
|
168
168
|
OpenCV.invoke('cvtColor', mat, mat, ColorConversionCodes.COLOR_BGR2GRAY);
|
|
169
169
|
|
|
170
|
-
|
|
171
|
-
const gaussianKernel = OpenCV.createObject(ObjectType.Size, 5, 5);
|
|
172
|
-
step = 'GaussianBlur';
|
|
173
|
-
reportStage(step);
|
|
174
|
-
OpenCV.invoke('GaussianBlur', mat, mat, gaussianKernel, 0);
|
|
175
|
-
|
|
176
|
-
// Morphological operations to enhance edges
|
|
177
|
-
const morphologyKernel = OpenCV.createObject(ObjectType.Size, 3, 3);
|
|
170
|
+
const morphologyKernel = OpenCV.createObject(ObjectType.Size, 5, 5);
|
|
178
171
|
step = 'getStructuringElement';
|
|
179
172
|
reportStage(step);
|
|
180
173
|
const element = OpenCV.invoke('getStructuringElement', MorphShapes.MORPH_RECT, morphologyKernel);
|
|
181
174
|
step = 'morphologyEx';
|
|
182
175
|
reportStage(step);
|
|
183
|
-
OpenCV.invoke('morphologyEx', mat, mat, MorphTypes.
|
|
176
|
+
OpenCV.invoke('morphologyEx', mat, mat, MorphTypes.MORPH_OPEN, element);
|
|
184
177
|
|
|
185
|
-
|
|
178
|
+
const gaussianKernel = OpenCV.createObject(ObjectType.Size, 5, 5);
|
|
179
|
+
step = 'GaussianBlur';
|
|
180
|
+
reportStage(step);
|
|
181
|
+
OpenCV.invoke('GaussianBlur', mat, mat, gaussianKernel, 0);
|
|
186
182
|
step = 'Canny';
|
|
187
183
|
reportStage(step);
|
|
188
184
|
OpenCV.invoke('Canny', mat, mat, 50, 150);
|
|
189
185
|
|
|
190
|
-
// Dilate edges slightly to connect nearby contours
|
|
191
|
-
step = 'dilate';
|
|
192
|
-
reportStage(step);
|
|
193
|
-
const dilateKernel = OpenCV.createObject(ObjectType.Size, 2, 2);
|
|
194
|
-
const dilateElement = OpenCV.invoke('getStructuringElement', MorphShapes.MORPH_RECT, dilateKernel);
|
|
195
|
-
OpenCV.invoke('dilate', mat, mat, dilateElement);
|
|
196
|
-
|
|
197
186
|
step = 'createContours';
|
|
198
187
|
reportStage(step);
|
|
199
188
|
const contours = OpenCV.createObject(ObjectType.PointVectorOfVectors);
|
|
@@ -222,9 +211,9 @@ export const DocScanner: React.FC<Props> = ({
|
|
|
222
211
|
console.log('[DocScanner] area ratio', areaRatio);
|
|
223
212
|
}
|
|
224
213
|
|
|
225
|
-
// 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
|
|
226
215
|
// This prevents detecting tiny noise or the entire frame
|
|
227
|
-
if (areaRatio < 0.
|
|
216
|
+
if (areaRatio < 0.001 || areaRatio > 0.98) {
|
|
228
217
|
continue;
|
|
229
218
|
}
|
|
230
219
|
|
|
@@ -236,8 +225,8 @@ export const DocScanner: React.FC<Props> = ({
|
|
|
236
225
|
let approxArray: Array<{ x: number; y: number }> = [];
|
|
237
226
|
|
|
238
227
|
// Start with smaller epsilon for more accurate corner detection
|
|
239
|
-
// Try epsilon values from 0.
|
|
240
|
-
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];
|
|
241
230
|
|
|
242
231
|
for (let attempt = 0; attempt < epsilonValues.length; attempt += 1) {
|
|
243
232
|
const epsilon = epsilonValues[attempt] * perimeter;
|
|
@@ -260,7 +249,34 @@ export const DocScanner: React.FC<Props> = ({
|
|
|
260
249
|
}
|
|
261
250
|
}
|
|
262
251
|
|
|
263
|
-
|
|
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
|
|
264
280
|
if (approxArray.length !== 4) {
|
|
265
281
|
continue;
|
|
266
282
|
}
|