Ask Your Question

Revision history [back]

click to hide/show revision 1
initial version

How to draw contours INSIDE the edges of detected shape/blob?

Following is an image of a blue colored blob detected in an Android app using OpenCV4Android. I used Core.inRange() and Imgproc.findContours() methods to find the contours, and Imgproc.drawContours() to draw em.

Mat mask = new Mat();
Core.inRange(rgbaMat, lowerThreshold, upperThreshold, mask);
...
contours = new ArrayList<>();
Imgproc.findContours(dilatedMat, contours, new Mat(), Imgproc.RETR_EXTERNAL, Imgproc.CHAIN_APPROX_SIMPLE);
...
for ( int contourIdx=0; contourIdx < contours.size(); contourIdx++ ) { 
    Imgproc.drawContours ( rgbaMat, contours, contourIdx, new Scalar(0, 255, 0), 1);
}

The contour (light green boundary) is outside the detected shape.

So, as you can see, it also includes some white area around the detected blue blob. I want the contour boundary to be inside the edges of the blue blob/shape. How can I do that?

How to draw contours INSIDE the edges of detected shape/blob?

Following is an image of a blue colored blob detected in an Android app using OpenCV4Android. I used Core.inRange() and Imgproc.findContours() methods to find the contours, and Imgproc.drawContours() to draw em.

Mat mask = new Mat();
Core.inRange(rgbaMat, lowerThreshold, upperThreshold, mask);
...
contours = new ArrayList<>();
Imgproc.findContours(dilatedMat, contours, new Mat(), Imgproc.RETR_EXTERNAL, Imgproc.CHAIN_APPROX_SIMPLE);
...
for ( int contourIdx=0; contourIdx < contours.size(); contourIdx++ ) { 
    Imgproc.drawContours ( rgbaMat, contours, contourIdx, new Scalar(0, 255, 0), 1);
}

The contour (light green boundary) is outside the detected shape.

So, as you can see, it also includes some white area around the detected blue blob. I want the contour boundary to be inside the edges of the blue blob/shape. How can I do that?

image description

How to draw contours INSIDE the edges of detected shape/blob?

Following is an image of a blue colored blob detected in an Android app using OpenCV4Android. I used Core.inRange() and Imgproc.findContours() methods to find the contours, and Imgproc.drawContours() to draw em.

Mat mask = new Mat();
Core.inRange(rgbaMat, lowerThreshold, upperThreshold, mask);
...
contours = new ArrayList<>();
Imgproc.findContours(dilatedMat, contours, new Mat(), Imgproc.RETR_EXTERNAL, Imgproc.CHAIN_APPROX_SIMPLE);
...
for ( int contourIdx=0; contourIdx < contours.size(); contourIdx++ ) { 
    Imgproc.drawContours ( rgbaMat, contours, contourIdx, new Scalar(0, 255, 0), 1);
}

The contour (light green boundary) is outside the detected shape.

So, as you can see, it also includes some white area around the detected blue blob. I want the contour boundary to be inside the edges of the blue blob/shape. How can I do that?

image description


EDIT: @sturkmen

Original Image:

image description

(These are my complete files:*

MainActivity.java:

public class MainActivity extends Activity implements CvCameraViewListener2 {
    private static final String TAG = MainActivity.class.getSimpleName();
    private static Mat rgbaFrame;
    private static final int pickImageRequestCode = 99;
    private Mat rgbaMat;
    private Mat rgbaMatCopy;
    private ArrayList<MatOfPoint> contours;
    private ImageView imageView;


    private CameraBridgeViewBase cameraBridgeViewBase;

    private BaseLoaderCallback baseLoaderCallback = new BaseLoaderCallback(this) {
        @Override
        public void onManagerConnected(int status) {
            switch (status) {
            case LoaderCallbackInterface.SUCCESS: {
                Log.i(TAG, "OpenCV loaded successfully!");
                if (cameraBridgeViewBase != null) {
                    cameraBridgeViewBase.enableView();
                }
            }
                break;
            default: {
                super.onManagerConnected(status);
            }
                break;
            }
        }
    };




    @Override
    public void onCameraViewStarted(int width, int height) {
        rgbaFrame = new Mat(height, width, CvType.CV_8UC4);
    }

    @Override
    public void onCameraViewStopped() {
        rgbaFrame.release();
    }

    @Override
    public Mat onCameraFrame(CvCameraViewFrame inputFrame) {
        rgbaFrame = inputFrame.rgba();
        return rgbaFrame;
    }





    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_main);
        imageView = (ImageView) findViewById(R.id.mainActivity_imageView);

        OpenCVLoader.initAsync(OpenCVLoader.OPENCV_VERSION_2_4_3, this, baseLoaderCallback);

        Intent intent = new Intent(Intent.ACTION_PICK,
                android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
        startActivityForResult(intent, pickImageRequestCode);
    }

    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent imageReturnedIntent) {
        super.onActivityResult(requestCode, resultCode, imageReturnedIntent);

        if (resultCode == Activity.RESULT_OK && requestCode == pickImageRequestCode) {
            Uri selectedImageUri = imageReturnedIntent.getData();
            String[] filePathColumn = { MediaStore.Images.Media.DATA };
            Cursor cursor = getContentResolver().query(selectedImageUri, filePathColumn, null, null, null);
            cursor.moveToFirst();
            int columnIndex = cursor.getColumnIndex(filePathColumn[0]);
            String filePath = cursor.getString(columnIndex);
            cursor.close();

            rgbaMat = new Mat();
            rgbaMatCopy = new Mat();
            rgbaMat = Highgui.imread(filePath);
            rgbaMatCopy = Highgui.imread(filePath);

            Imgproc.cvtColor(rgbaMat, rgbaMat, Imgproc.COLOR_BGR2RGB);
            Imgproc.cvtColor(rgbaMatCopy, rgbaMatCopy, Imgproc.COLOR_BGR2RGB);

            Mat hsvMat = new Mat();
            Imgproc.cvtColor(rgbaMatCopy, hsvMat, Imgproc.COLOR_RGB2HSV);

            Scalar lowerThreshold = new Scalar(100, 146, 148);
            Scalar upperThreshold = new Scalar(134, 255, 255);
            Mat mask = new Mat();
            Core.inRange(hsvMat, lowerThreshold, upperThreshold, mask);

            Mat dilatedMask = new Mat();
            Imgproc.dilate(mask, dilatedMask, new Mat());
            Imgproc.dilate(dilatedMask, dilatedMask, new Mat());

            contours = new ArrayList<>();
            Imgproc.findContours(dilatedMask, contours, new Mat(), Imgproc.RETR_EXTERNAL, Imgproc.CHAIN_APPROX_SIMPLE);

            for (int contourIdx = 0; contourIdx < contours.size(); contourIdx++) {
                Imgproc.drawContours(rgbaMatCopy, contours, contourIdx, new Scalar(0, 255, 0), 1);
            }

            Bitmap theBitmap = Bitmap.createBitmap(rgbaMatCopy.cols(), rgbaMatCopy.rows(),
                    Bitmap.Config.ARGB_8888);
            Utils.matToBitmap(rgbaMatCopy, theBitmap);
            imageView.setImageBitmap(theBitmap);
        }

    }
}

activity_main.xml:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="${relativePackage}.${activityClass}" >

    <ImageView
        android:id="@+id/mainActivity_imageView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:scaleType="fitXY" />

</RelativeLayout>