realsense d435i 在Ubuntu上标定的详细步骤以及内参的修正方法
时间: 2024-05-01 15:17:18 浏览: 505
Realsense D435i是一款深度相机,可以用于3D扫描、SLAM等应用。在使用前需要对相机进行标定,以获取相机的内参矩阵和畸变矩阵等参数,以便进行后续的图像处理和计算。
以下是在Ubuntu上对Realsense D435i进行标定的详细步骤:
1. 安装Realsense SDK
在Ubuntu上安装Realsense SDK,可以参考官方文档:https://github.com/IntelRealSense/librealsense/blob/master/doc/distribution_linux.md
2. 安装ROS
如果需要在ROS中使用Realsense D435i,需要先安装ROS。可以参考官方网站:http://wiki.ros.org/kinetic/Installation/Ubuntu
3. 安装相机驱动
在终端中输入以下命令安装相机驱动:
```bash
sudo apt-get install ros-kinetic-realsense2-camera
```
4. 运行标定程序
在终端中输入以下命令运行标定程序:
```bash
roslaunch realsense2_camera rs_camera.launch enable_pointcloud:=false align_depth:=true
```
此时会打开相机的RGB和深度图像窗口,并开始采集图像数据。可以使用鼠标点击RGB图像窗口中的某个点,将该点的像素坐标保存到文件中。
```bash
rosrun image_view image_view image:=/camera/color/image_raw
```
5. 编写标定程序
在终端中输入以下命令创建一个ROS包:
```bash
catkin_create_pkg calibrate_camera roscpp cv_bridge image_transport
```
然后在src目录下创建一个calibrate_camera.cpp文件,编写标定程序。程序的主要步骤如下:
1. 读取RGB和深度图像数据。
2. 根据RGB图像中的某个点的像素坐标,计算出该点在深度图像中的像素坐标和深度值。
3. 根据相机的内参矩阵、畸变矩阵和深度值,计算出该点的真实世界坐标。
4. 将多个真实世界坐标点和其对应的像素坐标保存到文件中。
5. 使用OpenCV的calibrateCamera函数对相机进行标定,得到相机的内参矩阵和畸变矩阵等参数。
以下是一个简单的标定程序示例:
```cpp
#include <ros/ros.h>
#include <cv_bridge/cv_bridge.h>
#include <image_transport/image_transport.h>
#include <opencv2/calib3d/calib3d.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
using namespace std;
using namespace cv;
const Size boardSize(9, 6); // 棋盘格大小
const float squareSize = 0.0245; // 棋盘格边长(单位:米)
int main(int argc, char **argv)
{
ros::init(argc, argv, "calibrate_camera");
ros::NodeHandle nh;
// 创建图像订阅者
image_transport::ImageTransport it(nh);
image_transport::Subscriber subRgb = it.subscribe("/camera/color/image_raw", 1);
image_transport::Subscriber subDepth = it.subscribe("/camera/aligned_depth_to_color/image_raw", 1);
// 读取图像数据
Mat imgRgb, imgDepth;
ros::Rate loopRate(30);
while (ros::ok())
{
if (subRgb.getNumPublishers() > 0 && subDepth.getNumPublishers() > 0)
{
imgRgb = cv_bridge::toCvCopy(subRgb, sensor_msgs::image_encodings::BGR8)->image;
imgDepth = cv_bridge::toCvCopy(subDepth, sensor_msgs::image_encodings::TYPE_16UC1)->image;
break;
}
ros::spinOnce();
loopRate.sleep();
}
// 获取棋盘格角点的像素坐标和真实世界坐标
vector<Point2f> corners;
vector<Point3f> objPoints;
bool found = findChessboardCorners(imgRgb, boardSize, corners);
if (found)
{
cvtColor(imgRgb, imgRgb, COLOR_BGR2GRAY);
cornerSubPix(imgRgb, corners, Size(11, 11), Size(-1, -1), TermCriteria(TermCriteria::EPS + TermCriteria::COUNT, 30, 0.1));
drawChessboardCorners(imgRgb, boardSize, corners, found);
imshow("Chessboard", imgRgb);
waitKey(0);
for (int i = 0; i < boardSize.height; i++)
{
for (int j = 0; j < boardSize.width; j++)
{
objPoints.push_back(Point3f(j * squareSize, i * squareSize, 0));
}
}
}
else
{
ROS_ERROR("Chessboard not found!");
return 0;
}
// 计算相机的内参矩阵和畸变矩阵
vector<vector<Point3f>> objPointsList;
vector<vector<Point2f>> imgPointsList;
objPointsList.push_back(objPoints);
imgPointsList.push_back(corners);
Mat cameraMatrix, distCoeffs;
vector<Mat> rvecs, tvecs;
calibrateCamera(objPointsList, imgPointsList, imgRgb.size(), cameraMatrix, distCoeffs, rvecs, tvecs);
// 打印相机的内参矩阵和畸变矩阵
cout << "Camera matrix:" << endl << cameraMatrix << endl;
cout << "Distortion coefficients:" << endl << distCoeffs << endl;
return 0;
}
```
6. 修正相机内参
有时候在实际使用中,由于相机的硬件或者环境等因素,可能会导致相机的内参矩阵和畸变矩阵与标定时得到的数值有所偏差,这时候就需要对相机的内参矩阵进行修正。
可以使用OpenCV的undistort函数对图像进行去畸变处理,然后观察去畸变后的图像是否更加清晰,如果是,则说明相机的内参矩阵需要进行修正。
以下是一个简单的相机内参修正示例:
```cpp
#include <ros/ros.h>
#include <cv_bridge/cv_bridge.h>
#include <image_transport/image_transport.h>
#include <opencv2/calib3d/calib3d.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
using namespace std;
using namespace cv;
int main(int argc, char **argv)
{
ros::init(argc, argv, "undistort_camera");
ros::NodeHandle nh;
// 创建图像订阅者
image_transport::ImageTransport it(nh);
image_transport::Subscriber subRgb = it.subscribe("/camera/color/image_raw", 1);
// 读取相机的内参矩阵和畸变矩阵
Mat cameraMatrix = (Mat_<double>(3, 3) << 617.0982666015625, 0, 325.7581787109375, 0, 617.1774291992188, 248.06704711914062, 0, 0, 1);
Mat distCoeffs = (Mat_<double>(1, 5) << -0.02965781861579418, 0.02609023815369606, -0.00583636328125, -0.0016021245323410034, -0.0077972412109375);
// 读取图像数据
Mat imgRgb, imgUndistorted;
ros::Rate loopRate(30);
while (ros::ok())
{
if (subRgb.getNumPublishers() > 0)
{
imgRgb = cv_bridge::toCvCopy(subRgb, sensor_msgs::image_encodings::BGR8)->image;
break;
}
ros::spinOnce();
loopRate.sleep();
}
// 对图像进行去畸变处理
undistort(imgRgb, imgUndistorted, cameraMatrix, distCoeffs);
// 显示去畸变后的图像
imshow("Undistorted", imgUndistorted);
waitKey(0);
return 0;
}
```
以上就是在Ubuntu上对Realsense D435i进行标定的详细步骤以及内参的修正方法。通过标定,可以获取相机的内参矩阵和畸变矩阵等参数,以便进行后续的图像处理和计算。如果发现相机的内参矩阵和畸变矩阵有所偏差,可以使用undistort函数对图像进行去畸变处理,并观察去畸变后的图像是否更加清晰,以判断是否需要对相机的内参矩阵进行修正。
阅读全文