C# Winform+Halcon结合标准视觉工具
介绍+
winform与halcon结合标准化工具实例
软件架构
软件架构说明 基于NET6 WINFORM+HALCON
实现标准化视觉检测工具
集成相机通讯
集成PLC通讯
TCP等常见通讯
支持常见halcon算子
- 图形采集
- blob分析
- 高精度匹配
- 颜色提取
- 找几何体
- 二维码提取
- OCR识别
- 等等

。。。

安装教程
https://dotnet.microsoft.com/zh-cn/download/dotnet/6.0
使用说明
安装 NET6 SDK,编译即可运行
对入门的同学应该有较好的学习意义
本项目涵盖了标准化视觉检测工具的大部分功能,有兴趣的小伙伴可以请我吃一顿肯德基,获取源码进行学习。
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Imaging;
using System.Linq;
using System.Reflection.Emit;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using HalconDotNet;
using MT_OCR5._0;
using PaddleOCRSharp;
namespace Vision.Winform.Algorithm
{ //识别各种二维码,一维码, 字符识别
namespace MT_code
{
public class QR
{
public ToolPar toolPar = new ToolPar();
public bool status = true;
internal HObject image = null;
//二维码识别句柄
internal HTuple modelID = null;
public string CodeType = "QR Code";
public string ParamName = "default_parameters";
public string ParamValue = "standard_recognition";
private void creathandle()
{
try
{
switch (toolPar.RunPar.QrMode)
{
case QrMode.QR:
CodeType = "QR Code";
break;
case QrMode.DM:
CodeType = "Data Matrix ECC 200";
break;
}
switch (toolPar.RunPar.QrRecognition)
{
case QRRecognition.standard_recognition:
ParamValue = "standard_recognition";
break;
case QRRecognition.enhanced_recognition:
ParamValue = "enhanced_recognition";
break;
case QRRecognition.maximum_recognition:
ParamValue = "maximum_recognition";
break;
}
if(modelID == null)
{
HOperatorSet.CreateDataCode2dModel((HTuple)CodeType, (HTuple)ParamName, (HTuple)ParamValue, out modelID);
}
}
catch (Exception)
{
status = false;
}
//return 0;
}
private void clearhandle()
{
HOperatorSet.ClearDataCode2dModel(modelID);
}
public void run()
{
creathandle();
try
{
toolPar.ResultPar.CodeResult = new List<BarcodeResult>();
if (modelID == null)
{
status = false;
return;
}
if (toolPar.InputPar.图像 != null)
{
if (toolPar.InputPar.ROI != null)
{
HOperatorSet.ReduceDomain(toolPar.InputPar.图像, toolPar.InputPar.ROI, out image);
}
else
{
image = toolPar.InputPar.图像;
}
//设置极性
string codePolarity= "dark_on_light";
switch (toolPar.RunPar.CodePolarity)
{
case CodePolarity.any: codePolarity = "any"; break;
case CodePolarity.positive: codePolarity = "dark_on_light"; break;
case CodePolarity.negative: codePolarity = "light_on_dark"; break;
}
HOperatorSet.SetDataCode2dParam(modelID, "polarity", codePolarity);
HOperatorSet.SetDataCode2dParam(modelID, "timeout", toolPar.RunPar.TimeOut);
HObject xlds;
HTuple strtmp, resultHandles;
HOperatorSet.FindDataCode2d(image,
out xlds,
modelID,
"stop_after_result_num", toolPar.RunPar.CodeNum,
out resultHandles,
out strtmp);
//把结果塞进去
for (int i = 0; i < strtmp.Length; i++)
{
BarcodeResult tmp;
HObject region;
HOperatorSet.GenRegionContourXld(xlds, out region, "filled");
tmp.region = region;
tmp.code = strtmp[i].S;
toolPar.ResultPar.CodeResult.Add(tmp);
}
toolPar.ResultPar.CodeNum = strtmp.Length;
//HOperatorSet.clear
}
else
{
status = false;
return;
}
}
catch (Exception)
{
clearhandle();
status = false;
}
clearhandle();
}
[Serializable]
public class ToolPar : ToolParBase
{
private InputPar _inputPar = new InputPar();
public InputPar InputPar
{
get { return _inputPar; }
set { _inputPar = value; }
}
private RunPar _runPar = new RunPar();
public RunPar RunPar
{
get { return _runPar; }
set { _runPar = value; }
}
private ResultPar _resultPar = new ResultPar();
public ResultPar ResultPar
{
get { return _resultPar; }
set { _resultPar = value; }
}
}
[Serializable]
public class InputPar
{
private HObject _图像;
public HObject 图像
{
get { return _图像; }
set { _图像 = value; }
}
private HObject _ROI;
public HObject ROI
{
get { return _ROI; }
set { _ROI = value; }
}
private HObject _屏蔽区域;
public HObject 屏蔽区域
{
get { return _屏蔽区域; }
set { _屏蔽区域 = value; }
}
public int FindCodeNum { set; get; } = 1;
}
[Serializable]
public class RunPar
{
public QRRecognition QrRecognition { get; set; }
public QrMode QrMode { get; set; }
public CodePolarity CodePolarity { get; set; }
public int TimeOut { get; set; }
public int CodeNum { get; set; }
}
[Serializable]
public class ResultPar
{
private List<BarcodeResult> _CodeResult;
public List<BarcodeResult> CodeResult
{
get { return _CodeResult; }
set { _CodeResult = value; }
}
private int _CodeNum;
public int CodeNum
{
get { return _CodeNum; }
set { _CodeNum = value; }
}
}
}
public class One_dimension
{
public ToolPar toolPar = new ToolPar();
public bool status = true;
internal HObject image = null;
//条形码识别句柄
internal HTuple modelID = null;
internal HTuple codetype = "auto";
private void creathandle()
{
try
{
HOperatorSet.CreateBarCodeModel(new HTuple(), new HTuple(), out modelID);
}
catch (Exception)
{
status = false;
}
//return 0;
}
private void clearhandle()
{
HOperatorSet.ClearBarCodeModel(modelID);
}
public void run()
{
creathandle();
toolPar.ResultPar.CodeResult = new List<BarcodeResult>();
try
{
if (modelID == null)
{
status = false;
return;
}
if (toolPar.InputPar.图像 != null)
{
if (toolPar.InputPar.ROI != null)
{
HOperatorSet.ReduceDomain(toolPar.InputPar.图像, toolPar.InputPar.ROI, out image);
}
else
{
image = toolPar.InputPar.图像;
}
HObject region;
HTuple strtmp;
HOperatorSet.SetBarCodeParam(modelID, "timeout", toolPar.RunPar.TimeOut);
HOperatorSet.SetBarCodeParam(modelID, "stop_after_result_num", toolPar.RunPar.CodeNum);
设置极性
//string codePolarity = "dark_on_light";
//switch (toolPar.RunPar.CodePolarity)
//{
// case CodePolarity.any: codePolarity = "any"; break;
// case CodePolarity.positive: codePolarity = "dark_on_light"; break;
// case CodePolarity.negative: codePolarity = "light_on_dark"; break;
//}
//HOperatorSet.SetBarCodeParam(modelID, "polarity", codePolarity);
HOperatorSet.FindBarCode(image, out region, modelID, codetype, out strtmp);
//把结果塞进去
for (int i = 0; i < strtmp.Length; i++)
{
BarcodeResult tmp;
tmp.region = region;
tmp.code = strtmp[i].S;
toolPar.ResultPar.CodeResult.Add(tmp);
}
toolPar.ResultPar.CodeNum = strtmp.Length;
//HOperatorSet.clear
}
else
{
status = false;
return;
}
}
catch (Exception)
{
clearhandle();
status = false;
}
clearhandle();
}
[Serializable]
public class ToolPar : ToolParBase
{
private InputPar _inputPar = new InputPar();
public InputPar InputPar
{
get { return _inputPar; }
set { _inputPar = value; }
}
private RunPar _runPar = new RunPar();
public RunPar RunPar
{
get { return _runPar; }
set { _runPar = value; }
}
private ResultPar _resultPar = new ResultPar();
public ResultPar ResultPar
{
get { return _resultPar; }
set { _resultPar = value; }
}
}
[Serializable]
public class InputPar
{
private HObject _图像;
public HObject 图像
{
get { return _图像; }
set { _图像 = value; }
}
private HObject _ROI;
public HObject ROI
{
get { return _ROI; }
set { _ROI = value; }
}
private HObject _屏蔽区域;
public HObject 屏蔽区域
{
get { return _屏蔽区域; }
set { _屏蔽区域 = value; }
}
}
[Serializable]
public class RunPar
{
//public BarRecognition BarRecognition { get; set; }
public BarMode BarMode { get; set; }
public CodePolarity CodePolarity { get; set; }
public int TimeOut { get; set; }
public int CodeNum { get; set; }
}
[Serializable]
public class ResultPar
{
private List<BarcodeResult> _CodeResult;
public List<BarcodeResult> CodeResult
{
get { return _CodeResult; }
set { _CodeResult = value; }
}
private int _CodeNum;
public int CodeNum
{
get { return _CodeNum; }
set { _CodeNum = value; }
}
}
}
public class OCR
{
public ToolPar toolPar = new ToolPar();
public bool status = true;
internal HObject image = null;
RunPar runPar=new RunPar ();
public void run()
{
try
{
if (toolPar.InputPar.图像 != null)
{
if (toolPar.InputPar.ROI != null && toolPar.InputPar.屏蔽区域 != null)
{
HObject reduce_region = new HObject();
reduce_region.Dispose();
HOperatorSet.Difference(toolPar.InputPar.ROI, toolPar.InputPar.屏蔽区域, out reduce_region);
//image.Dispose();
HOperatorSet.ReduceDomain(toolPar.InputPar.图像, reduce_region, out image);
HOperatorSet.CropDomain(image, out image);
reduce_region.Dispose();
}
else if (toolPar.InputPar.ROI != null && toolPar.InputPar.屏蔽区域 == null)
{
HOperatorSet.GenEmptyObj(out image);
HOperatorSet.ReduceDomain(toolPar.InputPar.图像, toolPar.InputPar.ROI, out image);
HOperatorSet.CropDomain(image, out image);
}
else if (toolPar.InputPar.ROI == null && toolPar.InputPar.屏蔽区域 != null)
{
HObject reduce_region = new HObject();
reduce_region.Dispose();
HOperatorSet.Difference(toolPar.InputPar.图像, toolPar.InputPar.屏蔽区域, out reduce_region);
//image.Dispose();
HOperatorSet.ReduceDomain(toolPar.InputPar.图像, reduce_region, out image);
HOperatorSet.CropDomain(image, out image);
reduce_region.Dispose();
}
else
{
if (image != null)
image.Dispose();
image = toolPar.InputPar.图像;
}
}
else
{
status = false;
return;
}
//初始化
//ocr_engine.OCR_INIT();
//HObject img;
//HOperatorSet.GenEmptyObj(out img);
//img = image;
检测
//string ocr_result = ocr_engine.OCR_Dect(img);
//ocr_engine.engine.Dispose();
//toolPar.ResultPar.OCRResult = ocr_result;
//ocr_result = String.Empty;
HOperatorSet.CountChannels(image, out var channels);
Bitmap img;
HObject multiChannelImage;
HOperatorSet.GenEmptyObj(out multiChannelImage);
if (channels == 3)
{
img=runPar.Honject2Bitmap24(image);
}
else
{
HOperatorSet.Compose3(image, image, image, out multiChannelImage);
img = runPar.Honject2Bitmap24(multiChannelImage);
}
runPar.ocrResult= runPar.engine.DetectText(img);
toolPar.ResultPar.OCRResult = runPar.ocrResult.Text;
}
catch (Exception)
{
status = false;
}
}
[Serializable]
public class ToolPar : ToolParBase
{
private InputPar _inputPar = new InputPar();
public InputPar InputPar
{
get { return _inputPar; }
set { _inputPar = value; }
}
private RunPar _runPar = new RunPar();
public RunPar RunPar
{
get { return _runPar; }
set { _runPar = value; }
}
private ResultPar _resultPar = new ResultPar();
public ResultPar ResultPar
{
get { return _resultPar; }
set { _resultPar = value; }
}
}
[Serializable]
public class InputPar
{
private HObject _图像;
public HObject 图像
{
get { return _图像; }
set { _图像 = value; }
}
private HObject _ROI;
public HObject ROI
{
get { return _ROI; }
set { _ROI = value; }
}
private HObject _屏蔽区域;
public HObject 屏蔽区域
{
get { return _屏蔽区域; }
set { _屏蔽区域 = value; }
}
}
[Serializable]
public class RunPar
{
public OCRModelConfig config = null;
public OCRParameter oCRParameter = new OCRParameter();
public OCRResult ocrResult = new OCRResult();
public PaddleOCREngine engine;
public RunPar()
{
engine = new PaddleOCREngine(config, oCRParameter);
}
[DllImport("kernel32.dll")]
public static extern void CopyMemory(int Destination, int add, int Length);
public Bitmap Honject2Bitmap24(HObject hObject)
{
HTuple width = new HTuple();
HTuple height = new HTuple();
HTuple pointer = new HTuple();
HTuple type = new HTuple();
HTuple width2 = new HTuple();
HTuple height2 = new HTuple();
HObject interleavedImage = new HObject();
HOperatorSet.GetImageSize(hObject, out width, out height);
HOperatorSet.InterleaveChannels(hObject, out interleavedImage, "rgb", 4 * width, 0);
HOperatorSet.GetImagePointer1(interleavedImage, out pointer, out type, out width2, out height2);
IntPtr scan = pointer;
return new Bitmap(width2 / 4, height2, width2, PixelFormat.Format24bppRgb, scan);
}
public void HObject2Bitmap8(HObject image, out Bitmap res)
{
HOperatorSet.GetImagePointer1(image, out var pointer, out var _, out var width, out var height);
res = new Bitmap(width, height, PixelFormat.Format8bppIndexed);
ColorPalette palette = res.Palette;
for (int i = 0; i <= 255; i++)
{
palette.Entries[i] = Color.FromArgb(255, i, i, i);
}
res.Palette = palette;
System.Drawing.Rectangle rect = new System.Drawing.Rectangle(0, 0, width, height);
BitmapData bitmapData = res.LockBits(rect, ImageLockMode.WriteOnly, PixelFormat.Format8bppIndexed);
int num = Image.GetPixelFormatSize(bitmapData.PixelFormat) / 8;
IntPtr scan = bitmapData.Scan0;
IntPtr source = pointer;
int num2 = width * height;
byte[] array = new byte[num2];
Marshal.Copy(source, array, 0, num2);
Marshal.Copy(array, 0, scan, num2);
res.UnlockBits(bitmapData);
}
}
[Serializable]
public class ResultPar
{
private string _OCRResult { get; set; }
public string OCRResult { get { return _OCRResult; } set { _OCRResult = value; } }
}
}
}
}
相关文章:
C# Winform+Halcon结合标准视觉工具
介绍 winform与halcon结合标准化工具实例 软件架构 软件架构说明 基于NET6 WINFORMHALCON 实现标准化视觉检测工具 集成相机通讯 集成PLC通讯 TCP等常见通讯 支持常见halcon算子 图形采集blob分析高精度匹配颜色提取找几何体二维码提取OCR识别等等 。。。 安装教程 …...
英语单词量测试
网址:https://preply.com/en/learn/english/test-your-vocab 测试结果: 细节:英语母语者有20000-35000个单词的词汇量,8岁孩子的词汇量在8000个左右。而不是我们教育系统里说的,6000个单词足够用了。足够用࿰…...
三、安装node_exporter
目录 一、简介 二、下载安装 一、简介 Exporter是Prometheus的指标数据收集组件。它负责从目标Jobs收集数据,并把收集到的数据转换为Prometheus支持的时序数据格式。 和传统的指标数据收集组件不同的是,他只负责收集,并不向Server端发送数据…...
kafka基础知识
kafka架构 producer -> kafka cluster(broker>topic>partition) -> consumer -> zookeeper kafka压测 kafka-producer-perf-test.sh kafka-consumer-perf-test.sh kafka日志保存位置及消息保存时间 /tpdata/client/Kafka/kafka/config/server.properties log.…...
华为昇腾310B1平台视频解码失败[ERROR] Send frame to vdec failed, errorno:507018
目录 1 [ERROR] Send frame to vdec failed, errorno:507018 2 bug解决尝试1 3 bug解决尝试2 4 最终解决方法 参考文献: 1 [ERROR] Send frame to vdec failed, errorno:507018 某项目中的代码运行报错 [ERROR] Send frame to vdec failed, errorno:507018 Ac…...
Flutter 中的 SwitchListTile 小部件:全面指南
Flutter 中的 SwitchListTile 小部件:全面指南 在Flutter的Material组件库中,SwitchListTile是一个包含开关(Switch)的列表项,非常适合用来创建带有标题、副标题以及开关的列表项,常用于设置界面ÿ…...
详细分析Vue3中的defineExpose(附Demo)
目录 前言1. 基本知识2. Demo3. 实战 前言 其基本知识可参考官网:Vue3中的defineExpose 1. 基本知识 defineExpose 是 Vue 3 的 Composition API 中一个新的实用函数,用于在 <script setup> 语法下显式暴露组件的公共属性和方法 这在处理子组件…...
合合信息:TextIn文档解析技术与高精度文本向量化模型再加速
文章目录 前言现有大模型文档解析问题表格无法解析无法按照阅读顺序解析文档编码错误 诉求文档解析技术技术难点技术架构关键技术回根溯源 文本向量化模型结语 前言 随着人工智能技术的持续演进,大语言模型在我们日常生活中正逐渐占据举足轻重的地位。大模型语言通…...
Git与Gitlab
第1章Git概述 Git是一个免费的、开源的分布式版本控制系统,可以快速高效地处理从小型到大型的各种项目。 代码托管中心,记录每个版本的代码,从项目创建到现在使用的代码,中间所有的修改都有记录。 1. 何为版本控制 版本控制是…...
MySQL数据库从入门到精通(下)
对表做了修改之后,记得点击对应图标按钮重新执行一下。 1.创建角色表 数据库一开始就要设计好,轻易不要改动。一个账号下可能有多个角色,所以我们单独再创建另一个表role用来存储所有的角色信息。其中idrole表示角色id,name表示名…...
从融媒到智媒,小程序框架可助力传媒企业在AI实践下的服务变现
过去5年,媒体行业一直都在进行着信息化建设向融媒体平台建设的转变。一些融媒体的建设演变总结如下: 新闻终端的端侧内容矩阵建设,如App新闻端,社交平台上的官方媒体等 新闻本地生活双旗舰客户端,兼顾主流媒体核心宣传…...
MES系统在电线电缆行业生产上的应用
MES系统在线缆行业的应用可以带来多重价值,包括提高生产效率、降低生产成本、提高产品质量、优化库存管理、改善生产环境和提高企业竞争力等方面。因此,在电线电缆行业中广泛应用MES系统可以提高企业的经济效益和社会效益,推动企业发展和行业…...
怎么把图片上的字去掉
将图片上的字去掉通常需要使用图像编辑软件或在线工具。以下是一些常用的方法和步骤: 使用Adobe Photoshop: 打开Photoshop,导入需要编辑的图片。 选择“橡皮擦工具”或“克隆图章工具”。 如果使用“橡皮擦工具”,调整橡皮擦的…...
BFS和DFS优先搜索算法
1. BFS与DFS 1.1 BFS DFS即Depth First Search,深度优先搜索。它是一种图遍历算法,它从一个起始点开始,逐层扩展搜索范围,直到找到目标节点为止。 这种算法通常用于解决“最短路径”问题,比如在迷宫中找到从起点到终…...
python将两张图片对齐
目录 需要对齐的照片如下: 源码: 结果: 需要对齐的照片如下: 源码: import cv2 import numpy as np from matplotlib import pyplot as plt# 读取两张图片 imgA cv2.imread(./out/out/3.png) imgB cv2.imread(./…...
Linux修炼之路之初识操作系统+基础指令(1)
目录 引言 一:对操作系统(OS)的简单了解 1.操作系统(OS) 是什么 2.操作系统好坏的衡量标准 3.操作系统存在的重要性 4.理解所有在计算机上的操作 二:Linux与windows操作的特点区别 三:基础指令 1.ls 指令 1.使用 2.常用选项 2.…...
Flink中基于Chandy-Lamport算法的分布式快照实现详解
Apache Flink利用了一种基于Chandy-Lamport分布式快照算法的变体——异步屏障快照(Asynchronous Barrier Snapshotting, ABS)来实现其强大的容错机制。Chandy-Lamport算法最初由K.M. Chandy和Leslie Lamport于1985年提出,是一种用于分布式系统…...
软件3班20240513
java.util.PropertyResourceBundle4554617c package com.yanyu;import java.sql.*; import java.util.ResourceBundle;public class JDBCTest01 {public static void main(String[] args) throws SQLException { // 获取属性配置文件ResourceBundle bundle Res…...
【小程序】怎么优化小程序的性能
优化小程序的性能是提高用户体验和确保应用顺畅运行的关键。以下是一些优化小程序性能的方法: 1. 代码优化2. 图片优化3. 网络请求优化4. 页面渲染优化5. 分包加载6. 使用性能分析工具7. 后端优化8. 用户体验优化 1. 代码优化 精简代码:删除不必要的代码…...
告别信用卡绑定烦恼:探索这个全功能的Azure语音替代品,包含AI视频制作!(微软Azure语音替代方案)
文章目录 📖 介绍 📖🏡 演示环境 🏡📒 文章内容 📒📝 语音合成的替代方案📝 功能特色📝 使用步骤示例⚓️ 相关链接 ⚓️📖 介绍 📖 虽然微软Azure语音服务为个人用户提供了充足的免费语音合成额度,但其注册过程中的信用卡绑定要求、繁琐的API配置步骤却…...
rknn优化教程(二)
文章目录 1. 前述2. 三方库的封装2.1 xrepo中的库2.2 xrepo之外的库2.2.1 opencv2.2.2 rknnrt2.2.3 spdlog 3. rknn_engine库 1. 前述 OK,开始写第二篇的内容了。这篇博客主要能写一下: 如何给一些三方库按照xmake方式进行封装,供调用如何按…...
在rocky linux 9.5上在线安装 docker
前面是指南,后面是日志 sudo dnf config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo sudo dnf install docker-ce docker-ce-cli containerd.io -y docker version sudo systemctl start docker sudo systemctl status docker …...
《从零掌握MIPI CSI-2: 协议精解与FPGA摄像头开发实战》-- CSI-2 协议详细解析 (一)
CSI-2 协议详细解析 (一) 1. CSI-2层定义(CSI-2 Layer Definitions) 分层结构 :CSI-2协议分为6层: 物理层(PHY Layer) : 定义电气特性、时钟机制和传输介质(导线&#…...
1688商品列表API与其他数据源的对接思路
将1688商品列表API与其他数据源对接时,需结合业务场景设计数据流转链路,重点关注数据格式兼容性、接口调用频率控制及数据一致性维护。以下是具体对接思路及关键技术点: 一、核心对接场景与目标 商品数据同步 场景:将1688商品信息…...
2025盘古石杯决赛【手机取证】
前言 第三届盘古石杯国际电子数据取证大赛决赛 最后一题没有解出来,实在找不到,希望有大佬教一下我。 还有就会议时间,我感觉不是图片时间,因为在电脑看到是其他时间用老会议系统开的会。 手机取证 1、分析鸿蒙手机检材&#x…...
成都鼎讯硬核科技!雷达目标与干扰模拟器,以卓越性能制胜电磁频谱战
在现代战争中,电磁频谱已成为继陆、海、空、天之后的 “第五维战场”,雷达作为电磁频谱领域的关键装备,其干扰与抗干扰能力的较量,直接影响着战争的胜负走向。由成都鼎讯科技匠心打造的雷达目标与干扰模拟器,凭借数字射…...
管理学院权限管理系统开发总结
文章目录 🎓 管理学院权限管理系统开发总结 - 现代化Web应用实践之路📝 项目概述🏗️ 技术架构设计后端技术栈前端技术栈 💡 核心功能特性1. 用户管理模块2. 权限管理系统3. 统计报表功能4. 用户体验优化 🗄️ 数据库设…...
AI+无人机如何守护濒危物种?YOLOv8实现95%精准识别
【导读】 野生动物监测在理解和保护生态系统中发挥着至关重要的作用。然而,传统的野生动物观察方法往往耗时耗力、成本高昂且范围有限。无人机的出现为野生动物监测提供了有前景的替代方案,能够实现大范围覆盖并远程采集数据。尽管具备这些优势…...
push [特殊字符] present
push 🆚 present 前言present和dismiss特点代码演示 push和pop特点代码演示 前言 在 iOS 开发中,push 和 present 是两种不同的视图控制器切换方式,它们有着显著的区别。 present和dismiss 特点 在当前控制器上方新建视图层级需要手动调用…...
LabVIEW双光子成像系统技术
双光子成像技术的核心特性 双光子成像通过双低能量光子协同激发机制,展现出显著的技术优势: 深层组织穿透能力:适用于活体组织深度成像 高分辨率观测性能:满足微观结构的精细研究需求 低光毒性特点:减少对样本的损伤…...
