Ask Your Question
0

How to compare images and draw rectangles to mention the difference in Android

asked 2018-10-04 02:07:36 -0600

satheesh kumar gravatar image

updated 2018-10-04 02:45:06 -0600

I am a newbie for OpenCV and working with Android. For my case I need to find out the differences between two images and mark them with rectangles to the second image like the following image. Kindly help me for this. \

image description

I worked on comparing the two source images(second and third) and got the output image(fourth) as below. And tried to get contours of the output image and draw rectangles on that. But it didn't work. I have attached the activity code. Kindly look into that and help me to achieve this.

Thanks in advanced.

CODE:


package com.example.akshika.opencvtest;

import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.util.Log; import android.widget.ImageView;

import org.opencv.android.BaseLoaderCallback; import org.opencv.android.LoaderCallbackInterface; import org.opencv.android.OpenCVLoader; import org.opencv.android.Utils; import org.opencv.core.Core; import org.opencv.core.CvType; import org.opencv.core.Mat; import org.opencv.core.MatOfPoint; import org.opencv.core.Point; import org.opencv.core.Rect; import org.opencv.core.Scalar; import org.opencv.imgproc.Imgproc;

import java.util.ArrayList; import java.util.List;

public class Main2Activity extends AppCompatActivity { Mat firstMat, secondMat, outputImageMat, outputMat = new Mat(); Bitmap firstBitmap, secondBitmap; ImageView firstImage, secondImage, outputImage;

static {
    if (!OpenCVLoader.initDebug())
        Log.d("ERROR", "Unable to load OpenCV");
    else
        Log.d("SUCCESS", "OpenCV loaded");
}

private BaseLoaderCallback mLoaderCallback = new BaseLoaderCallback(this) {
    @Override
    public void onManagerConnected(int status) {
        switch (status) {
            case LoaderCallbackInterface.SUCCESS: {
                Log.v("OpenCV", "OpenCV loaded successfully");
            }
            break;
            default: {
                Log.v("OpenCV", "OpenCV loaded fail");
                super.onManagerConnected(status);
            }
            break;
        }
    }
};

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main2);

    firstImage = (ImageView) findViewById(R.id.imageinput1);
    secondImage = (ImageView) findViewById(R.id.imageinput2);
    outputImage = (ImageView) findViewById(R.id.imageoutput);

    firstBitmap = drawableToBitmap(R.drawable.image1);
    secondBitmap = drawableToBitmap(R.drawable.image2);

    firstImage.setImageBitmap(firstBitmap);
    secondImage.setImageBitmap(secondBitmap);
    outputImage.setImageResource(R.drawable.img);

    firstMat = setBitmapToMat(firstBitmap);
    secondMat = setBitmapToMat(secondBitmap);
    outputImageMat = new Mat(secondMat.size(), CvType.CV_8UC1);

    Core.compare(firstMat, secondMat, outputImageMat, Core.CMP_LE);

// Core.absdiff(firstMat, secondMat, outputImageMat);

    List<MatOfPoint> contours = new ArrayList<>();

    Imgproc.cvtColor(outputImageMat, outputMat, Imgproc.COLOR_BGR2GRAY);
    Imgproc.findContours(outputMat, contours, new Mat(), Imgproc.RETR_EXTERNAL, Imgproc.CHAIN_APPROX_SIMPLE);

    for (int i = 0; i < contours.size(); i++) {
        Rect rect = Imgproc.boundingRect(contours.get(i));
        Imgproc.rectangle(outputImageMat, new Point(rect.x, rect.y), new Point(rect.x + rect.width,
                rect.y + rect.height), new Scalar(0, 0, 255), 2);
    }
    outputImage.setImageBitmap(setOutputMatToBitmap(outputImageMat));

}

Bitmap drawableToBitmap(int drawable) {
    BitmapFactory.Options opt = new BitmapFactory.Options();
    opt.inMutable = true;
    return BitmapFactory.decodeResource(getResources(), drawable, opt);
}

