简体   繁体   中英

Watershed in Opencv Android

I was trying to implement watershed function from OpenCV on Android. However my program always crashed at the place where watershed function is called. I can output the marker's result perfectly fine. But the watershed function always just crashes. Here is my code:

         Mat threeChannel = new Mat();
         Imgproc.cvtColor(mRgba, threeChannel, Imgproc.COLOR_BGR2GRAY);
         Imgproc.threshold(threeChannel, threeChannel, 100, 255, Imgproc.THRESH_BINARY);

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

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

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

         WatershedSegmenter segmenter = new WatershedSegmenter();
         segmenter.setMarkers(markers);
         Mat result = segmenter.process(mRgba);

         return result;

WatershedSegmenter calss is as follows:

public class WatershedSegmenter{
    public Mat markers;

    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;
    }
}

Has anybody managed to get this working on Android before? I managed to get it to work in C++ with Qt before following this tutorial: link . However I haven't got any luck on Android at the moment.

I found out the reason of crash now. watershed is taking a 8 bit 3 channel format of data, and RGBA is a 4 channel data. I just convert it from RGBA to RGB, and it solved all the issues.

Your Mat doesn't match the correct .depth() and/or .channel(). The first step is to double-check each Mat has the type you think it does by using the myMat.depth() and myMat.channels() functions. The function watershed uses two Mat arguments. The first should be an 8-bit, 3-channel image, and the second should be a 32-bit single-channel image.

If they are not the right kind of image, use cvtColor to convert from what you have to what you need.

Try out this solution

BitmapFactory.Options o = new BitmapFactory.Options();
       o.inDither = false;
       o.inSampleSize=4;

       int width , height ;
       width  = src_Bitmap.getWidth();
       height = src_Bitmap.getHeight();



       Mat rgba = new Mat();
       Mat gray_mat= new Mat();
       Mat threeChannel = new Mat();



       Utils.bitmapToMat(src_Bitmap,gray_mat);

       Imgproc.cvtColor(gray_mat,rgba , Imgproc.COLOR_RGBA2RGB);


       Imgproc.cvtColor(rgba, threeChannel, Imgproc.COLOR_RGB2GRAY);
       Imgproc.threshold(threeChannel, threeChannel, 100, 255, Imgproc.THRESH_OTSU);


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

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



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

       // Start the WaterShed Segmentation :


       Mat marker_tempo = new 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,4 );
       Utils.matToBitmap( markers,result_Bitmap);


        myImageView.setImageBitmap(result_Bitmap);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM