链接: http://ronny.rest/tutorials/module/pointclouds_01/point_cloud_mpl/
链接: https://blog.csdn.net/learning_tortosie/article/details/88828388
图像和点云坐标先要理解好图像和点云坐标的关系是完成整个流程关键的基础
蓝色坐标轴就是图像的坐标系,黄色坐标指的是点云的坐标系。
在这里注意:
1.图像坐标系中的对应坐标轴始终为正值
2.图像坐标系的原点是在图像的左上角点
3.图像坐标系坐标值是int整数型
4.点云坐标原点是相机点
5.至于点云坐标系中的x轴y轴z轴指向要看你的鸟瞰视图视哪一个方向的,以我距离,我的是以上图片的坐标系。
如上如所看,我的坐标系以及款选点云框与坐标系之间的关系:
**在这里规定:
x_img表示图像坐标系中,x轴坐标
y_img表示图像坐标系中,y轴坐标
x_max表示图像的x轴大小,用于设置图像大小
y_max表示图像y轴大小,用于设置图像大小
pixel_values表示在图像坐标系中对应坐标的函数值
**
float side_range [] = { -1500,800 };
float fwd_range[] = { -500 ,500 };
float height_range[] = { -2,2};//y轴相关
//记录筛选出来的点云下标
vectorindices;
//获取用矩形框款住想要的点云 利用循环每一个点云,筛选出属于规定框中的点云
for (int i = 0; i < cloud->points.size(); i++) {
if ((cloud->points[i].x > fwd_range[0] && cloud->points[i].x < fwd_range[1]) && (cloud->points[i].z > side_range[0] && cloud- >points[i].z < side_range[1]))
{
indices.push_back(i);
}
};
将点云的厚度信息经过比例转化成255对应值,赋值到img图像对应的坐标值中
//将点云的厚度信息经过比例转化成255对应值,赋值到img图像对应的坐标值中
for (int i = 0; i < indices.size(); i++) {
pixel_values[i]=scale_to_255(pixel_values[i], height_range[0], height_range[1]);
}
//将a值缩放到0-255之间,放回的类型是整型int
int scale_to_255(int pixel_value, int min, int max) {
return int((((pixel_value - min) / float(max - min)) * 255));
}
源代码
注释比较清晰,欢迎大家一起交流,本人小白,不断摸索,有不足之处欢迎提供建议
#include
#include
#include
#include
#include
using namespace std;
//将a值缩放到0-255之间,放回的类型是整型int
int scale_to_255(int pixel_value, int min, int max) {
return int((((pixel_value - min) / float(max - min)) * 255));
}
void use_pcdTopicture_main(pcl::PointCloud< pcl::PointXYZRGB>::Ptr cloud, float res, float side_range_left, float side_range_right, float fwd_range_behind , float fwd_range_front, float height_range_min,float height_range_max) {
/*初始化
cloud 表示点云地址
res 表示分辨率
side_range left - most to right - most
fwd_range back - most to forward - most
height_range bottom - most to upper - most*/
res = 1.0;
//获取点云的最值
pcl::PointXYZRGB min, max;
pcl::getMinMax3D(*cloud, min, max);
//将点云的最值设置为框住点云的边界,自动设置边框大小,目的就是构建图片大小。
//在cloudcompare中绿色坐标轴代表y,红色坐标轴代表x,蓝色坐标轴代表z,因此我们想要的是水平面也就是XOZ面
//根据双目成像原理我认为点云的原点就是相机的位置。,所以我认为款选的是要固定的
float side_range [] = { -1500,800 };
float fwd_range[] = { -500 ,500 };
float height_range[] = { -2,2};//y轴相关
//记录筛选出来的点云下标
vectorindices;
//获取用矩形框款住想要的点云 利用循环每一个点云,筛选出属于规定框中的点云
for (int i = 0; i < cloud->points.size(); i++) {
if ((cloud->points[i].x > fwd_range[0] && cloud->points[i].x < fwd_range[1]) && (cloud->points[i].z > side_range[0] && cloud->points[i].z < side_range[1]))
{
indices.push_back(i);
}
};
//在img图像中坐标
vectorx_img;
vectory_img;
//将点云的值映射到像素位置中,分辨率为1的话则,将点云的值原封不动的映射到图像中
for (int i = 0; i < indices.size(); i++) {
x_img.push_back(-cloud->points[i].z/res);
y_img.push_back(-cloud->points[i].x / res);
}
//平移图像数据到点云的最左上角
for (int i = 0; i < indices.size(); i++) {
x_img[i]-=int(floor(side_range[0]/res));
y_img[i] += int(ceil(fwd_range[1] / res));
}
//将厚度信息的值转化为255值,并且填充到对应的img中对应的坐标中
vectorpixel_values;
//先筛选符合厚度条件的点云
for (int i = 0; i < indices.size(); i++) {
if (cloud->points[i].y > height_range[0] && cloud->points[i].y < height_range[1])
{
pixel_values.push_back(cloud->points[i].y);
}
}
//将点云的厚度信息经过比例转化成255对应值,赋值到img图像对应的坐标值中
for (int i = 0; i < indices.size(); i++) {
pixel_values[i]=scale_to_255(pixel_values[i], height_range[0], height_range[1]);
}
//创建图像大小,取决于我们所定义的框选矩形和分辨率
int x_max = 1 + int((side_range[1] - side_range[0]) / res);
int y_max = 1 + int((fwd_range[1] - fwd_range[0]) / res);
//利用opencv创建一个Mat类型来存储图像的信息
cv::Mat im = cv::Mat::zeros(x_max, y_max, CV_8U);
//im[x_img, y_img]=pixel_values;
//创建一个循环,遍历x_img或者y_img的点,给Mat类型的图像,对应的x_img,y_img坐标赋值pixel_values值
for (int i = 0; i < x_img.size(); i++) {
im.at(x_img[i], y_img[i]) = pixel_values[i];
}
//数据图片打印信息
cout << "图像中x轴最小点坐标值为x_img min:"<< *min_element(x_img.begin(), x_img.end()) << endl;
cout << "图像中x轴最大点坐标值为x_img max:" << *max_element(x_img.begin(), x_img.end()) << endl;
cout << "图像中y轴最小点坐标值为y_img min:" << *min_element(y_img.begin(), y_img.end()) << endl;
cout << "图像中y轴最大点坐标值为y_img max:" << *max_element(y_img.begin(), y_img.end()) << endl;
//可视化
cvNamedWindow("img_result");
cv::imshow("img_result", im);
//取反
cv::Mat im_reverse;
im_reverse = 255 - im;
cvNamedWindow("img_reverse_result");
cv::imshow("img_reverse_result", im_reverse);
cvvWaitKey();
//将图片保存
std::vectorparam;
param.push_back(CV_IMWRITE_PXM_BINARY);
cv::imwrite("img_reverse_result.bmp", im_reverse, param);
cout << "save img" << endl;
}
如果复制本人代码,希望能够引出引用,尊重本人成果
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)