- mongodb - 在 MongoDB mapreduce 中,如何展平值对象?
- javascript - 对象传播与 Object.assign
- html - 输入类型 ="submit"Vs 按钮标签它们可以互换吗?
- sql - 使用 MongoDB 而不是 MS SQL Server 的优缺点
当我使用 OpenCV 3.0 calibrateCamera 时,我得到了意想不到的结果。这是我的算法:
我的点很嘈杂,只是图像的一小部分。单个 View 有 30 个共面点,因此我无法获得相机内在函数,但应该能够获得失真系数和单应性以创建正面平行 View 。
正如预期的那样,误差因校准标志而异。然而,它的变化与我的预期相反。如果我允许所有变量进行调整,我希望错误会下降。我不是说我期待更好的模型;我实际上期望过度拟合,但这仍然应该减少错误。我看到的是,我使用的变量越少,我的错误就越低。最好的结果是使用直单应性。
我有两个可疑的原因,但它们似乎不太可能,我想在播放它们之前听到一个纯粹的答案。我已经提取了代码来做我正在谈论的事情。有点长,但是包含了加载点。
代码似乎没有错误;我使用了“更好”的点并且效果很好。我想强调的是,这里的解决方案不能是使用更好的点或进行更好的校准;练习的重点是了解各种校准模型如何响应不同质量的校准数据。
有什么想法吗?
已添加
明确地说,我知道结果会很糟糕,我希望如此。我也明白,当测试未用于训练模型的点时,我可能会学习到糟糕的失真参数,这会导致更糟糕的结果。我不明白的是,当使用训练集作为测试集时,失真模型如何有更多的错误。也就是说,如果 cv::calibrateCamera 应该选择参数来减少所提供的训练集上的误差,但它产生的误差比它刚刚为 K!, K2, ... K6, P1 选择 0 时产生的误差更大, P2。不管数据不好与否,它至少应该在训练集上做得更好。在我说这些数据不适合这个模型之前,我必须确保我正在尽我所能利用可用的数据,而且在这个阶段我不能这么说。
这里是示例图片
标有绿色引脚的点。这显然只是一个测试图像。
这里有更多示例
下面的图片是从上面的大图裁剪而来的。中心没有改变。这就是当我仅使用从绿色引脚手动标记的点并允许 K1(仅 K1)从 0 变化时发生的情况:
之前
之后
我会把它归结为一个错误,但是当我使用覆盖更多屏幕的更大点集时,即使是从一个平面上,它也能很好地工作。这看起来很可怕。不过,这个错误并没有您从图片中想象的那么严重。
// Load image points
std::vector<cv::Point2f> im_points;
im_points.push_back(cv::Point2f(1206, 1454));
im_points.push_back(cv::Point2f(1245, 1443));
im_points.push_back(cv::Point2f(1284, 1429));
im_points.push_back(cv::Point2f(1315, 1456));
im_points.push_back(cv::Point2f(1352, 1443));
im_points.push_back(cv::Point2f(1383, 1431));
im_points.push_back(cv::Point2f(1431, 1458));
im_points.push_back(cv::Point2f(1463, 1445));
im_points.push_back(cv::Point2f(1489, 1432));
im_points.push_back(cv::Point2f(1550, 1461));
im_points.push_back(cv::Point2f(1574, 1447));
im_points.push_back(cv::Point2f(1597, 1434));
im_points.push_back(cv::Point2f(1673, 1463));
im_points.push_back(cv::Point2f(1691, 1449));
im_points.push_back(cv::Point2f(1708, 1436));
im_points.push_back(cv::Point2f(1798, 1464));
im_points.push_back(cv::Point2f(1809, 1451));
im_points.push_back(cv::Point2f(1819, 1438));
im_points.push_back(cv::Point2f(1925, 1467));
im_points.push_back(cv::Point2f(1929, 1454));
im_points.push_back(cv::Point2f(1935, 1440));
im_points.push_back(cv::Point2f(2054, 1470));
im_points.push_back(cv::Point2f(2052, 1456));
im_points.push_back(cv::Point2f(2051, 1443));
im_points.push_back(cv::Point2f(2182, 1474));
im_points.push_back(cv::Point2f(2171, 1459));
im_points.push_back(cv::Point2f(2164, 1446));
im_points.push_back(cv::Point2f(2306, 1474));
im_points.push_back(cv::Point2f(2292, 1462));
im_points.push_back(cv::Point2f(2278, 1449));
// Create corresponding world / object points
std::vector<cv::Point3f> world_points;
for (int i = 0; i < 30; i++) {
world_points.push_back(cv::Point3f(5 * (i / 3), 4 * (i % 3), 0.0f));
}
// Perform calibration
// Flags are set out so they can be commented out and "freed" easily
int calibration_flags = 0
| cv::CALIB_FIX_K1
| cv::CALIB_FIX_K2
| cv::CALIB_FIX_K3
| cv::CALIB_FIX_K4
| cv::CALIB_FIX_K5
| cv::CALIB_FIX_K6
| cv::CALIB_ZERO_TANGENT_DIST
| 0;
// Initialise matrix
cv::Mat intrinsic_matrix = cv::Mat(3, 3, CV_64F);
intrinsic_matrix.ptr<float>(0)[0] = 1;
intrinsic_matrix.ptr<float>(1)[1] = 1;
cv::Mat distortion_coeffs = cv::Mat::zeros(5, 1, CV_64F);
// Rotation and translation vectors
std::vector<cv::Mat> undistort_rvecs;
std::vector<cv::Mat> undistort_tvecs;
// Wrap in an outer vector for calibration
std::vector<std::vector<cv::Point2f>>im_points_v(1, im_points);
std::vector<std::vector<cv::Point3f>>w_points_v(1, world_points);
// Calibrate; only 1 plane, so intrinsics can't be trusted
cv::Size image_size(4000, 3000);
calibrateCamera(w_points_v, im_points_v,
image_size, intrinsic_matrix, distortion_coeffs,
undistort_rvecs, undistort_tvecs, calibration_flags);
// Undistort im_points
std::vector<cv::Point2f> ud_points;
cv::undistortPoints(im_points, ud_points, intrinsic_matrix, distortion_coeffs);
// ud_points have been "unintrinsiced", but we don't know the intrinsics, so reverse that
double fx = intrinsic_matrix.at<double>(0, 0);
double fy = intrinsic_matrix.at<double>(1, 1);
double cx = intrinsic_matrix.at<double>(0, 2);
double cy = intrinsic_matrix.at<double>(1, 2);
for (std::vector<cv::Point2f>::iterator iter = ud_points.begin(); iter != ud_points.end(); iter++) {
iter->x = iter->x * fx + cx;
iter->y = iter->y * fy + cy;
}
// Find a homography mapping the undistorted points to the known world points, ground plane
cv::Mat homography = cv::findHomography(ud_points, world_points);
// Transform the undistorted image points to the world points (2d only, but z is constant)
std::vector<cv::Point2f> estimated_world_points;
std::cout << "homography" << homography << std::endl;
cv::perspectiveTransform(ud_points, estimated_world_points, homography);
// Work out error
double sum_sq_error = 0;
for (int i = 0; i < 30; i++) {
double err_x = estimated_world_points.at(i).x - world_points.at(i).x;
double err_y = estimated_world_points.at(i).y - world_points.at(i).y;
sum_sq_error += err_x*err_x + err_y*err_y;
}
std::cout << "Sum squared error is: " << sum_sq_error << std::endl;
最佳答案
我会随机抽取 30 个输入点的样本,并在每种情况下计算单应性以及估计的单应性下的误差,一个 RANSAC 方案,并验证误差水平和单应性参数之间的一致性,这可以只是一个验证全局优化过程。我知道这似乎没有必要,但这只是对程序对输入(噪声级别、位置)的敏感程度的健全性检查
此外,修复大多数变量似乎可以使您的错误最少,因为最小化过程中的自由度较小。我会尝试修复不同的问题以建立另一个共识。至少这会让你知道哪些变量对输入的噪声水平最敏感。
希望图像的这么小部分靠近图像中心,因为它会产生最少的镜头失真。在您的情况下是否可以使用不同的失真模型?一种更可行的方法是在给定图案相对于图像中心的位置的情况下调整失真参数的数量。
在不知道算法约束的情况下,我可能误解了这个问题,这也是一种选择,在这种情况下我可以回滚。
我想将此作为评论,但我没有足够的积分。
关于c++ - OpenCV 3.0 : Calibration not fitting as expected,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31292266/
就目前而言,这个问题不适合我们的问答形式。我们希望答案得到事实、引用资料或专业知识的支持,但这个问题可能会引发辩论、争论、投票或扩展讨论。如果您觉得这个问题可以改进并可能重新打开,visit the
我是脚本新手。如何编写 Expect 脚本以通过 ssh 连接到设备并提示用户输入密码?我们使用 pin + RSA token 代码作为密码,因此我无法存储密码。 #!/usr/bin/expect
我编写了以下代码并尝试执行它。但我在执行 do {”时遇到“无效的命令名称“do”” 代码: #!/usr/bin/expect set val 0; set input 5; do { pu
我已经查看了 Expect 联机帮助页并用 Google 搜索了它,但我还没有找到 expect 的 -r 是什么。我看到这个选项以前是这样用的 expect -r "\r\n\r\n" 在 expe
我的 shebang 看起来像这样: #!/usr/bin/expect -d 当我从命令行运行脚本时,它会提供我想要的内容。 但是,我通过 crontab 运行这个脚本。是否可以将调试开关保持打开状
我是 Expect 脚本的新手。 我在 Linux 机器上为 ssh 编写了一个 Expect 脚本,在那里我在 ssh 到不同的 Linux 机器时遇到了问题。下面我复制了脚本。 !/usr/loc
Scene 1, Layer 'script', Frame 1, Line 9 1084: Syntax error: expecting identifier before this. Sc
我正在运行调试命令以将命令的输出记录到文件中。我尝试了 log_file 命令,但它没有记录输出。我的代码如下: log_file -a gdb.txt send "~/debugulator.sh
我希望 expect_user 有一个无限的(或非常大的)超时和 expect 的默认超时。有没有办法设置不同的超时?或者我是否只需要在每次更改用途之前手动执行此操作? 最佳答案 expect 和ex
我正在学习 iOS 编程(我来自 Android),我正在寻找更容易获取字符串的方法。有了这个建议,我定义了下一个宏并在一些代码片段中使用它: #define STRING_BASE @"InfoPl
你好我是 rspec 的新手,我想弄清楚将 block 传递给 expect{} 和只使用 expect() 之间的区别 这是一个简单的例子 require "rails_helper" RSpec.
我正在尝试为 React JS 运行单元测试 - 使用 jest/enzyme。 目前测试失败。不太清楚为什么,也许我没有正确调用 expect(wrapper.find)。这是我测试的一部分: F
例如,现在我有一个“root.exp”期望脚本如下: spawn ssh user@ip expect "Password:" send "password" 然后,我要发送到这个ssh服务器的exp
您好,我是 Expect 脚本编写的新手,我一直在尝试使用以下方法将 IP 地址获取到变量中: set timeout -1 spawn $env(SHELL) match_max 100000 se
expect.anything() 不适用于 expect.toBe(),但适用于 expect.toEqual() test("this will pass", () => { expect("
我有一个如下所示的简单脚本,从命令行读取 2 个数字并将它们加在一起: $cat runexp.sh #!/bin/bash echo "read 1st number" read n1 echo "
当 Linux 机器的 $IP 登录后询问密码时,下面的 expect 脚本工作正常 但在某些情况下,某些Linux机器不需要ssh密码(我们可以不用密码登录), 所以我需要更改我的期望脚本以支持没有
我正在尝试使用 expect 远程登录服务器并更改用户密码。该应用程序要求,如果您要更改的密码包含特殊字符,则将其引用。问题是,还需要引用 expect send 语句,当我尝试将两者结合起来时,脚本
下面这个简单的 expect 脚本的目标是获取远程机器上的 hostname 名称 有时期望脚本无法执行到 $IP_ADDRESS 的 ssh(因为远程机器不活动等) 所以在这种情况下,expect
我试图创建一个宏来替换, first: Some(first.as_ref().parse::().expect("Could not parse 'first'")) 我在其他模块(如 Clap w
我是一名优秀的程序员,十分优秀!