当前位置: 首页 > news >正文

2025年测绘程序设计比赛--基于统计滤波的点云去噪(已获国特)

小编最近的更新频率比较慢,是因为最近在准备这个全国大学生测绘学科创新创业智能大赛(测绘程序设计)–专业组的比赛,为了这个比赛,小编高强度的准备了一个月,也是取得了较为喜人的成绩。
在这里插入图片描述

如果有准备在2026年参加这个比赛的,可以加入小编和其它大佬所建的群242845175一起来备赛,为2026年的比赛打基础,也可以私信小编,为你答疑解惑

话不多说,接下来是代码与正文

一、读写数据文件

public static List<Point> pts= new List<Point>();public static List<Point> Readfile(string filename)
{string str;StreamReader sr = new StreamReader(filename);int n = 1;while(!sr.EndOfStream){str= sr.ReadLine();string[]Buf=str.Split(new char[]{' ','\t'},StringSplitOptions.RemoveEmptyEntries);Point pt=new Point(double.Parse(Buf[0]), double.Parse(Buf[1]), double.Parse(Buf[2]),n);pts.Add(pt);n++;}return pts;
}
public static void Savefile(string report)
{SaveFileDialog sf=  new SaveFileDialog();sf.Filter = "文本数据|*.txt";sf.Title = "选择保存路径";sf.FileName = "result";if(sf.ShowDialog() == DialogResult.OK){StreamWriter sw= new StreamWriter(sf.FileName);sw.Write(report);sw.Flush();}
}

二、点的相关属性

    public class Point{public double x;public double y;public double z;public int n;//格网划分所需参数public int i;public int j;public int k;//候选点public List<Point> after=new List<Point>();//最近邻点public List<(int, double)> mind =new List<(int, double)>();//平均距离public double avd;public double sigema;//噪点判定public int number;public Point(double x, double y, double z,int n){this.x= x; this.y= y;this.z= z;this.n= n;}public override string ToString(){StringBuilder sb = new StringBuilder();sb.Append(x.ToString()+" "+y.ToString()+" "+z.ToString()+" "+n.ToString());return sb.ToString();}}
}

在这里插入图片描述

三、格网划分与点云分配

在这里插入图片描述

public static double fai = 3;
public static List<Point> zaopoint = new List<Point>(); 
//寻找各项极值
public static void Jizhi(out double xmax,out double ymax,out double zmax,out double xmin,out double ymin,out double zmin)
{xmax = Read.pts.Max(p => p.x);ymax = Read.pts.Max(p => p.y);zmax = Read.pts.Max(p => p.z);xmin = Read.pts.Min(p => p.x);ymin = Read.pts.Min(p => p.y);zmin = Read.pts.Min(p => p.z);
}//计算格网最大值
public static void Gewang(out double xmax1,out double ymax1,out double zmax1)
{Jizhi(out double xmax, out double ymax, out double zmax, out double xmin, out double ymin, out double zmin);xmax1 = (int)((xmax - xmin) / fai + 1) * fai + xmin;ymax1 = (int)((ymax - ymin) / fai + 1) * fai + ymin;zmax1 = (int)((zmax - zmin) / fai + 1) * fai + zmin;
}//格网划分
public static void Classify(List<Point> pts,out int sum)
{Jizhi(out double xmax, out double ymax, out double zmax, out double xmin, out double ymin, out double zmin);foreach (Point p in pts){p.i = (int)((p.x - xmin) / fai);p.j = (int)((p.y - ymin) / fai);p.k = (int)((p.z - zmin) / fai);}//统计(0,0,0)的个数sum = 0;foreach(Point p in pts){if (p.i == 0 && p.j == 0 && p.k == 0){sum++;}}
}

四、k邻近点搜索(k=6)

值得注意的是,有些点的候选点可能不足6个,需要进行特殊处理(不足六个点,则全部选取)
在这里插入图片描述

 //欧式距离计算public static double Distance(Point P1,Point P2){double d = (P1.x - P2.x) * (P1.x - P2.x) + (P1.y - P2.y) * (P1.y - P2.y) + (P1.z - P2.z) * (P1.z - P2.z);return Math.Sqrt(d);}//统计点的候选点//(pt.i-p.i=1||pt.i-p.i=0||pt.i-p.i=-1)&&(pt.j-p.j=1||pt.j-p.j=0||pt.j-p.j=-1)&&(pt.k-p.k=1||pt.k-p.k=0||pt.k-p.k=-1)//Math.Abs(pt.i-p.i)<=1&& Math.Abs(pt.j - p.j) <= 1 && Math.Abs(pt.k - p.k) <= 1public static List<Point> Tongji(Point p){List<Point> list = new List<Point>();foreach(Point pt in Read.pts){if(Math.Abs(pt.i - p.i) <= 1 && Math.Abs(pt.j - p.j) <= 1 && Math.Abs(pt.k - p.k) <= 1){list.Add(pt);//此处并未排除自身点,在后续输出中进行排除}}return list;}//计算每个点最近邻点public static void Mind(List<Point> pts){foreach(Point pt in pts){pt.after = Tongji(pt);List<(int,double)> list = new List< (int, double) >();foreach(Point p in pt.after){if (p.n == pt.n){continue;}list.Add((p.n, Distance(pt,p)));}List<(int, double)> before = new List<(int, double)>();before = list.OrderBy(p => p.Item2).ToList();int k = 0;if (before.Count > 6){k=6;}else{k=before.Count;}for (int i = 0; i < k; i++){pt.mind.Add(before[i]);}}}

