C#视觉模板匹配与动态绘制实战(绘制和保存,加载tb块,处理vpp脚本的方式)

1绘制和保存

1. 模板文件加载 + 控件关联 + 事件绑定(Form 加载核心)

csharp

运行

复制代码
// 从本地vpp文件加载已保存的PMAlign工具配置(含模板、参数)
pma = CogSerializer.LoadObjectFromFile("文件路径.vpp") as CogPMAlignTool;
cogPMAlignEditV21.Subject = pma; // 绑定工具到编辑控件,可视化编辑模板
pma.Run += Pma_Ran; // 绑定工具运行完成事件(运行后执行绘制/结果处理)

// 读取工具参数并赋值给界面控件(实现参数可视化)
textBox1.Text = pma.RunParams.ApproximateNumberToFind.ToString(); // 读取查找数量
numericUpDown1.Value = (decimal)pma.RunParams.AcceptThreshold;    // 读取匹配阈值
2. 运行完成事件(核心:匹配结果获取 + 动态绘制图形)

csharp

运行

复制代码
private void Pma_Ran(object sender, EventArgs e)
{
    // 将匹配结果绑定到显示控件,可视化匹配过程/结果
    cogRecordDisplay1.Record = pma.CreateLastRunRecord().SubRecords[0];
    cogRecordDisplay1.Fit(); // 自适应显示图像

    // 遍历所有匹配结果(支持多目标匹配)
    for (int i = 0; i < pma.Results.Count; i++)
    {
        CogPMAlignResult result = pma.Results[i]; // 获取单个匹配结果
        CogCircle cir = new CogCircle();          // 实例化绘制圆形(可替换为矩形/线)
        // 关键:将匹配结果的位姿坐标赋值给绘制图形(精准定位匹配目标中心)
        cir.CenterX = result.GetPose().TranslationX;
        cir.CenterY = result.GetPose().TranslationY;
        // 绘制图形样式设置
        cir.Radius = 20;                          // 圆半径
        cir.LineWidthInScreenPixels = 2;          // 线宽
        cir.Color = CogColorConstants.Red;        // 绘制颜色(红色)
        // 将绘制图形添加到显示控件,实现匹配目标标注
        cogRecordDisplay1.StaticGraphics.Add(cir, "唯一标识");
    }
}
3. 手动运行工具 + 界面参数回写(按钮触发)

csharp

运行

复制代码
// 从界面控件读取参数,赋值给工具并执行匹配
int num1 = int.Parse(textBox1.Text); // 读取界面设置的查找数量
pma.RunParams.ApproximateNumberToFind = num1; // 回写查找数量参数
pma.RunParams.AcceptThreshold = (double)numericUpDown1.Value; // 回写匹配阈值参数
pma.Run(); // 执行模板匹配(触发Run事件)
3. 工具配置保存(按钮触发,永久保存模板 / 参数)

csharp

运行

复制代码
// 将PMAlign工具的所有配置(模板、参数、绘制等)保存为vpp文件,下次可直接加载
CogSerializer.SaveObjectToFile(pma, "保存路径.vpp");

关键 API 速查

