解决.tiff文件转.pcd文件滤波后转回.tiff文件点的序列被打乱的问题

解决思路

1、.tiff转点云.pcd格式,定义数据结构记录对应点的三轴坐标与对应的行列信息

.tiff存放点云信息,将点的三轴坐标作为Mat的三个通道的值,三个通道分别对应了点的Z、Y、X坐标

struct pointindex{float x;float y;float z;int i;int j;
};std::vector<pointindex> pointList;//tiff转点云
pcl::PointCloud<pcl::PointXYZ>::Ptr tiff2Cloud(cv::Mat src)
{//创建点云pcl::PointCloud<pcl::PointXYZ>::Ptr cloud (new pcl::PointCloud<pcl::PointXYZ>);if (src.type() == CV_32FC3){for (int i = 0; i < src.rows; i++){const float *p_src = src.ptr<float>(i);for (int j = 0; j < src.cols; j++){if(p_src[3*j]!=0){pcl::PointXYZ point;point.x = p_src[3*j+2];point.y = p_src[3*j+1];point.z = p_src[3*j];cloud->push_back(point);pointindex point_;point_.x = point.x = p_src[3*j+2];point_.y = p_src[3*j+1];point_.z = p_src[3*j];point_.i = i;point_.j = j;pointList.push_back(point_);}}}}return cloud;
}

2、点云离群滤波

点云的可视化尽量采用pcl::visualization::PCLVisualizer::Ptr这个类

//点云可视化
void showCloud(std::string windowname,pcl::PointCloud<pcl::PointXYZ>::Ptr cloud){pcl::visualization::PCLVisualizer::Ptr viewer (new pcl::visualization::PCLVisualizer (windowname));viewer->setBackgroundColor (0.5, 0.5, 0.5);  //设置背景viewer->addPointCloud<pcl::PointXYZ> (cloud, "sample cloud");  //显示点云viewer->setPointCloudRenderingProperties (pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 1, "sample cloud");  //设置点尺寸viewer->addCoordinateSystem (100.0);  //设置坐标轴尺寸
//    while (!viewer->wasStopped ())
//    {//      viewer->spinOnce (100);
//      boost::this_thread::sleep (boost::posix_time::microseconds (100000));
//    }cout<<"Point couting in "<<windowname<<": "<<cloud->size()<<endl;
}//离群滤波pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_filtered (new pcl::PointCloud<pcl::PointXYZ>);pcl::PointCloud<pcl::PointXYZ>::Ptr remove (new pcl::PointCloud<pcl::PointXYZ>);pcl::StatisticalOutlierRemoval<pcl::PointXYZ> sor;sor.setInputCloud (cloud);sor.setMeanK (50);sor.setStddevMulThresh (1.0);sor.filter(*cloud_filtered);showCloud("filtered",cloud_filtered);sor.setNegative(true);sor.filter(*remove);

3、拿离群点的X、Y、Z三轴坐标与前面记录的作比对,找出离群点在原Mat中对应的行列信息,复原离群点在原图中的情况

//点云转tiff
cv::Mat cloud2Tiff(std::vector<pointindex> list,int width,int height){cv::Mat output = cv::Mat::zeros(cv::Size(height,width) ,CV_32FC3);for(auto&p:list){output.ptr<float>(p.i)[3*p.j+2] = p.x;output.ptr<float>(p.i)[3*p.j+1] = p.y;output.ptr<float>(p.i)[3*p.j] = p.z;}return output;
}std::vector<pointindex> filteredpoints;for(int num = 0;num<remove->points.size();num++){for (int index = 0;index<pointList.size();index++){if (std::abs(remove->points[num].x - pointList[index].x) < 0.000001&& std::abs(remove->points[num].y - pointList[index].y) < 0.000001&& std::abs(remove->points[num].z - pointList[index].z) < 0.000001){filteredpoints.push_back(pointList[index]);}}}//离群点云转图cv::Mat src = cloud2Tiff(filteredpoints,img.rows,img.cols);

