- objective-c - iOS 5 : Can you override UIAppearance customisations in specific classes?
- iphone - 如何将 CGFontRef 转换为 UIFont?
- ios - 以编程方式关闭标记的信息窗口 google maps iOS
- ios - Xcode 5 - 尝试验证存档时出现 "No application records were found"
我正在尝试在一张照片上构建静态增强现实场景,其中平面和图像上的共面点之间有 4 个定义的对应关系。
这是一个分步流程:
我还测量了 iPhone 摄像头相对于 A4 纸中心的位置。所以对于这个镜头,位置是 (0, 14, 42.5),以厘米为单位测量。我的 iPhone 也稍微倾斜到 table 上(5-10 度)
使用此数据,我设置了 SCNCamera
以获得第三张图像上蓝色平面的所需视角:
let camera = SCNCamera()
camera.xFov = 66
camera.zFar = 1000
camera.zNear = 0.01
cameraNode.camera = camera
cameraAngle = -7 * CGFloat.pi / 180
cameraNode.rotation = SCNVector4(x: 1, y: 0, z: 0, w: Float(cameraAngle))
cameraNode.position = SCNVector3(x: 0, y: 14, z: 42.5)
这将给我一个引用,以便与我的结果进行比较。
为了使用 SceneKit 构建 AR,我需要:
H - 单应性; K - 内矩阵; <强>[R | t] - 外部矩阵
我尝试了两种方法来找到相机的变换矩阵:使用 OpenCV 的 solvePnP 和基于 4 个共面点的单应性手动计算。
<强>1。找出单应性
这一步成功完成,因为世界原点的 UV 坐标似乎是正确的。
<强>2。内在矩阵
为了获得 iPhone 6 的固有矩阵,我使用了 this应用程序,从 100 张分辨率为 640*480 的图像中得到以下结果:
假设输入图像的宽高比为 4:3,我可以根据分辨率缩放上述矩阵
我不确定,但感觉这里有一个潜在问题。我使用 cv::calibrationMatrixValues 检查 fovx 计算出的内在矩阵,结果是 ~50°,而它应该接近 60°。
<强>3。相机位姿矩阵
func findCameraPose(homography h: matrix_float3x3, size: CGSize) -> matrix_float4x3? {
guard let intrinsic = intrinsicMatrix(imageSize: size),
let intrinsicInverse = intrinsic.inverse else { return nil }
let l1 = 1.0 / (intrinsicInverse * h.columns.0).norm
let l2 = 1.0 / (intrinsicInverse * h.columns.1).norm
let l3 = (l1+l2)/2
let r1 = l1 * (intrinsicInverse * h.columns.0)
let r2 = l2 * (intrinsicInverse * h.columns.1)
let r3 = cross(r1, r2)
let t = l3 * (intrinsicInverse * h.columns.2)
return matrix_float4x3(columns: (r1, r2, r3, t))
}
结果:
因为我测量了这个特定图像的大致位置和方向,所以我知道变换矩阵,它会给出预期的结果并且它是完全不同的:
我也有点担心引用旋转矩阵的 2-3 个元素,它是 -9.1,而它应该接近于零,因为旋转非常轻微。
有一个solvePnP OpenCV 中的函数可以解决这类问题,所以我尝试使用它而不是重新发明轮子。
Objective-C++ 中的 OpenCV:
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;
}
在 Swift 中的用法:
func testSolvePnP() {
let source = modelPoints().map { NSValue(cgPoint: $0) }
let destination = perspectivePicker.currentPerspective.map { NSValue(cgPoint: $0)}
let cameraPose = CameraPoseDetector.findCameraPose(source, imagePoints: destination, size: backgroundImageView.size);
cameraNode.rotation = cameraPose.rotationVector
cameraNode.position = cameraPose.translationVector
}
输出:
结果更好,但与我的预期相去甚远。
我还尝试过一些其他的东西:
我真的被这个问题困住了,所以非常感谢任何帮助。
最佳答案
实际上,我距离使用 OpenCV 的工作解决方案只有一步之遥。
第二种方法的问题是我忘记将 solvePnP
的输出转换回 SpriteKit 的坐标系。
请注意,输入(图像和世界点)实际上已正确转换为 OpenCV 坐标系(convertObjectPoints:
和 convertImagePoints:withSize:
方法)
所以这是一个固定的 findCameraPose
方法,其中打印了一些注释和中间结果:
+ (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];
std::cout << "object points: " << cvObjectPoints << std::endl;
std::cout << "image points: " << cvImagePoints << std::endl;
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);
std::cout << "rvec: " << rvec << std::endl;
std::cout << "tvec: " << tvec << std::endl;
std::vector<cv::Point2f> projectedPoints;
cvObjectPoints.push_back(Point3f(0.0, 0.0, 0.0));
cv::projectPoints(cvObjectPoints, rvec, tvec, cameraMatrix, distCoeffs, projectedPoints);
for(unsigned int i = 0; i < projectedPoints.size(); ++i) {
std::cout << "Image point: " << cvImagePoints[i] << " Projected to " << projectedPoints[i] << std::endl;
}
cv::Mat RotX(3, 3, cv::DataType<double>::type);
cv::setIdentity(RotX);
RotX.at<double>(4) = -1; //cos(180) = -1
RotX.at<double>(8) = -1;
cv::Mat R;
cv::Rodrigues(rvec, R);
R = R.t(); // rotation of inverse
Mat rvecConverted;
Rodrigues(R, rvecConverted); //
std::cout << "rvec in world coords:\n" << rvecConverted << std::endl;
rvecConverted = RotX * rvecConverted;
std::cout << "rvec scenekit :\n" << rvecConverted << std::endl;
Mat tvecConverted = -R * tvec;
std::cout << "tvec in world coords:\n" << tvecConverted << std::endl;
tvecConverted = RotX * tvecConverted;
std::cout << "tvec scenekit :\n" << tvecConverted << std::endl;
SCNVector4 rotationVector = SCNVector4Make(rvecConverted.at<double>(0), rvecConverted.at<double>(1), rvecConverted.at<double>(2), norm(rvecConverted));
SCNVector3 translationVector = SCNVector3Make(tvecConverted.at<double>(0), tvecConverted.at<double>(1), tvecConverted.at<double>(2));
return CameraPose{rotationVector, translationVector};
}
注意事项:
关于ios - 从单应性或使用 solvePnP() 函数估计相机姿态,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44008003/
我正在尝试借助 OpenCV 的 solvePNP() 获取相机的姿势。 运行程序后出现以下错误: OpenCV Error: Assertion failed (npoints >= 0 && np
我有一个非常简单的任务:获取平面三角形的欧拉角。图案看起来像 this 因此,算法: 1) 从网络摄像头获取图像 -- 完成 2) 转换为灰阶、滤镜等——完成 3) 获取所有连接组件的质量中心,并过滤
有人可以帮助我计算相机的 Y 轴旋转吗?我使用 SolvePnP 来获取 rvec。从这个 rvec 我想知道我的相机绕着它自己的 Y 轴旋转了多少。 PointF[] ImagePointsCam
我正在使用运动结构进行多 View 几何重建。到目前为止,我有以下内容 两张图片作为初始输入相机参数和畸变系数初始输入图像的工作校正流水线创建视差图通过遍历视差图并将值作为 z(x 和 y 是视差图中
我正在使用函数 solvePnP 通过视觉标记来估计我的机器人的姿势。有时我在两个连续的帧中得到错误的结果。在文件 problem.cpp 中,您可以看到其中一个结果。 点集对应于两个连续帧中的相同标
我在使用OpenCV中的cv2.solvePnP函数时遇到问题。此功能用于获取棋盘的姿势估计。在以下代码之后,我得到一个错误: for fname in glob.glob('Images/Calib
我对 OpenCV 中 solvePnP 函数的使用有一点困惑。 我有相机内部参数的矩阵,我已经确定了图像中的一些关键点,我正在尝试估计校准的外部参数。 solvePnP 的文档说: cv2.solv
我目前正在尝试通过获取两个摄像头都可以看到的跟踪模式的位置来获取两个 Kinect v2 的相对位置。不幸的是,我似乎无法获得图案原点的正确位置。 这是我当前获取图案相对于相机位置的代码: std::
我正在像这样使用 solvePnP.. import cv2 import numpy as np # Read Image im = cv2.imread("headPose.jpg"); size
我无法理解 Perspective-n-Point问题。几个问题: s 有什么用?为什么我们需要图像点的比例因子? K[R|T] 是一个“坐标变换矩阵”,它将同质世界点 p_w 移动到 2D 的坐标空
我有一个类似于 this 的不对称圆点图案.我使用 opencv solvePnP 函数根据 a) 已知的 3D 图案点来估计图案的姿态; b) 二维图像中检测到的图案点 我发现在某些情况下(当图案正
我正在尝试在一张照片上构建静态增强现实场景,其中平面和图像上的共面点之间有 4 个定义的对应关系。 这是一个分步流程: 用户使用设备的相机添加图像。假设它包含一个以某种视角捕获的矩形。 用户定义矩形的
我正在尝试使用单应性在 Blender 3d 中校准和查找单个虚拟相机的位置和旋转。我正在使用 Blender,以便在进入更困难的现实世界之前仔细检查我的结果。 我在我的固定相机的视野中渲染了十张棋盘
这是错误: cv2.solvePnP(obj_points, image_points, mtx, dist) cv2.error: OpenCV(4.2.0) C:\projects\opencv-
是否可以将 OpenCV 的 solvePNP 与 equirectangular 图像一起使用?我有一个 equirectangular 图像,我在这个图像中有四个点(红点)和它们的像素坐标,然后我
我想获得高架摄像机的姿势(翻译:x、y、z 和旋转:世界坐标系中的 Rx、Ry、Rz)。通过用机械臂移动 ChArUco 校准板,我得到了许多物点和图像点(像这样 https://www.youtub
我正在使用棋盘来获取外部矩阵。findChessboardCorners 正确找到图像点,并且应该正确设置对象点。但是当捕捉相同的场景时,我得到了非常奇怪的结果。 我正在使用 OpenCV 2.1.0
我使用以下代码对图像进行地理配准 有输入 grid = "for example a utm grid" img_raw = cv2.imread(filename) mtx, dist = "
在过去的几周里,我尝试学习纠正图像,并且在这里的人们的帮助下,我已经设法更好地理解它。大约一周前,我设置了一个我想纠正的测试示例(查看上图)。使用函数 T = cv2.getPerspectiveTr
我有一个校准过的相机(固有矩阵和失真系数),我想知道相机位置,知道图像中的一些 3d 点及其对应点(2d 点)。 我知道 cv::solvePnP 可以帮助我,并且在阅读 this 之后和 this我
我是一名优秀的程序员,十分优秀!