@@ -33,8 +33,10 @@ fun detectDocumentQuad(mask: Bitmap, minQuadAreaRatio: Double = 0.02): Quad? {
3333 val gray = Mat ()
3434 Imgproc .cvtColor(mat, gray, Imgproc .COLOR_BGR2GRAY )
3535
36+ val refinedMask = refineMask(gray)
37+
3638 val blurred = Mat ()
37- Imgproc .GaussianBlur (gray , blurred, Size (5.0 , 5.0 ), 0.0 )
39+ Imgproc .GaussianBlur (refinedMask , blurred, Size (5.0 , 5.0 ), 0.0 )
3840
3941 val edges = Mat ()
4042 Imgproc .Canny (blurred, edges, 75.0 , 200.0 )
@@ -69,6 +71,32 @@ fun detectDocumentQuad(mask: Bitmap, minQuadAreaRatio: Double = 0.02): Quad? {
6971 return createQuad(vertices)
7072}
7173
74+ /* *
75+ * Applies morphological operations to improve a document mask.
76+ */
77+ fun refineMask (original : Mat ): Mat {
78+ // Step 0: Ensure the mask is binary (just in case)
79+ val binaryMask = Mat ()
80+ Imgproc .threshold(original, binaryMask, 0.0 , 255.0 , Imgproc .THRESH_BINARY )
81+
82+ // Step 1: Closing (fills small holes)
83+ val kernelClose = Imgproc .getStructuringElement(Imgproc .MORPH_ELLIPSE , Size (5.0 , 5.0 ))
84+ val closed = Mat ()
85+ Imgproc .morphologyEx(binaryMask, closed, Imgproc .MORPH_CLOSE , kernelClose)
86+
87+ // Step 2: Gentle opening (removes isolated noise)
88+ val kernelOpen = Imgproc .getStructuringElement(Imgproc .MORPH_ELLIPSE , Size (5.0 , 5.0 ))
89+ val opened = Mat ()
90+ Imgproc .morphologyEx(closed, opened, Imgproc .MORPH_OPEN , kernelOpen)
91+
92+ // Step 3: Light dilation (connects almost touching parts)
93+ val kernelDilate = Imgproc .getStructuringElement(Imgproc .MORPH_ELLIPSE , Size (5.0 , 5.0 ))
94+ val dilated = Mat ()
95+ Imgproc .dilate(opened, dilated, kernelDilate, org.opencv.core.Point (- 1.0 , - 1.0 ), 1 )
96+
97+ return dilated
98+ }
99+
72100fun extractDocument (originalBitmap : Bitmap , quad : Quad , rotationDegrees : Int ): Bitmap {
73101 val widthTop = norm(quad.topLeft, quad.topRight)
74102 val widthBottom = norm(quad.bottomLeft, quad.bottomRight)
0 commit comments