如何使用Homography从2D图像关键点自动计算3D对象点和图像点?

时间:2018-11-04 12:39:13

标签: opencv camera-calibration homography projection-matrix opencv-solvepnp

我正在尝试使用 opencv 中的 solvePnP 函数找到旋转和平移矢量来计算相机姿态。 solvePnP 函数需要3D 对象点,2D 图像点相机矩阵来发送参数值。

我已经计算出相机帧输入图像特征关键点和火车图像特征关键点以及摄像机矩阵。但是我需要将相机框架输入的2D图像点转换为3D对象点。怎么做 ?我对对象点感到困惑。我还从相机框架图像和火车图像功能关键点匹配中计算了单应性。有什么方法可以从单应性查找3D对象点吗?

我的目标是:

  1. 将摄像机输入的2D图像点转换为3D对象点。
  2. 查找相机姿势-旋转和平移矢量。
  3. 将摄影机姿态转换为场景套件摄影机姿态旋转和平移矢量。

我正在尝试使用此代码-

typedef struct CameraPose {
    SCNVector4 rotationVector;
    SCNVector3 translationVector; 
} CameraPose;


+ (CameraPose)findCameraPose: (NSArray<NSValue *> *) objectPoints imagePoints: (NSArray<NSValue *> *) imagePoints size: (CGSize) size {

    vector<Point3f> cvObjectPoints = [self convertObjectPoints:objectPoints];
    vector<Point2f> cvImagePoints = [self convertImagePoints:imagePoints withSize: size];

    cv::Mat distCoeffs(4,1,cv::DataType<double>::type, 0.0);
    cv::Mat rvec(3,1,cv::DataType<double>::type);
    cv::Mat tvec(3,1,cv::DataType<double>::type);
    cv::Mat cameraMatrix = [self intrinsicMatrixWithImageSize: size];

    cv::solvePnP(cvObjectPoints, cvImagePoints, cameraMatrix, distCoeffs, rvec, tvec);

    SCNVector4 rotationVector = SCNVector4Make(rvec.at<double>(0), rvec.at<double>(1), rvec.at<double>(2), norm(rvec));
    SCNVector3 translationVector = SCNVector3Make(tvec.at<double>(0), tvec.at<double>(1), tvec.at<double>(2));
    CameraPose result = CameraPose{rotationVector, translationVector};

    return result;
}

+ (vector<Point2f>) convertImagePoints: (NSArray<NSValue *> *) array withSize: (CGSize) size {
    vector<Point2f> points;
    for (NSValue * value in array) {
        CGPoint point = [value CGPointValue];
        points.push_back(Point2f(point.x - size.width/2, point.y - size.height/2));
    }
    return points;
}

+ (vector<Point3f>) convertObjectPoints: (NSArray<NSValue *> *) array {
    vector<Point3f> points;
    for (NSValue * value in array) {
        CGPoint point = [value CGPointValue];
        points.push_back(Point3f(point.x, 0.0, -point.y));
    }
    return points;
}

+ (cv::Mat) intrinsicMatrixWithImageSize: (CGSize) imageSize {
    double f = 0.84 * max(imageSize.width, imageSize.height);
    Mat result(3,3,cv::DataType<double>::type);
    cv::setIdentity(result);
    result.at<double>(0) = f;
    result.at<double>(4) = f;
    return result;
}

我该如何解决这个问题?

0 个答案:

没有答案