Question

I am trying to run the feature detection program of javacv to compare the similar features in 2 images however I am getting a runtimeexception. Since I am completely new to javacv I don't know how to resolve this.

The exception trace is

OpenCV Error: Assertion failed (queryDescriptors.type() == trainDescCollection[0].type()) in     unknown function, file ..\..\..\src\opencv\modules\features2d\src\matchers.cpp, line 351
Exception in thread "main"   java.lang.RuntimeException: ..\..\..\src\opencv\modules\features2d\src\matchers.cpp:351: error: (-215) queryDescriptors.type() == trainDescCollection[0].type()


at com.googlecode.javacv.cpp.opencv_features2d$DescriptorMatcher.match(Native Method)
at Ex7DescribingSURF.main(Ex7DescribingSURF.java:63)

Here is the source code

    import static com.googlecode.javacv.cpp.opencv_core.NORM_L2;
    import static com.googlecode.javacv.cpp.opencv_core.cvCreateImage;
    import static com.googlecode.javacv.cpp.opencv_features2d.drawMatches;
    import static com.googlecode.javacv.cpp.opencv_highgui.cvLoadImage;
    import java.util.Arrays;
    import java.util.Comparator;        
    import javax.swing.JFrame;

    import com.googlecode.javacv.CanvasFrame;
    import com.googlecode.javacv.cpp.opencv_core.CvMat;
    import com.googlecode.javacv.cpp.opencv_core.CvScalar;
    import com.googlecode.javacv.cpp.opencv_core.CvSize;
    import com.googlecode.javacv.cpp.opencv_core.IplImage;
    import com.googlecode.javacv.cpp.opencv_features2d.BFMatcher;
    import com.googlecode.javacv.cpp.opencv_features2d.DMatch;
    import com.googlecode.javacv.cpp.opencv_features2d.DescriptorExtractor;
    import com.googlecode.javacv.cpp.opencv_features2d.DrawMatchesFlags;
    import com.googlecode.javacv.cpp.opencv_features2d.KeyPoint;
    import com.googlecode.javacv.cpp.opencv_nonfree.SURF;

    public class Ex7DescribingSURF {

        /**
         * Example for section "Describing SURF features" in chapter 8, page 212.
         * 
         * Computes SURF features, extracts their descriptors, and finds best
         * matching descriptors between two images of the same object. There are a
         * couple of tricky steps, in particular sorting the descriptors.
         */
        public static void main(String[] args) {
            IplImage img = cvLoadImage("A.jpg");
            IplImage template = cvLoadImage("B.jpg");
            IplImage images[] = { img, template };

            // Setup SURF feature detector and descriptor.
            double hessianThreshold = 2500d;
            int nOctaves = 4;
            int nOctaveLayers = 2;
            boolean extended = true;
            boolean upright = false;
            SURF surf = new SURF(hessianThreshold, nOctaves, nOctaveLayers,
                    extended, upright);
            DescriptorExtractor surfDesc = DescriptorExtractor.create("SURF");
            KeyPoint keyPoints[] = { new KeyPoint(), new KeyPoint() };
            CvMat descriptors[] = new CvMat[2];

            // Detect SURF features and compute descriptors for both images
            for (int i = 0; i < 1; i++) {
                surf.detect(images[i], null, keyPoints[i]);
                // Create CvMat initialized with empty pointer, using simply `new
                // CvMat()` leads to an exception.
                descriptors[i] = new CvMat(null);
                surfDesc.compute(images[i], keyPoints[i], descriptors[i]);
            }

            // Create feature matcher
            BFMatcher matcher = new BFMatcher(NORM_L2, true);

            DMatch matches = new DMatch();
            // "match" is a keyword in Scala, to avoid conflict between a keyword
            // and a method match of the BFMatcher,
            // we need to enclose method name in ticks: `match`.
            matcher.match(descriptors[0], descriptors[1], matches, null);
            System.out.println("Matched: " + matches.capacity());

            // Select only 25 best matches
            DMatch bestMatches = selectBest(matches, 25);

            // Draw best matches
            IplImage imageMatches = cvCreateImage(new CvSize(images[0].width()
                    + images[1].width(), images[0].height()), images[0].depth(), 3);
            drawMatches(images[0], keyPoints[0], images[1], keyPoints[1],
                    bestMatches, imageMatches, CvScalar.BLUE, CvScalar.RED, null,
                    DrawMatchesFlags.DEFAULT);

            CanvasFrame canvas = new CanvasFrame("");

            canvas.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

            canvas.showImage(imageMatches);

        }

        // ----------------------------------------------------------------------------------------------------------------

        /** Select only the best matches from the list. Return new list. */
        private static DMatch selectBest(DMatch matches, int numberToSelect) {
            // Convert to Scala collection for the sake of sorting
            int oldPosition = matches.position();
            DMatch a[] = new DMatch[matches.capacity()];
            for (int i = 0; i < a.length; i++) {
                DMatch src = matches.position(i);
                DMatch dest = new DMatch();
                copy(src, dest);
                a[i] = dest;
            }
            // Reset position explicitly to avoid issues from other uses of this
            // position-based container.
            matches.position(oldPosition);

            // Sort

            DMatch aSorted[] = a;
            Arrays.sort(aSorted, new DistanceComparator());

            // DMatch aSorted[]=sort(a);

            // Create new JavaCV list
            DMatch best = new DMatch(numberToSelect);
            for (int i = 0; i < numberToSelect; i++) {
                // Since there is no may to `put` objects into a list DMatch,
                // We have to reassign all values individually, and hope that API
                // will not any new ones.
                copy(aSorted[i], best.position(i));
            }

            // Set position to 0 explicitly to avoid issues from other uses of this
            // position-based container.
            best.position(0);

            return best;
        }

        private static void copy(DMatch src, DMatch dest) {
            // TODO: use Pointer.copy() after JavaCV/JavaCPP 0.3 is released
            // (http://code.google.com/p/javacpp/source/detail?r=51f4daa13d618c6bd6a5556ff2096d0e834638cc)
            // dest.put(src)
            dest.distance(src.distance());
            dest.imgIdx(src.imgIdx());
            dest.queryIdx(src.queryIdx());
            dest.trainIdx(src.trainIdx());
        }

        static class DistanceComparator implements Comparator<DMatch> {
            public int compare(DMatch o1, DMatch o2) {
                if (o1.compare(o2))
                    return -1;
                else
                    return 1;
            }
        };

    }

Does anybody know what I might need more to make this work.. Any help appreciated

Was it helpful?

Solution 2

The CvMat was not initialized properly which was giving the error.

descriptors[i] = new CvMat(null);

Instead I put it like this which solved the problem.

descriptors[i] = CvMat.create(1, 1);

OTHER TIPS

As the error clearly says that descriptor types does not match. You have to check for the condition if the descriptor types match.

A simple if statement before matcher.match would solve your problem

       if (descriptors[0].type() == descriptors[1].type())
{
        matcher.match(descriptors[0], descriptors[1], matches, null);
        System.out.println("Matched: " + matches.capacity());
}

Don't know if still needed, but I found answer. In code there's problem with this loop:

for (int i = 0; i < 1; i++) {
    surf.detect(images[i], null, keyPoints[i]);
    // Create CvMat initialized with empty pointer, using simply `new
    // CvMat()` leads to an exception.
    descriptors[i] = new CvMat(null);
    surfDesc.compute(images[i], keyPoints[i], descriptors[i]);
}

i is just 0, than the loop exits and you try to use object descriptors[1] which is absent.
Change it to for( int i = 0, i < 2, i++) {

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top