首页 > 解决方案 > 你如何重新扭曲一个点?

问题描述

我有一个扭曲的图像,我使用Cv2.Undistort()它来纠正它。在此之后,我在图像中找到了一些点。我需要得到扭曲图像中这些点的位置。

我已经尝试Cv2.ProjectPoints()但未能获得适当的坐标。它们超出了图像的范围。

这就是我这样做的方式:

List<float> arr = new List<float>();
foreach (var i in points)
{
    arr.Add(i.X);
    arr.Add(i.Y);
    arr.Add(0);
}
Mat pointArr = new Mat(3, points.Count, MatType.CV_32FC1, arr.ToArray());
float[] rotArr = {  1, 0, 0,
                    0, 1, 0,
                    0, 0, 1};

float[] transArr = { 0, 0, 0 };

Mat rot = new Mat(3, 1, MatType.CV_32F, rotArr);
Mat trans = new Mat(3, 1, MatType.CV_32F, transArr);


Cv2.ProjectPoints(pointArr, rot, trans, camMatrix, dist, outputPoints);
List<Point2f> point2Fs = new List<Point2f>();
var lngt = outputPoints.Rows * outputPoints.Cols * outputPoints.Channels();
var matarr = new List<float>();
for (int i = 0; i < outputPoints.Rows; i++)
{
    point2Fs.Add(new Point2f(outputPoints.ExtractChannel(0).At<float>(0, i), outputPoints.ExtractChannel(1).At<float>(0, i)));
}

points - 我想在原始图像中找到的未失真图像中的点

有什么建议么?

谢谢!

标签: c#.netopencvcomputer-visioncamera-calibration

解决方案


不幸的是,OpenCV 没有提供直接做你想做的事情的功能,即将失真系数应用于未失真的 2D 点。你可以:

选项1

您使用 projectPoints() 走在正确的轨道上。理解这是如何工作的诀窍是未失真图像中的一个点“存在”在图像平面中,看起来像这样(图片来自https://docs.opencv.org/2.4/modules/calib3d/doc/camera_calibration_and_3d_reconstruction .html):

在此处输入图像描述

图像平面位于距原点的f(焦距)处,xy 坐标相对于c xc y

您需要做的是从未失真的 2D 点 (x u , y u ) 构建您的 3D 点 (x,y,z),如下所示:

x = (x_u - c_x) / f_x
y = (y_u - c_y) / f_y
z = 1

而不是在第一个foreach循环中使用 (x u , y u , 0) 。

然后调用 projectPoints()。

您正确地使用了身份旋转和 0 平移。f x、 f y、 c x和 c y位于 cameraMatrix 中:

|f_x  0  c_x|
| 0  f_y c_y|
| 0   0   1 |

选项 2:

您可以直接应用失真方程(https://docs.opencv.org/2.4/modules/calib3d/doc/camera_calibration_and_3d_reconstruction.html):

在此处输入图像描述

在第一步中,您将 x' 和 y' 替换为:

x' = (x_u - c_x) / f_x
y' = (y_u - c_y) / f_y

然后应用其余的方程。这就是 projectPoints() 所做的,没有旋转/平移部分。


推荐阅读