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

man*_*elt 0 android opencv image-processing 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);
Run Code Online (Sandbox Code Playgroud)

匹配的类型为MatOfDMatch.

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

Mat fundamental_matrix = Calib3d.findFundamentalMat(nextPts, prevPts, Calib3d.FM_RANSAC,3, 0.99);
Run Code Online (Sandbox Code Playgroud)

第一个问题:如何将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]));
}
Run Code Online (Sandbox Code Playgroud)

但是当我打电话的时候

prevPts = getMatOfPoint2fFromDMatchesTrain(matches, prevKP);
nextPts = getMatOfPoint2fFromDMatchesQuery(matches, actKP);
Mat fundamental_matrix = Calib3d.findFundamentalMat(
        nextPts, prevPts, Calib3d.FM_RANSAC, 3, 0.99);
Run Code Online (Sandbox Code Playgroud)

问题是我得到错误-215.错误:

错误:(-215)npoints> = 0 && points2.checkVector(2)== npoints && points1.type()== points2.type()in function cv :: Mat cv :: findFundamentalMat(...

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

你建议的代码行:

return new MatOfPoint2f(lp2.toArray(new Point[0]));
Run Code Online (Sandbox Code Playgroud)

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

再次感谢

And*_*aev 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]));
Run Code Online (Sandbox Code Playgroud)