1

I am writing an sample using watershed algorithm of OpenCV. I am able to create the mask image, however, the mask has a white background instead of transparent background.Is there a way to remove this white background and make it transparent? The code I am using is provided below:

Mat threeChannel = new Mat();

Imgproc.cvtColor(croppedImageMat, threeChannel, Imgproc.COLOR_BGR2GRAY);
Imgproc.threshold(threeChannel, threeChannel, 100, 255, Imgproc.THRESH_BINARY | Imgproc.THRESH_OTSU);

Mat fg = new Mat(croppedImageMat.size(), CvType.CV_8U);
Imgproc.erode(threeChannel, fg, new Mat(), new Point(-1, -1), 12);

Mat bg = new Mat(croppedImageMat.size(), CvType.CV_8U);
Imgproc.dilate(threeChannel, bg, new Mat(), new Point(-1, -1), 12);
Imgproc.threshold(bg, bg, 1, 128, Imgproc.THRESH_BINARY_INV);

Mat markers = new Mat(croppedImageMat.size(), CvType.CV_8U, new Scalar(0));
Core.add(fg, bg, markers);

WatershedSegmenter segmenter = new WatershedSegmenter();
segmenter.setMarkers(markers);
Mat result = segmenter.process(croppedImageMat);
Bitmap resultBmp = Bitmap.createBitmap(result.cols(), result.rows(), Bitmap.Config.ARGB_8888);
Utils.matToBitmap(result, resultBmp);
Constants.writeBitmapToFile(resultBmp);

public class WatershedSegmenter {
    public Mat markers = new Mat();

    public void setMarkers(Mat markerImage) {
        markerImage.convertTo(markers, CvType.CV_32S);
    }

    public Mat process(Mat image) {
        Imgproc.watershed(image, markers);
        markers.convertTo(markers, CvType.CV_8U);
        return markers;
    }
}

I intend to create an image using Android's PorterDuff mode by drawing the source image and mask to an offscreen canvas. Please let me know if I doing something wrong here.

Vivek
  • 680
  • 1
  • 12
  • 24
  • i'm really in need of help with this question, can you help me, please? https://stackoverflow.com/questions/61216402/how-to-improve-image-segmentation-using-the-watershed – Carlos Diego Apr 28 '20 at 17:14

1 Answers1

1

You can use binary mask to get transparency effect.

Just use this mask for copying your fragment to background.

see method A.copyTo(B,mask);

If you want get semitransparency, you can use the equation

R=fg.mul(mask)+bg.mul(1.0-mask);

where

  • R - result matrix (CV_32FC1),
  • fg - foreground image (CV_32FC1),
  • bg - background image (CV_32FC1),
  • mask - transparency layer (CV_32FC1) values range should be [0.0;1.0]

.

If you want work with 3 channel images, use cv::split metod, then process each channel as described above, after processing combine channels with cv::merge method.

Andrey Smorodov
  • 10,649
  • 2
  • 35
  • 42