一、核心知识点梳理(按功能模块)
| 模块 | 核心知识点 | 关键注意事项 |
|---|---|---|
| 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保存成功!");
}
三、核心注意事项(避坑清单)
- 跨线程操作 :加载 ToolBlock 必须用
this.Invoke,否则会触发 WinForms 跨线程访问控件异常; - 路径与命名 :文件名不能包含
:、--、/等非法字符,推荐用Path.Combine拼接路径; - 资源释放 :Bitmap 对象必须用
using包裹或手动Dispose,避免内存泄漏; - 参数名匹配:Inputs/Outputs 的参数名必须和 ToolBlock 内定义的完全一致(大小写敏感);
- 异常处理:加载 vpp、读取图片时建议加 try-catch,避免程序崩溃。