功能 核心 API / 对象
PMAlign 工具实例化 CogPMAlignTool
序列化加载 / 保存 CogSerializer.Load/SaveObjectToFile
匹配结果集 pma.Results
单个匹配位姿坐标 result.GetPose().TranslationX/Y
图像显示控件赋值 cogRecordDisplay1.Record
动态绘制图形 CogCircle/CogRectangle + StaticGraphics.Add
核心运行参数 pma.RunParams.ApproximateNumberToFind/AcceptThreshold
cs 复制代码
namespace _02绘制和保存
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }
        CogPMAlignTool pma = new CogPMAlignTool();
        //加载
        private void Form1_Load(object sender, EventArgs e)
        {
            string path = @"C:\Users\Administrator\Desktop\新建文件夹\huizhibaocun.vpp";
            pma = CogSerializer.LoadObjectFromFile(path) as CogPMAlignTool;//sb
            cogPMAlignEditV21.Subject = pma;
            pma.Ran += Pma_Ran;
            textBox1.Text = pma.RunParams.ApproximateNumberToFind.ToString(); //获取查找概数
            MessageBox.Show(pma.RunParams.AcceptThreshold + "");
            numericUpDown1.Value = (decimal)pma.RunParams.AcceptThreshold ;// 获取接收阈值

        }

        private void Pma_Ran(object sender, EventArgs e)
        {

            cogRecordDisplay1.Record = pma.CreateLastRunRecord().SubRecords[0];
            cogRecordDisplay1.Fit();
            for (int i = 0; i < pma.Results.Count; i++)
            {
                CogPMAlignResult result = pma.Results[i];
                CogCircle cir = new CogCircle();
                cir.CenterX = result.GetPose().TranslationX;// 获取x坐标
                cir.CenterY = result.GetPose().TranslationY;
                cir.Radius = 20;
                cir.LineWidthInScreenPixels = 2; ;// 线宽
                cir.Color = CogColorConstants.Red;
                cogRecordDisplay1.StaticGraphics.Add(cir, "ss"); //把圆添加到cogRecordDisplay1上
               

            }

        }

        //运行
        private void button1_Click(object sender, EventArgs e)
        {
            //获取查找概数
            int num1 = int.Parse(textBox1.Text);
            pma.RunParams.ApproximateNumberToFind = num1;
            // 获取接收阈值
            pma.RunParams.AcceptThreshold = (double)numericUpDown1.Value;
            pma.Run();//执行

        }
        //保存
        private void button2_Click(object sender, EventArgs e)
        {
            CogSerializer.SaveObjectToFile(pma, @"C:\Users\Administrator\Desktop\新建文件夹\huizhibaocun.vpp");//保存vpp
           
        }
    }

2 加载tb块

1. 全局核心对象(ToolBlock 是核心,整合多工具的容器)
复制代码
CogToolBlock tb = new CogToolBlock(); // 实例化ToolBlock工具块(整合多视觉工具的容器)
List<string> pics = new List<string>(); // 存储批量读取的图像路径
int index = 0; // 图像遍历索引(用于切换/批量处理图像)
2. 窗体加载:多线程加载 ToolBlock(避免 UI 卡顿,核心优化)
复制代码
private void Form1_Load(object sender, EventArgs e)
{
    Thread th = new Thread(f1); // 开启子线程加载vpp文件
    th.Start();
}
// 子线程执行:加载ToolBlock+跨线程绑定UI控件
public void f1()
{
    // 从vpp文件加载ToolBlock(含内部所有视觉工具、参数、流程)
    tb = CogSerializer.LoadObjectFromFile("tb.vpp路径") as CogToolBlock;
    // 跨线程更新UI(子线程不能直接操作WinForm控件,Invoke是必用)
    this.Invoke(new Action(() =>
    {
        cogToolBlockEditV21.Subject = tb; // 绑定工具块到编辑控件,可视化编辑内部流程
    }));
}
3. 选择文件夹:批量读取图像路径 + 单张图像初始化运行
复制代码
FolderBrowserDialog fd = new FolderBrowserDialog(); // 文件夹选择对话框
if (fd.ShowDialog() == DialogResult.OK)
{
    string[] s1 = Directory.GetFiles(fd.SelectedPath); // 获取文件夹下所有文件路径
    foreach (var item in s1) pics.Add(item); // 存入图像路径集合

    // 图像格式转换:本地图片(Bitmap) → VisionPro可识别的CogImage24PlanarColor
    Bitmap map = Image.FromFile(pics[0]) as Bitmap;
    CogImage24PlanarColor img = new CogImage24PlanarColor(map);

    // 关键:给ToolBlock输入参数赋值(对接工具块内部的图像输入)
    tb.Inputs["OutputImage"].Value = img;
    tb.Run(); // 执行ToolBlock内部所有视觉工具

    // 显示运行结果到图像控件
    cogRecordDisplay1.Record = tb.CreateLastRunRecord().SubRecords[0];
    cogRecordDisplay1.Fit(); // 自适应显示
}
4. 批量运行:图像切换 + ToolBlock 执行 + 输出参数获取 + OK/NG 分类保存(核心业务)
复制代码
index++; // 切换下一张图像
if (index == pics.Count) index = 0; // 循环遍历图像

// 1. 图像加载+格式转换+ToolBlock输入赋值+执行
Bitmap map = Image.FromFile(pics[index]) as Bitmap;
CogImage24PlanarColor img = new CogImage24PlanarColor(map);
tb.Inputs["OutputImage"].Value = img;
tb.Run();

// 2. 结果显示
cogRecordDisplay1.Record = tb.CreateLastRunRecord().SubRecords[0];
cogRecordDisplay1.Fit();

