C++ Opencv三维点到二维图像点投影

C++ Opencv三维点到二维图像点投影,c++,opencv,C++,Opencv,我正在将激光雷达点转换为相机图像 激光雷达点和相机图像来自模拟器。 为了简单起见,我将它们放置在完全相同的位置,面向相同的方向,没有任何滚动、俯仰和偏航。(因此相机坐标系与激光雷达坐标系相同) 如果我理解正确,我就可以使用一个空的t_-vec/r_-vec/d_-vec(因为相机图像中也没有失真) 图像是785x785 //为调试目的添加 std::矢量点激光雷达{ cv::Point3d{0,0,4.5}, cv::Point3d{1.88,-0.42,4.50}, cv::Point3d{1

我正在将激光雷达点转换为相机图像

激光雷达点和相机图像来自模拟器。 为了简单起见,我将它们放置在完全相同的位置,面向相同的方向,没有任何滚动、俯仰和偏航。(因此相机坐标系与激光雷达坐标系相同)

如果我理解正确,我就可以使用一个空的t_-vec/r_-vec/d_-vec(因为相机图像中也没有失真)

图像是785x785

//为调试目的添加
std::矢量点激光雷达{
cv::Point3d{0,0,4.5},
cv::Point3d{1.88,-0.42,4.50},
cv::Point3d{1.85,-0.42,4.49},
cv::Point3d{1.84,-0.42,4.49},
cv::Point3d{1.83,-0.42,4.51},
cv::Point3d{1.82,-0.42,4.52},
cv::Point3d{1.81,-0.41,4.52},
};
cv::Mat d_vec=cv::Mat::zeros(4,1,cv::DataType::type);
cv::Mat r_vec=cv::Mat::zeros(3,1,cv::DataType::type);
cv::Mat t_vec=cv::Mat::zeros(3,1,cv::DataType::type);
双摄像头垫[3][3]={
{785,0,0},
{0,785,0},
{0,0,1}
};
cv::Mat摄像机(3,3,cv::数据类型::类型,摄像机\ Mat);
std::向量点{};
cv::投影点(点激光雷达、r_矢量、t_矢量、相机、d_矢量、点相机);
用于(常数自动和p:点/摄像机){
cv::Point2i pp;
pp.x=(int)(p.x+785/2);
pp.y=(int)((1-p.y)+785/2);
cv::circle(图像->图像,pp,5,cv::Scalar(0,0,255),-1);
}
不幸的是,投影点与3d点几乎不匹配,并且距离图像的右/底部太远

有人看到问题吗

编辑: 我测试了一个没有opencv的简单解决方案 在@ema的评论之后,我测试了一个没有opencv的非常简单的解决方案。这实际上会产生正确的图像像素,但速度要慢得多(使用opencv时约5ms,而使用opencv时约1ms)

用于(常数自动和p_激光雷达:点激光雷达){
cv::point2dp{p_lidar.x/p_lidar.z,p_lidar.y/p_lidar.z};
p、 x=(p.x+cam.canvas_宽度/2)/2;
p、 y=(p.y+凸轮轴高度/2)/2;
cv::Point2i p_光栅;
p_光栅x=标准::地板(p.x*凸轮图像宽度);
p_光栅y=标准::地板((1-p.y)*凸轮图像高度);
cv::circle(图像->图像,p_光栅,3,cv::Scalar(0,0,255),-1);
}

由于在下一次处理迭代开始之前,管道还有大约100ms的时间,我仍然希望使用opencv进行优化计算。

这可能无法解决问题,但是
785/2
风险很大,请将其设为双除法(
785.0/2
)。例如,如果
p.x
为1.85,则将785/2=392添加到该值,然后将其转换为int,则得到393,这并不完全是答案。如果你把它们加在一起,然后进行投影,它会是394。如果相机坐标系与激光雷达坐标系相同,那么要得到投影点,你只需要将3d点除以z(或-z),例如,{1.88,-0.42,4.50}/4.5={0.41778,-0.09333,1}(或{1.88,-0.42,4.50}/-4.5={-0.41778,0.09333 1})@Ema,但在此基础上,您仍然需要将其转换为光栅坐标。我遵循这个指南。这仍然会导致错误的结果。主要是因为我没有真正理解“画布宽度和高度”,尝试将摄影机矩阵设置为双摄影机_mat[3][3]={{1,0392.5},{0,1392.5},{0,0,1};这可能无法解决问题,但
785/2
风险很大,请将其设置为双除法(
785.0/2
)。例如,如果
p.x
为1.85,则将785/2=392添加到该值,然后将其转换为int,则得到393,这并不完全是答案。如果你把它们加在一起,然后进行投影,它会是394。如果相机坐标系与激光雷达坐标系相同,那么要得到投影点,你只需要将3d点除以z(或-z),例如,{1.88,-0.42,4.50}/4.5={0.41778,-0.09333,1}(或{1.88,-0.42,4.50}/-4.5={-0.41778,0.09333 1})@Ema,但在此基础上,您仍然需要将其转换为光栅坐标。我遵循这个指南。这仍然会导致错误的结果。主要是因为我没有真正理解“画布宽度和高度”,尝试将摄影机矩阵设置为双摄影机_mat[3][3]={{1,0392.5},{0,1392.5},{0,0,1};