1. 双峰自适应阈值二值化 2. 多边形检测 3. 四边形筛选 4. 提取四边形顶点 |
1. 多边形拟合结果必须为四边形,即筛选出二值化图中的四边形 2. 四边形面积必须大于某阈值(opencv源码中这个超参适用于筛选棋盘格的,我们要把这个阈值搞得大一些,用于筛选大方格) 3. 相邻边长不可相差过多 4. 选取黑色的四边形,而不是白色的四边形 5. 限制四边形分布范围,即四边形不能过于靠近图像边缘,具体情况与相机的位姿相关 |
//函数定义 void solveRtFromPnP(const vector &corners2D, const vector &obj3D, const Mat &intrinsic, Mat &R, Mat &t) { Mat r = Mat::zeros(3, 1, CV_32FC1); solvePnP(obj3D, corners2D, intrinsic, cv::Mat(), r, t); Rodrigues(r, R); } //函数调用 solveRtFromPnP(corners_2D, obj_3D, m_intrinsic_undis, R, t);
以上,我们获取到了虚拟相机->真实部署相机之间的位姿R,t。至于R,t为什么不是从真实部署相机->虚拟相机,可以从PNP算法的公式推导中得知(前面已经讲过),或者见视觉SLAM第二版P180-P181。再回到投影变换H模型图中,图中的A就是虚拟相机,B就是真实部署相机。我们已经通过PNP计算出虚拟相机->真实部署相机的R,t。但是我们想要的是如何将真实相机拍摄到的某个平面(对于车轮视角而言是地面)通过H转换到虚拟相机的视角下。因此我们需要对R,t做一些处理,将其转化为真实部署相机->虚拟相机的位姿关系:公式推导:
//基于Rt计算H Mat solveHFromRt(const Mat &R, const Mat &t, const float d, const Mat &n, const Mat &intrinsic) { Mat intrinsic_inverse; invert(intrinsic, intrinsic_inverse, DECOMP_LU); Mat H = intrinsic * (R + t / d * n.t()) * intrinsic_inverse; return H; }
PNP求解外参:/****************************************************************************************************************/ //R t:PNP算出的结果,从虚拟相机->真实部署相机的位姿 //计算出 真实部署相机->虚拟相机的位姿 Mat R_Camera2Real; invert(R, R_Real2Virtual, DECOMP_LU); Mat t_Real2Virtual = -R_Real2Virtual * t; //虚拟相机到地面的垂直单位向量 Mat n = (Mat_(3, 1) << 0, 1, 0); //真实部署相机到地面的垂直单位向量 n = R * n; // rotation float theta_X = m_wheel_sight_angle / 180.f * 3.14f; Mat R_virtual = (Mat_(3, 3) << 1, 0, 0, 0, cos(theta_X), -sin(theta_X), 0, sin(theta_X), cos(theta_X)); R_Camera2Virtual = R_virtual * R_Camera2Virtual; t_Camera2Virtual = R_virtual * t_Camera2Virtual; //计算单应矩阵H:真实视角->虚拟视角 Mat H = solveHFromRt(R_Camera2Virtual, t_Camera2Virtual, d, n, intrinsic);
几点说明:·n(0,1,0),说明单应矩阵选取的平面为地面。不要忘了我们最开始强调的,H描述的是在不同位姿下的两个相机cam1,cam2拍摄同一个平面(例如标定板),这个平面在两个相机成像平面上的成像结果之间的变换关系。因此这个平面的选择,对最终的投影结果有很大的影响。车轮视角选取地面作为我们要进行投影的平面,最终的效果非常nice。·代码中还包含rotation部分,这是因为我们在标定的时候让虚拟相机朝正前方,但显然理想的车轮视角相机应该朝向车轮,即应加一个俯仰角pitch。
1. 假设虚拟相机的位姿为朝向正前方,光轴与正前方的那面墙垂直,坐标系x、y、z如上表中“位姿校正的广角”所示 2. 标定出地面上那些角点在虚拟相机坐标系下的三维坐标 3. 在真实相机拍摄的图像中提取角点的图像坐标(实际上在第一章的标定过程中已经完成) 4. PNP计算虚拟相机->真实相机的位姿 RT 5. 计算真实相机->虚拟相机的位姿rt 6. 我们选定的是垂直于相机光轴的平面,计算这个平面从真实相机->虚拟相机的单应矩阵H,在我们的算法中,这个平面距离相机的距离d=10m,这是一个经验值。 |
Mat H_left = getPerspectiveTransform(p_src_left, p_dst_left); Mat H_right = getPerspectiveTransform(p_src_right, p_dst_right);
//calculate pose solveRtFromPnP(img_corners, obj_corners, intrinsic_undis, R, t); //3dsmax->camera Mat pts_3DsMax = (Mat_<float>(3, 1) << vertex[i].x, vertex[i].y, vertex[i].z); Mat camera_points = R * pts_3DsMax + t; //camera coordinate ->img coordinate Mat coor = intrinsic_undis * camera_points / camera_points.at<float>(2, 0);
上述代码将解析出来的3dsmax坐标系下的 3d碗模型的顶点三维坐标转换到相机坐标系下,然后通过相机内参转换到图像坐标系。最终建立起3d碗模型与图像纹理之间的映射关系。算法流程如下:算法流程1. 标定3dsmax坐标系下 标定布上角点的三维坐标。(即车身中心为原点的车身坐标系) 2. 检测相机拍摄到图像中标定布上角点的图像坐标。(第一章中已标定) 3. 利用1、2的坐标信息,通过PNP计算出 3dsmax坐标系与相机坐标系之间的位姿关系 R,t 4. 解析3d碗状模型的obj文件 5. 将解析出来的3d碗状模型的顶点三维坐标,通过R,t转换到相机坐标系下 6. 通过内参将相机坐标系的坐标转换到图像坐标系,建立起3d模型与相机图像之间的纹理映射关系 |
全部0条评论
快来发表一下你的评论吧 !