0

I'm pretty new to openCV, and at the moment im tryin to get an object detection running on an android device. What i basically do, is displaying a a camera preview in my app, and when i click on it it captures a picture. Then this picture is given to the runFeatureHomography - method, which first grabs the second image to which the taken image has to be compared. Then the method finds the keypoints in both pictures, computes them and matches them into one Mat called img_matches. As basic as it can be i guess.

The object im trying to detect here at the moment is some kind of card, just like the format of a credit card. The card is blue and has lots of white and yellow text on it. I can only post one link, thats why i cant show pictures of them.

I dont know why, but when i display the result in the end / or save the result as a bitmap to my phone, it always looks kinda like this:

http://oi44.tinypic.com/oaqel0.jpg <-- result image after everything is done.

This shows me that the object i wanted to detect was indeed detected, but i dont know why there is a black background and not the pictures of the cards. Why doesn't it show my two images the way the are, just with all the lines on them?

In my code im using those three:

FeatureDetector detector = FeatureDetector.create(FeatureDetector.ORB);
DescriptorExtractor extractor = DescriptorExtractor.create(DescriptorExtractor.ORB);
DescriptorMatchermatcher = DescriptorMatcher.create(DescriptorMatcher.BRUTEFORCE);

Here is some of my code:

private void runFeatureHomography(Bitmap image)
{

    Mat img_object = getObjectImage();
    Mat img_scene = newEmptyMat();

    Bitmap myimg = image.copy(Bitmap.Config.ARGB_8888, true);

    Utils.bitmapToMat(myimg, img_scene);

    MatOfKeyPoint keyPoints_object = detectObjectKeyPoints();
    MatOfKeyPoint keyPoints_scene = new MatOfKeyPoint();

    this.detector.detect(img_scene, keyPoints_scene);

    Mat descriptors_object = calculateObjectDescriptor();
    Mat descriptors_scene = newEmptyMat();

    this.extractor.compute(img_scene, keyPoints_scene, descriptors_scene);

    MatOfDMatch matches = new MatOfDMatch();

    matcher.match(descriptors_object, descriptors_scene, matches);

    double min_dist = Double.MAX_VALUE;
    for (int i = -1; ++i < descriptors_object.rows();)
    {
        double dist = matches.toArray()[i].distance;
        if (dist < min_dist)
        {
            min_dist = dist;
        }
    }


    List<DMatch> good_matches = new ArrayList<DMatch>();
    for (int i = -1; ++i < descriptors_object.rows();)
    {
        if (matches.toArray()[i].distance <= 3 * min_dist)
        {
            good_matches.add(matches.toArray()[i]);
        }
    }

    System.out.println("4");
    Mat img_matches = newEmptyMat();
    Features2d.drawMatches(
            img_object,
            keyPoints_object,
            img_scene,
            keyPoints_scene,
            new MatOfDMatch(good_matches.toArray(new DMatch[good_matches
                    .size()])), img_matches, Scalar.all(-1),
            Scalar.all(-1), new MatOfByte(),
            Features2d.NOT_DRAW_SINGLE_POINTS);

    List<Point> object = new ArrayList<Point>();
    List<Point> scene = new ArrayList<Point>();
    for (int i = -1; ++i < good_matches.size();)
    {
        object.add(keyPoints_object.toArray()[good_matches.get(i).queryIdx].pt);
        scene.add(keyPoints_scene.toArray()[good_matches.get(i).trainIdx].pt);
    }

    Mat H = Calib3d.findHomography(
            new MatOfPoint2f(object.toArray(new Point[object.size()])),
            new MatOfPoint2f(scene.toArray(new Point[scene.size()])),
            Calib3d.RANSAC, 3);

    Point[] object_corners = new Point[4];
    object_corners[0] = new Point(0, 0);
    object_corners[1] = new Point(img_object.cols(), 0);
    object_corners[2] = new Point(img_object.cols(), img_object.rows());
    object_corners[3] = new Point(0, img_object.rows());

    MatOfPoint2f scene_corners2f = new MatOfPoint2f();
    Core.perspectiveTransform(new MatOfPoint2f(object_corners),
            scene_corners2f, H);

    Point[] scene_corners = scene_corners2f.toArray();
    Point[] scene_corners_norm = new Point[4];
    scene_corners_norm[0] = new Point(scene_corners[0].x
            + img_object.cols(), scene_corners[0].y);
    scene_corners_norm[1] = new Point(scene_corners[1].x
            + img_object.cols(), scene_corners[1].y);
    scene_corners_norm[2] = new Point(scene_corners[2].x
            + img_object.cols(), scene_corners[2].y);
    scene_corners_norm[3] = new Point(scene_corners[3].x
            + img_object.cols(), scene_corners[3].y);
    Core.line(img_matches, scene_corners_norm[0], scene_corners_norm[1],
            new Scalar(0, 255, 0), 4);
    Core.line(img_matches, scene_corners_norm[1], scene_corners_norm[2],
            new Scalar(0, 255, 0), 4);
    Core.line(img_matches, scene_corners_norm[2], scene_corners_norm[3],
            new Scalar(0, 255, 0), 4);
    Core.line(img_matches, scene_corners_norm[3], scene_corners_norm[0],
            new Scalar(0, 255, 0), 4);

    bmp = Bitmap.createBitmap(img_matches.cols(), img_matches.rows(),
            Bitmap.Config.ARGB_8888);


     Intent resultIntent = new Intent("com.example.capturetest.Result");
     startActivity(resultIntent);

}

