基于.NET 6和WPF的OpenCVSharp与ReactiveUI学习实践:3D点云数据处...
这是一个使用.net 6 基于wpf 、OpencvSharp(opencv的.net wrapper)、ReactiveUI等开发的自用工具主要用来做ReactiveUI与OpencvSharp学习过程中的尝试以及opencv算子参数的调试等该程序还可以显示3D点云数据(目前程序中的点云数据是由格雷码条纹拍摄的照片反算生成了还可以导入标准的3d格式的文件stl、obj、objz、ply、3ds、lwo、off)还包含有opencv调用yolov4深度学习模型实现目标识别 本源码内包含部分解释最近在折腾一个自用工具把ReactiveUI、OpenCVSharp这些技术栈揉在一起玩。这玩意儿主要用来快速验证图像处理算法顺便当个3D点云查看器。界面虽然糙了点但胜在能实时调参——毕竟用滑块控制卷积核大小可比改代码重新编译舒坦多了。先看ReactiveUI和WPF的化学反应。ViewModel里定义个图像处理命令长这样public ReactiveCommandUnit, Mat ProcessImage { get; } // 构造函数里初始化 ProcessImage ReactiveCommand.CreateFromTask(async () { using var src new Mat(ImagePath); return await Task.Run(() _opencvService.CannyEdgeDetect(src)); });UI绑定直接用WhenAnyValue监听参数变化触发处理。这种响应式绑定比传统事件驱动清爽多了特别是处理多个参数联动时再也不用写那些if (e.PropertyName XXX)的样板代码。图像处理核心部分用OpenCVSharp封装了个服务类。比如Canny边缘检测的实现public Mat CannyEdgeDetect(Mat src, int threshold1 50, int threshold2 150) { var edges new Mat(); Cv2.Canny(src, edges, threshold1, threshold2); // 调试时打印矩阵前10x10区域 if (DebugMode) Console.WriteLine(edges[0..10, 0..10].Dump()); return edges; }有意思的是阈值参数通过WPF滑块双向绑定配合ReactiveUI的Throttle方法防止滑块拖动时高频触发计算。这种实时反馈对理解算法参数影响特别直观比如把高斯模糊的kernelSize从5调到15能肉眼看到图像从锐利到模糊的渐变过程。这是一个使用.net 6 基于wpf 、OpencvSharp(opencv的.net wrapper)、ReactiveUI等开发的自用工具主要用来做ReactiveUI与OpencvSharp学习过程中的尝试以及opencv算子参数的调试等该程序还可以显示3D点云数据(目前程序中的点云数据是由格雷码条纹拍摄的照片反算生成了还可以导入标准的3d格式的文件stl、obj、objz、ply、3ds、lwo、off)还包含有opencv调用yolov4深度学习模型实现目标识别 本源码内包含部分解释3D点云模块支持多种格式导入其中格雷码解码生成点云的算法最有意思。核心是利用相位偏移公式计算深度var phaseMap new Mat(); Cv2.PhaseShift(images, phaseMap, projectorResolution); // 三角法计算三维坐标 for (int y 0; y phaseMap.Rows; y) { for (int x 0; x phaseMap.Cols; x) { var phase phaseMap.Atdouble(y, x); var depth baseline * focalLength / (phase disparity); points.Add(new Point3D(x, y, depth)); } }这里有个坑是相位展开算法容易受环境光干扰后来加了归一化处理才稳定。点云渲染用HelixToolkit实现支持鼠标拖拽查看不同视角——虽然性能比不上专业软件但用来验证算法足够了。最后是YOLOv4集成部分。加载ONNX模型进行目标检测的代码比想象中简单using var net CvDnn.ReadNetFromONNX(yolov4.onnx); var blob CvDnn.BlobFromImage(image, 1/255f, new Size(416, 416)); net.SetInput(blob); var output net.Forward(); ParseYoloOutput(output, image.Width, image.Height);但预处理和后处理才是重点。比如输入图像要归一化到0-1范围输出层需要做非极大值抑制。这部分代码写了三个版本同步阻塞版、Task.Run后台版、GPU加速版。实测发现对于640x480的图片CPU版本处理需要200ms而用CUDA加速后直接飙到30ms——果然该让显卡干的活就别为难CPU。源码里到处散落着//TODO: 这里需要重构的注释充分暴露了边学边写的开发过程。比如最开始用事件总线传图像数据后来全改成ReactiveUI的MessageBus消息处理流畅度直接提升一个level。这种渐进式优化的体验比一开始就设计完美架构要有趣得多。项目还在持续魔改中下一步打算把点云配准算法整合进来。毕竟能把自己写的算法变成可视化工具调试的时候连摸鱼都变得理直气壮了呢笑。
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2432589.html
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!