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.
@@ -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
- // Apply Gaussian blur to reduce noise
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.MORPH_CLOSE, element);
166
- // Canny edge detection with optimized thresholds
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 5% and at most 95% of frame
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.05 || areaRatio > 0.95) {
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.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];
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
- // Only proceed if we found exactly 4 corners
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-native-rectangle-doc-scanner",
3
- "version": "0.28.0",
3
+ "version": "0.29.0",
4
4
  "main": "dist/index.js",
5
5
  "types": "dist/index.d.ts",
6
6
  "repository": {
@@ -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
- // Apply Gaussian blur to reduce noise
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.MORPH_CLOSE, element);
176
+ OpenCV.invoke('morphologyEx', mat, mat, MorphTypes.MORPH_OPEN, element);
184
177
 
185
- // Canny edge detection with optimized thresholds
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 5% and at most 95% of frame
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.05 || areaRatio > 0.95) {
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.5% to 5% of perimeter
240
- const epsilonValues = [0.005, 0.01, 0.015, 0.02, 0.025, 0.03, 0.035, 0.04, 0.045, 0.05];
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
- // Only proceed if we found exactly 4 corners
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
  }