Ask Your Question

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

asked 2016-06-25 05:57:54 -0500

Solace gravatar image

updated 2016-06-26 04:11:52 -0500

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:*

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) {
        public void onManagerConnected(int status) {
            switch (status) {
            case LoaderCallbackInterface.SUCCESS: {
                Log.i(TAG, "OpenCV loaded successfully!");
                if (cameraBridgeViewBase != null) {
            default: {

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

    public void onCameraViewStopped() {

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

    protected void onCreate(Bundle savedInstanceState) {

        imageView = (ImageView) findViewById(;

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

        Intent intent = new Intent(Intent.ACTION_PICK,
        startActivityForResult(intent, pickImageRequestCode);

    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);
            int columnIndex = cursor.getColumnIndex(filePathColumn[0]);
            String filePath = cursor.getString(columnIndex);

            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(),
            Utils.matToBitmap(rgbaMatCopy, theBitmap);



<RelativeLayout xmlns:android=""
    tools:context="${relativePackage}.${activityClass}" >

        android:layout_height ...
edit retag flag offensive close merge delete



i can help you if you post your whole code and the original image.

sturkmen gravatar imagesturkmen ( 2016-06-25 18:10:30 -0500 )edit

@sturkmen Thank you. I posted the complete code and the original image in the question.

Solace gravatar imageSolace ( 2016-06-26 04:12:59 -0500 )edit

1 answer

Sort by ยป oldest newest most voted

answered 2016-06-26 09:38:52 -0500

these lines are the key

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

you could try changing like

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

or to draw exact contour of blob

        Mat dilatedMask = mask.clone();
edit flag offensive delete link more
Login/Signup to Answer

Question Tools

1 follower


Asked: 2016-06-25 05:57:54 -0500

Seen: 427 times

Last updated: Jun 26 '16