Skip to content

Commit 2a0d367

Browse files
author
Dan Oprea
committed
Add inpaint to fill black areas after warping.
It uses SHIFTMAP algorithm. NOTE: it can be slow !
1 parent 1e6486d commit 2a0d367

File tree

2 files changed

+28
-4
lines changed

2 files changed

+28
-4
lines changed

app/src/main/java/com/dan/perspective/MainActivity.kt

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -33,9 +33,11 @@ import org.opencv.core.Core.minMaxLoc
3333
import org.opencv.core.CvType.*
3434
import org.opencv.core.Mat
3535
import org.opencv.core.MatOfInt
36+
import org.opencv.core.Scalar
3637
import org.opencv.core.Size
3738
import org.opencv.imgcodecs.Imgcodecs
3839
import org.opencv.imgproc.Imgproc.*
40+
import org.opencv.xphoto.Xphoto
3941
import java.io.File
4042
import kotlin.math.PI
4143
import kotlin.math.abs
@@ -240,7 +242,7 @@ class MainActivity : AppCompatActivity() {
240242
)
241243
)
242244

243-
return true;
245+
return true
244246
}
245247
}
246248

@@ -395,6 +397,7 @@ class MainActivity : AppCompatActivity() {
395397
binding.radioButtonPointDirectionAll.isEnabled = enabled
396398
binding.radioButtonPointDirectionHorizontal.isEnabled = enabled
397399
binding.radioButtonPointDirectionVertical.isEnabled = enabled
400+
binding.checkBoxInpaint.isEnabled = enabled
398401

399402
menuSave?.isEnabled = enabled
400403
menuPrevPerspective?.isEnabled = enabled && settings.prevHeight > 0
@@ -420,7 +423,7 @@ class MainActivity : AppCompatActivity() {
420423
private fun saveImageAsync() {
421424
if (inputImage.empty()) return
422425

423-
warpImageAsync()
426+
warpImageAsync( binding.checkBoxInpaint.isChecked )
424427
if (outputImage.empty()) return
425428

426429
setBusyDialogTitleAsync(MSG_SAVE)
@@ -523,7 +526,7 @@ class MainActivity : AppCompatActivity() {
523526
}
524527
}
525528

526-
private fun warpImageAsync() {
529+
private fun warpImageAsync( inpaint: Boolean ) {
527530
if (inputImage.empty()) return
528531
if (!outputImage.empty()) return
529532

@@ -557,6 +560,14 @@ class MainActivity : AppCompatActivity() {
557560
val perspectiveMat = getPerspectiveTransform(srcMat, destMat)
558561
warpPerspective(inputImage, outputImage, perspectiveMat, inputImage.size(), INTER_LANCZOS4)
559562

563+
if (inpaint) {
564+
val tmpMat = Mat(inputImage.width(), inputImage.height(), CV_8UC1, Scalar(255.0))
565+
val warpedMask = Mat()
566+
warpPerspective(tmpMat, warpedMask, perspectiveMat, inputImage.size(), INTER_NEAREST)
567+
Xphoto.inpaint( outputImage, warpedMask, tmpMat, Xphoto.INPAINT_SHIFTMAP )
568+
outputImage = tmpMat
569+
}
570+
560571
runOnUiThread {
561572
binding.imagePreview.setBitmap(matToBitmap(outputImage))
562573
}
@@ -566,8 +577,10 @@ class MainActivity : AppCompatActivity() {
566577
if (inputImage.empty()) return
567578
if (!outputImage.empty()) return
568579

580+
val inpaint = binding.checkBoxInpaint.isChecked
581+
569582
runAsync(MSG_WARP) {
570-
warpImageAsync()
583+
warpImageAsync(inpaint)
571584
}
572585
}
573586

@@ -755,6 +768,10 @@ class MainActivity : AppCompatActivity() {
755768
setContentView(binding.root)
756769
updateButtons()
757770

771+
binding.checkBoxInpaint.setOnCheckedChangeListener { _, _ ->
772+
clearOutputImage()
773+
}
774+
758775
binding.buttonReset.setOnClickListener {
759776
binding.imageEdit.resetPoints()
760777
}

app/src/main/res/layout/activity_main.xml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,13 @@
4444
android:textAllCaps="false"
4545
android:textColor="@color/button_text" />
4646

47+
<CheckBox
48+
android:id="@+id/checkBoxInpaint"
49+
android:layout_width="wrap_content"
50+
android:layout_height="wrap_content"
51+
android:layout_weight="0"
52+
android:text="Inpaint" />
53+
4754
<TextView
4855
android:id="@+id/textView3"
4956
android:layout_width="wrap_content"

0 commit comments

Comments
 (0)