五、统计特征计算

在这里插入图片描述

//计算每个点的平均距离和标准差
public static void Alhelp(List<Point> pts)
{foreach(Point pt in pts){pt.avd = pt.mind.Average(p => p.Item2);double sum = 0;for(int i=0;i < pt.mind.Count; i++){sum += (pt.mind[i].Item2 - pt.avd) * (pt.mind[i].Item2 - pt.avd);}pt.sigema=Math.Sqrt(sum/ pt.mind.Count);}
}//计算全局平均距离均值和标准差
public static void Allpoint(out double avds,out double sigemas)
{avds=Read.pts.Average(p=>p.avd);sigemas=Read.pts.Average(p=> p.sigema);
}

六、全局噪点判断

在这里插入图片描述

 //全局判断噪点public static void Alljudge(List<Point> pts){Allpoint(out double avds, out double sigemas);foreach (Point pt in pts){if(pt.avd > (avds + 2 * sigemas)){pt.number = 1;}else{zaopoint.Add(pt);pt.number = 0;}}}

窗体交互

public partial class Form1 : Form
{public Form1(){InitializeComponent();openFile.FileOk += openFile_FileOk;}public static List<Point> before=new List<Point>();public string report;private void toolStripLabel1_Click(object sender, EventArgs e){if (openFile.ShowDialog() == DialogResult.OK){string name=openFile.FileName; before=Read.Readfile(name);dataGridView1.RowCount= before.Count;for(int i = 0; i < before.Count; i++){dataGridView1[0, i].Value = before[i].x;dataGridView1[1,i].Value = before[i].y;dataGridView1[2,i].Value = before[i].z;}}}private void openFile_FileOk(object sender, CancelEventArgs e){}private void toolStripLabel2_Click(object sender, EventArgs e){report += "1\t点 P1 的 x 坐标 " + Read.pts[0].x.ToString("F3") + "\n";report += "2\t点 P6 的 y 坐标 " + Read.pts[5].y.ToString("F3") + "\n";report += "3\t点 P789 的 z 坐标 " + Read.pts[788].z.ToString("F3") + "\n";report += "4\t原始点云的总点数 " + Read.pts.Count + "\n";Alpoint.Jizhi(out double xmax,out double ymax,out double zmax,out double xmin,out double ymin,out double zmin);Alpoint.Gewang(out double xmax1, out double ymax1, out double zmax1);report += "5\t点云数据x最大值 " + xmax.ToString("F3") + "\n";report += "6\t点云数据y最大值 " + ymax.ToString("F3") + "\n";report += "7\t点云数据z最大值" + zmax.ToString("F3") + "\n";report += "8\t格网 xmin " + xmin.ToString("F3") + "\n";report += "9\t格网 xmax1 " + xmax1.ToString("F3") + "\n";report += "10\t格网 ymin " + ymin.ToString("F3") + "\n";report += "11\t格网 ymax1 " + ymax1.ToString("F3") + "\n";report += "12\t格网 zmin" + zmin.ToString("F3") + "\n";report += "13\t格网 zmax1 " + zmax1.ToString("F3") + "\n";Alpoint.Classify(Read.pts, out int sum);report += "14\t网格 (0,0,0) 内的点个数 " + sum + "\n";report += "15\t点 P1 的网格索引(i,j,k)中i分量 " + Read.pts[0].i + "\n";report += "16\t点 P6 的网格索引(i,j,k)中j分量" + Read.pts[5].j + "\n";Alpoint.Mind(Read.pts);report += "17\t点 P1 的候选点总数 " + (Read.pts[0].after.Count-1) + "\n";report += "18\t点 P6 的候选点总数 " + (Read.pts[5].after.Count-1) + "\n";int b = Read.pts[5].mind.Max(p => p.Item1);int a = Read.pts[0].mind.Max(p => p.Item1);report += "19\t点 P1 的 6 个邻近点序号中最大值" + a + "\n";report += "20\t点 P6 的 6 个邻近点序号中最大值 " + b+ "\n";Alpoint.Alhelp(Read.pts);Alpoint.Allpoint(out double avds, out double sigemas);Alpoint.Alljudge(Read.pts);report += "21\t点 P1 的邻域平均距离 u₁ " + Read.pts[0].avd.ToString("F3") + "\n";report += "22\t点 P1 的邻域距离标准差 σ₁ " + Read.pts[0].sigema.ToString("F3") + "\n";report += "23\t点 P6 的邻域平均距离 u₆" + Read.pts[5].avd.ToString("F3") + "\n";report += "24\t点 P6 的邻域距离标准差 σ₆ " + Read.pts[5].sigema.ToString("F3") + "\n";report += "25\t全局平均距离均值 μ " + avds.ToString("F3") + "\n";report += "26\t全局距离标准差 σ " + sigemas.ToString("F3") + "\n";report += "27\t点 P1 是否为噪声点(0、1分别表示否、是) " + Read.pts[0].number + "\n";report += "28\t点 P6 是否为噪声点(0、1分别表示否、是)" + Read.pts[5].number + "\n";report += "29\t去噪后保留的点云总数 " + Alpoint.zaopoint.Count + "\n";richTextBox1.Text = report;}private void toolStripLabel3_Click(object sender, EventArgs e){Read.Savefile(report);}
}