private volatile Mat cachedObjectDescriptor = null;
private volatile MatOfKeyPoint cachedObjectKeyPoints = null;
private volatile Mat cachedObjectImage = null;

private Mat calculateObjectDescriptor()
{
    Mat objectDescriptor = this.cachedObjectDescriptor;
    if (objectDescriptor == null)
    {
        Mat objectImage = getObjectImage();
        MatOfKeyPoint objectKeyPoints = detectObjectKeyPoints();
        objectDescriptor = newEmptyMat();
        this.extractor.compute(objectImage, objectKeyPoints,
                objectDescriptor);
        this.cachedObjectDescriptor = objectDescriptor;
    }
    return objectDescriptor;
}

private MatOfKeyPoint detectObjectKeyPoints()
{
    MatOfKeyPoint objectKeyPoints = this.cachedObjectKeyPoints;
    if (objectKeyPoints == null)
    {
        Mat objectImage = getObjectImage();
        objectKeyPoints = new MatOfKeyPoint();
        this.detector.detect(objectImage, objectKeyPoints);
        this.cachedObjectKeyPoints = objectKeyPoints;
    }
    return objectKeyPoints;
}

private Mat getObjectImage()
{
    Mat objectImage = this.cachedObjectImage;
    if (objectImage == null)
    {
        objectImage = newEmptyMat();
        Bitmap bitmap = ((BitmapDrawable) iv.getDrawable()).getBitmap();
        Bitmap img = bitmap.copy(Bitmap.Config.ARGB_8888, false);
        Utils.bitmapToMat(img, objectImage);

        this.cachedObjectImage = objectImage;
    }
    return objectImage;
}

private Mat newEmptyMat()
{
    return new Mat();
}

After this line matcher.match(descriptors_object, descriptors_scene, matches); i tried to convert the three Mat img_object, img_scene and matches to bitmaps and saved them to my android device just for checking. They all look as they are supposed to look, so until this point everthing is fine.

But after this part...

 Mat img_matches = newEmptyMat();
    Features2d.drawMatches(
            img_object,
            keyPoints_object,
            img_scene,
            keyPoints_scene,
            new MatOfDMatch(good_matches.toArray(new DMatch[good_matches
                    .size()])), img_matches, Scalar.all(-1),
            Scalar.all(-1), new MatOfByte(),
            Features2d.NOT_DRAW_SINGLE_POINTS);

... i tried to convert the Mat img_matches (which is supposed to have all the information of the two input pictures if i get it right), to a bitmap and save it on my android device, but the picture looks like the picture in the link above (black pictures with lines instead of card-pictures with lines).

Does any of you know what im doing wrong here? I seem to be stuck at the moment.

Thanks in advance guys.

Edit:

Just wanted to let you know that i got the same code running and WORKING as a normal java program on my desktop. The picture is taken from the webcam there. The result image is diplayed absolutely correct in the desktop program, with cards and lines instead of black and lines ;)

user2677466
  • 139
  • 1
  • 13
  • Have you found the solution??, the answer given by user2677466 doesnt seems to be work for me. I have used your code and i got error in findHomography method, does same thing happened with you?, can you please help me out – Mehul Thakkar Jan 01 '14 at 10:05
  • if possible can you please provide me java code that is working for your desktop program... – Mehul Thakkar Jan 01 '14 at 10:09

1 Answers1

0

Alright, found a working way:

Imgproc.cvtColor(img_object, img_object, Imgproc.COLOR_RGBA2RGB);
Imgproc.cvtColor(img_scene, img_scene, Imgproc.COLOR_RGBA2RGB);

It seems that after i converted my Bitmaps to Mats i have to use the above two lines to convert them from RGBA to RGB. It also works with RGBA to GRAY if you prefer gray pictures.

It seems that RGBA format is not working in this case.

Hope this helps anybody coming here from google.

user2677466
  • 139
  • 1
  • 13
  • I have tried the code above, but it is not working, actually the error i m getting in that one is in method findHomography – Mehul Thakkar Jan 01 '14 at 10:07