// 3. 关键:获取ToolBlock**输出参数**(内部工具的运算结果,如灰度均值)
double huiduzhi = (double)tb.Outputs["Result_Mean"].Value;
this.Text = huiduzhi.ToString(); // 窗体标题实时显示结果值

// 4. OK/NG文件夹初始化(不存在则创建)
string okPath = Path.Combine(Directory.GetCurrentDirectory(), "OK");
string ngPath = Path.Combine(Directory.GetCurrentDirectory(), "NG");
if (!Directory.Exists(okPath)) Directory.CreateDirectory(okPath);
if (!Directory.Exists(ngPath)) Directory.CreateDirectory(ngPath);

// 5. 按判定条件分类保存图像(保存显示控件上的结果图,含标注)
Bitmap resultBmp = cogRecordDisplay1.CreateContentBitmap(CogDisplayContentBitmapConstants.Image) as Bitmap;
string saveName = $"{DateTime.Now:yyyyMMddHHmmss}.bmp"; // 时间戳命名,避免重复
if (huiduzhi > 100) // OK判定条件
    resultBmp.Save(Path.Combine(okPath, saveName));
else // NG判定条件
    resultBmp.Save(Path.Combine(ngPath, saveName));
5. ToolBlock 保存:永久保存工具块配置(含内部所有工具、参数)

csharp

运行

复制代码
// 将ToolBlock的完整配置(内部工具、流程、参数)保存为vpp文件,下次可直接加载
CogSerializer.SaveObjectToFile(tb, @"C:\Users\Administrator\Desktop\新建文件夹\tb.vpp");

关键 API 速查(ToolBlock 专属 + 核心操作)

功能 核心 API / 语法
ToolBlock 实例化 / 加载 CogToolBlock + CogSerializer.LoadObjectFromFile
工具块输入赋值 tb.Inputs["输入参数名"].Value = 赋值
工具块输出取值 tb.Outputs["输出参数名"].Value
跨线程更新 UI this.Invoke(new Action(() => { UI操作 }))
批量获取文件路径 Directory.GetFiles(文件夹路径)
文件夹创建 / 判断 Directory.Exists/CreateDirectory
结果图保存 cogRecordDisplay1.CreateContentBitmap(转 Bitmap)+ Save
时间戳命名 DateTime.Now.ToString("yyyyMMddhhmmss")
ToolBlock 保存 CogSerializer.SaveObjectToFile(tb, 路径)
cs 复制代码
namespace _03加载tb块
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }
         //窗体加载事件
        private void Form1_Load(object sender, EventArgs e)
        {
            Thread th = new Thread(f1);
            th.Start();
        }
        CogToolBlock tb = new CogToolBlock();
        public void f1()
        {
            string path = @"C:\Users\Administrator\Desktop\新建文件夹\tb.vpp";
            tb = CogSerializer.LoadObjectFromFile(path) as CogToolBlock; // 类似于vpp里面高级脚本的mToolBlock对象
                                                                         //tb.Tools["工具名"] as 对应的类型 获取对应的工具
            this.Invoke(new Action(() =>
            {
                cogToolBlockEditV21.Subject = tb;
            }));

        }
        List<string> pics = new List<string>(); //图片路径
        //选择图像
        private void button1_Click(object sender, EventArgs e)
        {

            FolderBrowserDialog fd = new FolderBrowserDialog();//文件夹浏览框
            if (fd.ShowDialog()==DialogResult.OK)
            {
                //  fd.SelectedPath //文件夹的路径
               string[] s1 =  Directory.GetFiles(fd.SelectedPath);

                foreach (var item in s1)
                {
                    pics.Add(item);
                }
                Bitmap map = Image.FromFile(pics[0]) as Bitmap;
                CogImage24PlanarColor img = new CogImage24PlanarColor(map);
                //  tb.Inputs tb块输入对象
                //  tb.Inputs["OutputImage"] tb块OutputImage的输入参数
                tb.Inputs["OutputImage"].Value = img;
                tb.Run();

                cogRecordDisplay1.Record = tb.CreateLastRunRecord().SubRecords[0];
                cogRecordDisplay1.Fit();

            }

        }
        int index = 0;
        //运行
        private void button2_Click(object sender, EventArgs e)
        {
            index++;
            if (index==pics.Count)
            {
                index = 0;
            }
            Bitmap map = Image.FromFile(pics[index]) as Bitmap;
            CogImage24PlanarColor img = new CogImage24PlanarColor(map);
            tb.Inputs["OutputImage"].Value = img;
            tb.Run();
            cogRecordDisplay1.Record = tb.CreateLastRunRecord().SubRecords[0];
            cogRecordDisplay1.Fit();

            // 获取输出参数
            this.Text = tb.Outputs["Result_Mean"].Value + "";

            double huiduzhi = (double)tb.Outputs["Result_Mean"].Value;

            string ok = Directory.GetCurrentDirectory() + "\\OK";
            string ng = Directory.GetCurrentDirectory() + "\\NG";
            if (!Directory.Exists(ok))
            {
                Directory.CreateDirectory(ok);

            }
            if (!Directory.Exists(ng))
            {
                Directory.CreateDirectory(ng);
            }
         
            if (huiduzhi>100) //ok图
            {

               Bitmap map1= cogRecordDisplay1.CreateContentBitmap(Cognex.VisionPro.Display.CogDisplayContentBitmapConstants.Image) as Bitmap;//把控件上记录转成位图

                map1.Save(ok + $"\\{DateTime.Now.ToString("yyyyMMddhhmmss")}.bmp");

            }
            else  // ng图
            {
                Bitmap map1 = (Bitmap)cogRecordDisplay1.CreateContentBitmap(Cognex.VisionPro.Display.CogDisplayContentBitmapConstants.Image);//把控件上记录转成位图
            
                map1.Save(ng + $"\\{DateTime.Now.ToString("yyyyMMddhhmmss")}.bmp");
                
            }

        }
        // 保存
        private void button3_Click(object sender, EventArgs e)
        {
            CogSerializer.SaveObjectToFile(tb, @"C:\Users\Administrator\Desktop\新建文件夹\tb.vpp");
        }
    }