Bitmap setOutputMatToBitmap(Mat mat) {
    Bitmap scale = Bitmap.createBitmap(mat.width(), mat.height(), Bitmap.Config.ARGB_8888);

// Imgproc.cvtColor(mat, mat, Imgproc.COLOR_BGR2RGBA); Utils.matToBitmap(mat, scale); return scale; }

Mat setBitmapToMat(Bitmap bitmap) {
    Mat mat = new Mat();

    Bitmap bmp32 = bitmap.copy(Bitmap.Config.ARGB_8888, true);
    Utils.bitmapToMat(bmp32, mat);
    return mat;
}

}


image description

image description image description

edit retag flag offensive close merge delete

Comments

what have you tried, so far ? please show your attempt.

berak gravatar imageberak ( 2018-10-04 02:14:02 -0600 )edit
1

Thanks for reply berak. I have updated the question. Kindly look into that.

satheesh kumar gravatar imagesatheesh kumar ( 2018-10-04 02:43:13 -0600 )edit

cool, thank you ! (esp. the images were helpful to diagnose your problem.)

berak gravatar imageberak ( 2018-10-04 02:43:57 -0600 )edit

1 answer

Sort by ยป oldest newest most voted
0

answered 2018-10-04 03:02:58 -0600

berak gravatar image

updated 2018-10-04 03:09:08 -0600

you're almost there !

when using Imgproc.RETR_EXTERNAL with findContours() , it expects white fg and black background (and you got it the other way round), so either:

Core.bitwise_not(outputMat, outputMat); // invert white / black

or simply invert the comparison:

Core.compare(firstMat, secondMat, outputImageMat, Core.CMP_GT);
edit flag offensive delete link more

Comments

I tried with the below code. But it gives blank Mat.

Core.compare(firstMat, secondMat, outputImageMat, Core.CMP_GT); Core.bitwise_not(outputMat,outputMat);

    List<MatOfPoint> contours = new ArrayList<>();

    Imgproc.cvtColor(outputImageMat, outputMat, Imgproc.COLOR_BGR2GRAY);
    Imgproc.findContours(outputMat, contours, new Mat(), Imgproc.RETR_EXTERNAL, Imgproc.CHAIN_APPROX_SIMPLE);

    for (int i = 0; i < contours.size(); i++) {
        Rect rect = Imgproc.boundingRect(contours.get(i));
        Imgproc.rectangle(outputImageMat, new Point(rect.x, rect.y), new Point(rect.x + rect.width,
                rect.y + rect.height), new Scalar(0, 0, 255), 2);
    }
    outputImage.setImageBitmap(setOutputMatToBitmap(outputImageMat));
satheesh kumar gravatar imagesatheesh kumar ( 2018-10-04 03:32:43 -0600 )edit

ok, i did not test it (no android here)

put the Core.bitwise_not(outputMat,outputMat); directly before the findContours()

berak gravatar imageberak ( 2018-10-04 03:36:11 -0600 )edit

That also not working. Anything I need to remove ( Core.Compare(...) or Imgproc.cvtcolor(...) ) from the above code?

satheesh kumar gravatar imagesatheesh kumar ( 2018-10-04 04:45:52 -0600 )edit

no, don't remove anything.

maybe you need to get creative, and come up with your own solution, the main point is still:

you need white foreground and black background for findContours
berak gravatar imageberak ( 2018-10-04 04:51:32 -0600 )edit

Let me try bro. Thanks for the useful reply. :-)

satheesh kumar gravatar imagesatheesh kumar ( 2018-10-04 04:59:01 -0600 )edit

Hi berak,

I got the desired result by using Core.absdiff(...) instead of Core.compare(...) . The "compare" method produces result as the same contours between the images and "absdiff" produces the different contours. I don't know whether I am right or wrong. Thanks for your kind support and information you shared. Thanks again. :-)

satheesh kumar gravatar imagesatheesh kumar ( 2018-10-04 23:57:55 -0600 )edit

Question Tools

1 follower

Stats

Asked: 2018-10-04 02:06:18 -0600

Seen: 3,491 times

Last updated: Oct 04 '18