react-native-rectangle-doc-scanner 0.32.0 → 0.34.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.
@@ -184,7 +184,10 @@ const DocScanner = ({ onCapture, overlayColor = '#e7a649', autoCapture = true, m
184
184
  reportStage(step);
185
185
  const { value: area } = react_native_fast_opencv_1.OpenCV.invoke('contourArea', contour, false);
186
186
  // Skip extremely small contours, but keep threshold very low to allow distant documents
187
- if (area < 200) {
187
+ if (typeof area !== 'number' || !isFinite(area)) {
188
+ continue;
189
+ }
190
+ if (area < 50) {
188
191
  continue;
189
192
  }
190
193
  step = `contour_${i}_area`; // ratio stage
@@ -193,25 +196,23 @@ const DocScanner = ({ onCapture, overlayColor = '#e7a649', autoCapture = true, m
193
196
  if (__DEV__) {
194
197
  console.log('[DocScanner] area', area, 'ratio', areaRatio);
195
198
  }
196
- if (areaRatio < 0.00002 || areaRatio > 0.99) {
199
+ // Skip if area ratio is too small or too large
200
+ if (areaRatio < 0.01 || areaRatio > 0.95) {
197
201
  continue;
198
202
  }
199
- // Use convex hull to simplify contour before polygon approximation
200
- const hull = react_native_fast_opencv_1.OpenCV.createObject(react_native_fast_opencv_1.ObjectType.PointVector);
201
- react_native_fast_opencv_1.OpenCV.invoke('convexHull', contour, hull);
202
203
  step = `contour_${i}_arcLength`;
203
204
  reportStage(step);
204
- const { value: perimeter } = react_native_fast_opencv_1.OpenCV.invoke('arcLength', hull, true);
205
+ const { value: perimeter } = react_native_fast_opencv_1.OpenCV.invoke('arcLength', contour, true);
205
206
  const approx = react_native_fast_opencv_1.OpenCV.createObject(react_native_fast_opencv_1.ObjectType.PointVector);
206
207
  let approxArray = [];
207
208
  // Start with smaller epsilon for more accurate corner detection
208
- // Try epsilon values from 0.4% up to 6% of perimeter
209
- const epsilonValues = [0.004, 0.006, 0.008, 0.01, 0.012, 0.015, 0.02, 0.03, 0.04, 0.05, 0.06];
209
+ // Try epsilon values from 0.5% to 5% of perimeter
210
+ const epsilonValues = [0.005, 0.01, 0.015, 0.02, 0.025, 0.03, 0.035, 0.04, 0.045, 0.05];
210
211
  for (let attempt = 0; attempt < epsilonValues.length; attempt += 1) {
211
212
  const epsilon = epsilonValues[attempt] * perimeter;
212
213
  step = `contour_${i}_approxPolyDP_attempt_${attempt}`;
213
214
  reportStage(step);
214
- react_native_fast_opencv_1.OpenCV.invoke('approxPolyDP', hull, approx, epsilon, true);
215
+ react_native_fast_opencv_1.OpenCV.invoke('approxPolyDP', contour, approx, epsilon, true);
215
216
  step = `contour_${i}_toJS_attempt_${attempt}`;
216
217
  reportStage(step);
217
218
  const approxValue = react_native_fast_opencv_1.OpenCV.toJSValue(approx);
@@ -224,40 +225,7 @@ const DocScanner = ({ onCapture, overlayColor = '#e7a649', autoCapture = true, m
224
225
  break;
225
226
  }
226
227
  }
227
- if (approxArray.length !== 4) {
228
- // fallback: rotated rectangle using minAreaRect
229
- try {
230
- const rect = react_native_fast_opencv_1.OpenCV.invoke('minAreaRect', contour);
231
- const rectValue = rect?.value ?? rect;
232
- const centerX = rectValue.centerX ?? rectValue.center?.x ?? 0;
233
- const centerY = rectValue.centerY ?? rectValue.center?.y ?? 0;
234
- const rectW = rectValue.width ?? rectValue.size?.width ?? 0;
235
- const rectH = rectValue.height ?? rectValue.size?.height ?? 0;
236
- const angleDeg = rectValue.angle ?? rectValue.rotation ?? 0;
237
- if (rectW > 0 && rectH > 0) {
238
- const angleRad = (angleDeg * Math.PI) / 180;
239
- const cosA = Math.cos(angleRad);
240
- const sinA = Math.sin(angleRad);
241
- const halfW = rectW / 2;
242
- const halfH = rectH / 2;
243
- approxArray = [
244
- { x: centerX - halfW * cosA + halfH * sinA, y: centerY - halfW * sinA - halfH * cosA },
245
- { x: centerX + halfW * cosA + halfH * sinA, y: centerY + halfW * sinA - halfH * cosA },
246
- { x: centerX + halfW * cosA - halfH * sinA, y: centerY + halfW * sinA + halfH * cosA },
247
- { x: centerX - halfW * cosA - halfH * sinA, y: centerY - halfW * sinA + halfH * cosA },
248
- ];
249
- if (__DEV__) {
250
- console.log('[DocScanner] minAreaRect fallback', rectValue, approxArray);
251
- }
252
- }
253
- }
254
- catch (err) {
255
- if (__DEV__) {
256
- console.warn('[DocScanner] minAreaRect fallback failed', err);
257
- }
258
- }
259
- }
260
- // Only proceed if we found exactly 4 corners after fallback
228
+ // Only proceed if we found exactly 4 corners
261
229
  if (approxArray.length !== 4) {
262
230
  continue;
263
231
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-native-rectangle-doc-scanner",
3
- "version": "0.32.0",
3
+ "version": "0.34.0",
4
4
  "main": "dist/index.js",
5
5
  "types": "dist/index.d.ts",
6
6
  "repository": {
@@ -208,7 +208,11 @@ export const DocScanner: React.FC<Props> = ({
208
208
  const { value: area } = OpenCV.invoke('contourArea', contour, false);
209
209
 
210
210
  // Skip extremely small contours, but keep threshold very low to allow distant documents
211
- if (area < 200) {
211
+ if (typeof area !== 'number' || !isFinite(area)) {
212
+ continue;
213
+ }
214
+
215
+ if (area < 50) {
212
216
  continue;
213
217
  }
214
218
 
@@ -220,30 +224,27 @@ export const DocScanner: React.FC<Props> = ({
220
224
  console.log('[DocScanner] area', area, 'ratio', areaRatio);
221
225
  }
222
226
 
223
- if (areaRatio < 0.00002 || areaRatio > 0.99) {
227
+ // Skip if area ratio is too small or too large
228
+ if (areaRatio < 0.01 || areaRatio > 0.95) {
224
229
  continue;
225
230
  }
226
231
 
227
- // Use convex hull to simplify contour before polygon approximation
228
- const hull = OpenCV.createObject(ObjectType.PointVector);
229
- OpenCV.invoke('convexHull', contour, hull);
230
-
231
232
  step = `contour_${i}_arcLength`;
232
233
  reportStage(step);
233
- const { value: perimeter } = OpenCV.invoke('arcLength', hull, true);
234
+ const { value: perimeter } = OpenCV.invoke('arcLength', contour, true);
234
235
  const approx = OpenCV.createObject(ObjectType.PointVector);
235
236
 
236
237
  let approxArray: Array<{ x: number; y: number }> = [];
237
238
 
238
239
  // Start with smaller epsilon for more accurate corner detection
239
- // Try epsilon values from 0.4% up to 6% of perimeter
240
- const epsilonValues = [0.004, 0.006, 0.008, 0.01, 0.012, 0.015, 0.02, 0.03, 0.04, 0.05, 0.06];
240
+ // Try epsilon values from 0.5% to 5% of perimeter
241
+ const epsilonValues = [0.005, 0.01, 0.015, 0.02, 0.025, 0.03, 0.035, 0.04, 0.045, 0.05];
241
242
 
242
243
  for (let attempt = 0; attempt < epsilonValues.length; attempt += 1) {
243
244
  const epsilon = epsilonValues[attempt] * perimeter;
244
245
  step = `contour_${i}_approxPolyDP_attempt_${attempt}`;
245
246
  reportStage(step);
246
- OpenCV.invoke('approxPolyDP', hull, approx, epsilon, true);
247
+ OpenCV.invoke('approxPolyDP', contour, approx, epsilon, true);
247
248
 
248
249
  step = `contour_${i}_toJS_attempt_${attempt}`;
249
250
  reportStage(step);
@@ -260,44 +261,7 @@ export const DocScanner: React.FC<Props> = ({
260
261
  }
261
262
  }
262
263
 
263
- if (approxArray.length !== 4) {
264
- // fallback: rotated rectangle using minAreaRect
265
- try {
266
- const rect = OpenCV.invoke('minAreaRect', contour);
267
- const rectValue = rect?.value ?? rect;
268
-
269
- const centerX = rectValue.centerX ?? rectValue.center?.x ?? 0;
270
- const centerY = rectValue.centerY ?? rectValue.center?.y ?? 0;
271
- const rectW = rectValue.width ?? rectValue.size?.width ?? 0;
272
- const rectH = rectValue.height ?? rectValue.size?.height ?? 0;
273
- const angleDeg = rectValue.angle ?? rectValue.rotation ?? 0;
274
-
275
- if (rectW > 0 && rectH > 0) {
276
- const angleRad = (angleDeg * Math.PI) / 180;
277
- const cosA = Math.cos(angleRad);
278
- const sinA = Math.sin(angleRad);
279
- const halfW = rectW / 2;
280
- const halfH = rectH / 2;
281
-
282
- approxArray = [
283
- { x: centerX - halfW * cosA + halfH * sinA, y: centerY - halfW * sinA - halfH * cosA },
284
- { x: centerX + halfW * cosA + halfH * sinA, y: centerY + halfW * sinA - halfH * cosA },
285
- { x: centerX + halfW * cosA - halfH * sinA, y: centerY + halfW * sinA + halfH * cosA },
286
- { x: centerX - halfW * cosA - halfH * sinA, y: centerY - halfW * sinA + halfH * cosA },
287
- ];
288
-
289
- if (__DEV__) {
290
- console.log('[DocScanner] minAreaRect fallback', rectValue, approxArray);
291
- }
292
- }
293
- } catch (err) {
294
- if (__DEV__) {
295
- console.warn('[DocScanner] minAreaRect fallback failed', err);
296
- }
297
- }
298
- }
299
-
300
- // Only proceed if we found exactly 4 corners after fallback
264
+ // Only proceed if we found exactly 4 corners
301
265
  if (approxArray.length !== 4) {
302
266
  continue;
303
267
  }