相机照片的像素坐标和世界坐标转换

这篇具有很好参考价值的文章主要介绍了相机照片的像素坐标和世界坐标转换。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

相机坐标和世界坐标变换原理就是在4个坐标系直接转换, 如果考虑GIS系统那么还需要考虑空间参考坐标, 空间参考坐标系又需要考虑地理和投影坐标系,  加起来就是6个坐标系. 示例图如下

相机坐标系转世界坐标系,基础知识,C++札记,GIS开发,opencv,计算机视觉,人工智能

 

此段代码基于opencv,  畸变参数未考虑,  采用pnp求解内外参数,封装相机坐标和世界坐标转换方法, GIS系统的坐标系都是一种世界坐标,  一般标定都是局部世界坐标系和GIS中投影空间参考坐标有一个x,y方向的平移参数即可完成转换, 投影转地理这直接GDAL中转换即可搞定. 具体代码如下:文章来源地址https://www.toymoban.com/news/detail-536695.html


#include <iostream>
 
#include <opencv2/opencv.hpp>
#include <iostream>
#include <ctype.h>
using namespace cv;
using namespace std;
#ifdef _DEBUG
	#pragma comment(lib,"opencv_world460d.lib")
#else
	#pragma comment(lib,"opencv_world460.lib")
#endif // _DEBUG

void CameraToWorld(InputArray cameraMatrix, InputArray rV, InputArray tV, Point2d& imgPoints, Point3d& worldPoints)
{
	cv::Mat cameraMatrix1 = cameraMatrix.getMat();
	///根据公式求Zc,即s
	cv::Mat imagePoint = cv::Mat::ones(3, 1, cv::DataType<double>::type);
	cv::Mat tempMat, tempMat2;
	//输入一个2D坐标点,便可以求出相应的s
	imagePoint.at<double>(0, 0) = imgPoints.x;
	imagePoint.at<double>(1, 0) = imgPoints.y;
	imagePoint.at<double>(2, 0) = 1;
	double zConst = 0;//实际坐标系的距离
	//计算参数s
	double s;
	tempMat = rV.getMat().inv() * cameraMatrix1.inv() * imagePoint;
	tempMat2 = rV.getMat().inv() * tV.getMat();
	s = zConst + tempMat2.at<double>(2, 0);
	s /= tempMat.at<double>(2, 0);

	cv::Mat imagePoint_your_know = cv::Mat::ones(3, 1, cv::DataType<double>::type); //u,v,1
	imagePoint_your_know.at<double>(0, 0) = imgPoints.x;
	imagePoint_your_know.at<double>(1, 0) = imgPoints.y;
	imagePoint_your_know.at<double>(2, 0) = 1;
	Mat wcPoint = rV.getMat().inv() * (cameraMatrix1.inv() * s * imagePoint_your_know - tV.getMat());

	worldPoints.x = wcPoint.at<double>(0, 0);
	worldPoints.y = wcPoint.at<double>(1, 0);
	worldPoints.z = wcPoint.at<double>(2, 0);
	cout << "CameraToWorld 2D to 3D:   " << worldPoints << endl;
}

void WorldToCamera(InputArray cameraMatrix, InputArray rV, InputArray tV, Point3d& worldPoint, Point2d& imgPoint)
{
	cv::Mat cameraMatrix1 = cameraMatrix.getMat();

	cv::Mat worldPoints = Mat::ones(4, 1, cv::DataType<double>::type);
	worldPoints.at<double>(0, 0) = worldPoint.x;
	worldPoints.at<double>(1, 0) = worldPoint.y;
	worldPoints.at<double>(2, 0) = worldPoint.z;
	cout << "world Points :  " << worldPoints << endl;
	Mat image_points = Mat::ones(3, 1, cv::DataType<double>::type);
	//setIdentity(image_points);
	Mat RT_;
	hconcat(rV, tV, RT_);
	cout << "RT_" << RT_ << endl;
	cout << "cameraMatrix1_" << cameraMatrix1 << endl;
	image_points = cameraMatrix1 * RT_ * worldPoints;
	Mat D_Points = Mat::ones(3, 1, cv::DataType<double>::type);
	D_Points.at<double>(0, 0) = image_points.at<double>(0, 0) / image_points.at<double>(2, 0);
	D_Points.at<double>(1, 0) = image_points.at<double>(1, 0) / image_points.at<double>(2, 0);
	//cv::projectPoints(worldPoints, rV, tV, cameraMatrix1, distCoeffs1, imagePoints);
	cout << "WorldToCamera 3D to 2D:   " << D_Points << endl;
}

