bounty到期在6天内。该问题的答案有资格获得+ 50声望赏金。Carlos Diego希望引起更多关注对此问题:我需要使用分水岭来执行此任务,所以请有人可以帮助我更新此代码。
我正在开发一个用于检测病变区域的应用程序,为此,我正在使用抓取来检测ROI并从图像中删除背景。但是,在某些图像中,它不能很好地工作。他最终没有很好地确定感兴趣区域的边界。分水岭可以更好地识别此类工作的边缘,但是,我很难从抓斗过渡到分水岭。在处理抓取图像之前,用户使用touchevent在感兴趣的图像(伤口区域)周围标记一个矩形,以方便算法的工作。如下图所示。
但是,使用其他伤口图像,分割效果不好,显示了ROI检测的缺陷。
[在应用中使用抓取图像
使用桌面中的分水岭的图像
这是代码:private fun extractForegroundFromBackground(coordinates: Coordinates, currentPhotoPath: String): String {
// TODO: Provide complex object that has both path and extension
// Matrices that OpenCV will be using internally
val gray_mat = Mat()
val threeChannel = Mat()
val srcImage = Imgcodecs.imread(currentPhotoPath)
val iterations = 5
Imgproc.cvtColor(srcImage, gray_mat, Imgproc.COLOR_RGBA2RGB)
Imgproc.cvtColor(srcImage, threeChannel, Imgproc.COLOR_RGB2GRAY)
Imgproc.threshold(threeChannel, threeChannel, 0.0, 255.0, Imgproc.THRESH_OTSU)
val fg = Mat(srcImage.size(), CvType.CV_8U)
Imgproc.erode(threeChannel, fg, Mat(), Point(-1.0, -1.0), 2)
val bg = Mat(srcImage.size(), CvType.CV_8U)
Imgproc.dilate(threeChannel, bg, Mat(), Point(-1.0, -1.0), 3)
Imgproc.threshold(bg, bg, 1.0, 128.0, Imgproc.THRESH_BINARY_INV)
val firstMask = Mat(srcImage.size(), CvType.CV_8U, Scalar(0.0))
val marker_tempo = Mat()
firstMask.convertTo(marker_tempo, CvType.CV_32S)
Imgproc.watershed(srcImage, marker_tempo)
marker_tempo.convertTo(firstMask, CvType.CV_8U)
// Mask image where we specify which areas are background, foreground or probable background/foreground
//val firstMask = Mat()
val source = Mat(1, 1, CvType.CV_8U, Scalar(Imgproc.GC_PR_FGD.toDouble()))
val rect = Rect(coordinates.first, coordinates.second)
// Run the grab cut algorithm with a rectangle (for subsequent iterations with touch-up strokes,
// flag should be Imgproc.GC_INIT_WITH_MASK)
Imgproc.grabCut(srcImage, firstMask, rect, bg, fg, iterations, Imgproc.GC_INIT_WITH_RECT)
// Create a matrix of 0s and 1s, indicating whether individual pixels are equal
// or different between "firstMask" and "source" objects
// Result is stored back to "firstMask"
Core.compare(firstMask, source, firstMask, Core.CMP_EQ)
// Create a matrix to represent the foreground, filled with white color
val foreground = Mat(srcImage.size(), CvType.CV_8UC3, Scalar(255.0, 255.0, 255.0))
// Copy the foreground matrix to the first mask
srcImage.copyTo(foreground, firstMask)
// Create a red color
val color = Scalar(255.0, 0.0, 0.0, 255.0)
// Draw a rectangle using the coordinates of the bounding box that surrounds the foreground
Imgproc.rectangle(srcImage, coordinates.first, coordinates.second, color)
// Create a new matrix to represent the background, filled with black color
val background = Mat(srcImage.size(), CvType.CV_8UC3, Scalar(0.0, 0.0, 0.0))
val mask = Mat(foreground.size(), CvType.CV_8UC1, Scalar(255.0, 255.0, 255.0))
// Convert the foreground's color space from BGR to gray scale
Imgproc.cvtColor(foreground, mask, Imgproc.COLOR_BGR2GRAY)
// Separate out regions of the mask by comparing the pixel intensity with respect to a threshold value
Imgproc.threshold(mask, mask, 254.0, 255.0, Imgproc.THRESH_BINARY_INV)
// Create a matrix to hold the final image
val dst = Mat()
// copy the background matrix onto the matrix that represents the final result
background.copyTo(dst)
val vals = Mat(1, 1, CvType.CV_8UC3, Scalar(0.0))
// Replace all 0 values in the background matrix given the foreground mask
background.setTo(vals, mask)
// Add the sum of the background and foreground matrices by applying the mask
Core.add(background, foreground, dst, mask)
// Save the final image to storage
Imgcodecs.imwrite(currentPhotoPath + "_tmp.png", dst)
// Clean up used resources
firstMask.release()
source.release()
bg.release()
fg.release()
vals.release()
dst.release()
return currentPhotoPath
}
如何更新代码以使用分水岭而不是抓取?