react-native-rectangle-doc-scanner 3.230.0 → 3.232.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.
|
@@ -25,6 +25,7 @@ import androidx.core.content.ContextCompat
|
|
|
25
25
|
import java.io.File
|
|
26
26
|
import java.io.FileOutputStream
|
|
27
27
|
import java.util.concurrent.atomic.AtomicReference
|
|
28
|
+
import java.util.concurrent.atomic.AtomicBoolean
|
|
28
29
|
import kotlin.math.abs
|
|
29
30
|
import kotlin.math.max
|
|
30
31
|
|
|
@@ -55,6 +56,7 @@ class CameraController(
|
|
|
55
56
|
private var torchEnabled = false
|
|
56
57
|
|
|
57
58
|
private val pendingCapture = AtomicReference<PendingCapture?>()
|
|
59
|
+
private val analysisInFlight = AtomicBoolean(false)
|
|
58
60
|
|
|
59
61
|
var onFrameAnalyzed: ((Rectangle?, Int, Int) -> Unit)? = null
|
|
60
62
|
|
|
@@ -245,10 +247,32 @@ class CameraController(
|
|
|
245
247
|
yuvReader = ImageReader.newInstance(analysis.width, analysis.height, ImageFormat.YUV_420_888, 2).apply {
|
|
246
248
|
setOnImageAvailableListener({ reader ->
|
|
247
249
|
if (!detectionEnabled || onFrameAnalyzed == null) {
|
|
248
|
-
|
|
250
|
+
try {
|
|
251
|
+
reader.acquireLatestImage()?.close()
|
|
252
|
+
} catch (e: Exception) {
|
|
253
|
+
Log.w(TAG, "[CAMERA2] Failed to drain analysis image", e)
|
|
254
|
+
}
|
|
255
|
+
return@setOnImageAvailableListener
|
|
256
|
+
}
|
|
257
|
+
if (!analysisInFlight.compareAndSet(false, true)) {
|
|
258
|
+
try {
|
|
259
|
+
reader.acquireLatestImage()?.close()
|
|
260
|
+
} catch (e: Exception) {
|
|
261
|
+
Log.w(TAG, "[CAMERA2] Failed to drop analysis image", e)
|
|
262
|
+
}
|
|
263
|
+
return@setOnImageAvailableListener
|
|
264
|
+
}
|
|
265
|
+
val image = try {
|
|
266
|
+
reader.acquireLatestImage()
|
|
267
|
+
} catch (e: Exception) {
|
|
268
|
+
analysisInFlight.set(false)
|
|
269
|
+
Log.w(TAG, "[CAMERA2] acquireLatestImage failed", e)
|
|
270
|
+
null
|
|
271
|
+
}
|
|
272
|
+
if (image == null) {
|
|
273
|
+
analysisInFlight.set(false)
|
|
249
274
|
return@setOnImageAvailableListener
|
|
250
275
|
}
|
|
251
|
-
val image = reader.acquireLatestImage() ?: return@setOnImageAvailableListener
|
|
252
276
|
analysisHandler.post { analyzeImage(image) }
|
|
253
277
|
}, cameraHandler)
|
|
254
278
|
}
|
|
@@ -340,6 +364,7 @@ class CameraController(
|
|
|
340
364
|
Log.e(TAG, "[CAMERA2] Error analyzing frame", e)
|
|
341
365
|
} finally {
|
|
342
366
|
image.close()
|
|
367
|
+
analysisInFlight.set(false)
|
|
343
368
|
}
|
|
344
369
|
}
|
|
345
370
|
|
|
@@ -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
|
|
117
|
-
Imgproc.GaussianBlur(grayMat, blurredMat, Size(
|
|
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,
|
|
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
|
-
|
|
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 <
|
|
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
|
|
package/package.json
CHANGED