艰难的方法:
i) 您会在图像中找到 CLOCKWISE 矩形二维角。
std::vector<cv::Point2f> rect_corners_2d; // TODO find clockwise rectangle 2D corners in image
我想自从你画了矩形后你就有了这些点。
ii) 只要矩形正好位于相机上,并以面向它的光轴为中心,您就可以以物理单位定义 CLOCKWISE 矩形 3D 角。
float width; // TODO set rectangle's physical width
float height; // TODO set rectangle's physical height
std::vector<cv::Point3f> rect_corners_3d =
{
cv::Point3f(-width/2, -height/2, 0.0), // top-left
cv::Point3f(width/2, -height/2, 0.0), // top-right
cv::Point3f(width/2, height/2, 0.0), // bottom-right
cv::Point3f(-width/2, height/2, 0.0) // bottom-left
};
iii) 旋转图像点,使每个 2D 角对应其 3D 对应点。
// rectangle's top-left corner must be the first in 2D image points since it is the first in 3D defined ones
int index; // TODO set index of top-left corner in 2D image points
std::rotate(rect_corners_2d.begin(), rect_corners_2d.begin() + index, rect_corners_2d.end());
iv) 了解您的相机内在参数和镜头畸变系数。
cv::Mat_<double> intrinsic_parameters; // TODO set camera matrix
cv::Mat_<double> distortion_coefficients; // TODO set lens distortion coefficients
我希望你的相机校准好了。
v) 提取相机相对于所见矩形的位姿:http://docs.opencv.org/2.4/modules/calib3d/doc/camera_calibration_and_3d_reconstruction.html#solvepnp
cv::Vec3d rotation;
cv::Vec3d position;
cv::solvePnP(rect_corners_3d, rect_corners_2d, intrinsic_parameters, distortion_coefficients, rotation, position);
此处的位置与您在 ii) 中用于定义 3D 角点的单位相同。
vi) 读取您的水平角度。
double hangle = rotation[1]; // Y axis <--> horizontal angle
结论:计算出的姿势是相机相对于所见矩形的姿势,而不是您预期的相反方向。位置和旋转需要反转。另请注意,相机的 Y 轴向下,OpenCV 使用右手坐标系。您可能需要重新考虑最终角的符号。