@@ -9,15 +9,15 @@ import android.media.MediaScannerConnection
99import android.net.Uri
1010import android.os.Bundle
1111import android.os.Parcelable
12+ import android.util.Log
1213import android.view.*
1314import androidx.appcompat.app.AppCompatActivity
1415import androidx.documentfile.provider.DocumentFile
1516import com.dan.perspective.databinding.MainFragmentBinding
1617import org.opencv.android.Utils
17- import org.opencv.core.Core.mean
18- import org.opencv.core.Core.minMaxLoc
1918import org.opencv.core.CvType.*
2019import org.opencv.core.Mat
20+ import org.opencv.core.Rect
2121import org.opencv.core.Size
2222import org.opencv.imgproc.Imgproc.*
2323import java.io.File
@@ -45,13 +45,23 @@ class MainFragment(activity: MainActivity) : AppFragment(activity) {
4545
4646 private var inputImage = Mat ()
4747 private var outputImage = Mat ()
48+ private var outputImageCropped = Mat ()
4849 private var menuSave: MenuItem ? = null
4950 private var menuPrevPerspective: MenuItem ? = null
51+ private val sharedParams = SharedParams ()
5052
5153 private lateinit var binding: MainFragmentBinding // : ActivityMainBinding by lazy { ActivityMainBinding.inflate(layoutInflater) }
5254 private var outputName = Settings .DEFAULT_NAME
5355 private var inputUri: Uri ? = null
5456
57+ private fun updateToSharedParams () {
58+ sharedParams.cropped = binding.switchCrop.isChecked
59+ }
60+
61+ private fun updateFromSharedParams () {
62+ binding.switchCrop.isChecked = sharedParams.cropped
63+ }
64+
5565 override fun onCreateOptionsMenu (menu : Menu , inflater : MenuInflater ) {
5666 inflater.inflate(R .menu.main_menu, menu)
5767
@@ -214,7 +224,12 @@ class MainFragment(activity: MainActivity) : AppFragment(activity) {
214224
215225 warpImageAsync()
216226 if (outputImage.empty()) return
217- val bitmap = matToBitmap(outputImage) ? : return
227+
228+ val bitmap = matToBitmap(
229+ if (binding.switchCrop.isChecked)
230+ outputImageCropped
231+ else
232+ outputImage) ? : return
218233
219234 setBusyDialogTitleAsync(MSG_SAVE )
220235
@@ -312,17 +327,37 @@ class MainFragment(activity: MainActivity) : AppFragment(activity) {
312327
313328 val perspectiveMat = getPerspectiveTransform(srcMat, destMat)
314329 warpPerspective(inputImage, outputImage, perspectiveMat, inputImage.size(), INTER_LANCZOS4 )
330+
331+ val destLeftInt = destLeft.toInt() + 1
332+ val destRightInt = destRight.toInt() - 1
333+ val destTopInt = destTop.toInt() + 1
334+ val destBottomInt = destBottom.toInt() - 1
335+
336+ outputImageCropped = Mat (
337+ outputImage,
338+ Rect (
339+ destLeftInt,
340+ destTopInt,
341+ destRightInt - destLeftInt - 1 ,
342+ destBottomInt - destTopInt - 1 ))
315343 }
316344
317345 private fun showPreview () {
318346 if (inputImage.empty()) return
319347 if (outputImage.empty()) return
320- val bitmap = matToBitmap(outputImage) ? : return
348+ val bitmap = matToBitmap( outputImage) ? : return
349+ val bitmapCropped = matToBitmap( outputImageCropped ) ? : return
321350 runOnUiThread {
322- PreviewFragment .show(activity, bitmap)
351+ updateToSharedParams()
352+ PreviewFragment .show(activity, bitmap, bitmapCropped, sharedParams)
323353 }
324354 }
325355
356+ override fun onActivate () {
357+ updateFromSharedParams()
358+ super .onActivate()
359+ }
360+
326361 private fun warpImage () {
327362 if (inputImage.empty()) return
328363 if (! outputImage.empty()) {
@@ -338,6 +373,7 @@ class MainFragment(activity: MainActivity) : AppFragment(activity) {
338373
339374 private fun clearOutputImage () {
340375 outputImage.release()
376+ outputImageCropped.release()
341377 }
342378
343379 private fun lineIntersection ( line1 : Pair <PointF , PointF >, line2 : Pair <PointF , PointF > ): PointF ? {
@@ -376,44 +412,34 @@ class MainFragment(activity: MainActivity) : AppFragment(activity) {
376412 Size ( AUTO_DETECT_WORK_SIZE .toDouble(), AUTO_DETECT_WORK_SIZE .toDouble()) ,
377413 0.0 ,
378414 0.0 ,
379- INTER_AREA
415+ INTER_NEAREST_EXACT
380416 )
381417
382418 cvtColor( image, image, COLOR_BGR2GRAY )
383-
384- // blur reduce number of edge detected
385- blur( image, image, Size (3.0 , 3.0 ) )
386-
387- val meanValue = mean(image).`val `[0 ].toInt()
388- val minMax = minMaxLoc(image)
389- val minVal = minMax.minVal
390- val maxVal = minMax.maxVal
391- val lowerThreshold = (minVal + meanValue) / 2
392- val upperThreshold = (maxVal + meanValue) / 2
419+ blur(image, image, Size (9.0 ,9.0 ))
420+ threshold( image, image, 0.0 ,255.0 ,THRESH_BINARY + THRESH_OTSU )
393421
394422 val edges = Mat ()
395- Canny ( image, edges, lowerThreshold, upperThreshold )
423+ Canny ( image, edges, 100.0 , 200.0 )
396424
397425 val hLines = mutableListOf<Pair <Point , Point >>()
398426 val vLines = mutableListOf<Pair <Point , Point >>()
399427
400- for ( threshold in 200 downTo 100 step 20 ) {
401- hLines.clear()
402- vLines.clear()
403-
404- val lines = Mat ()
405- HoughLinesP (edges, lines, 1.0 , PI / 1024 , threshold, 300.0 , 100.0 )
406- if (lines.empty()) continue
407-
428+ val lines = Mat ()
429+ HoughLinesP (edges, lines, 1.0 , PI / 360 , 10 , 100.0 , 100.0 )
430+ if (! lines.empty()) {
408431 for (lineIndex in 0 until lines.rows()) {
409- val startPoint = Point ( lines.get(lineIndex, 0 )[0 ].toInt(), lines.get(lineIndex, 0 )[1 ].toInt() )
410- val endPoint = Point ( lines.get(lineIndex, 0 )[2 ].toInt(), lines.get(lineIndex, 0 )[3 ].toInt() )
432+ val line = lines.get(lineIndex, 0 )
433+ val startPoint = Point ( line[0 ].toInt(), line[1 ].toInt() )
434+ val endPoint = Point ( line[2 ].toInt(), line[3 ].toInt() )
411435 val delta = Point ( abs(endPoint.x - startPoint.x), abs(endPoint.y - startPoint.y) )
412436 val ratio = min(delta.x, delta.y).toFloat() / max(delta.x, delta.y)
413437
414- // avoid lines that are too harsh
438+ // avoid lines that are too close to 45°
415439 if (ratio >= 0.3 ) continue
416440
441+ Log .i(" ABCDEFG" , " dx: ${delta.x} , dy: ${delta.y} " )
442+
417443 if (delta.x > delta.y) {
418444 if (startPoint.y >= minValue && endPoint.y >= minValue && startPoint.y <= maxValue && endPoint.y <= maxValue) {
419445 hLines.add( Pair (startPoint, endPoint) )
@@ -424,8 +450,6 @@ class MainFragment(activity: MainActivity) : AppFragment(activity) {
424450 }
425451 }
426452 }
427-
428- if (hLines.size >= 2 && vLines.size >= 2 ) break
429453 }
430454
431455 val hLineTop: Pair <Point , Point >
0 commit comments