react-native-rectangle-doc-scanner 10.24.0 → 10.25.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.
@@ -173,8 +173,40 @@ class DocumentDetector {
173
173
  // Apply a light blur to reduce noise without killing small edges.
174
174
  Imgproc.GaussianBlur(grayMat, blurredMat, Size(5.0, 5.0), 0.0)
175
175
 
176
- // Apply Canny edge detection with lower thresholds for better corner detection.
177
- Imgproc.Canny(blurredMat, cannyMat, 30.0, 90.0)
176
+ fun computeMedian(mat: Mat): Double {
177
+ val hist = Mat()
178
+ return try {
179
+ Imgproc.calcHist(
180
+ listOf(mat),
181
+ MatOfInt(0),
182
+ Mat(),
183
+ hist,
184
+ MatOfInt(256),
185
+ MatOfFloat(0f, 256f)
186
+ )
187
+ val total = mat.total().toDouble()
188
+ var cumulative = 0.0
189
+ var median = 0.0
190
+ for (i in 0 until 256) {
191
+ cumulative += hist.get(i, 0)[0]
192
+ if (cumulative >= total * 0.5) {
193
+ median = i.toDouble()
194
+ break
195
+ }
196
+ }
197
+ median
198
+ } finally {
199
+ hist.release()
200
+ }
201
+ }
202
+
203
+ val median = computeMedian(blurredMat)
204
+ val sigma = 0.33
205
+ val cannyLow = max(20.0, (1.0 - sigma) * median)
206
+ val cannyHigh = max(60.0, (1.0 + sigma) * median)
207
+
208
+ // Apply Canny edge detection with adaptive thresholds for better corner detection.
209
+ Imgproc.Canny(blurredMat, cannyMat, cannyLow, cannyHigh)
178
210
  val kernel = Imgproc.getStructuringElement(Imgproc.MORPH_RECT, Size(3.0, 3.0))
179
211
  Imgproc.morphologyEx(cannyMat, morphMat, Imgproc.MORPH_CLOSE, kernel)
180
212
  kernel.release()
@@ -218,8 +250,8 @@ class DocumentDetector {
218
250
  )
219
251
 
220
252
  var largestRectangle: Rectangle? = null
221
- var largestArea = 0.0
222
- val minArea = max(300.0, (srcMat.rows() * srcMat.cols()) * 0.0005)
253
+ var bestScore = 0.0
254
+ val minArea = max(800.0, (srcMat.rows() * srcMat.cols()) * 0.001)
223
255
 
224
256
  for (contour in contours) {
225
257
  val contourArea = Imgproc.contourArea(contour)
@@ -243,9 +275,15 @@ class DocumentDetector {
243
275
 
244
276
  if (quad.total() == 4L && Imgproc.isContourConvex(MatOfPoint(*quad.toArray()))) {
245
277
  val points = quad.toArray()
246
- if (contourArea > largestArea) {
247
- largestArea = contourArea
248
- largestRectangle = refineRectangle(grayMat, orderPoints(points))
278
+ val rect = Imgproc.minAreaRect(MatOfPoint2f(*points))
279
+ val rectArea = rect.size.area()
280
+ val rectangularity = if (rectArea > 1.0) contourArea / rectArea else 0.0
281
+ if (rectangularity >= 0.6) {
282
+ val score = contourArea * rectangularity
283
+ if (score > bestScore) {
284
+ bestScore = score
285
+ largestRectangle = refineRectangle(grayMat, orderPoints(points))
286
+ }
249
287
  }
250
288
  } else {
251
289
  // Fallback: use rotated bounding box when contour is near-rectangular.
@@ -255,11 +293,14 @@ class DocumentDetector {
255
293
  val rectArea = rotated.size.area()
256
294
  if (rectArea > 1.0) {
257
295
  val rectangularity = contourArea / rectArea
258
- if (rectangularity >= 0.6 && contourArea > largestArea) {
296
+ if (rectangularity >= 0.6) {
259
297
  val boxPoints = Array(4) { Point() }
260
298
  rotated.points(boxPoints)
261
- largestArea = contourArea
262
- largestRectangle = refineRectangle(grayMat, orderPoints(boxPoints))
299
+ val score = contourArea * rectangularity
300
+ if (score > bestScore) {
301
+ bestScore = score
302
+ largestRectangle = refineRectangle(grayMat, orderPoints(boxPoints))
303
+ }
263
304
  }
264
305
  }
265
306
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-native-rectangle-doc-scanner",
3
- "version": "10.24.0",
3
+ "version": "10.25.0",
4
4
  "description": "Native-backed document scanner for React Native with customizable overlays.",
5
5
  "license": "MIT",
6
6
  "main": "dist/index.js",