这是一段使用了 PCL(Point Cloud Library)和 OpenCV 库的 C++ 代码。这段代码似乎是用来生成一张雷达扫描的范围图像并保存为图片文件。
这段代码主要做了以下几件事情:
- 使用 PCL 加载点云数据。
- 根据点云数据计算出每个点在范围图像中的位置,并将范围信息映射到颜色上。
- 生成 HSV 图像以更好地显示范围图像。
- 将 HSV 图像转换为 RGB 图像,并保存为图片文件。
#include <gflags/gflags.h>
#include <glog/logging.h>
#include <pcl/io/pcd_io.h>
#include <pcl/point_cloud.h>
#include <pcl/point_types.h>
#include <opencv2/opencv.hpp>
using PointType = pcl::PointXYZI;
using PointCloudType = pcl::PointCloud<PointType>;
DEFINE_string(pcd_path, "./data/ch5/scan_example.pcd", "点云文件路径");
DEFINE_double(azimuth_resolution_deg, 0.3, "方位角分辨率(度)");
DEFINE_int32(elevation_rows, 16, "俯仰角对应的行数");
DEFINE_double(elevation_range, 15.0, "俯仰角范围"); // VLP-16 上下各15度范围
DEFINE_double(lidar_height, 1.128, "雷达安装高度");
void GenerateRangeImage(PointCloudType::Ptr cloud) {
int image_cols = int(360 / FLAGS_azimuth_resolution_deg); // 水平为360度,按分辨率切分即可
int image_rows = FLAGS_elevation_rows; // 图像行数固定
LOG(INFO) << "range image: " << image_rows << "x" << image_cols;
// 我们生成一个HSV图像以更好地显示图像
cv::Mat image(image_rows, image_cols, CV_8UC3, cv::Scalar(0, 0, 0));
double ele_resolution = FLAGS_elevation_range * 2 / FLAGS_elevation_rows; // elevation分辨率
for (const auto& pt : cloud->points) {
double azimuth = atan2(pt.y, pt.x) * 180 / M_PI;
double range = sqrt(pt.x * pt.x + pt.y * pt.y);
double elevation = asin((pt.z - FLAGS_lidar_height) / range) * 180 / M_PI;
// keep in 0~360
if (azimuth < 0) {
azimuth += 360;
}
int x = int(azimuth / FLAGS_azimuth_resolution_deg); // 行
int y = int((elevation + FLAGS_elevation_range) / ele_resolution + 0.5); // 列
if (x >= 0 && x < image.cols && y >= 0 && y < image.rows) {
image.at<cv::Vec3b>(y, x) = cv::Vec3b(uchar(range / 100 * 255.0), 255, 127);
}
}
// 沿Y轴翻转,因为我们希望Z轴朝上时Y朝上
cv::Mat image_flipped;
cv::flip(image, image_flipped, 0);
// hsv to rgb
cv::Mat image_rgb;
cv::cvtColor(image_flipped, image_rgb, cv::COLOR_HSV2BGR);
cv::imwrite("./range_image.png", image_rgb);
}
int main(int argc, char** argv) {
google::InitGoogleLogging(argv[0]);
FLAGS_stderrthreshold = google::INFO;
FLAGS_colorlogtostderr = true;
google::ParseCommandLineFlags(&argc, &argv, true);
if (FLAGS_pcd_path.empty()) {
LOG(ERROR) << "pcd path is empty";
return -1;
}
// 读取点云
PointCloudType::Ptr cloud(new PointCloudType);
pcl::io::loadPCDFile(FLAGS_pcd_path, *cloud);
if (cloud->empty()) {
LOG(ERROR) << "cannot load cloud file";
return -1;
}
LOG(INFO) << "cloud points: " << cloud->size();
GenerateRangeImage(cloud);
return 0;
}
直接运行报错。
在 `.vscode
` 文件夹中创建一个名为 `tasks.json
` 的文件,请将 `output_filename
` 替换为您希望生成的可执行文件的名称,将 `input_filename.cc
` 替换为您的 C++ 源代码文件的名称。
-
在 VSCode 中按 `
Ctrl+Shift+B
`(或者在菜单栏中选择“终端”->“运行生成任务”),这将会运行您的构建任务并生成可执行文件。---->报错 -
最后,您可以按 `
Ctrl+~
` 打开终端,并输入 `./output_filename
` 来运行您的可执行文件。
{
"version": "2.0.0",
"tasks": [
{
"label": "build",
"type": "shell",
"command": "g++",
"args": ["-o",
"trans",
"trans.cc",
"-l", "pcl_common", "-l", "pcl_io", "-l", "pcl_visualization"],
"group": {
"kind": "build",
"isDefault": true
}
}
]
}
问题:
正在执行任务: g++ -o trans trans.cc -l pcl_common -l pcl_io -l pcl_visualization
trans.cc:3:10: fatal error: gflags/gflags.h: No such file or directory
#include <gflags/gflags.h>
^~~~~~~~~~~~~~~~~
compilation terminated.类似的报错还有<glog/logging.h>、<pcl/io/pcd_io.h>
解决:
安装vcpkg。vcpkg是微软 C++ 团队开发的适用于 C 和 C++ 库的跨平台开源软件包管理器,便于安装第三方库。
利用vcpkg安装缺的库。再把库中包含头文件的地址写入task.json。
vcpkg install gflags/glog/pcl
在task.json中添加行例如:
"-I\"D:\\download_software\\vcpkg\\vcpkg\\packages\\gflags_x64-windows\\include\"",
"-L<path_to_gflags_libraries>",
"-l", "gflags",
所以c++引入的那些头文件应该需要一个一个安装,然后把安装地址写到task.json里面才能用。
没解决:
[增压钴]x64-windows 上的构建错误 ·问题 #37007 ·微软/vcpkg ·GitHub上
问题:
arcsinx取值范围[-1,1],由于lidar_height数据不准确(或者数据有不准确的噪声),导致超出定义域使elevation为NaN。
解决:使elevation 值为nan时,指定它的值为0,这能让程序继续运行。后续改进其他方式。
最后放弃掉了c++,让gpt转换成python代码了。呵呵。准备重学。