一、环境:
(161条消息) vs2017配置opencv详细步骤(附详细图解)_vs2017对应的opencv版本_想成为大佬啊的博客-CSDN博客
vs2017配置liblas库+测试代码 - CodeAntenna
第一个没问题
第二个出错
找不到 liblas.dll
添加了dll所在文件夹为环境变量,解决了。
二、代码:
(161条消息) 点云投影至xoy平面生成强度图像_点云生成强度图像_zzu_圈圈的博客-CSDN博客
// opencv
#include <opencv2/opencv.hpp>
#include <opencv2/imgproc.hpp>
#include <opencv2/highgui/highgui.hpp>
// pcl
#include <pcl/io/pcd_io.h>
#include <pcl/point_types.h>
//lablas
#include <liblas/liblas.hpp>
using namespace std;
using namespace cv;
typedef pcl::PointCloud<pcl::PointXYZI>::Ptr pcXYZIPtr;
typedef pcl::PointCloud<pcl::PointXYZI> pcXYZI;
/*!
* @brief 读取las格式点云数据函数
* param[in] file_name:las文件
* param[in] point_cloud:点云指针
*/
bool readLasFile(const string &file_name, const pcXYZIPtr &point_cloud)
{
std::ifstream ifs;
ifs.open(file_name, std::ios::in | std::ios::binary);
if (ifs.bad())
{
cout << "Failed to load las File" << endl;
}
liblas::ReaderFactory f;
liblas::Reader reader = f.CreateWithStream(ifs);
int number_points = reader.GetHeader().GetPointRecordsCount();//获取las数据点的个数
point_cloud->width = number_points;
point_cloud->height = 1;
point_cloud->is_dense = false;
point_cloud->resize(point_cloud->width * point_cloud->height);
liblas::Header const &header = reader.GetHeader();
int i = 0;
while (reader.ReadNextPoint())
{
point_cloud->points[i].x = reader.GetPoint().GetX();
point_cloud->points[i].y = reader.GetPoint().GetY();
point_cloud->points[i].z = reader.GetPoint().GetZ();
point_cloud->points[i].intensity = reader.GetPoint().GetIntensity();
i++;
}
// 检查 强度信息是否存在
if (point_cloud->points[0].intensity == 0) //check if the intensity exsit
{
cout << "Warning! Point cloud intensity may not be imported properly, check the scalar field's name.\n" << endl;
}
return 1;
}
/*!
* @brief 点云转强度图像函数
* param[in] cloud:点云指针
* param[in] resolution:点云转图像分辨率
* param[out] img: 点云生成的强度图像
*/
cv::Mat pointCloud2imgI(const pcXYZIPtr &cloud, double resolution)
{
float minx, miny, maxx, maxy, mini, maxi;
minx = miny = mini = FLT_MAX;
maxx = maxy = maxi = -FLT_MAX;
// 获取点云的最大最小 x、y点的坐标
for (int i = 0; i < cloud->points.size(); i++)
{
minx = min(minx, cloud->points[i].x);
miny = min(miny, cloud->points[i].y);
maxx = max(maxx, cloud->points[i].x);
maxy = max(maxy, cloud->points[i].y);
maxi = max(maxi, cloud->points[i].intensity);
}
double lx = maxx - minx; //点云长度
double ly = maxy - miny; //点云宽度
int rows = round(ly / resolution); //图像高度
int clos = round(lx / resolution); //图像宽度
cv::Mat img = cv::Mat::zeros(rows, clos, CV_8UC3);
//强度格网矩阵
vector<vector<float>> vec_grid_intensity;
//格网分配空间 及初始化
vec_grid_intensity.resize(rows);
//初始化格网
for (int i = 0; i < rows; i++)
{
vec_grid_intensity[i].resize(clos);
}
//依次将点压入所在格网
for (int i = 0; i < cloud->points.size(); i++)
{
int m = (maxy - cloud->points[i].y) / resolution;
int n = (cloud->points[i].x - minx) / resolution;
if (m > 0 && m < rows && n > 0 && n < clos)
{
// 将格网中的点云的最大强度值作为格网的强度值
vec_grid_intensity[m][n] = max(cloud->points[i].intensity, vec_grid_intensity[m][n]);
}
}
//强度拉伸到0-255之间赋值
for (int i = 0; i < rows; i++)
{
uchar * data = img.ptr<uchar>(i);
for (int j = 0; j < clos; j++)
{
if (vec_grid_intensity[i][j] > 0)
{
int pixel = (int)(vec_grid_intensity[i][j] / maxi * 255);
//各通道像素赋值
data[3 * j] = pixel;
data[3 * j + 1] = pixel;
data[3 * j + 2] = pixel;
}
}
}
return img;
}
int main()
{
const string las_path = "D:/toWuda/lidar/lidarnew/CGdomYRJ-114(CK0-17)_D_21.las";
const double resolution = 0.05;
pcXYZIPtr cloud(new pcXYZI);
readLasFile(las_path, cloud);
Mat cloud_imgI = pointCloud2imgI(cloud, resolution);
imwrite("cloud_img.jpg", cloud_imgI);
}
三、代码学习:
typedef pcl::PointCloud<pcl::PointXYZI>::Ptr pcXYZIPtr;
typedef pcl::PointCloud<pcl::PointXYZI> pcXYZI;
typedef type newname;
typedef int P(); // 简单的
class X {
public:
P(eat_shit); // 等价于声明`int eat_shit();
}
加了ptr的是指针类型
(162条消息) [PCL教程]基础数据结构 PointCloud &PointT_pcl::pointcloud_Deephome的博客-CSDN博客
数据类型是PointXYZI,I为intensity,强度
pcXYZIPtr cloud(new pcXYZI);
bool readLasFile(const string &file_name, const pcXYZIPtr &point_cloud)
const string las_path = "D:/toWuda/lidar/lidarnew/CGdomYRJ-114(CK0-17)_D_21.las";
readLasFile(las_path, cloud);
liblas::ReaderFactory f;
//使用ReaderFactory从stream中构造Reader而不是直接调用Reader构造函数
//因为las可能是压缩的
liblas::Reader reader = f.CreateWithStream(ifs);
cv::Mat pointCloud2imgI(const pcXYZIPtr &cloud, double resolution)
Mat cloud_imgI = pointCloud2imgI(cloud, resolution);
FLT_MAX //最大的正浮点数
cv::Mat img = cv::Mat::zeros(rows, clos, CV_8UC3);
//深度8位 unsigned int–无符号整形 3通道
// opencv
#include <opencv2/opencv.hpp>
#include <opencv2/imgproc.hpp>
#include <opencv2/highgui/highgui.hpp>
// pcl
#include <pcl/io/pcd_io.h>
#include <pcl/point_types.h>
//lablas
#include <liblas/liblas.hpp>
using namespace std;
using namespace cv;
typedef pcl::PointCloud<pcl::PointXYZI>::Ptr pcXYZIPtr;
typedef pcl::PointCloud<pcl::PointXYZI> pcXYZI;
/*!
* @brief 读取las格式点云数据函数
* param[in] file_name:las文件
* param[in] point_cloud:点云指针
*/
bool readLasFile(const string &file_name, const pcXYZIPtr &point_cloud)
{
std::ifstream ifs;
ifs.open(file_name, std::ios::in | std::ios::binary);
if (ifs.bad())
{
cout << "Failed to load las File" << endl;
}
liblas::ReaderFactory f;
liblas::Reader reader = f.CreateWithStream(ifs);
int number_points = reader.GetHeader().GetPointRecordsCount();//获取las数据点的个数
point_cloud->width = number_points;
point_cloud->height = 1;
point_cloud->is_dense = false;
point_cloud->resize(point_cloud->width * point_cloud->height);
liblas::Header const &header = reader.GetHeader();
int i = 0;
while (reader.ReadNextPoint())
{
point_cloud->points[i].x = reader.GetPoint().GetX();
point_cloud->points[i].y = reader.GetPoint().GetY();
point_cloud->points[i].z = reader.GetPoint().GetZ();
point_cloud->points[i].intensity = reader.GetPoint().GetIntensity();
i++;
}
// 检查 强度信息是否存在
if (point_cloud->points[0].intensity == 0) //check if the intensity exsit
{
cout << "Warning! Point cloud intensity may not be imported properly, check the scalar field's name.\n" << endl;
}
return 1;
}
/*!
* @brief 点云转强度图像函数
* param[in] cloud:点云指针
* param[in] resolution:点云转图像分辨率
* param[out] img: 点云生成的强度图像
*/
cv::Mat pointCloud2imgI(const pcXYZIPtr &cloud, double resolution)
{
float minx, miny, maxx, maxy, mini, maxi;
minx = miny = mini = FLT_MAX;
maxx = maxy = maxi = -FLT_MAX;
// 获取点云的最大最小 x、y点的坐标
for (int i = 0; i < cloud->points.size(); i++)
{
minx = min(minx, cloud->points[i].x);
miny = min(miny, cloud->points[i].y);
maxx = max(maxx, cloud->points[i].x);
maxy = max(maxy, cloud->points[i].y);
maxi = max(maxi, cloud->points[i].intensity);
}
double lx = maxx - minx; //点云长度
double ly = maxy - miny; //点云宽度
int rows = round(ly / resolution); //图像高度
int clos = round(lx / resolution); //图像宽度
cv::Mat img = cv::Mat::zeros(rows, clos, CV_8UC3);
//强度格网矩阵
vector<vector<float>> vec_grid_intensity;
//格网分配空间 及初始化
vec_grid_intensity.resize(rows);
//初始化格网
for (int i = 0; i < rows; i++)
{
vec_grid_intensity[i].resize(clos);
}
//依次将点压入所在格网
for (int i = 0; i < cloud->points.size(); i++)
{
int m = (maxy - cloud->points[i].y) / resolution;
int n = (cloud->points[i].x - minx) / resolution;
if (m > 0 && m < rows && n > 0 && n < clos)
{
// 将格网中的点云的最大强度值作为格网的强度值
vec_grid_intensity[m][n] = max(cloud->points[i].intensity, vec_grid_intensity[m][n]);
}
}
//强度拉伸到0-255之间赋值
for (int i = 0; i < rows; i++)
{
uchar * data = img.ptr<uchar>(i);
for (int j = 0; j < clos; j++)
{
if (vec_grid_intensity[i][j] > 0)
{
int pixel = (int)(vec_grid_intensity[i][j] / maxi * 255);
//各通道像素赋值
data[3 * j] = pixel;
data[3 * j + 1] = pixel;
data[3 * j + 2] = pixel;
}
}
}
return img;
}
int main()
{
const string las_path = "D:/toWuda/lidar/lidarnew/CGdomYRJ-114(CK0-17)_D_21.las";
const double resolution = 0.1;
pcXYZIPtr cloud(new pcXYZI);
readLasFile(las_path, cloud);
Mat cloud_imgI = pointCloud2imgI(cloud, resolution);
imwrite("cloud_img.jpg", cloud_imgI);
}
结果
软件处理结果对比