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
|
-
|
|
177
|
-
|
|
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
|
|
222
|
-
val minArea = max(
|
|
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
|
-
|
|
247
|
-
|
|
248
|
-
|
|
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
|
|
296
|
+
if (rectangularity >= 0.6) {
|
|
259
297
|
val boxPoints = Array(4) { Point() }
|
|
260
298
|
rotated.points(boxPoints)
|
|
261
|
-
|
|
262
|
-
|
|
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