react-native-rectangle-doc-scanner 3.231.0 → 3.233.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.
@@ -104,6 +104,7 @@ class DocumentDetector {
104
104
  val grayMat = Mat()
105
105
  val blurredMat = Mat()
106
106
  val cannyMat = Mat()
107
+ val morphMat = Mat()
107
108
 
108
109
  try {
109
110
  // Convert to grayscale
@@ -113,17 +114,20 @@ class DocumentDetector {
113
114
  srcMat.copyTo(grayMat)
114
115
  }
115
116
 
116
- // Apply Gaussian blur to reduce noise
117
- Imgproc.GaussianBlur(grayMat, blurredMat, Size(5.0, 5.0), 0.0)
117
+ // Apply a light blur to reduce noise without killing small edges.
118
+ Imgproc.GaussianBlur(grayMat, blurredMat, Size(3.0, 3.0), 0.0)
118
119
 
119
- // Apply Canny edge detection
120
- Imgproc.Canny(blurredMat, cannyMat, 75.0, 200.0)
120
+ // Apply Canny edge detection with slightly lower thresholds for small documents.
121
+ Imgproc.Canny(blurredMat, cannyMat, 50.0, 150.0)
122
+ val kernel = Imgproc.getStructuringElement(Imgproc.MORPH_RECT, Size(3.0, 3.0))
123
+ Imgproc.morphologyEx(cannyMat, morphMat, Imgproc.MORPH_CLOSE, kernel)
124
+ kernel.release()
121
125
 
122
126
  // Find contours
123
127
  val contours = mutableListOf<MatOfPoint>()
124
128
  val hierarchy = Mat()
125
129
  Imgproc.findContours(
126
- cannyMat,
130
+ morphMat,
127
131
  contours,
128
132
  hierarchy,
129
133
  Imgproc.RETR_EXTERNAL,
@@ -133,12 +137,13 @@ class DocumentDetector {
133
137
  // Find the largest contour that approximates to a quadrilateral
134
138
  var largestRectangle: Rectangle? = null
135
139
  var largestArea = 0.0
140
+ val minArea = max(1000.0, (srcMat.rows() * srcMat.cols()) * 0.002)
136
141
 
137
142
  for (contour in contours) {
138
143
  val contourArea = Imgproc.contourArea(contour)
139
144
 
140
145
  // Filter small contours
141
- if (contourArea < 1000) continue
146
+ if (contourArea < minArea) continue
142
147
 
143
148
  // Approximate contour to polygon
144
149
  val approx = MatOfPoint2f()
@@ -168,6 +173,7 @@ class DocumentDetector {
168
173
  grayMat.release()
169
174
  blurredMat.release()
170
175
  cannyMat.release()
176
+ morphMat.release()
171
177
  }
172
178
  }
173
179
 
@@ -222,6 +228,42 @@ class DocumentDetector {
222
228
  return RectangleQuality.GOOD
223
229
  }
224
230
 
231
+ /**
232
+ * Evaluate rectangle quality in view coordinates (closer to iOS behavior).
233
+ */
234
+ fun evaluateRectangleQualityInView(
235
+ rectangle: Rectangle,
236
+ viewWidth: Int,
237
+ viewHeight: Int
238
+ ): RectangleQuality {
239
+ if (viewWidth == 0 || viewHeight == 0) {
240
+ return RectangleQuality.TOO_FAR
241
+ }
242
+
243
+ val minDim = min(viewWidth.toDouble(), viewHeight.toDouble())
244
+ val angleThreshold = max(60.0, minDim * 0.05)
245
+
246
+ val topYDiff = abs(rectangle.topRight.y - rectangle.topLeft.y)
247
+ val bottomYDiff = abs(rectangle.bottomLeft.y - rectangle.bottomRight.y)
248
+ val leftXDiff = abs(rectangle.topLeft.x - rectangle.bottomLeft.x)
249
+ val rightXDiff = abs(rectangle.topRight.x - rectangle.bottomRight.x)
250
+
251
+ if (topYDiff > angleThreshold || bottomYDiff > angleThreshold || leftXDiff > angleThreshold || rightXDiff > angleThreshold) {
252
+ return RectangleQuality.BAD_ANGLE
253
+ }
254
+
255
+ val margin = max(150.0, minDim * 0.15)
256
+ if (rectangle.topLeft.y > margin ||
257
+ rectangle.topRight.y > margin ||
258
+ rectangle.bottomLeft.y < (viewHeight - margin) ||
259
+ rectangle.bottomRight.y < (viewHeight - margin)
260
+ ) {
261
+ return RectangleQuality.TOO_FAR
262
+ }
263
+
264
+ return RectangleQuality.GOOD
265
+ }
266
+
225
267
  /**
226
268
  * Calculate perimeter of rectangle
227
269
  */
@@ -186,17 +186,17 @@ class DocumentScannerView(context: ThemedReactContext) : FrameLayout(context), L
186
186
  }
187
187
  lastDetectionTimestamp = now
188
188
 
189
- val quality = if (rectangle != null) {
190
- DocumentDetector.evaluateRectangleQuality(rectangle, imageWidth, imageHeight)
191
- } else {
192
- RectangleQuality.TOO_FAR
193
- }
194
-
195
189
  val rectangleOnScreen = if (rectangle != null && width > 0 && height > 0) {
196
190
  DocumentDetector.transformRectangleToViewCoordinates(rectangle, imageWidth, imageHeight, width, height)
197
191
  } else {
198
192
  null
199
193
  }
194
+ val quality = when {
195
+ rectangleOnScreen != null && width > 0 && height > 0 ->
196
+ DocumentDetector.evaluateRectangleQualityInView(rectangleOnScreen, width, height)
197
+ rectangle != null -> DocumentDetector.evaluateRectangleQuality(rectangle, imageWidth, imageHeight)
198
+ else -> RectangleQuality.TOO_FAR
199
+ }
200
200
 
201
201
  post {
202
202
  onRectangleDetected(rectangleOnScreen, rectangle, quality, imageWidth, imageHeight)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-native-rectangle-doc-scanner",
3
- "version": "3.231.0",
3
+ "version": "3.233.0",
4
4
  "description": "Native-backed document scanner for React Native with customizable overlays.",
5
5
  "license": "MIT",
6
6
  "main": "dist/index.js",