我正在开发一个应用程序,它根据用户在屏幕上绘制的坐标删除图像的背景。用户在感兴趣的图像周围绘制一个矩形。有了这个,我使用分水岭来分割图像并从图像中删除背景。但是,我无法在算法中插入坐标以便删除整个背景。在下图中,我只选择了 4 个硬币,分割后,我只希望这 4 个硬币留在图像中,其他的消失。然而,这不是正在发生的事情。有人可以根据用户传递的区域帮我做这个删除段吗?
代码:
typealias Coordinates = Pair<Point, Point>
private fun extractForegroundFromBackground(coordinates: Coordinates){
// TODO: Provide complex object that has both path and extension
val width: Int
val height: Int
val rect = Rect(coordinates.first, coordinates.second)
width = bitmap.getWidth()
height = bitmap.getHeight()
val rgba = Mat()
val gray_mat = Mat()
val threeChannel = Mat()
Utils.bitmapToMat(bitmap, gray_mat)
Imgproc.cvtColor(gray_mat, rgba, Imgproc.COLOR_RGBA2RGB)
Imgproc.cvtColor(rgba, threeChannel, Imgproc.COLOR_RGB2GRAY)
Imgproc.threshold(threeChannel, threeChannel, 100.0, 255.0, Imgproc.THRESH_OTSU)
Imgproc.GaussianBlur(threeChannel, threeChannel, Size(5.0,5.0), 0.0)
val edges = Mat()
Imgproc.Canny(threeChannel, edges, 50.0, 200.0)
val contours: List<MatOfPoint> = ArrayList()
val hierarchy = Mat()
Imgproc.findContours(edges, contours, hierarchy, Imgproc.RETR_EXTERNAL, Imgproc.CHAIN_APPROX_SIMPLE)
val fg = Mat(rgba.size(), CvType.CV_8U)
Imgproc.erode(threeChannel, fg, Mat(), Point(-1.0, -1.0), 2)
val bg = Mat(rgba.size(), CvType.CV_8U)
Imgproc.dilate(threeChannel, bg, Mat(), Point(-1.0, -1.0), 3)
Imgproc.threshold(bg, bg, 1.0, 127.0, Imgproc.THRESH_BINARY_INV)
val markers = Mat(rect.size(), CvType.CV_8U, Scalar(0.0))
val frame = Mat()
val rectImage = Mat(rgba.size(), CvType.CV_8U)
Imgproc.rectangle(rectImage, coordinates.first, coordinates.second, Scalar(255.0, 255.0, 255.0), FILLED)
Log.i("teste,", coordinates.first.toString() + "\n"+ coordinates.second.toString())
Core.add(fg, bg, markers, rectImage)
// Start the WaterShed Segmentation :
val marker_tempo = Mat()
markers.convertTo(marker_tempo, CvType.CV_32S)
Imgproc.watershed(rgba, marker_tempo)
marker_tempo.convertTo(markers, CvType.CV_8U)
result_Bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565)
Imgproc.applyColorMap(markers, markers, COLORMAP_BONE)
Utils.matToBitmap(markers, result_Bitmap)
image.setImageBitmap(result_Bitmap)
return currentPhotoPath
}
}
输出:
最佳答案
最简单的方法是添加mask
参数到 add方法。您需要创建 image of rectangle rect
为此工作。使用厚度 = FILLED绘制填充矩形。
val rectImage = Mat(rgba.size(), CvType.CV_8U)
Imgproc.rectangle(rectImage, coordinates, Scalar(255, 255, 255), Imgproc.FILLED)
Core.add(fg, bg, markers, rectImage)
其他选项
你可以乘
markers
矩形图像逐像素图像。只有矩形内的硬币像素将保留。但是,在这种情况下,您需要确保要相乘的图像范围为 [0, 1],但您的图像范围为 [0, 255]。所以,为了让它工作,只需divide图片按 255,然后 multiply他们,最后multiply结果为 255。还有方法 multiply(Mat src1, Mat src2, Mat dst, double scale)可以将矩阵相乘,然后一次将结果乘以 255。
另一种方法是使用 bitwise and手术。在这种情况下,您无需转换为范围 [0, 1]。
val rectImage = Mat(rgba.size(), CvType.CV_8U)
Imgproc.rectangle(rectImage, coordinates, Scalar(255, 255, 255), Imgproc.FILLED)
val clippedMarkers = Mat(rgba.size(), CvType.CV_8U)
Core.bitwise_and(markers, rectImage, clippedMarkers)
另一种选择是使用 copyTo方法。它将掩码作为第三个参数。
val rectImage = Mat(rgba.size(), CvType.CV_8U)
Imgproc.rectangle(rectImage, coordinates, Scalar(255, 255, 255), Imgproc.FILLED)
val clippedMarkers = Mat(rgba.size(), CvType.CV_8U)
Core.copyTo(markers, clippedMarkers, rectImage)
关于java - 如何在分水岭的分割中添加坐标?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61531980/