3处理vpp脚本的方式

1. 核心全局对象(ToolBlock 工具块为核心容器)
复制代码
CogToolBlock mToolBlock = new CogToolBlock(); // 实例化ToolBlock,承载vpp内所有视觉工具
2. 窗体加载:ToolBlock 加载 + UI 控件绑定(基础必备)
复制代码
// 从vpp文件加载ToolBlock(含内部所有子工具、参数,支持不同vpp切换)
string path = @"对应vpp文件路径";
mToolBlock = CogSerializer.LoadObjectFromFile(path) as CogToolBlock;
cogToolBlockEditV21.Subject = mToolBlock; // 绑定到编辑控件,可视化查看/编辑vpp内流程
3. 方式 1:VPP 内置脚本(逻辑写在 VisionPro 的 vpp 中,VS 仅调用执行)
复制代码
// 极简调用:直接运行ToolBlock,所有逻辑(运算、判断、输出)由vpp内置脚本完成
mToolBlock.Run();
// 直接获取vpp内脚本定义的输出参数,无需在VS中写业务逻辑
this.Text = mToolBlock.Outputs["text"].Value + "";
4. 方式 2:VS 外部编写逻辑(核心:提取 ToolBlock 内子工具 + 单独调用 / 二次处理)
复制代码
if (mToolBlock != null)
{
    // 1. 先执行整个ToolBlock
    mToolBlock.Run();

    // 2. 关键:从ToolBlock中提取指定子工具(按vpp内工具名强转)
    CogPMAlignTool pma = mToolBlock.Tools["CogPMAlignTool1"] as CogPMAlignTool; // 模板匹配工具
    CogCompositeColorMatchTool color = mToolBlock.Tools["CogCompositeColorMatchTool1"] as CogCompositeColorMatchTool; // 颜色匹配工具

    // 3. 遍历子工具结果,自定义业务逻辑(VS中灵活编写)
    string s = "";
    for (int i = 0; i < pma.Results.Count; i++)
    {
        // 3.1 从模板匹配结果获取位姿,创建仿射矩形(适配目标旋转/位移)
        CogRectangleAffine rect = new CogRectangleAffine();
        rect.CenterX = pma.Results[i].GetPose().TranslationX; // 匹配目标X中心
        rect.CenterY = pma.Results[i].GetPose().TranslationY; // 匹配目标Y中心
        rect.Rotation = pma.Results[i].GetPose().Rotation;    // 匹配目标旋转角度
        rect.SideXLength = 100; rect.SideYLength = 10;       // 矩形尺寸

        // 3.2 给颜色匹配工具赋值检测区域(模板匹配定位+颜色匹配检测)
        color.Region = rect;
        // 3.3 单独运行颜色匹配工具,执行检测
        color.Run();

        // 3.4 提取颜色匹配结果,拼接自定义逻辑结果
        s += color.Result.ResultOfBestMatch.Color.Name;
    }

    // 3.5 展示自定义逻辑处理结果
    this.Text = s;
}