4、离群点Mat与原Mat通道相减

//通道相减
cv::Mat channelSubtract(cv::Mat img,cv::Mat src){if (src.rows==img.rows && src.cols==img.cols){for(int i=0;i<src.rows;i++){for(int j=0;j<src.cols;j++){src.ptr<float>(i)[3*j] = img.ptr<float>(i)[3*j] - src.ptr<float>(i)[3*j];src.ptr<float>(i)[3*j+1] = img.ptr<float>(i)[3*j+1] - src.ptr<float>(i)[3*j+1];src.ptr<float>(i)[3*j+2] = img.ptr<float>(i)[3*j+2] - src.ptr<float>(i)[3*j+2];}}}return src;
}//离群点云图与原图通道相减src = channelSubtract(img,src);

效果

完整代码

#include <QCoreApplication>
#include<opencv2/opencv.hpp>
#include <pcl/visualization/pcl_visualizer.h>
#include<iostream>//标准C++库中的输入输出类相关头文件。
#include<pcl/io/io.h>
#include<pcl/io/pcd_io.h>//pcd 读写类相关的头文件。
#include<pcl/io/ply_io.h>
#include<pcl/point_types.h> //PCL中支持的点类型头文件。
#include <pcl/filters/statistical_outlier_removal.h>
#include <string.h>struct pointindex{float x;float y;float z;int i;int j;
};std::vector<pointindex> pointList;//tiff转点云
pcl::PointCloud<pcl::PointXYZ>::Ptr tiff2Cloud(cv::Mat src)
{//创建点云pcl::PointCloud<pcl::PointXYZ>::Ptr cloud (new pcl::PointCloud<pcl::PointXYZ>);if (src.type() == CV_32FC3){for (int i = 0; i < src.rows; i++){const float *p_src = src.ptr<float>(i);for (int j = 0; j < src.cols; j++){if(p_src[3*j+2]>0){pcl::PointXYZ point;point.x = p_src[3*j];point.y = p_src[3*j+1];point.z = p_src[3*j+2];cloud->push_back(point);pointindex point_;point_.x = point.x = p_src[3*j];point_.y = p_src[3*j+1];point_.z = p_src[3*j+2];point_.i = i;point_.j = j;pointList.push_back(point_);}}}}return cloud;
}//点云转tiff
cv::Mat cloud2Tiff(std::vector<pointindex> list,int width,int height){cv::Mat output = cv::Mat::zeros(cv::Size(height,width) ,CV_32FC3);for(auto&p:list){output.ptr<float>(p.i)[3*p.j] = p.x;output.ptr<float>(p.i)[3*p.j+1] = p.y;output.ptr<float>(p.i)[3*p.j+2] = p.z;}return output;
}//点云可视化
void showCloud(std::string windowname,pcl::PointCloud<pcl::PointXYZ>::Ptr cloud){pcl::visualization::PCLVisualizer::Ptr viewer (new pcl::visualization::PCLVisualizer (windowname));viewer->setBackgroundColor (0.5, 0.5, 0.5);  //设置背景viewer->addPointCloud<pcl::PointXYZ> (cloud, "sample cloud");  //显示点云viewer->setPointCloudRenderingProperties (pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 1, "sample cloud");  //设置点尺寸viewer->addCoordinateSystem (100.0);  //设置坐标轴尺寸
//    while (!viewer->wasStopped ())
//    {//      viewer->spinOnce (100);
//      boost::this_thread::sleep (boost::posix_time::microseconds (100000));
//    }cout<<"Point couting in "<<windowname<<": "<<cloud->size()<<endl;
}//通道相减
cv::Mat channelSubtract(cv::Mat img,cv::Mat src){if (src.rows==img.rows && src.cols==img.cols){for(int i=0;i<src.rows;i++){for(int j=0;j<src.cols;j++){src.ptr<float>(i)[3*j] = img.ptr<float>(i)[3*j] - src.ptr<float>(i)[3*j];src.ptr<float>(i)[3*j+1] = img.ptr<float>(i)[3*j+1] - src.ptr<float>(i)[3*j+1];src.ptr<float>(i)[3*j+2] = img.ptr<float>(i)[3*j+2] - src.ptr<float>(i)[3*j+2];}}}return src;
}int main(int argc, char *argv[])
{QCoreApplication a(argc, argv);//tiff转pcdcv::Mat img = cv::imread("D:\\Qt_Project\\model123.tiff",cv::IMREAD_UNCHANGED|cv::IMREAD_ANYCOLOR|cv::IMREAD_ANYDEPTH);cv::imshow("before filter",img);pcl::PointCloud<pcl::PointXYZ>::Ptr cloud (new pcl::PointCloud<pcl::PointXYZ>);//图转点云cloud = tiff2Cloud(img);//显示点云showCloud("before filter",cloud);//离群滤波pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_filtered (new pcl::PointCloud<pcl::PointXYZ>);pcl::PointCloud<pcl::PointXYZ>::Ptr remove (new pcl::PointCloud<pcl::PointXYZ>);pcl::StatisticalOutlierRemoval<pcl::PointXYZ> sor;sor.setInputCloud (cloud);sor.setMeanK (50);sor.setStddevMulThresh (1.0);sor.filter(*cloud_filtered);showCloud("filtered",cloud_filtered);sor.setNegative(true);sor.filter(*remove);std::vector<pointindex> filteredpoints;for(int num = 0;num<remove->points.size();num++){for (int index = 0;index<pointList.size();index++){if (std::abs(remove->points[num].x - pointList[index].x) < 0.000001&& std::abs(remove->points[num].y - pointList[index].y) < 0.000001&& std::abs(remove->points[num].z - pointList[index].z) < 0.000001){filteredpoints.push_back(pointList[index]);}}}//离群点云转图cv::Mat src = cloud2Tiff(filteredpoints,img.rows,img.cols);//离群点云图与原图通道相减src = channelSubtract(img,src);cv::imshow("filtered",src);return a.exec();
}

