Ask Your Question

Revision history [back]

click to hide/show revision 1
initial version

Feature recognition: perspective transform

I have implemented the C++ code found here in Java. However, it does not seem to work as I am getting this instead of a nice green outline around the detected image. Can anyone point out where the problem is?

My code is as following (and it's not the most beautiful one because of the so many needed conversions):

Note I am doing this matching with multiple images and the best matching (and other things) is stored at index 'bestMatch'; so in the scene image (index 0), I am looking for the best image match stored at index 1 to n, with bestMatch deemed best based on shortest distance.

//get the best match and show the matching with the original picture
        Mat matOut = new Mat();
        MatOfDMatch finalMatchess = new MatOfDMatch();
        DMatch[] finalMatches = new DMatch[goodMatches[bestMatch].size()];  //goodMatches contains the matches with 3*min_dist as in the C++ code
        for (int x=0;x<goodMatches[bestMatch].size();x++) {
            finalMatches[x] = goodMatches[bestMatch].get(x);
        }
        finalMatchess.fromArray(finalMatches);
        Features2d.drawMatches(mats[bestMatch],keyPoints[bestMatch],mats[0],keyPoints[0],finalMatchess,matOut);

        // stored the indexes for the good matches
        int[] usedQueryIds = new int[goodMatches[bestMatch].size()];
        int[] usedTrainIds = new int[goodMatches[bestMatch].size()];
        for (int x=0;x<goodMatches[bestMatch].size();x++) {
            usedQueryIds[x] = goodMatches[bestMatch].get(x).queryIdx;
            usedTrainIds[x] = goodMatches[bestMatch].get(x).trainIdx;
        }

        //get the points used in the matching
        Point[] kpBox = new Point[goodMatches[bestMatch].size()];
        Point[] kpBox2 = new Point[goodMatches[bestMatch].size()];
        KeyPoint[] kpp = keyPoints[bestMatch].toArray();
        for (int q=0;q<kpBox.length;q++) {
            kpBox[q] = kpp[usedQueryIds[q]].pt;
            kpBox2[q] = kp[usedTrainIds[q]].pt;
        }
        MatOfPoint2f bla = new MatOfPoint2f();
        MatOfPoint2f bla2 = new MatOfPoint2f();
        bla.fromArray(kpBox);
        bla2.fromArray(kpBox2);

        Mat H = Calib3d.findHomography(bla,bla2,Calib3d.RANSAC,5.);

        //create the points at the corners 
        List<Point> corners = new ArrayList<Point>();
        corners.add(new Point(0,0));
        corners.add(new Point(mats[bestMatch].cols(),0));
        corners.add(new Point(mats[bestMatch].cols(),mats[bestMatch].rows()));
        corners.add(new Point(0,mats[bestMatch].rows()));
        List<Point> sceneCorners = new ArrayList<Point>();

        //conversions
        MatOfPoint2f cornersMat = new MatOfPoint2f();
        cornersMat.fromList(corners);
        MatOfPoint2f sceneCornersMat = new MatOfPoint2f();
        sceneCornersMat.fromList(sceneCorners);

        Core.perspectiveTransform(cornersMat,sceneCornersMat,H);

        Point[] list = sceneCornersMat.toArray();

        Log.d(TAG,list[0].x + ",," + list[0].y);    //HERE they are too close together, not even forming a square
        Log.d(TAG,list[1].x + ",," + list[1].y);
        Log.d(TAG,list[2].x + ",," + list[2].y);
        Log.d(TAG,list[3].x + ",," + list[3].y);

        sceneCornersMat.put(0,0, sceneCornersMat.get(0,0)[0] + mats[bestMatch].cols(),sceneCornersMat.get(0,0)[1]);
        sceneCornersMat.put(1,0, sceneCornersMat.get(1,0)[0] + mats[bestMatch].cols(),sceneCornersMat.get(1,0)[1]);
        sceneCornersMat.put(2,0, sceneCornersMat.get(2,0)[0] + mats[bestMatch].cols(),sceneCornersMat.get(2,0)[1]);
        sceneCornersMat.put(3,0, sceneCornersMat.get(3,0)[0] + mats[bestMatch].cols(),sceneCornersMat.get(3,0)[1]);

        Imgproc.line(matOut,new Point(sceneCornersMat.get(0,0)),new Point(sceneCornersMat.get(1,0)), new Scalar(0,255,0),40);
        Imgproc.line(matOut,new Point(sceneCornersMat.get(1,0)),new Point(sceneCornersMat.get(2,0)), new Scalar(0,255,0),40);
        Imgproc.line(matOut,new Point(sceneCornersMat.get(2,0)),new Point(sceneCornersMat.get(3,0)), new Scalar(0,255,0),40);
        Imgproc.line(matOut,new Point(sceneCornersMat.get(3,0)),new Point(sceneCornersMat.get(1,0)), new Scalar(0,255,0),40);