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
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);