这篇博客解决的问题是如何将.tiff文件转.pcd文件滤波后再转回.tiff文件同时保持像素的一致,下方链接中的源码仅解决了将.tiff文件转.pcd文件这个问题,注意甄别。
tiff转PCL
里面有完整的tiff转pcl代码以及用到的数据集

解决.tiff文件转.pcd文件滤波后转回.tiff文件点的序列被打乱的问题相关推荐

  1. 将一个c 语言源程序文件中所有注释去掉后,存入另一个文件.,C实验内容.doc

    C实验内容 C实验内容 实验一 基本数据处理 1.1 显示短句 在屏幕上显示一个短句"Programming is fun!" 1.2 求两个数的和与差 1.3 求平方根 输入1 ...

  2. win10不能上传文件到服务器,Win10系统下蓝牙无法传输文件怎么解决

    在win10系统中,自带有蓝牙功能,可以方便用户们进行数据传输等,但是有些用户却反映说遇到蓝牙无法传输文件的情况,该怎么解决这样的情况呢?本文就给大家讲解一下Win10系统下蓝牙无法传输文件的具体解决 ...

  3. 电脑重启后python导入的库不见_每次重启电脑后,桌面的文件就不见了,怎么回事啊...

    展开全部 这是由于电2113脑上安装了还原5261精灵,冰点还原,影子系统之类的还原类软件4102或硬件. 安装了此类1653产品后,它们会在后台拦截系统的读写,将读写的内容写到临时的目录中,并不是真 ...

  4. 解决MongoDB 日志文件过大,清理后还占用很大磁盘空间的问题

    解决MongoDB 日志文件过大,清理后还占用很大磁盘空间的问题 参考文章: (1)解决MongoDB 日志文件过大,清理后还占用很大磁盘空间的问题 (2)https://www.cnblogs.co ...

  5. python画图保存成html格式、用浏览器打开页面为空白_解决pyecharts运行后产生的html文件用浏览器打开空白...

    根据网站资源引用说明:pyecharts 使用的所有静态资源文件存放于 pyecharts-assets 项目中,默认挂载在 https://assets.pyecharts.org/assets/ ...

  6. RAMdisk保存文件方案,解决关机后无盘镜像文件没了的方案

    RAMdisk保存文件方案,解决关机后 无盘 镜像文件没了的方案 内存大了用不完 可以用ramdisk在内存中虚拟一个磁盘 把常用软件.系统缓存.浏览器缓存.bt下载都放到这个 虚拟磁盘 中 速度又快 ...

  7. tomcat下只有.class文件 没有java文件_解决tomcat发布工程后,WEB-INF/classes下文件不编译的问题...

    今天部署项目到tomcat,发布完后,启动tomcat,报class not found: 临时找了个解决方案,由于项目是copy过来的,于是就将原来项目的classes下面编译好的class文件也一 ...

  8. vue打包后出现一些map文件的解决方法

    Vue打包后出现一些map文件的解决办法: 问题: 可能很多人在做vue项目打包,打包之后js中,会自动生成一些map文件,那我们怎么把它去掉不要呢? 1.运行  cnpm run build  开始 ...

  9. bangteng文件夹各种方式尝试后删除不了的解决办法

    今天突然之间发现,在C盘的C:\Program Files 下 和 C:\Program Files (x86) 文件夹下发现了有一个 bangteng 的文件夹,里面还有个kangle文件夹, 尝试 ...

