Ask Your Question

Revision history [back]

Simplest way to do an image registration

Hello, I'm literally losing my mind to find a solution to my problem: I've an Android App which shots two images on a small delta time. Now even if this delta is very small images are always a bit shifted (around 20/30px). My question is simple, I want just know how many pixel they shifted, nothing more. I think that OpenCV is the better solution since I'm not able to understand how SURF keypoint detection implementation works, but I getting many troubles to implement this in my Android App. Please could someone tell me the right way to do this? maybe even with a small piece of code (in pure Java or android native C)?

This is what I've now (looking around some tutorials) but I really don't know how move forward.

Thank you

//Bitmap to Mat
    Utils.bitmapToMat(tmp2, mObjectMat);
    Utils.bitmapToMat(tmp1, mSceneMat);
    Mat img3 = mSceneMat.clone();

    //Use the FeatureDetector interface in order to find interest points/keypoints in an image.
    FeatureDetector fd = FeatureDetector.create(FeatureDetector.ORB);
    fd.detect(mObjectMat, keypoints_object );
    fd.detect(mSceneMat, keypoints_scene );

    //DescriptorExtractor
    //A descriptor extractor is an algorithm that generates a description of a keypoint that
    // makes this keypoint recognizable by a matcher. Famous descriptors are SIFT, FREAK...
    DescriptorExtractor extractor = DescriptorExtractor.create(DescriptorExtractor.ORB);
    extractor.compute(mObjectMat, keypoints_object, descriptors_object );
    extractor.compute(mSceneMat, keypoints_scene, descriptors_scene );

    //DescriptorMatcher
    //Use a DescriptorMatcher for matching keypoint descriptors.
    DescriptorMatcher matcher = DescriptorMatcher.create(DescriptorMatcher.BRUTEFORCE_HAMMING);
    matcher.match( descriptors_object, descriptors_scene, matches);

    //Calculate max and min distances between keypoints
    matchesList = matches.toList();
    for( int i = 0; i < descriptors_object.rows(); i++ )
    {
        Double dist = (double) matchesList.get(i).distance;
        if( dist < minDistance ) minDistance = dist;
        if( dist > maxDistance ) maxDistance = dist;
    }

    ////Draw only good matches
    for(int i = 0; i < descriptors_object.rows(); i++){
        if(matchesList.get(i).distance < 3*minDistance){
            good_matches.addLast(matchesList.get(i));
        }
    }
    gm.fromList(good_matches);
    matchesFound = good_matches.size();

    //Draw the matches
    Features2d.drawMatches(mObjectMat, keypoints_object, mSceneMat, keypoints_scene, gm, img3);

    //Localize the object & find the keypoints from the good matches
    List<KeyPoint> keypoints_objectList = keypoints_object.toList();
    List<KeyPoint> keypoints_sceneList = keypoints_scene.toList();

    for(int i = 0; i<good_matches.size(); i++){
        objList.addLast(keypoints_objectList.get(good_matches.get(i).queryIdx).pt);
        sceneList.addLast(keypoints_sceneList.get(good_matches.get(i).trainIdx).pt);
    }

    obj.fromList(objList);
    scene.fromList(sceneList);

    //Find homography between the scene and the object to recognize
    Mat hg = Calib3d.findHomography(obj, scene, Calib3d.RANSAC, minDistance);

    //Get the corners from the mObjectToDetectMat
    Mat obj_corners = new Mat(4,1, CvType.CV_32FC2);
    Mat scene_corners = new Mat(4,1,CvType.CV_32FC2);

    obj_corners.put(0, 0, new double[] {0,0});
    obj_corners.put(1, 0, new double[] {mObjectMat.cols(),0});
    obj_corners.put(2, 0, new double[] {mObjectMat.cols(),mObjectMat.rows()});
    obj_corners.put(3, 0, new double[] {0,mObjectMat.rows()});

    Core.perspectiveTransform(obj_corners, scene_corners, hg);

    Imgproc.line(img3, new Point(scene_corners.get(0,0)), new Point(scene_corners.get(1,0)), new Scalar(0, 255, 0),4);
    Imgproc.line(img3, new Point(scene_corners.get(1,0)), new Point(scene_corners.get(2,0)), new Scalar(0, 255, 0),4);
    Imgproc.line(img3, new Point(scene_corners.get(2,0)), new Point(scene_corners.get(3,0)), new Scalar(0, 255, 0),4);
    Imgproc.line(img3, new Point(scene_corners.get(3,0)), new Point(scene_corners.get(0,0)), new Scalar(0, 255, 0),4);