OpenCV:转换MatOfDMatch,MatOfPoint2f,MatOfKeypoint,找到FundamentalMatrix的aaproach

时间:2012-12-06 16:59:35

标签: android image-processing opencv computer-vision

它可能是一个简单/愚蠢的问题,但我在opencv(android)中有转换问题。

我的目标是从两个连续的图像中计算出相应匹配的基本矩阵。

我编程到目前为止(和工作):

detector.detect(actImg, actKP);
detector.detect(prevImg, prevKP);
descExtractor.compute(prevImg, prevKP, descriptorPrev);
descExtractor.compute(actImg, actKP, descriptorAct);
descMatcher.match(descriptorPrev, descriptorAct, matches);
Features2d.drawMatches(prevImg, prevKP, actImg, actKP,matches, mRgba);

匹配的类型为MatOfDMatch。

现在我将从相互匹配的点中计算出基本矩阵。因此,我必须知道在第二张图像(actKP)中找到第一张图像(prevKP)中的哪些关键点。

Mat fundamental_matrix = Calib3d.findFundamentalMat(nextPts, prevPts, Calib3d.FM_RANSAC,3, 0.99);

第一个问题: 如何将MatOfKeyPoints提取/转换为MatOfPoint2f(它们可以传递给findFundamentalMatrix)

第二个问题: 如何只将匹配的关键点传递给函数findFundamentalMatrix。 这是一个很好的方式吗?

非常感谢advace!

修改

非常感谢您的详细回复! 我把你的代码编写成两个函数:

private MatOfPoint2f getMatOfPoint2fFromDMatchesTrain(MatOfDMatch matches2,
        MatOfKeyPoint prevKP2) {
    DMatch dm[] = matches2.toArray();
    List<Point> lp1 = new ArrayList<Point>(dm.length);
    KeyPoint tkp[] = prevKP2.toArray();
    for (int i = 0; i < dm.length; i++) {
        DMatch dmm = dm[i];
        if (dmm.trainIdx < tkp.length) 
            lp1.add(tkp[dmm.trainIdx].pt);
    }
    return new MatOfPoint2f(lp1.toArray(new Point[0]));
}

private MatOfPoint2f getMatOfPoint2fFromDMatchesQuery(MatOfDMatch matches2,
        MatOfKeyPoint actKP2) {
    DMatch dm[] = matches2.toArray();
    List<Point> lp2 = new ArrayList<Point>(dm.length);
    KeyPoint qkp[] = actKP2.toArray();
    for (int i = 0; i < dm.length; i++) {
        DMatch dmm = dm[i];
        if (dmm.queryIdx < qkp.length)
            lp2.add(qkp[dmm.queryIdx].pt);
    }
    return new MatOfPoint2f(lp2.toArray(new Point[0]));
}

但是当我打电话时

prevPts = getMatOfPoint2fFromDMatchesTrain(matches, prevKP);
nextPts = getMatOfPoint2fFromDMatchesQuery(matches, actKP);
Mat fundamental_matrix = Calib3d.findFundamentalMat(
        nextPts, prevPts, Calib3d.FM_RANSAC, 3, 0.99);
问题是我得到错误-215。 错误:

  

错误:(-215)npoints&gt; = 0&amp;&amp; points2.checkVector(2)== npoints&amp;&amp;函数cv :: Mat中的points1.type()== points2.type()   CV :: findFundamentalMat(...

我证明prevPts和nextPts低于10分(对于ransac)。 所以我猜这个错误就是积分和浮点数。但我用调试器检查了这些点是浮点数。

您建议的代码行:

return new MatOfPoint2f(lp2.toArray(new Point[0]));

应该将点转换为浮点还是我错了?

再次感谢

1 个答案:

答案 0 :(得分:6)

不幸的是,没有比循环遍历所有匹配并将值复制到新Mat(或向量)更好的方法(即使在C ++ API中)。

在Java中,您可以按照以下方式执行此操作:

DMatch dm[] = matches.toArray();
List<Point> lp1 = new ArrayList<Point>(dm.length);
List<Point> lp2 = new ArrayList<Point>(dm.length);
KeyPoint tkp[] = prevKP.toArray();
KeyPoint qkp[] = actKP.toArray();
for (int i = 0; i < dm.length; i++) {
    DMatch dm = dm[i];
    lp1.add(tkp[dm.trainIdx].pt);
    lp2.add(qkp[dm.queryIdx].pt);
}

MatOfPoint2f pointsPrev = new MatOfPoint2f(lp1.toArray(new Point[0]));
MatOfPoint2f pointsAct  = new MatOfPoint2f(lp2.toArray(new Point[0]));