最新文章

  1. 飞书与IAI国际广告奖,协同实现国内营销史上的创新“云终审”
  2. C++文本处理_文件读写
  3. “影响100活动”答记者问(二)
  4. boost::geometry::index::detail::union_content用法的测试程序
  5. mmseg java_MMSeg中文分词算法
  6. php说明代码怎么写,代码怎么写 - 起步 - PHP基础 - KK的小故事
  7. java基础—网络编程———聊天窗口的建立
  8. Flume Sink Processor
  9. VI/VIM常用命令
  10. 网易云音乐:歌曲鉴赏人选品
  11. 动图在线压缩怎么操作?教你快速压缩动图
  12. 公司企业邮箱域名如何注册?怎么申请公司域名邮箱?
  13. sprintf和fprintf
  14. 中继器系列:中继器增删改查
  15. 中国露营、户外和越野拖车市场运行动态与发展趋势分析报告2022-2028年
  16. php php_sapi cli,php_sapi_name() cli
  17. 推荐几款jQuery时间轴插件Timeline
  18. java生成二值图,如何创建java poi条形图,结合两个条形值,如给定的图像?
  19. [php] thinkphp实现 163 qq 邮箱收发邮件(切实可用)
  20. Android 生成原生系统签名jks 与 keystore

热门文章

  1. solidworks2018安装
  2. 锐捷三层交换机route-map设置
  3. 科学计算机自动显示小数,卡西欧计算器FX-82MS怎么能让计算器永久显示小数计数而不是科学技术法啊?好烦啊,每次都是显示科学技术法,我试过SHI...
  4. android 最简洁的日历,简洁日历 - 日历与 ToDo 的完美结合 #Android
  5. JAVA斗地主案例(单列)
  6. Foresight AI 创始人袁昌:搭建3D视觉数据平台,助推自动驾驶商业化
  7. PyCharm报错:Please specify a different SDK name解决方法
  8. Smart Tomcat插件的使用详解
  9. tushare获得沪深300和中证500的股票
  10. 基于卷积神经网络的数字手势识别APP(安卓) 毕业设计 附完整代码