工具块与vs的联合编程(豆包总结生成)

一、核心知识点梳理(按功能模块)

模块 核心知识点 关键注意事项
ToolBlock 基础操作 1. CogToolBlock 是 VisionPro 工具块容器,封装多个视觉工具2. 序列化:CogSerializer.Load/SaveObjectFromFile 读写 vpp 文件3. 跨线程操作 UI 必须用Invoke 1. vpp 文件路径必须正确,否则加载失败2. 跨线程直接操作 UI 控件会抛异常
图片与 ToolBlock 交互 1. 本地 Bitmap 转 VisionPro 图像对象 CogImage24PlanarColor2. tb.Inputs["参数名"].Value给工具块输入赋值 仅支持 24 位彩色图,灰度图需用 CogImage8Grey
ToolBlock 运行 1. tb.Run()执行工具块所有工具2. CreateLastRunRecord()获取运行记录绑定到 CogRecordDisplay Run () 前必须确保输入参数已赋值,否则工具执行失败
结果处理 1. tb.Outputs["参数名"].Value获取工具块输出结果2. 数值转换(Convert.ToDouble)判断 OK/NG 输出参数名必须和 ToolBlock 内定义的一致(大小写敏感)
图片保存 1. CogRecordDisplay 转 Bitmap:CreateContentBitmap2. 动态创建 OK/NG 目录3. DateTime 生成唯一文件名 1. 文件名不能包含:--等非法字符2. Bitmap 使用后需 Dispose 释放内存

二、可复用关键代码片段(标注用途,直接复制用)

1. 异步加载 ToolBlock(窗体加载,避免 UI 阻塞)

csharp

运行

复制代码
// 全局变量(窗体类内)
private CogToolBlock _toolBlock; // 工具块核心对象
private List<string> _imagePaths = new List<string>(); // 图片路径列表
private int _currentImgIndex = 0; // 当前图片索引

// 窗体加载事件:跨线程加载ToolBlock(核心)
private void Form1_Load(object sender, EventArgs e)
{
    // 异步线程加载,避免UI卡死
    Thread loadThread = new Thread(LoadToolBlock);
    loadThread.IsBackground = true; // 设为后台线程,窗口关闭自动退出
    loadThread.Start();
}

// 加载ToolBlock的核心方法
private void LoadToolBlock()
{
    try
    {
        // 跨线程操作UI控件必须用Invoke
        this.Invoke(new Action(() =>
        {
            // 加载vpp工具块文件(替换为你的路径)
            string tbPath = @"D:\C#\绘制与保存\加载工具块\bin\Debug\tb.vpp";
            _toolBlock = CogSerializer.LoadObjectFromFile(tbPath) as CogToolBlock;
            cogToolBlockEditV21.Subject = _toolBlock; // 绑定到编辑控件
        }));
    }
    catch (Exception ex)
    {
        this.Invoke(new Action(() => MessageBox.Show($"加载ToolBlock失败:{ex.Message}")));
    }
}
2. 选择图片文件夹(按钮点击)

csharp

运行

复制代码
private void btnSelectImages_Click(object sender, EventArgs e)
{
    _imagePaths.Clear();
    using (FolderBrowserDialog fbd = new FolderBrowserDialog())
    {
        if (fbd.ShowDialog() != DialogResult.OK) return;

        // 获取文件夹内所有图片(可过滤格式:*.png|*.jpg|*.bmp)
        _imagePaths.AddRange(Directory.GetFiles(fbd.SelectedPath, "*.*", SearchOption.TopDirectoryOnly)
                             .Where(path => path.EndsWith(".png") || path.EndsWith(".jpg") || path.EndsWith(".bmp")));

        if (_imagePaths.Count == 0)
        {
            MessageBox.Show("文件夹内无图片!");
            return;
        }

        // 加载首张图片并执行ToolBlock
        RunToolBlockWithImage(_imagePaths[0]);
    }
}
3. 执行 ToolBlock 并显示结果(通用方法,可复用)

csharp

运行

复制代码
/// <summary>
/// 通用方法:传入图片路径,执行ToolBlock并显示结果
/// </summary>
/// <param name="imgPath">图片路径</param>
private void RunToolBlockWithImage(string imgPath)
{
    if (_toolBlock == null)
    {
        MessageBox.Show("ToolBlock未加载!");
        return;
    }

    // 1. 本地图片转VisionPro图像对象
    using (Bitmap bmp = new Bitmap(imgPath))
    {
        CogImage24PlanarColor cogImg = new CogImage24PlanarColor(bmp);
        
        // 2. 给ToolBlock输入参数赋值(OutputImage为工具块内定义的输入名)
        _toolBlock.Inputs["OutputImage"].Value = cogImg;
        
        // 3. 执行ToolBlock
        _toolBlock.Run();
        
        // 4. 绑定运行记录到显示控件
        cogRecordDisplay1.Record = _toolBlock.CreateLastRunRecord().SubRecords[0];
        cogRecordDisplay1.Fit(); // 适配显示区域
    }
}
4. 切换图片 + OK/NG 分类保存(运行按钮)