七,运行结果

1 点 P1 的 x 坐标 533599.690
2 点 P6 的 y 坐标 3377146.850
3 点 P789 的 z 坐标 28.890
4 原始点云的总点数 44518
5 点云数据x最大值 533774.000
6 点云数据y最大值 3377195.000
7 点云数据z最大值113.120
8 格网 xmin 533574.000
9 格网 xmax1 533775.000
10 格网 ymin 3377000.000
11 格网 ymax1 3377198.000
12 格网 zmin8.560
13 格网 zmax1 113.560
14 网格 (0,0,0) 内的点个数 0
15 点 P1 的网格索引(i,j,k)中i分量 8
16 点 P6 的网格索引(i,j,k)中j分量48
17 点 P1 的候选点总数 69
18 点 P6 的候选点总数 47
19 点 P1 的 6 个邻近点序号中最大值44391
20 点 P6 的 6 个邻近点序号中最大值 1508
21 点 P1 的邻域平均距离 u₁ 1.981
22 点 P1 的邻域距离标准差 σ₁ 0.329
23 点 P6 的邻域平均距离 u₆1.411
24 点 P6 的邻域距离标准差 σ₆ 0.186
25 全局平均距离均值 μ 1.668
26 全局距离标准差 σ 0.339
27 点 P1 是否为噪声点(0、1分别表示否、是) 0
28 点 P6 是否为噪声点(0、1分别表示否、是)0
29 去噪后保留的点云总数 42555

八、报告文档

第一页为封面
在这里插入图片描述
第二页为目录
在这里插入图片描述
后面为正常模板
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

总结

本次的比赛也是收获匪浅,总体来说,还是要多练,今年的题目明显带有一定的挑战性质,需要不断多练,不要抱有侥幸心理,认为考过相似的题,就不会再考了,这几年的竞争压力还是很大的,所以一定要抓住时间,勤奋多练,我和诸多大佬都会在群里为你们答疑解惑的,C#,python,C++都有的,欢迎大家进群讨论242845175

http://www.lryc.cn/news/609357.html

相关文章:

  • 【AI】文档理解
  • 旧笔记本电脑如何安装飞牛OS
  • 嵌入式学习日志——数据结构(一)
  • 渗透高级-----应急响应
  • LLM调研
  • nestjs @Param 从入门到精通
  • 大模型能力测评(提示词请帮我把这个项目改写成为python项目)
  • 数据结构基础 - 平衡二叉树
  • 关于 xrdp远程桌面报错“Error connecting to sesman on 127.0.0.1:3350“的解决方法
  • lua table常用函数汇总
  • 6. 平台总线
  • 模型学习系列之参数
  • 秋招笔记-8.3
  • 关于记录一下“bug”,在做图片上传的时候出现的小问题
  • 验房收房怎么避免被坑?
  • 我的世界进阶模组开发教程——伤害(2)
  • 自己实现一个freertos(2)任务调度 1——最基本的TCB
  • 深入解析HashMap:原理与性能优化
  • Redis实战(7)-- 高级特性 Redis Stream数据结构与基础命令
  • spring batch处理数据模板(Reader-Processor-Writer模式)
  • Timer实现定时调度的原理是什么?
  • PPT 转高精度 PDF API 接口
  • 使用DrissionPage实现xhs笔记自动翻页并爬取笔记视频、图片
  • Coin Combinations I(Dynamic Programming)
  • Docker环境离线安装指南
  • 解剖 .NET 经典:从 Component 到 BackgroundWorker
  • node.js常用函数
  • GaussDB case when的用法
  • SpringBoot AI自动化测试实战案例
  • GitCode疑难问题诊疗