1. 环境配置
1. 安装驱动
sudo apt-get install ros-indigo-freenect-*
rospack profile
2. 设置环境变量
echo $TURTLEBOT_3D_SENSOR
如果你看到一个3D传感器,例如asus_xtion_pro ,您将需要设置环境变量的默认值,修改和重新启动终端:
echo "export TURTLEBOT_3D_SENSOR=kinect" >> .bashrc
2. 录制rosbag包
2.1 启动相机
roslaunch turtlebot_bringup minimal.launch
roslaunch freenect_launch freenect-registered-xyzrgb.launch (新版本)--> 实验室版本
roslaunch openni_launch openni.launch (或旧版本)
roslaunch openni2_launch openni2.launch depth_registration:=true
2.2 测试相机
图像,在工作站打开终端执行:
rosrun image_view image_view image:=/camera/rgb/image_color
rosrun image_view image_view image:=/camera/depth_registered/image_raw
2.3 录制
rosbag record -o/O xxx.bag /camera/rgb/image_color /camera/depth_registered/image_raw
3. 提取rosbag包
import roslib;
import rosbag
import rospy
import cv2
from sensor_msgs.msg import Image
from cv_bridge import CvBridge
from cv_bridge import CvBridgeError
rgb_path = '/.../rgb/'
depth_path= '/.../depth/'
class ImageCreator():
def __init__(self):
self.bridge = CvBridge()
with rosbag.Bag('/.../2019-05-10-09-00-55.bag', 'r') as bag:
for topic,msg,t in bag.read_messages():
if topic == "/camera/rgb/image_color":
try:
cv_image = self.bridge.imgmsg_to_cv2(msg,"bgr8")
except CvBridgeError as e:
print e
timestr = "%.6f" % msg.header.stamp.to_sec()
image_name = timestr+ ".png"
cv2.imwrite(rgb_path + image_name, cv_image)
elif topic == "/camera/depth_registered/image_raw":
try:
cv_image = self.bridge.imgmsg_to_cv2(msg,"16UC1")
except CvBridgeError as e:
print e
timestr = "%.6f" % msg.header.stamp.to_sec()
image_name = timestr+ ".png"
cv2.imwrite(depth_path + image_name, cv_image)
if __name__ == '__main__':
try:
image_creator = ImageCreator()
except rospy.ROSInterruptException:
pass
4. 生成rgb.txt 与 depth.txt
#include <iostream>
#include <fmt/os.h>
#include <fmt/core.h>
#include <fmt/format.h>
#include <string>
#include <vector>
#include <algorithm>
extern "C"
{
#include <sys/types.h>
#include <sys/dir.h>
#include <dirent.h>
}
using namespace std;
void getNamesToText(const char *filepath,const char *filetype)
{
DIR *streamp = nullptr;
dirent *dep = nullptr;
string filename(filepath);
auto out = fmt::output_file("../"+string(filetype));
vector<string> names;
streamp = opendir(filepath);
errno = 0;
while ((dep = readdir(streamp)) != NULL)
{
if ((dep->d_name == ".") || (dep->d_name == ".."))
{
continue;
}
names.push_back(dep->d_name);
}
if (errno != 0)
{
fmt::print("error");
}
closedir(streamp);
for (vector<string>::iterator ite = names.begin(); ite != names.end();)
{
if ((*ite == ".") || (*ite == ".."))
{
ite = names.erase(ite);
}
else
{
++ite;
}
}
sort(names.begin(), names.end());
for (auto &item : names)
{
auto pos = item.find_last_of('.');
string filenum;
for (int i = 0; i < pos; i++)
{
filenum += item[i];
}
if(strcmp(filetype,"rgb.txt")==0)
{
out.print("{} rgb/{}\n",filenum,item);
}
else if(strcmp(filetype,"depth.txt")==0)
{
out.print("{} depth/{}\n",filenum,item);
}
}
fmt::print("{} finished\n",filetype);
}
int main(int argc, char *argv[])
{
if(argc<3)
{
fmt::print("Usage: [executable] [rgb/depth path] [type]");
return 0;
}
const char *filepath =argv[1];
const char *filetype =argv[2];
getNamesToText(filepath,filetype);
return 0;
}
5. RGB-D相机标定
5.1 标定板角点提取
#include <iostream>
#include <opencv2/opencv.hpp>
#include <opencv2/highgui/highgui.hpp>
using namespace std;
using namespace cv;
int main()
{
Mat img_1 = cv::imread("C:\\Users\\ZhaoCheng\\source\\repos\\OpenCV\\OpenCV\\rec.jpg");
Mat img_2 = cv::imread("C:\\Users\\ZhaoCheng\\source\\repos\\OpenCV\\OpenCV\\circle.jpg");
if (img_1.empty() || img_2.empty())
{
return -1;
}
Mat gray_1, gray_2;
cvtColor(img_1, gray_1, COLOR_BGR2GRAY);
cvtColor(img_2, gray_2, COLOR_BGR2GRAY);
Size board_size_1 = Size(9, 6);
Size board_size_2 = Size(7,7);
vector<Point2f> img_points_1, img_points_2;
findChessboardCorners(gray_1, board_size_1, img_points_1);
findCirclesGrid(gray_2, board_size_2, img_points_2);
find4QuadCornerSubpix(gray_1, img_points_1, Size(5, 5));
find4QuadCornerSubpix(gray_2, img_points_2, Size(5, 5));
drawChessboardCorners(img_1, board_size_1, img_points_1, true);
drawChessboardCorners(img_2, board_size_2, img_points_2, true);
imshow("方格标定", img_1);
imshow("圆形标定", img_2);
imwrite("方格标定.jpg",img_1);
imwrite("圆形标定.jpg",img_2);
waitKey(0);
return 0;
}
5.2 相机内参
#include <vector>
#include <fstream>
#include <iostream>
#include <opencv2/opencv.hpp>
#include <opencv2/highgui/highgui.hpp>
using namespace std;
using namespace cv;
int main()
{
vector<Mat> imgs;
string image_name;
ifstream infile("calibdata.txt");
if (!infile)
{
cout << "open error" << endl;
return -1;
}
while (getline(infile,image_name))
{
static unsigned int num = 0;
Mat img = imread(image_name);
imgs.push_back(img);
}
Size board_size = Size(9, 6);
vector<vector<Point2f>> imgs_points;
for (int i = 0; i < imgs.size(); i++)
{
Mat img1 = imgs[i];
Mat gray1;
cvtColor(img1, gray1, COLOR_BGR2GRAY);
vector<Point2f> img1_points;
findChessboardCorners(gray1, board_size, img1_points);
find4QuadCornerSubpix(gray1, img1_points, Size(5, 5));
drawChessboardCorners(img1, board_size, img1_points, true);
imgs_points.push_back(img1_points);
}
Size square_size = Size(24, 24);
vector<vector<Point3f>> object_points;
for (int i = 0; i < imgs_points.size(); i++)
{
vector<Point3f> temp_points;
for (int j = 0; j < board_size.height; j++)
{
for (int k = 0; k < board_size.width; k++)
{
Point3f real_point;
real_point.x = j * square_size.width;
real_point.y = k * square_size.height;
real_point.z = 0;
temp_points.push_back(real_point);
}
}
object_points.push_back(temp_points);
}
vector<int> point_number;
for (int i = 0; i < imgs_points.size(); i++)
{
point_number.push_back(board_size.width * board_size.height);
}
Size img_size;
img_size.width = imgs.at(0).cols;
img_size.height = imgs.at(0).rows;
Mat camera_matrix = Mat(3, 3, CV_32FC1, Scalar::all(0));
Mat dist_coeffs = Mat(1, 5, CV_32FC1, Scalar::all(0));
vector<Mat> rvecs;
vector<Mat> tvecs;
calibrateCamera(object_points, imgs_points, img_size, camera_matrix, dist_coeffs, rvecs, tvecs, 0);
cout << "相机的内参矩阵:\n" << camera_matrix << endl;
cout << "相机畸变系数:\n" << dist_coeffs << endl;
waitKey(0);
return 0;
}
5.3 ROS包-kinectv1 – camera_calibration
5.3.1 标定板下载
标定板下载
5.3.2 相机和标定程序
1. roslaunch freenect_launch freenect.launch
2. rosrun camera_calibration cameracalibrator.py --size 8x6 --square 0.0245 image:=/camera/rgb/image_raw camera:=/camera/rgb
注意:
CALIBRATE 被激活后,点击CALIBRATE 按钮,稍等1-2 分钟,SAVE 按钮和COMMIT 按钮被激活,点击save 校准数据会被保存到/temp 文件夹下;点击COMMIT 将结果保存到/home/.ros/camera_info/ 文件夹下。
5.3.3 标定深度相机
rosrun camera_calibration cameracalibrator.py image:=/camera/ir/image_raw camera:=/camera/ir --size 8x6 --square 0.024
注意:深度相机标定的时候尽量在暗处,遮光最好,用不透光的物品把红外发射装置遮住。
image_width: 640
image_height: 480
camera_name: rgb_A00361D00635137A
camera_matrix:
rows: 3
cols: 3
data: [519.162926187449, 0, 306.2870356586101, 0, 519.1127779687413, 266.2205037810496, 0, 0, 1]
distortion_model: plumb_bob
distortion_coefficients:
rows: 1
cols: 5
data: [0.1746622752778997, -0.2169260940804337, 0.007160603616569282, -0.0121890591153448, 0]
rectification_matrix:
rows: 3
cols: 3
data: [1, 0, 0, 0, 1, 0, 0, 0, 1]
projection_matrix:
rows: 3
cols: 4
data: [537.52587890625, 0, 298.1487616194645, 0, 0, 541.44287109375, 269.0468311393488, 0, 0, 0, 1, 0]
image_width: 640
image_height: 480
camera_name: rgb_A00361D00635137A
camera_matrix:
rows: 3
cols: 3
data: [525.9082191482263, 0, 306.061301256364, 0, 524.0230229561403, 249.5250446033006, 0, 0, 1]
distortion_model: plumb_bob
distortion_coefficients:
rows: 1
cols: 5
data: [0.1765549953084217, -0.3142127236680227, 0.0004540028525181106, -0.003012224131173345, 0]
rectification_matrix:
rows: 3
cols: 3
data: [1, 0, 0, 0, 1, 0, 0, 0, 1]
projection_matrix:
rows: 3
cols: 4
data: [536.6383666992188, 0, 303.3809178001175, 0, 0, 536.6723022460938, 249.1436858015313, 0, 0, 0, 1, 0]
camera_matrix:
[522.536,0,306.174]
[0,521.567,257.872]
[0, 0, 1]
distortion_coefficients:
[0.1756,-0.2655,0.0038,-0.0076,0]
|