csharp

运行

复制代码
private void btnRunNext_Click(object sender, EventArgs e)
{
    if (_imagePaths.Count == 0)
    {
        MessageBox.Show("无图片,请先选择图片文件夹!");
        return;
    }

    // 切换图片索引(循环)
    _currentImgIndex++;
    if (_currentImgIndex >= _imagePaths.Count) _currentImgIndex = 0;

    // 执行ToolBlock并显示
    string currentImgPath = _imagePaths[_currentImgIndex];
    RunToolBlockWithImage(currentImgPath);

    // 5. 获取ToolBlock输出参数(Result_Mean为工具块内定义的输出名)
    double resultValue = Convert.ToDouble(_toolBlock.Outputs["Result_Mean"].Value);
    this.Text = $"当前结果:{resultValue}";

    // 6. OK/NG分类保存图片(避坑:文件名去掉非法字符)
    string okDir = Path.Combine(Directory.GetCurrentDirectory(), "OK");
    string ngDir = Path.Combine(Directory.GetCurrentDirectory(), "NG");
    CreateDirectoryIfNotExists(okDir);
    CreateDirectoryIfNotExists(ngDir);

    // 生成唯一文件名(避免--等非法字符)
    string fileName = DateTime.Now.ToString("yyyy-MM-dd-HH-mm-ss") + ".png";
    string savePath = resultValue > 100 ? Path.Combine(okDir, fileName) : Path.Combine(ngDir, fileName);

    // 从显示控件导出图片并保存
    using (Bitmap saveBmp = (Bitmap)cogRecordDisplay1.CreateContentBitmap(CogDisplayContentBitmapConstants.Image))
    {
        saveBmp.Save(savePath);
    }
}

// 通用方法:创建目录(不存在则创建)
private void CreateDirectoryIfNotExists(string dirPath)
{
    if (!Directory.Exists(dirPath))
    {
        Directory.CreateDirectory(dirPath);
    }
}
5. 保存 ToolBlock 到 vpp 文件(保存按钮)

csharp

运行

复制代码
private void btnSaveToolBlock_Click(object sender, EventArgs e)
{
    if (_toolBlock == null)
    {
        MessageBox.Show("ToolBlock未加载,无法保存!");
        return;
    }

    string savePath = @"D:\C#\绘制与保存\加载工具块\bin\Debug\tb.vpp";
    CogSerializer.SaveObjectToFile(_toolBlock, savePath);
    MessageBox.Show("ToolBlock保存成功!");
}

三、核心注意事项(避坑清单)

  1. 跨线程操作 :加载 ToolBlock 必须用this.Invoke,否则会触发 WinForms 跨线程访问控件异常;
  2. 路径与命名 :文件名不能包含:--/等非法字符,推荐用Path.Combine拼接路径;
  3. 资源释放 :Bitmap 对象必须用using包裹或手动Dispose,避免内存泄漏;
  4. 参数名匹配:Inputs/Outputs 的参数名必须和 ToolBlock 内定义的完全一致(大小写敏感);
  5. 异常处理:加载 vpp、读取图片时建议加 try-catch,避免程序崩溃。
相关推荐
阿蒙Amon6 分钟前
C#常用类库-详解Polly
开发语言·c#
唐青枫1 小时前
C#.NET stackalloc 深入解析:栈上分配、Span 配合与使用边界
c#·.net
C++ 老炮儿的技术栈1 小时前
C++、C#常用语法对比
c语言·开发语言·c++·qt·c#·visual studio
猹叉叉(学习版)1 小时前
【ASP.NET CORE】 13. DDD初步实现
笔记·后端·架构·c#·asp.net·.netcore
2501_930707782 小时前
使用C#代码将 PDF 转换为 PostScript(PS)格式
开发语言·pdf·c#
金山几座2 小时前
C#学习记录-泛型
开发语言·学习·c#
武藤一雄2 小时前
WPF Command 设计思想与实现剖析
windows·微软·c#·.net·wpf·.netcore
小陈phd2 小时前
多模态大模型学习笔记(十九)——基于 LangChain+Faiss的本地知识库问答系统实战
开发语言·c#
yue0082 小时前
C#读取App.Config配置文件
开发语言·c#
武藤一雄2 小时前
WPF 资源解析:StaticResource & DynamicResource 实战指南
微软·c#·.net·wpf·.netcore