gpt4 book ai didi

ios - OpenCV:解决PnP检测问题

转载 作者:IT王子 更新时间:2023-10-29 08:06:45 31 4
gpt4 key购买 nike

我在使用 OpenCV 精确检测标记时遇到了问题。

我已经录制了介绍该问题的视频:http://youtu.be/IeSSW4MdyfU

如您所见,我正在检测的标记在某些摄像机角度略有移动。我在网上看到这可能是相机校准问题,所以我会告诉你们我是如何校准相机的,也许你能告诉我我做错了什么?

在开始时,我从各种图像中收集数据,并将校准角存储在 _imagePoints 向量中,如下所示

std::vector<cv::Point2f> corners;
_imageSize = cvSize(image->size().width, image->size().height);

bool found = cv::findChessboardCorners(*image, _patternSize, corners);

if (found) {
cv::Mat *gray_image = new cv::Mat(image->size().height, image->size().width, CV_8UC1);
cv::cvtColor(*image, *gray_image, CV_RGB2GRAY);

cv::cornerSubPix(*gray_image, corners, cvSize(11, 11), cvSize(-1, -1), cvTermCriteria(CV_TERMCRIT_EPS+ CV_TERMCRIT_ITER, 30, 0.1));

cv::drawChessboardCorners(*image, _patternSize, corners, found);
}

_imagePoints->push_back(_corners);

然后,在收集到足够的数据后,我正在使用以下代码计算相机矩阵和系数:

std::vector< std::vector<cv::Point3f> > *objectPoints = new std::vector< std::vector< cv::Point3f> >();

for (unsigned long i = 0; i < _imagePoints->size(); i++) {
std::vector<cv::Point2f> currentImagePoints = _imagePoints->at(i);
std::vector<cv::Point3f> currentObjectPoints;

for (int j = 0; j < currentImagePoints.size(); j++) {
cv::Point3f newPoint = cv::Point3f(j % _patternSize.width, j / _patternSize.width, 0);

currentObjectPoints.push_back(newPoint);
}

objectPoints->push_back(currentObjectPoints);
}

std::vector<cv::Mat> rvecs, tvecs;

static CGSize size = CGSizeMake(_imageSize.width, _imageSize.height);
cv::Mat cameraMatrix = [_userDefaultsManager cameraMatrixwithCurrentResolution:size]; // previously detected matrix
cv::Mat coeffs = _userDefaultsManager.distCoeffs; // previously detected coeffs
cv::calibrateCamera(*objectPoints, *_imagePoints, _imageSize, cameraMatrix, coeffs, rvecs, tvecs);

结果就像您在视频中看到的那样。

我做错了什么?这是代码中的问题吗?我应该使用多少图像来执行校准(现在我正在尝试在校准结束前获取 20-30 张图像)。

我是否应该使用包含错误检测到的棋盘角的图像,如下所示:

photo 1

或者我应该只使用像这样正确检测到的棋盘:

photo 2 photo 3

我一直在试验圆网格而不是棋盘,但结果比现在差得多。

如果对我如何检测标记有疑问:我正在使用 solvepnp 函数:

solvePnP(modelPoints, imagePoints, [_arEngine currentCameraMatrix], _userDefaultsManager.distCoeffs, rvec, tvec);

像这样指定模型点:

    markerPoints3D.push_back(cv::Point3d(-kMarkerRealSize / 2.0f, -kMarkerRealSize / 2.0f, 0));
markerPoints3D.push_back(cv::Point3d(kMarkerRealSize / 2.0f, -kMarkerRealSize / 2.0f, 0));
markerPoints3D.push_back(cv::Point3d(kMarkerRealSize / 2.0f, kMarkerRealSize / 2.0f, 0));
markerPoints3D.push_back(cv::Point3d(-kMarkerRealSize / 2.0f, kMarkerRealSize / 2.0f, 0));

imagePoints 是处理图像时标记角的坐标(我使用自定义算法来做到这一点)

最佳答案

为了正确调试您的问题,我需要所有代码:-)

我假设您正在遵循 calibration 引用的教程(pose@kobejohn)中建议的方法在他的 comment以便您的代码遵循以下步骤:

  1. 收集棋盘目标的各种图像
  2. 在第 1) 点的图像中找到棋盘角
  3. 校准相机(使用 cv::calibrateCamera),因此获得相机的固有参数(我们称它们为 intrinsic)和镜头畸变参数(让我们称它们为失真)
  4. 收集一张自己自定义目标的图片(目标见0:57 in your video),如下图Axadiw's own custom target并在其中找到一些相关点(我们将您在图像 image_custom_target_verticesworld_custom_target_vertices 中找到的点称为相应的 3D 点)。
  5. 根据您获得的自定义目标图像估计相机的旋转矩阵(我们称之为R)和平移向量(我们称之为t)在第 4 点中),调用 cv::solvePnP像这样 cv::solvePnP(world_custom_target_vertices,image_custom_target_vertices,intrinsic,distortion,R,t)
  6. 在 3D 中给出 8 个角的立方体(我们称它们为 world_cube_vertices),您可以通过调用 获得 8 个 2D 图像点(我们称它们为 image_cube_vertices) code>cv2::projectPoints 像这样 cv::projectPoints(world_cube_vertices,R,t,intrinsic,distortion,image_cube_vertices)
  7. 使用您自己的draw 函数绘制立方体。

现在,绘制过程的最终结果取决于所有先前计算的数据,我们必须找出问题所在:

校准:如您在 answer 中观察到的那样, 在 3) 中,您应该丢弃未正确检测到角的图像。您需要重新投影错误的阈值才能丢弃“坏”棋盘目标图像。引用自 calibration tutorial :

Re-projection Error

Re-projection error gives a good estimation of just how exact is the found parameters. This should be as close to zero as possible. Given the intrinsic, distortion, rotation and translation matrices, we first transform the object point to image point using cv2.projectPoints(). Then we calculate the absolute norm between what we got with our transformation and the corner finding algorithm. To find the average error we calculate the arithmetical mean of the errors calculate for all the calibration images.

通常你会通过一些实验找到一个合适的阈值。通过这个额外的步骤,您将获得更好的 intrinsicdistortion 值。

找到您自己的自定义目标:在我看来,您没有在我标记为第 4 点的步骤中解释如何找到您自己的自定义目标。您是否获得了预期的 image_custom_target_vertices?你会丢弃结果“不好”的图像吗?

相机的姿势:我认为在 5) 中你使用了在 3) 中找到的 intrinsic,你确定同时相机没有发生任何变化吗?引用Callari's Second Rule of Camera Calibration :

Second Rule of Camera Calibration: "Thou shalt not touch the lens after calibration". In particular, you may not refocus nor change the f-stop, because both focusing and iris affect the nonlinear lens distortion and (albeit less so, depending on the lens) the field of view. Of course, you are completely free to change the exposure time, as it does not affect the lens geometry at all.

然后draw函数可能会出现一些问题。

关于ios - OpenCV:解决PnP检测问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19849683/

31 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com