int main()
{
	// 求内外参数通过PnP求解相机的R&T//
	Point2f point;
	vector<Point2f> boxPoints; //存入像素坐标
	// Loading image
	Mat sourceImage = imread("D:/source/kernel/example/opencv_uvxyztest/x64/Debug/a.bmp");
	namedWindow("Source", 1);
	// Setting box corners in image
		//one Point
		point = Point2f((float)558, (float)259); //640X480
	boxPoints.push_back(point);
	circle(sourceImage, boxPoints[0], 3, Scalar(0, 255, 0), -1, 8);

	//two Point
		point = Point2f((float)629, (float)212); //640X480
	boxPoints.push_back(point);
	circle(sourceImage, boxPoints[1], 3, Scalar(0, 255, 0), -1, 8);

	//three Point
		point = Point2f((float)744, (float)260); //640X480
	boxPoints.push_back(point);
	circle(sourceImage, boxPoints[2], 3, Scalar(0, 255, 0), -1, 8);

	//four Point
		point = Point2f((float)693, (float)209); //640X480
	boxPoints.push_back(point);
	circle(sourceImage, boxPoints[3], 3, Scalar(0, 255, 0), -1, 8);

	//Setting box corners in real world
	vector<Point3f> worldBoxPoints;  //存入世界坐标
	Point3f tmpPoint;
	tmpPoint = Point3f((float)2750, (float)890, (float)0);
	worldBoxPoints.push_back(tmpPoint);
	tmpPoint = Point3f((float)3500, (float)450, (float)0);
	worldBoxPoints.push_back(tmpPoint);
	tmpPoint = Point3f((float)2790, (float)-240, (float)0);
	worldBoxPoints.push_back(tmpPoint);
	tmpPoint = Point3f((float)3620, (float)-50, (float)0);
	worldBoxPoints.push_back(tmpPoint);
	//camera  intristic///
	cv::Mat cameraMatrix1 = Mat::eye(3, 3, cv::DataType<double>::type);  //相机内参矩阵
	cv::Mat distCoeffs1(5, 1, cv::DataType<double>::type);  //畸变参数
	distCoeffs1.at<double>(0, 0) = 0.061439051;
	distCoeffs1.at<double>(1, 0) = 0.03187556;
	distCoeffs1.at<double>(2, 0) = -0.00726151;
	distCoeffs1.at<double>(3, 0) = -0.00111799;
	distCoeffs1.at<double>(4, 0) = -0.00678974;

	//Taken from Mastring OpenCV d  相机固定参数
	double fx = 328.61652824;
	double fy = 328.56512516;
	double cx = 629.80551148;
	double cy = 340.5442837;
	cameraMatrix1.at<double>(0, 0) = fx;
	cameraMatrix1.at<double>(1, 1) = fy;
	cameraMatrix1.at<double>(0, 2) = cx;
	cameraMatrix1.at<double>(1, 2) = cy;

	//PnP solve R&T///
	cv::Mat rvec1(3, 1, cv::DataType<double>::type);  //旋转向量
	cv::Mat tvec1(3, 1, cv::DataType<double>::type);  //平移向量
	cv::solvePnP(worldBoxPoints, boxPoints, cameraMatrix1, distCoeffs1, rvec1, tvec1, false, 0);
	cv::Mat rvecM1(3, 3, cv::DataType<double>::type);  //旋转矩阵
	cv::Rodrigues(rvec1, rvecM1);

	//此处用于求相机位于坐标系内的旋转角度, 2D - 3D的转换并不用求
	const double PI = 3.1415926;
	double thetaZ = atan2(rvecM1.at<double>(1, 0), rvecM1.at<double>(0, 0)) / PI * 180;
	double thetaY = atan2(-1 * rvecM1.at<double>(2, 0), sqrt(rvecM1.at<double>(2, 1)*rvecM1.at<double>(2, 1)
		+ rvecM1.at<double>(2, 2)*rvecM1.at<double>(2, 2))) / PI * 180;
	double thetaX = atan2(rvecM1.at<double>(2, 1), rvecM1.at<double>(2, 2)) / PI * 180;
	cout << "theta x  " << thetaX << endl << "theta Y: " << thetaY << endl << "theta Z: " << thetaZ << endl;



	///World To Camera
	Point2d d2p;
	Point3d wd(3620, -590, 345);
	cout << "world Points :  " << wd << endl;
	WorldToCamera(cameraMatrix1, rvecM1, tvec1, wd, d2p);

	// Camera To World
	Point2d d2pcw(757.0414822810177, 213.3698894820287);
	Point3d wdcw;
	cout << "camera Points :  " << d2pcw << endl;
	CameraToWorld(cameraMatrix1, rvecM1, tvec1, d2pcw, wdcw);

	return 0;
}

