react-native-rectangle-doc-scanner 3.249.0 → 3.250.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.
|
@@ -70,7 +70,6 @@ class CameraController(
|
|
|
70
70
|
.enableMultipleObjects()
|
|
71
71
|
.build()
|
|
72
72
|
)
|
|
73
|
-
private var lastRefineTimestamp = 0L
|
|
74
73
|
private var lastRectangle: Rectangle? = null
|
|
75
74
|
private var lastRectangleTimestamp = 0L
|
|
76
75
|
|
|
@@ -78,7 +77,7 @@ class CameraController(
|
|
|
78
77
|
|
|
79
78
|
companion object {
|
|
80
79
|
private const val TAG = "CameraController"
|
|
81
|
-
private const val ANALYSIS_MAX_AREA =
|
|
80
|
+
private const val ANALYSIS_MAX_AREA = 2560 * 1920
|
|
82
81
|
private const val ANALYSIS_ASPECT_TOLERANCE = 0.15
|
|
83
82
|
}
|
|
84
83
|
|
|
@@ -412,13 +411,7 @@ class CameraController(
|
|
|
412
411
|
box.width() * box.height()
|
|
413
412
|
}
|
|
414
413
|
val mlBox = best?.boundingBox
|
|
415
|
-
val rectangle =
|
|
416
|
-
mlBox == null -> null
|
|
417
|
-
shouldRefineWithOpenCv() ->
|
|
418
|
-
refineWithOpenCv(nv21, imageWidth, imageHeight, rotationDegrees, mlBox)
|
|
419
|
-
?: boxToRectangle(mlBox)
|
|
420
|
-
else -> boxToRectangle(mlBox)
|
|
421
|
-
}
|
|
414
|
+
val rectangle = refineWithOpenCv(nv21, imageWidth, imageHeight, rotationDegrees, mlBox)
|
|
422
415
|
|
|
423
416
|
val frameWidth = if (rotationDegrees == 90 || rotationDegrees == 270) imageHeight else imageWidth
|
|
424
417
|
val frameHeight = if (rotationDegrees == 90 || rotationDegrees == 270) imageWidth else imageHeight
|
|
@@ -426,6 +419,15 @@ class CameraController(
|
|
|
426
419
|
}
|
|
427
420
|
.addOnFailureListener { e ->
|
|
428
421
|
Log.e(TAG, "[CAMERA2] ML Kit detection failed", e)
|
|
422
|
+
val rectangle = try {
|
|
423
|
+
DocumentDetector.detectRectangleInYUV(nv21, imageWidth, imageHeight, rotationDegrees)
|
|
424
|
+
} catch (detectError: Exception) {
|
|
425
|
+
Log.w(TAG, "[CAMERA2] OpenCV fallback failed", detectError)
|
|
426
|
+
null
|
|
427
|
+
}
|
|
428
|
+
val frameWidth = if (rotationDegrees == 90 || rotationDegrees == 270) imageHeight else imageWidth
|
|
429
|
+
val frameHeight = if (rotationDegrees == 90 || rotationDegrees == 270) imageWidth else imageHeight
|
|
430
|
+
onFrameAnalyzed?.invoke(smoothRectangle(rectangle), frameWidth, frameHeight)
|
|
429
431
|
}
|
|
430
432
|
.addOnCompleteListener {
|
|
431
433
|
analysisInFlight.set(false)
|
|
@@ -568,38 +570,32 @@ class CameraController(
|
|
|
568
570
|
return Bitmap.createBitmap(bitmap, 0, 0, bitmap.width, bitmap.height, matrix, true)
|
|
569
571
|
}
|
|
570
572
|
|
|
571
|
-
private fun shouldRefineWithOpenCv(): Boolean {
|
|
572
|
-
val now = System.currentTimeMillis()
|
|
573
|
-
if (now - lastRefineTimestamp < 150) {
|
|
574
|
-
return false
|
|
575
|
-
}
|
|
576
|
-
lastRefineTimestamp = now
|
|
577
|
-
return true
|
|
578
|
-
}
|
|
579
|
-
|
|
580
573
|
private fun refineWithOpenCv(
|
|
581
574
|
nv21: ByteArray,
|
|
582
575
|
imageWidth: Int,
|
|
583
576
|
imageHeight: Int,
|
|
584
577
|
rotationDegrees: Int,
|
|
585
|
-
mlBox: Rect
|
|
578
|
+
mlBox: Rect?
|
|
586
579
|
): Rectangle? {
|
|
587
580
|
return try {
|
|
588
581
|
val uprightWidth = if (rotationDegrees == 90 || rotationDegrees == 270) imageHeight else imageWidth
|
|
589
582
|
val uprightHeight = if (rotationDegrees == 90 || rotationDegrees == 270) imageWidth else imageHeight
|
|
590
|
-
val
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
583
|
+
val openCvRect = if (mlBox != null) {
|
|
584
|
+
val expanded = expandRect(mlBox, uprightWidth, uprightHeight, 0.2f)
|
|
585
|
+
DocumentDetector.detectRectangleInYUVWithRoi(
|
|
586
|
+
nv21,
|
|
587
|
+
imageWidth,
|
|
588
|
+
imageHeight,
|
|
589
|
+
rotationDegrees,
|
|
590
|
+
expanded
|
|
591
|
+
)
|
|
592
|
+
} else {
|
|
593
|
+
DocumentDetector.detectRectangleInYUV(nv21, imageWidth, imageHeight, rotationDegrees)
|
|
594
|
+
}
|
|
598
595
|
if (openCvRect == null) {
|
|
599
|
-
|
|
596
|
+
mlBox?.let { boxToRectangle(it) }
|
|
600
597
|
} else {
|
|
601
|
-
|
|
602
|
-
if (computeIoU(openRectBounds, mlBox) >= 0.2f) openCvRect else null
|
|
598
|
+
openCvRect
|
|
603
599
|
}
|
|
604
600
|
} catch (e: Exception) {
|
|
605
601
|
Log.w(TAG, "[CAMERA2] OpenCV refine failed", e)
|
|
@@ -630,32 +626,16 @@ class CameraController(
|
|
|
630
626
|
val now = System.currentTimeMillis()
|
|
631
627
|
val last = lastRectangle
|
|
632
628
|
if (current == null) {
|
|
633
|
-
if (last != null && now - lastRectangleTimestamp <
|
|
629
|
+
if (last != null && now - lastRectangleTimestamp < 150) {
|
|
634
630
|
return last
|
|
635
631
|
}
|
|
636
632
|
lastRectangle = null
|
|
637
633
|
return null
|
|
638
634
|
}
|
|
639
635
|
|
|
640
|
-
|
|
641
|
-
val t = 0.35
|
|
642
|
-
Rectangle(
|
|
643
|
-
Point(lerp(last.topLeft.x, current.topLeft.x, t), lerp(last.topLeft.y, current.topLeft.y, t)),
|
|
644
|
-
Point(lerp(last.topRight.x, current.topRight.x, t), lerp(last.topRight.y, current.topRight.y, t)),
|
|
645
|
-
Point(lerp(last.bottomLeft.x, current.bottomLeft.x, t), lerp(last.bottomLeft.y, current.bottomLeft.y, t)),
|
|
646
|
-
Point(lerp(last.bottomRight.x, current.bottomRight.x, t), lerp(last.bottomRight.y, current.bottomRight.y, t))
|
|
647
|
-
)
|
|
648
|
-
} else {
|
|
649
|
-
current
|
|
650
|
-
}
|
|
651
|
-
|
|
652
|
-
lastRectangle = smoothed
|
|
636
|
+
lastRectangle = current
|
|
653
637
|
lastRectangleTimestamp = now
|
|
654
|
-
return
|
|
655
|
-
}
|
|
656
|
-
|
|
657
|
-
private fun lerp(start: Double, end: Double, t: Double): Double {
|
|
658
|
-
return start + (end - start) * t
|
|
638
|
+
return current
|
|
659
639
|
}
|
|
660
640
|
|
|
661
641
|
private fun rectangleBounds(rectangle: Rectangle): Rect {
|
|
@@ -666,17 +646,6 @@ class CameraController(
|
|
|
666
646
|
return Rect(left.toInt(), top.toInt(), right.toInt(), bottom.toInt())
|
|
667
647
|
}
|
|
668
648
|
|
|
669
|
-
private fun computeIoU(a: Rect, b: Rect): Float {
|
|
670
|
-
val left = max(a.left, b.left)
|
|
671
|
-
val top = max(a.top, b.top)
|
|
672
|
-
val right = minOf(a.right, b.right)
|
|
673
|
-
val bottom = minOf(a.bottom, b.bottom)
|
|
674
|
-
if (right <= left || bottom <= top) return 0f
|
|
675
|
-
val intersection = (right - left).toFloat() * (bottom - top).toFloat()
|
|
676
|
-
val union = (a.width() * a.height() + b.width() * b.height() - intersection).toFloat()
|
|
677
|
-
return if (union <= 0f) 0f else intersection / union
|
|
678
|
-
}
|
|
679
|
-
|
|
680
649
|
private fun imageToNv21(image: Image): ByteArray {
|
|
681
650
|
val width = image.width
|
|
682
651
|
val height = image.height
|
package/package.json
CHANGED