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.
@@ -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
- // Apply bilateral filter for better edge preservation
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', thresh, mat, react_native_fast_opencv_1.MorphTypes.MORPH_CLOSE, element);
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 5% and at most 95% of frame
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.05 || areaRatio > 0.95) {
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.5% to 5% of perimeter
214
- 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];
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
- // 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
233
245
  if (approxArray.length !== 4) {
234
246
  continue;
235
247
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-native-rectangle-doc-scanner",
3
- "version": "0.27.0",
3
+ "version": "0.29.0",
4
4
  "main": "dist/index.js",
5
5
  "types": "dist/index.d.ts",
6
6
  "repository": {
@@ -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
- // Apply bilateral filter for better edge preservation
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', thresh, mat, MorphTypes.MORPH_CLOSE, element);
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 5% and at most 95% of frame
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.05 || areaRatio > 0.95) {
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.5% to 5% of perimeter
245
- 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];
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
- // 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
269
280
  if (approxArray.length !== 4) {
270
281
  continue;
271
282
  }