问题
I am developing an application that segments images of wounds using the watershed algorithm. For this, the user draws a line in the internal area of the wound (region of interest) and another drawing in the background. With that, I pass the coordinates of this drawing to the watershed to perform the segmentation. I used this code in python to guide me through this step. However, in addition to not performing the correct segmentation, the black / white image is being saved in a different orientation than the original image. In the final image, the segmented image is not appearing, but the original image. I would like someone to help me correct these errors.
Code:
override fun onActivityResult(requestCode: Int, resultCode: Int, resultData: Intent?) {
super.onActivityResult(requestCode, resultCode, resultData)
if (requestCode == PICK_IMAGE_INTENT && resultCode == Activity.RESULT_OK && resultData != null && resultData.data != null) {
tryOpenUri(resultData.data!!, resultData)
val selectedImage = if (resultData.data != null) {
resultData.data
} else {
resultData.clipData?.getItemAt(0)?.uri
}
imageUpload = true
val filePathColumn = arrayOf(MediaStore.Images.Media.DATA)
val cursor = contentResolver.query(selectedImage!!, filePathColumn, null, null, null)!!
cursor.moveToFirst()
currentPhotoPath = cursor.moveToFirst()
.let { cursor.getString(cursor.getColumnIndex(filePathColumn[0])) }
.also { cursor.close() }
cursor.close()
} else if (requestCode == SAVE_IMAGE_INTENT && resultCode == Activity.RESULT_OK && resultData != null && resultData.data != null) {
val outputStream = contentResolver.openOutputStream(resultData.data!!)
saveToOutputStream(outputStream, defaultPath.getCompressionFormat(), false)
savedPathsHash = my_canvas.getDrawingHashCode()
imageUpload = true
}
}
private fun regionBackground() {
progressDialog = ProgressDialog(this, R.style.MyDialogTheme)
progressDialog.setTitle("Wait..")
progressDialog.setMessage("save the draw...")
progressDialog.show()
progressDialog.setCancelable(false)
//Load the image
srcOriginal = Imgcodecs.imread(currentPhotoPath)
//Create a blank image of zeros (same dimension as img)
//It should be grayscale (1 color channel)
markers = Mat.zeros(srcOriginal.rows(), srcOriginal.cols(), CvType.CV_32S)
//This step is manual. The goal is to find the points
//which create the result we want. I suggest using a
//tool to get the pixel coordinates.
//Dictate the background and set the markers to 1
for (value in 0..my_canvas.pointsToDrawY.size - 1) {
markers.put(
my_canvas.pointsToDrawX[value].toInt(),
my_canvas.pointsToDrawY[value].toInt(),
1.0
)
}
my_canvas.pointsToDrawXStepTwo.clear()
my_canvas.pointsToDrawYStepTwo.clear()
//Log.i("teste", my_canvas.pointsToDrawXStepTwo.toString()+"x"+my_canvas.pointsToDrawYStepTwo)
Handler().postDelayed({
progressDialog.dismiss()
}, 1000)
}
private fun regionOfInterest() {
//Log.i("teste", my_canvas.pointsToDrawXStepTwo.toString()+"x"+my_canvas.pointsToDrawYStepTwo)
progressDialog = ProgressDialog(this, R.style.MyDialogTheme)
progressDialog.setTitle("Wait..")
progressDialog.setMessage("save the draw...")
progressDialog.show()
progressDialog.setCancelable(false)
//Dictate the area of interest
//I used different values for each part of the car (for visibility)
for (value in 0..my_canvas.pointsToDrawYStepTwo.size - 1) {
markers.put(
my_canvas.pointsToDrawXStepTwo[value].toInt(),
my_canvas.pointsToDrawYStepTwo[value].toInt(),
255.0
)
}
Handler().postDelayed({
watershedSegmentation()
}, 1000)
}
private fun watershedSegmentation() {
//Now we have set the markers, we use the watershed
//algorithm to generate a marked image
watershed(srcOriginal, markers)
//Plot this one. If it does what we want, proceed;
//otherwise edit your markers and repeat
val mPath1 = Environment.getExternalStorageDirectory().toString() + "/watershed.png"
Imgcodecs.imwrite(mPath1,markers)
//Make the background black, and what we want to keep white
for (x in 0 until srcOriginal.rows()-1) {
for (y in 0 until srcOriginal.cols()-1) {
if(markers.get(x,y).get(0).equals(1.0)){
markers.put(
x,
y,
0.0
)
}
if((markers[x, y].get(0) == 255.0)){
markers.put(
x,
y,
255.0
)
}
}
}
//Use a kernel to dilate the image, to not lose any detail on the outline
//I used a kernel of 3x3 pixels
val marker_tempo = Mat()
val dilatation = Mat()
markers.convertTo(marker_tempo, CvType.CV_8U)
val kernel = Mat(1, 1, CvType.CV_8U)
//Plot again to check whether the dilation is according to our needs
//If not, repeat by using a smaller/bigger kernel, or more/less iterations
Imgproc.dilate(marker_tempo, dilatation, kernel)
val mPath2 = Environment.getExternalStorageDirectory().toString() + "/dilatation.png"
Imgcodecs.imwrite(mPath2,dilatation)
//Now apply the mask we created on the initial image
Core.bitwise_and(srcOriginal, srcOriginal, dilatation)
//Plot the final result
val mPath = Environment.getExternalStorageDirectory().toString() + "/final.png"
Imgcodecs.imwrite(mPath,dilatation)
Handler().postDelayed({
progressDialog.dismiss()
Toast.makeText(this, "Image segmented!", Toast.LENGTH_SHORT).show()
}, 1000)
}
original image
Draw regions
Create a blank image of zeros (same dimension as img original) - why is it getting rotated? and how to improve this segmentation?
output image dilated:
output image final:
what's missing to be able to target this image correctly?
来源:https://stackoverflow.com/questions/62159692/problem-in-image-segmentation-using-watershed-on-android