在这个基本示例中,OpenCV::projectPoints的Java实现似乎被破坏了

在这个基本示例中,OpenCV::projectPoints的Java实现似乎被破坏了,java,opencv,opencv3.0,Java,Opencv,Opencv3.0,当我使用下面的java代码和最简单的输入运行projectPoints函数时,我得到了我认为不正确的答案。我错过什么了吗 我得到了这个答案 (x,y,z)= [{0.0, 1.0, 1.0}, {0.0, 1.0, 5.0}, {0.0, 1.0, 10.0}] (u,v)= [{0.0, 78.5398178100586}, {0.0, 19.73955535888672}, {0.0, 9.966865539550781}] 应该是 u、 v=[{0.0,100.0},{0.0,20.0}

当我使用下面的java代码和最简单的输入运行projectPoints函数时,我得到了我认为不正确的答案。我错过什么了吗

我得到了这个答案

(x,y,z)= [{0.0, 1.0, 1.0}, {0.0, 1.0, 5.0}, {0.0, 1.0, 10.0}]
(u,v)= [{0.0, 78.5398178100586}, {0.0, 19.73955535888672}, {0.0, 9.966865539550781}]
应该是 u、 v=[{0.0,100.0},{0.0,20.0},{0.0,10.0}]

下面是调用projectPoint或我编写的一个函数的代码,该函数可以在不失真的情况下正常工作

public static void main(String[] args) {
    setDllLibraryPath("C:/aaa_eric/code/lib/x64");
    System.loadLibrary(Core.NATIVE_LIBRARY_NAME);

    MatOfPoint3f objectPts3f = new MatOfPoint3f(
            new Point3(0.0,1.0, 1.0),
            new Point3(0.0,1.0, 5.0),
            new Point3(0.0,1.0,10.0));
    MatOfPoint2f imagePts2f = new MatOfPoint2f();
    Mat rVec =  Mat.zeros(3,1, CvType.CV_64F);
    Mat tVec = Mat.zeros(3,1, CvType.CV_64F);

    //camera matrix, no distortion
    Mat kMat = Mat.zeros(3, 3, CvType.CV_64F);
    kMat.put(0, 0,
            100.0, 0.0, 0.0,
            0.0, 100.0, 0.0,
            0.0, 0.0, 1.0);
    Mat dMat = Mat.zeros(4, 1, CvType.CV_64F);

    //this one is broken
    Calib3d.projectPoints(objectPts3f, imagePts2f, rVec, tVec, kMat, dMat);
    //this one works
    ppWorks(objectPts3f, imagePts2f, rVec, tVec, kMat, dMat);

    System.out.println(objectPts3f.toList());
    System.out.println(imagePts2f.toList());
}

static void ppWorks(MatOfPoint3f objPt3f,MatOfPoint2f imgPt2f,Mat rVec,Mat tVec,Mat kMat, Mat dMat) {
    double[] T = new double[3]; tVec.get(0,0,T);
    double[] K = new double[9]; kMat.get(0,0,K);
    double[] D = new double[4]; dMat.get(0,0,D);

    Mat rMat = Mat.zeros(3,3,CvType.CV_64F);
    Calib3d.Rodrigues(rVec, rMat);
    double[] R = new double[9]; rMat.get(0,0,R);

    Point3[] xf=objPt3f.toArray();
    List<Point> y=new ArrayList<>();
    for (int i = 0; i < objPt3f.total(); i++) {
        Point3 Xi =  xf[i];
        Point3 Y = new Point3(
                R[0]*Xi.x + R[1]*Xi.y + R[2]*Xi.z + T[0]*1.0,
                R[3]*Xi.x + R[4]*Xi.y + R[5]*Xi.z + T[1]*1.0,
                R[6]*Xi.x + R[7]*Xi.y + R[8]*Xi.z + T[2]*1.0
                );

        y.add(new Point(K[0]*Y.x/Y.z + K[2], K[4]*Y.y/Y.z + K[5]));
    }
    imgPt2f.fromList(y);
}

Java也面临同样的问题,OpenCV 3.4.1。看起来问题在于Calib3d类为标准和鱼眼相机模型混合了projectPoints方法,并具有相同的方法名称

您的自定义函数对我很有效,然后我简单地尝试了类似的OpenCV方法,但签名不同,结果成功了:

// distortion coefficients have to be MatOfDouble in this signature
MatOfDouble dMat = new MatOfDouble(0,0,0,0,0);
// this one works fine
Calib3d.projectPoints(objectPts3f, rVec, tVec, kMat, dMat, imagePts2f, new Mat(), 0);

请注意,OpenCV 4.0.0似乎已经通过在fisheye方法名称前加前缀解决了这个问题。

BTW,我在python中实现了类似的代码,OpenCV::projectPoints函数在那里工作。我还在openCV论坛上发布了这个问题,希望找到答案。如果在那里找到答案,我会向你汇报。