solvePNP問題

2312 ワード

OpenCVのsolvePnP関数には、次の4つのアルゴリズムがあります.
                    
SOLVEPNP_ITERATIVE 
適合点が同一平面上にある場合
SOLVEPNP_EPNP 
EPnP: Efficient Perspective-n-Point Camera Pose Estimation [91].点は異なる平面でなければなりません
SOLVEPNP_P3P 
Complete Solution Classification for the Perspective-Three-Point Problem [57].3点のみ
SOLVEPNP_DLS 
A Direct Least-Squares (DLS) Method for PnP [73].少なくとも4点は同じ平面にありません
同じ平面で原点と座標軸対称の点についてsolvePnPを用いたが,後の3つのアルゴリズムではカメラ位置が推定できない場合があり,第1のアルゴリズムではカメラ位置の推定に成功した.
投影とsolvePnP機能をテストするコード
void testProjection(std::vector<:point3f> &objs, cv::Mat &matrix, cv::Mat &coeff)
{
	//  
	std::vector<:point2f> projected_pts;
	cv::Mat rvec_test=(cv::Mat_(3,1)<<0.,0.,0.);
	cv::Mat tvec_test=(cv::Mat_(3,1)<<0.,0.,1000.);
	//cv::Mat blank_img(5000,5000,CV_8UC3,cv::Scalar(255,255,255));
	Debug("test project start!");
	Debug("objs");
	Debug(objs);
	cv::projectPoints(objs,rvec_test,tvec_test,matrix,coeff,projected_pts);
	Debug("test project end!");
	Debug("projected_pts");
	Debug(projected_pts);
	
 	 /* for(int i=0;i<5;i++)
	{
		cv::circle(blank_img,projected_pts[i],5,cv::Scalar(0,0,0),-1);
	} 
	cv::imwrite("blank.png",blank_img);
	Debug("Draw Points Completed!"); 
	Debug("start solvePnP"); */
	//PnP
	cv::Mat r_test;
	cv::Mat t_test;
	cv::Mat R_test(3,3,CV_32F);
	cv::solvePnP(objs,projected_pts,matrix,coeff,r_test,t_test,false,CV_ITERATIVE);
	cv::Rodrigues(r_test,R_test);
	cv::Mat cam_pose_pnp;
	Debug("R_test");
	Debug(R_test);
	Debug("t_test");
	Debug(t_test);
	cv::transpose(R_test,R_test);
	cam_pose_pnp=-R_test*t_test;
	Debug("cam_pose_pnp");
	Debug(cam_pose_pnp);
	
}

まとめてみます.
8点の場合:EPnPは良好、DLSは良好、EPnpはUpnp呼び出しの関数インタフェースと同じ
4点の場合:P 3 Pは良好、EPnpは良好であったが、P 3 Pの実際の入力点数は4点であり、最後の点はチェックに用いられた. 
Epnpは4点のときに良くも悪くも表現され,制御点の選択状況に関連している.5点に増えれば精度は著しく向上する
4点のITERATOR法はP 3 Pよりも良い効果を得た.P 3 Pは3点だけで計算に参加するからだ.
すなわち,制御点対数が少ない場合(4点),P 3 Pのみが正しい結果を与えることができる.
一対の制御点(5対になる)を追加すると,Epnpのロバスト性が急速に向上し,正確な結果が得られ,DLSも同様に正確な結果が得られた.
5対の制御点に増加するとP 3 Pは失効する、4点しか使わせないため、少なくない. 
同様に,5点のITERATORメソッドの結果は正しい. 
結論:4点より多いEPnPの使用が最も妥当である.