关键 API 速查(ToolBlock 子工具操作 + 核心联动)

功能 核心 API / 语法
提取 ToolBlock 内子工具 mToolBlock.Tools["vpp内工具名"] as 工具类型
模板匹配结果位姿获取 pma.Results[i].GetPose().TranslationX/Y/Rotation
仿射矩形创建 / 赋值 CogRectangleAffine(适配旋转目标)
颜色匹配区域赋值 color.Region = 几何图形(矩形/圆)
颜色匹配结果提取 color.Result.ResultOfBestMatch.Color.Name
ToolBlock 内工具单独运行 子工具对象.Run()(如color.Run()
VPP 内置脚本输出获取 mToolBlock.Outputs["vpp内定义输出名"].Value
cs 复制代码
namespace _04处理vpp脚本的方式
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }
        CogToolBlock mToolBlock = new CogToolBlock();
        private void Form1_Load(object sender, EventArgs e)
        {

            string path = @"C:\Users\Administrator\Desktop\新建文件夹\颜色.vpp";
            //string path = @"C:\Users\Administrator\Desktop\新建文件夹\tb2.vpp";
            mToolBlock =  CogSerializer.LoadObjectFromFile(path) as CogToolBlock;
            cogToolBlockEditV21.Subject = mToolBlock;

        }
        private void button1_Click(object sender, EventArgs e)
        {
            //这俩句代码为了颜色加载tb2.vpp, 把逻辑写在vpp里面
            //mToolBlock.Run();
            //this.Text = mToolBlock.Outputs["text"].Value + "";


            // 加载颜色.vpp 主要是演示把逻辑写在vs里面
            if (mToolBlock != null)
            {
                mToolBlock.Run();
                //获取tb块的工具
                CogPMAlignTool pma = mToolBlock.Tools["CogPMAlignTool1"] as CogPMAlignTool;
                CogCompositeColorMatchTool color = mToolBlock.Tools["CogCompositeColorMatchTool1"] as CogCompositeColorMatchTool;

                string s = "";
                for (int i = 0; i < pma.Results.Count; i++)
                {

                    CogRectangleAffine rect = new CogRectangleAffine();
                    rect.CenterX = pma.Results[i].GetPose().TranslationX;
                    rect.CenterY = pma.Results[i].GetPose().TranslationY;
                    rect.Rotation = pma.Results[i].GetPose().Rotation;
                    rect.SideXLength = 100;
                    rect.SideYLength = 10;
                    color.Region = rect;

                    //运行工具
                    color.Run();

                    s += color.Result.ResultOfBestMatch.Color.Name;

                }
                this.Text = s;
            }

        }

       
    }
}
相关推荐
朗迪锋2 小时前
筑梦天宫的数字基石:MultiViz与MakeReal3D共绘航天数智新图景
3d·信息可视化·数字孪生·数智孪生
南风知我意9572 小时前
【前端面试3】初中级难度
前端·javascript·面试
霍理迪2 小时前
JS作用域与预解析
开发语言·前端·javascript
切糕师学AI2 小时前
.NET Core Web 中的健康检查端点(Health Check Endpoint)
前端·kubernetes·.netcore
蓉妹妹2 小时前
在React中使用Scroll嵌套Scroll,出现里面Scroll滚动条超出高度却滚动没反应的问题,解决方案添加nestedScrollEnabled
javascript·react native·react.js
rosmis2 小时前
地铁病害检测系统软件改进记录-2-02
开发语言·前端·javascript
css趣多多2 小时前
解决ui组件flex1容器底部被撑开的问题
前端
乔江seven3 小时前
【python轻量级Web框架 Flask 】2 构建稳健 API:集成 MySQL 参数化查询与 DBUtils 连接池
前端·python·mysql·flask·web
Alaaaaaaan3 小时前
[DevOps]使用github-action工具部署docker容器(实现提交代码一键推送部署到服务器)
服务器·前端·docker·容器·github