react-native-rectangle-doc-scanner 3.238.0 → 3.239.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.
|
@@ -106,6 +106,7 @@ class DocumentDetector {
|
|
|
106
106
|
val blurredMat = Mat()
|
|
107
107
|
val cannyMat = Mat()
|
|
108
108
|
val morphMat = Mat()
|
|
109
|
+
val threshMat = Mat()
|
|
109
110
|
|
|
110
111
|
try {
|
|
111
112
|
// Convert to grayscale
|
|
@@ -124,57 +125,74 @@ class DocumentDetector {
|
|
|
124
125
|
Imgproc.morphologyEx(cannyMat, morphMat, Imgproc.MORPH_CLOSE, kernel)
|
|
125
126
|
kernel.release()
|
|
126
127
|
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
val points = approx.toArray()
|
|
158
|
-
|
|
159
|
-
if (contourArea > largestArea) {
|
|
160
|
-
largestArea = contourArea
|
|
161
|
-
largestRectangle = orderPoints(points)
|
|
128
|
+
fun findLargestRectangle(source: Mat): Rectangle? {
|
|
129
|
+
val contours = mutableListOf<MatOfPoint>()
|
|
130
|
+
val hierarchy = Mat()
|
|
131
|
+
Imgproc.findContours(
|
|
132
|
+
source,
|
|
133
|
+
contours,
|
|
134
|
+
hierarchy,
|
|
135
|
+
Imgproc.RETR_EXTERNAL,
|
|
136
|
+
Imgproc.CHAIN_APPROX_SIMPLE
|
|
137
|
+
)
|
|
138
|
+
|
|
139
|
+
var largestRectangle: Rectangle? = null
|
|
140
|
+
var largestArea = 0.0
|
|
141
|
+
val minArea = max(500.0, (srcMat.rows() * srcMat.cols()) * 0.0008)
|
|
142
|
+
|
|
143
|
+
for (contour in contours) {
|
|
144
|
+
val contourArea = Imgproc.contourArea(contour)
|
|
145
|
+
if (contourArea < minArea) continue
|
|
146
|
+
|
|
147
|
+
val approx = MatOfPoint2f()
|
|
148
|
+
val contour2f = MatOfPoint2f(*contour.toArray())
|
|
149
|
+
val epsilon = 0.018 * Imgproc.arcLength(contour2f, true)
|
|
150
|
+
Imgproc.approxPolyDP(contour2f, approx, epsilon, true)
|
|
151
|
+
|
|
152
|
+
if (approx.total() == 4L && Imgproc.isContourConvex(MatOfPoint(*approx.toArray()))) {
|
|
153
|
+
val points = approx.toArray()
|
|
154
|
+
if (contourArea > largestArea) {
|
|
155
|
+
largestArea = contourArea
|
|
156
|
+
largestRectangle = orderPoints(points)
|
|
157
|
+
}
|
|
162
158
|
}
|
|
159
|
+
|
|
160
|
+
approx.release()
|
|
161
|
+
contour2f.release()
|
|
163
162
|
}
|
|
164
163
|
|
|
165
|
-
|
|
166
|
-
|
|
164
|
+
hierarchy.release()
|
|
165
|
+
contours.forEach { it.release() }
|
|
166
|
+
return largestRectangle
|
|
167
167
|
}
|
|
168
168
|
|
|
169
|
-
|
|
170
|
-
|
|
169
|
+
// First pass: Canny-based edges (good for strong edges).
|
|
170
|
+
var rectangle = findLargestRectangle(morphMat)
|
|
171
|
+
|
|
172
|
+
// Fallback: adaptive threshold (better for low-contrast cards).
|
|
173
|
+
if (rectangle == null) {
|
|
174
|
+
Imgproc.adaptiveThreshold(
|
|
175
|
+
blurredMat,
|
|
176
|
+
threshMat,
|
|
177
|
+
255.0,
|
|
178
|
+
Imgproc.ADAPTIVE_THRESH_GAUSSIAN_C,
|
|
179
|
+
Imgproc.THRESH_BINARY,
|
|
180
|
+
15,
|
|
181
|
+
2.0
|
|
182
|
+
)
|
|
183
|
+
val kernel = Imgproc.getStructuringElement(Imgproc.MORPH_RECT, Size(3.0, 3.0))
|
|
184
|
+
Imgproc.morphologyEx(threshMat, morphMat, Imgproc.MORPH_CLOSE, kernel)
|
|
185
|
+
kernel.release()
|
|
186
|
+
rectangle = findLargestRectangle(morphMat)
|
|
187
|
+
}
|
|
171
188
|
|
|
172
|
-
return
|
|
189
|
+
return rectangle
|
|
173
190
|
} finally {
|
|
174
191
|
grayMat.release()
|
|
175
192
|
blurredMat.release()
|
|
176
193
|
cannyMat.release()
|
|
177
194
|
morphMat.release()
|
|
195
|
+
threshMat.release()
|
|
178
196
|
}
|
|
179
197
|
}
|
|
180
198
|
|
package/package.json
CHANGED