使用OpenTK展示3D点云图像(C#)

最近在研究3D显示,找到一款在winform上展示3D点云的控件,并且实现了点线面的展示,及光照渲染纹理贴图等功能,如下面几张图所展示。

一些基础知识可以在LearnOpenTK - OpenTK 这个网站上学习到。

我这边使用的是openTK3.3.3版本,展示点云很好实现,把读到的点云数据放进去即可展示。如下图展示点云。

我们需要把点连成面,有很多算法可以实现,但我拿到的图为一张tif格式16位的深度图,如下图

快速获取此图的深度信息

IntPtr pointer = model.ImgDepth.GetImagePointer1(out string type, out width, out height);
length = width * height;
short[] pointZCloud = new short[length];
Marshal.Copy(pointer, pointZCloud, 0, length);
point3Ds = new Vector3[length];
normals = new Vector3[length];
zGoodList = new List<float>();
for (int i = 0; i < length; i++)
{int row = i / width;int col = i % width;byte[] bytes = BitConverter.GetBytes(pointZCloud[i]);ushort z = BitConverter.ToUInt16(bytes, 0);float tempZ = z * model.ScaleZ +model.OffsetZ;point3Ds[i] = new Vector3(row * model.ScaleY, col * model.ScaleX, tempZ);if (z > 0){zGoodList.Add(tempZ);}
}

我们很容易知道哪三个点可以连成一个面,如某个点为(row,col),和它组成三角形的另外两个点为(row+1,col),(row,col+1),如下图组成一个个三角形,即可形成面

图中存在一个空的点,可通过阈值分割过滤掉,然后如何保证某个点必然存在后面两个和它构成三角形的点,用一个2x2的结构元腐蚀阈值分割出的区域,得到剩下所有的点必然每个点可以构成三角形,这种得到三角形的算法效率会非常高。

model.ImgDepth.Threshold((double)1, 65535).ErosionRectangle1(2, 2).GetRegionPoints(out HTuple rows1, out HTuple columns1);long[] rows1Int = rows1.LArr;
long[] columns1Int = columns1.LArr;
int triLength = rows1Int.Length;indices_Triangle = new uint[triLength * 6];
for (int i = 0; i < triLength; i++)
{uint a1 = (uint)(rows1Int[i] * width + columns1Int[i]);uint a2 = a1 + 1;uint a3 = a1 + (uint)width;uint a4 = a3 + 1;indices_Triangle[i * 6] = a1;indices_Triangle[i * 6 + 1] = a2;indices_Triangle[i * 6 + 2] = a3;indices_Triangle[i * 6 + 3] = a2;indices_Triangle[i * 6 + 4] = a3;indices_Triangle[i * 6 + 5] = a4;
}

不同高度渲染颜色从红色到蓝色

 objColors = new float[length * 3];for (int i = 0; i < length; i++){if (point3Ds[i].Z > zMid){objColors[i * 3] = (point3Ds[i].Z - zMid) / zHalfHigh;objColors[i * 3 + 1] = 1.0f - objColors[i * 3];objColors[i * 3 + 2] = 0;}else{objColors[i * 3] = 0;objColors[i * 3 + 1] = 1.0f - (zMid - point3Ds[i].Z) / zHalfHigh;objColors[i * 3 + 2] = (zMid - point3Ds[i].Z) / zHalfHigh;}}

然后还有光照,无光照和有光照效果差异很大,处理光照核心在于得到每个点的法向量,用上面的三角形的两条边构成的向量叉乘,及得到这个点的法向量,输入给着色器处理得到光照的渲染效果,如下面两张图对比

叉乘如下代码

Vector3 a1 = new Vector3(point3Ds[i].X, point3Ds[i].Y, point3Ds[i].Z);
Vector3 a2 = new Vector3(point3Ds[i + 1].X, point3Ds[i + 1].Y, point3Ds[i + 1].Z);
Vector3 a3 = new Vector3(point3Ds[i + width].X, point3Ds[i + width].Y, point3Ds[i + width].Z);
Vector3 b1 = a3 - a1;
Vector3 b2 = a2 - a1;
normals[i] = new Vector3(b1.Y * b2.Z - b2.Y * b1.Z, b1.Z * b2.X - b1.X * b2.Z, b1.X * b2.Y - b1.Y * b2.X);

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/63702.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【笔记】架构上篇Day6 法则四:为什么要顺应技术的生命周期?

法则四&#xff1a;为什么要顺应技术的生命周期&#xff1f; 简介&#xff1a;包含模块一 架构师的六大生存法则-法则四&#xff1a;为什么要顺应技术的生命周期&#xff1f;&法则四&#xff1a;架构设计中怎么判断和利用技术趋势&#xff1f; 2024-08-29 17:30:07 你好&am…

【Sentinel Go】新手指南、流量控制、熔断降级和并发隔离控制

随着微服务的流行&#xff0c;服务和服务之间的稳定性变得越来越重要。Sentinel 是面向分布式、多语言异构化服务架构的流量治理组件&#xff0c;主要以流量为切入点&#xff0c;从流量路由、流量控制、流量整形、熔断降级、系统自适应过载保护、热点流量防护等多个维度来帮助开…

Y3编辑器官方文档1:编辑器简介及菜单栏详解(文件、编辑、窗口、细节、调试)

文章目录 一、新建项目二、 编辑器主界面2.1 游戏场景2.2 导航栏/菜单栏2.3 功能栏三、菜单栏详细介绍3.1 文件3.1.1 版本管理3.1.2 项目管理(多关卡)3.1.2.1 多关卡功能说明3.1.2.2 关卡切换与关卡存档3.2 编辑3.2.1 通用设置3.2.2 键位设置3.3 窗口(日志)3.4 细节3.4.1 语言…

前端视角下的Go语法学习:创建 Go 项目

今日话题 使用 GoLand 创建 Go 项目 作者&#xff1a; 时间&#xff1a;2024年6月20日 17时16分14秒 主线任务 一、GoLand 创建项目 1、点击 “new Project” 按钮 2、已经有下载过两个 Golang SDK 版本&#xff0c;选择版本创建即可~ 3、如果没有下载过Golang SDK&#…

数据结构6.3--交换排序

目录 交换排序基本思想 1.冒泡排序 2.快速排序 2.1hoare版本 2.2挖坑法 2.3前后指针版本 交换排序基本思想 所谓交换&#xff0c;就是根据序列中两个记录键值的比较结果来对换这两个记录在序列中的位置&#xff0c;交换排序的特点是&#xff1a;将键值较大的记录向序列的尾…

Unity 制作一个视频播放器(打包后,可在外部编辑并放置新的视频)

效果展示&#xff1a; 在这里&#xff0c;我把视频名称&#xff08;Json&#xff09;和对应的视频资源都放在了StreamingAssets文件夹下&#xff0c;以便于打包后&#xff0c;客户还可以自己在外部增加、删除、修改对应的视频资料。 如有需要&#xff0c;请联细抠抠。

软件工程知识点

软件开发模型1 软件开发模型2 软件过程模型习惯上也称为软件开发模型&#xff0c;它是软件开发全部过程、活动和任务的结构框典型的软件过程模型有瀑布模型、增量模型、演化模型(原型模型、螺旋模型)、喷泉模型基于构件的开发模型和形式化方法模型等。 极限编程 开发方法 RUP…

Apache Echarts和POI

目录 Apache ECharts 介绍 入门 绘制一个简单的图表 Apache POI 介绍 通过POI创建Excel文件并且写入文件内容 通过POI读取Excel文件中的内容 导出Excel表格 Apache ECharts 介绍 Apache ECharts 是一款基于 Javascript 的数据可视化图表库&#xff0c;提供直观&#xf…

COLA学习之环境搭建(三)

小伙伴们&#xff0c;你们好&#xff0c;我是老寇&#xff0c;上一节&#xff0c;我们学习了COLA代码规范&#xff0c;继续跟老寇学习COLA环境搭建 首先&#xff0c;打开GitHub&#xff0c;搜索 COLA 请给这个COLA项目点个Star&#xff0c;养成好习惯&#xff0c;然后Fork到自…

【友加畅捷】软件保存/激活云加密/授权码的时候失败。

【问题现象】 畅捷通T1飞跃专业版&#xff0c;在保存云加密的时候提示&#xff1a; 获取加密失败&#xff0c;请检查数据库是否正确连接。 【解决方法】 服务器目录FYDogServer.ini文件&#xff0c;将DogCloud0改成DogCloud1&#xff0c; 然后重新保存。 【问题现象】 U通用…

单链表(数组模拟)

单链表的结构 用数组来模拟的话&#xff0c;需要两个数组&#xff0c;通过下标关联起来 例如&#xff1a; #include <bits/stdc.h>using namespace std;const int N 100010;int e[N]; //储存第i个插入的数的值 int ne[N]; //储存下标为i的next指针 int n; int idx1; int…

docker compose容器编排工具

华子目录 docker compose概述主要功能工作原理docker compose中的管理层docker compose的常用命令参数构建和重新构建服务docker compose的yaml文件一、服务&#xff08;services&#xff09;二、数据卷&#xff08;volumes&#xff09;三、网络&#xff08;networks&#xff0…

科普时刻 | 无线充电热管理:挑战与解决方案

无线充电器可通过电磁感应&#xff0c;在不直接进行电接触的情况下执行电能传输&#xff0c;因此无需繁杂的电缆电线连接&#xff0c;便可为我们的手机、手表、平板电脑以及耳机等设备供电。然而&#xff0c;随着对电子设备更快充电的需求不断增加&#xff0c;热管理对于防止过…

用ChatGPT-o1进行论文内容润色效果怎么样?

目录 1.引导问题发现 2.角色设定 3.整理常问修改 4.提供样例 5.小细节 小编在这篇文章中分享如何充分利用ChatGPT-o1-preview来提升论文润色的技巧。小编将持续跟进最新资源和最新的调研尝试结果&#xff0c;为宝子们补充更多实用的写作技巧。这些技巧将有助于您更有效地利…

数据可视化大屏UI组件库:B端科技感素材PSD

在数据可视化领域&#xff0c;一个出色的大屏UI设计不仅能够准确传达数据背后的信息&#xff0c;更能提升用户的视觉体验。然而&#xff0c;对于UI设计师而言&#xff0c;设计这样一款界面往往面临着寻找合适设计素材的挑战。为了应对这一难题&#xff0c;我们推出了这款数据可…

深度学习中的损失函数

损失函数是深度学习模型训练过程中不可或缺的一部分&#xff0c;是模型预测值与真实值之间差异的客观衡量标准。它们是模型训练的基础&#xff0c;指导算法调整模型参数&#xff0c;以最小化损失并提高预测准确性。它们衡量了模型预测值与真实值的吻合程度。通过最小化这种损失…

#自定义数据类型-简单模拟进程执行

#include <iostream> #include <string> #include <iomanip> using namespace std;//定义一个名为process的结构体&#xff0c;用于表示进程相关信息 //包含进程名、进程ID、进程优先级、进程状态、进程所需CPU时间、进程描述等成员 struct process {string …

【论文阅读】处理器芯片敏捷设计方法:问题与挑战

作者&#xff1a;包云岗老师 包云岗老师是计算机体系结构方向的大牛&#xff0c;推动了体系结构方面的开源事业! 欢迎对本栏目感兴趣的人学习"一生一芯"~ 学习体会&#xff1a; 已有的软硬件生态系统和开发成本制约了对新结构的探索。但目前仍在几种路线上做尝试~ 1…

Redis原理—4.核心原理摘要

大纲(9870字) 1.Redis服务器的Socket网络连接建立 2.Redis多路复用监听与文件事件模型 3.基于队列串行化的文件事件处理机制 4.完整的Redis Server网络通信流程 5.Redis串行化单线程模型为什么能高并发 6.Redis内核级请求处理流程与原理 7.Redis通信协议与内核级请求数据…

十五、K8s计划任务JobCronJob

K8s计划任务CronJob&Job 一、Job可以干什么 Job 控制器用于管理 Pod 对象运行一次性任务,比方说我们对数据库备份,可以直接在 k8s 上启动一个 mysqldump 备份程序,也可以启动一个 pod,这个 pod 专门用来备份用的,备份结束 pod 就可以终止了,不需要重启,而是将 Pod…