到了这里,关于相机照片的像素坐标和世界坐标转换的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 世界坐标系、相机坐标系和图像坐标系的转换

    之前只是停留在会用的阶段,一直没去读懂计算的原理,今天通读了大佬的文章,写的言简意赅,感谢感谢~~特此记录一下,仅用作个人笔记 贴链接,十分感谢~ https://blog.csdn.net/weixin_44278406/article/details/112986651 https://blog.csdn.net/guyuealian/article/details/104184551 将三维物体转换成照

    2023年04月15日
    浏览(31)
  • 相机照片的像素坐标和世界坐标转换

    相机坐标和世界坐标变换原理就是在4个坐标系直接转换, 如果考虑GIS系统那么还需要考虑空间参考坐标, 空间参考坐标系又需要考虑地理和投影坐标系,  加起来就是6个坐标系. 示例图如下   此段代码基于opencv,  畸变参数未考虑,  采用pnp求解内外参数,封装相机坐标和世界坐标

    2024年02月13日
    浏览(24)
  • Nuscenes——实现世界坐标3D点投影到像素坐标系中

    首先在 mmdetection3d/tools/data_converter/nuscenes_converter.py 中, get_2d_boxes() 可以直接从nuscenes原始sample数据中获取已标注的3D box信息,因此该函数就可以实现整体投影过程。 投影原理 投影过程分为以下几步: 世界坐标系 —— Ego坐标系(自身) 这里需要世界坐标系原点变换到自身的

    2024年02月11日
    浏览(19)
  • 机器人坐标系转换从局部坐标系转换到世界坐标系

    矩阵方式: 下面是代码: 函数方式: 根据三角函数的特性,可以进行一下简化: 下面是简化前的代码示例:

    2024年04月16日
    浏览(31)
  • 图像坐标系如何转换到相机坐标系。

    问题描述:图像坐标系如何转换到相机坐标系。 问题解答: 图像坐标系的定义: 图像坐标系是用于描述数字图像中像素位置的坐标系。图像坐标系的原点是相机光轴与成像平面的交点。X轴沿着成像平面的水平方向正向,Y轴沿着成像平面的垂直方向正向。 相机坐标系的定义

    2024年02月04日
    浏览(24)
  • Unity坐标系的转换—世界坐标转为UI坐标

    直接调用WorldToAnchorPos,传入对应的参数返回UGUI坐标

    2024年04月13日
    浏览(21)
  • 相机基础(二)——坐标系转换

    物体之间的坐标系变换都可以表示坐标系的旋转变换加上平移变换,则世界坐标系到相机坐标系的转换关系也是如此。绕着不同的轴旋转不同的角度得到不同的旋转矩阵。如下: 那么世界坐标系到相机坐标系的变换如下: 从相机坐标系到图像坐标系,属于透视投影关系,从

    2024年02月11日
    浏览(27)
  • 相机标定 >> 坐标系转换@内参、外参

    为了更好的理解标定,首先应熟悉各个坐标系。(坐标系图均取自百度百科) 该坐标系是以图像左上角为原点建立以像素为单位的二维坐标系u-v。(相对坐标系) 图像坐标系是以 O1 (是图像的主点,也即光轴与像平面的交点,一般就是像素坐标系的中点)为原点的二维坐标

    2024年02月12日
    浏览(25)
  • 相机的位姿在地固坐标系ECEF和ENU坐标系的转换

    在地球科学和导航领域,通常使用地心地固坐标系(ECEF,Earth-Centered, Earth-Fixed)和东北天坐标系(ENU,East-North-Up)来描述地球上的位置和姿态。如下图所示: ​地心地固坐标ecef和东北天ENU坐标系 在倾斜摄影测量过程中,通常涉及这两个坐标系的转换,将相机的位姿互转,

    2024年02月12日
    浏览(19)
  • C++ api调用realsense d435相机,将坐标转换到相机坐标系

            在使用Intel RealSense相机进行编程时,首先需要创建一个 rs2::pipeline 对象,并使用该对象启动相机的数据流。在启动数据流后,相机将根据配置的参数生成相应的数据流,例如深度、彩色或红外流,并将这些数据传输到计算机中。 RS2_STREAM_DEPTH :指定启用的流类型为

    2024年02月16日
    浏览(24)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包