我试图运行javacv的特征检测程序来比较2个图像中的类似功能,但是我得到一个运行时异常。由于我是javacv的新手,我不知道如何解决这个问题。
异常跟踪是OpenCV Error: Assertion failed (queryDescriptors.type() == trainDescCollection[0].type()) in unknown function, file ......srcopencvmodulesfeatures2dsrcmatchers.cpp, line 351
Exception in thread "main" java.lang.RuntimeException: ......srcopencvmodulesfeatures2dsrcmatchers.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)
下面是源代码
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;
}
};
}
有谁知道我还需要什么才能使这个工作…感谢您的帮助
由于错误清楚地表明描述符类型不匹配。您必须检查描述符类型是否匹配。
在matcher.match
之前一个简单的if语句将解决您的问题
if (descriptors[0].type() == descriptors[1].type())
{
matcher.match(descriptors[0], descriptors[1], matches, null);
System.out.println("Matched: " + matches.capacity());
}
CvMat未正确初始化,导致错误。
descriptors[i] = new CvMat(null);
相反,我把它写成这样解决了问题。
descriptors[i] = CvMat.create(1, 1);
不知道是否还需要,但我找到了答案。在代码中,这个循环有问题:
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
只是0
,然后循环退出,您尝试使用不存在的对象descriptors[1]
。
改成for( int i = 0, i < 2, i++) {