当前位置: 首页 > news >正文

VisionProC#联合编程相机实战开发

前言

上章已经讲过C#连接相机的方法 本章讲一个相机实战开发示例 通过C#连接的相机拍去照片然后进行图片检测分析 结果展示窗体上 和选择指定图片显示(弹出文件夹选择) 和拍去的照片保存 以及相机参数配置窗体 和TBlock作业配置使用了Menu菜单栏 

还封装了LoadVpp<T>方法 是为了以后我们加载多个vp对象 以及我们如果项目文件下没有这个vp可以重新创建vp 类型泛型
不在VisionPro创建新的vp好处: 1如果用户在不小心删除或传输文件丢失的情况 没有这个vp那我们加载这个vp就会报错 还需在VisionPro重新在创建新的vp在保存很不友好
而且当我们对不同的照片进行不同的新的工具检测可直接重新创建新的 所以如果程序运行没有原先vp 或 使用新的工具 可重新创建vp 不需在VisionPro在创建vp进行工具拖拽

界面展示

环境配置

在写程序之前我们要先配置相机保持连接正常

1..打开康耐视的配置器 把以太网改成相机的Ip 注意域名一致

相机

以太网

巨型帧: 找到你的以太网ipv4找到属性 点高级 修改9014即可

程序生成改x64

拍照检测

在拍照检测之前 我们要先加载配置好的vp方案 在创建相机配置对象工具 在监听拍完照事件 在开启拍照即可

 public CogAcqFifoTool acqFifoTool;//相机配置工具对象//取相机对象 从相机对象配置工具中自动获取ICogAcqFifo acq { get { return acqFifoTool.Operator; } }//因为有时创建新的vp会用之前的 所以要减去事件在重新走事件 不然会触发多次acq.StartAcquire();cogRecordDisplay1.Fit();acq.Complete -= Acq_Complete;acq.Complete += Acq_Complete;private void Acq_Complete(object sender, CogCompleteEventArgs e){//注意:这个拍完照事件是在分线程执行的 因此对控件的操作无效 必须使用BeginInvoke或 Invoke 是VisionPro封装的方法 有时候我们会出现卡退的问题但没有报错 其实就是已经报错了//拍照完成的事件触发 //取相int numPending, numReady;//等待状态,准备状态bool isBusy;//繁忙状态acq.GetFifoState(out numPending,out numReady,out isBusy);if (numReady > 0) //判断相机是否准备好{CogAcqInfo info = new CogAcqInfo();//创建acqinfo对象ICogImage image = acq.CompleteAcquireEx(info);//获取图像//因为我们有的是拍照检测和选择图片检测 所以创建一个方法传入不同图片ImageParcamer(image);//cogRecordDisplay1.Image=image as CogImage8Grey;//显示图片// myImage = image as CogImage8Grey;//赋值全局图片//cogRecordDisplay1.Fit()//;自适应}MessageBox.Show("拍照完成");

因为项目有拍取图片检测和选择图片 所以封装了一个方法 参数图片 

  private void ImageParcamer(ICogImage img){//InvokeRequired 当这个属性为true 表示当前不在主线程 要对控件的操作必须使用BeginInvoke或者Invoke//如果需要调用BeginInvoke或者Invoke//他俩区别BeginInvoke是不等待其他线程直接运行到底也就是不会卡线程 Invoke是等待上一个线程完成在执行下一步//所以我们需要使用Invoke 不然对象为空就会程序卡退if (InvokeRequired){//使用Invoke重新执行当前方法Invoke(new Action(() =>{ImageParcamer(img);}));}try{//展示图像cogRecordDisplay1.Image = img;cogRecordDisplay1.Fit();//图像根据控件大小适应toolBlock.Inputs["OutputImage"].Value=img;//给图片赋值toolBlock.Run();//运行ToolBlock//获取ToolBlock的运行状态//  ICogRunStatus status=toolBlock.RunStatus;//如果运行状态的代码不等于 "接受"则说明ToolBlock 运行出现错误// if (status.Result != CogToolResultConstants.Accept)//  {//MessageBox.Show(status.Message);//显示运行状态的提示信息// return;// }//显示运行结果ICogRecord record = toolBlock.CreateLastRunRecord().SubRecords[0];cogRecordDisplay1.Record = record;cogRecordDisplay1.Fit();if (toolBlock.Outputs["R"].Value != null && toolBlock.Outputs["Count"].Value!=null) //这是根据你的vp有多少个输出参数进行判断 可自己设置多个{//更新结果label4.Text = ((double)toolBlock.Outputs["R"].Value).ToString("F2");//第二种写法 VisionPro写法//(工具类型)CogBobTool blob(CogBobTool)toolBlock.Tools["CogBobTool1"]label5.Text = toolBlock.Outputs["Count"].Value.ToString(); ;}}catch (Exception ex) {MessageBox.Show("采集信息识别"+ex.Message);}}

选择图像并识别

 //选择图片识别private void button2_Click(object sender, EventArgs e){if (openFileDialog1.ShowDialog() == DialogResult.OK){Bitmap bitmap=new Bitmap(openFileDialog1.FileName);ICogImage image= new CogImage8Grey(bitmap);ImageParcamer(image);cogRecordDisplay1.Fit();}}

实时预览

  private void button3_Click(object sender, EventArgs e){cogRecordDisplay1.StartLiveDisplay(acq);}

保存图片

   private void button4_Click(object sender, EventArgs e){if (cogRecordDisplay1.Image != null){// 改用绝对路径(或确认相对路径有效),优先推荐系统临时目录/程序可写路径string saveDir = Path.Combine(Application.StartupPath, "Debug");// 确保文件夹存在(关键!)Directory.CreateDirectory(saveDir);string fileName = textBox1.Text.Trim();// 过滤非法字符(避免文件名含 \ / : * ? " < > | 等)fileName = Regex.Replace(fileName, @"[^\w\.]", "");string savePath = Path.Combine(saveDir, $"{fileName}.png");try{cogRecordDisplay1.Image.ToBitmap().Save(savePath);MessageBox.Show("保存成功");this.textBox1.Text = null;}catch (Exception ex){// 详细报错,替代原来的静默异常MessageBox.Show($"保存失败:{ex.Message}\n路径:{savePath}", "错误",MessageBoxButtons.OK, MessageBoxIcon.Error);}}else{MessageBox.Show("图像数据无效,无法保存");}}

窗体加载事件 加载的相机参数配置vp和TBlock vp

在这封装了LoadVpp方法当我们需要加载多个vp的时候直接创建对应的类型即可 类型是泛型

 private void Form1_Load(object sender, EventArgs e){//窗体加载事件之后读取两个vppacqFifoTool = CogSerializer.LoadObjectFromFile(Settings.CameraPath) as CogAcqFifoTool;toolBlock = CogSerializer.LoadObjectFromFile(Settings.TBpath) as CogToolBlock;// acqFifoTool =LoadVpp<CogAcqFifoTool>(Settings.CameraPath);// toolBlock = LoadVpp<CogToolBlock>(Settings.TBpath) ;}//封装这个方法 是为了以后我们加载多个vp对象 以及我们如果项目文件下没有这个vp可以重新创建vp//不在VisionPro创建新的vp好处: 1如果用户在不小心删除或传输文件丢失的情况 没有这个vp那我们加载这个vp就会报错 还需在VisionPro重新在创建新的vp在保存很不友好//而且当我们对不同的照片进行不同的新的工具检测可直接重新创建新的 所以如果程序运行没有原先vp 或 使用新的工具 可重新创建vp 不需在VisionPro在创建vp进行工具拖拽/// <summary>/// 用于加载vpp方法/// </summary>/// <typeparam name="T">vpp类型</typeparam>/// <param name="path">vpp路径</param>/// <returns>该类型的vsionPro对象</returns>//private T LoadVpp<T>(string path) where T : class, new()//{//    try//    {//        return CogSerializer.LoadObjectFromFile(Settings.TBpath) as T;//    }//    catch//    {//        return new T();//    }//}

相机参数配置窗体

在这里我们传的主窗体的vp 不需要在新窗体在创建 不然降低性能损耗以及创建新的等问题
好处:整个程序就用这一个对象 既能降低性能损耗 不会出现问题等 相当于单例模式 一个程序运用同一个类 (前几章火花塞的项目之前说过加载TBlock编辑窗体的时候保持程序使用同一个vpp)

  private void 相机配置ToolStripMenuItem_Click(object sender, EventArgs e){EditAcg editAcg = new EditAcg(acqFifoTool);editAcg.Show();}

cogAcqFifoEditV21控件

注:有时候会初始化失败 会弹窗警告 等待一会再去选择 或者一直点 就行

 这种情况重新运行就好了 或者从新配置就会一直弹警告

  //接收传递参数public EditAcg(CogAcqFifoTool acqFifoTool):this(){cogAcqFifoEditV21.Subject = acqFifoTool;}

TBlock作业窗体

 private void toolBlock配置ToolStripMenuItem_Click(object sender, EventArgs e){EditTB editTB = new EditTB(toolBlock);editTB.Show();}

 public EditTB(CogToolBlock toolBlock):this(){cogToolBlockEditV21.Subject = toolBlock;}

效果展示

完整代码

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using System.Windows.Forms;
using Cognex.VisionPro;
using Cognex.VisionPro.ToolBlock;namespace VisionPro相机联合编程开发
{public partial class Form1 : Form{public Form1(){InitializeComponent();}public CogToolBlock toolBlock; //ToolBlock作业对象public CogAcqFifoTool acqFifoTool;//相机配置工具对象//取相机对象 从相机对象配置工具中自动获取ICogAcqFifo acq { get { return acqFifoTool.Operator; } }private void Form1_Load(object sender, EventArgs e){//窗体加载事件之后读取两个vppacqFifoTool = CogSerializer.LoadObjectFromFile(Settings.CameraPath) as CogAcqFifoTool;toolBlock = CogSerializer.LoadObjectFromFile(Settings.TBpath) as CogToolBlock;// acqFifoTool =LoadVpp<CogAcqFifoTool>(Settings.CameraPath);// toolBlock = LoadVpp<CogToolBlock>(Settings.TBpath) ;}//封装这个方法 是为了以后我们加载多个vp对象 以及我们如果项目文件下没有这个vp可以重新创建vp//不在VisionPro创建新的vp好处: 1如果用户在不小心删除或传输文件丢失的情况 没有这个vp那我们加载这个vp就会报错 还需在VisionPro重新在创建新的vp在保存很不友好//而且当我们对不同的照片进行不同的新的工具检测可直接重新创建新的 所以如果程序运行没有原先vp 或 使用新的工具 可重新创建vp 不需在VisionPro在创建vp进行工具拖拽/// <summary>/// 用于加载vpp方法/// </summary>/// <typeparam name="T">vpp类型</typeparam>/// <param name="path">vpp路径</param>/// <returns>该类型的vsionPro对象</returns>//private T LoadVpp<T>(string path) where T : class, new()//{//    try//    {//        return CogSerializer.LoadObjectFromFile(Settings.TBpath) as T;//    }//    catch//    {//        return new T();//    }//}//相机配置界面private void 相机配置ToolStripMenuItem_Click(object sender, EventArgs e){//在这里我们传的主窗体的vp 不需要在新窗体在创建 不然降低性能损耗以及创建新的等问题//好处:整个程序就用这一个对象 既能降低性能损耗 不会出现问题等 相当于单例模式 一个程序运用同一个类EditAcg editAcg = new EditAcg(acqFifoTool);editAcg.Show();}//作业界面private void toolBlock配置ToolStripMenuItem_Click(object sender, EventArgs e){EditTB editTB = new EditTB(toolBlock);editTB.Show();}//拍照private void button1_Click(object sender, EventArgs e){// 停止实时预览// cogRecordDisplay1.StopLiveDisplay();//监听拍完照事件//因为有时创建新的vp会用之前的 所以要减去事件在重新走事件 不然会触发多次acq.StartAcquire();cogRecordDisplay1.Fit();acq.Complete -= Acq_Complete;acq.Complete += Acq_Complete;}public CogImage8Grey myImage;private void Acq_Complete(object sender, CogCompleteEventArgs e){//注意:这个拍完照事件是在分线程执行的 因此对控件的操作无效 必须使用BeginInvoke或 Invoke 是VisionPro封装的方法 有时候我们会出现卡退的问题但没有报错 其实就是已经报错了//拍照完成的事件触发 //取相int numPending, numReady;//等待状态,准备状态bool isBusy;//繁忙状态acq.GetFifoState(out numPending,out numReady,out isBusy);if (numReady > 0) //判断相机是否准备好{CogAcqInfo info = new CogAcqInfo();//创建acqinfo对象ICogImage image = acq.CompleteAcquireEx(info);//获取图像//因为我们有的是拍照检测和选择图片检测 所以创建一个方法传入不同图片ImageParcamer(image);//cogRecordDisplay1.Image=image as CogImage8Grey;//显示图片// myImage = image as CogImage8Grey;//赋值全局图片//cogRecordDisplay1.Fit()//;自适应}MessageBox.Show("拍照完成");}//选择图片识别private void button2_Click(object sender, EventArgs e){if (openFileDialog1.ShowDialog() == DialogResult.OK){Bitmap bitmap=new Bitmap(openFileDialog1.FileName);ICogImage image= new CogImage8Grey(bitmap);ImageParcamer(image);cogRecordDisplay1.Fit();}}private void ImageParcamer(ICogImage img){//InvokeRequired 当这个属性为true 表示当前不在主线程 要对控件的操作必须使用BeginInvoke或者Invoke//如果需要调用BeginInvoke或者Invoke//他俩区别BeginInvoke是不等待其他线程直接运行到底也就是不会卡线程 Invoke是等待上一个线程完成在执行下一步//所以我们需要使用Invoke 不然对象为空就会程序卡退if (InvokeRequired){//使用Invoke重新执行当前方法Invoke(new Action(() =>{ImageParcamer(img);}));}try{//展示图像cogRecordDisplay1.Image = img;cogRecordDisplay1.Fit();//图像根据控件大小适应toolBlock.Inputs["OutputImage"].Value=img;//给图片赋值toolBlock.Run();//运行ToolBlock//获取ToolBlock的运行状态//  ICogRunStatus status=toolBlock.RunStatus;//如果运行状态的代码不等于 "接受"则说明ToolBlock 运行出现错误// if (status.Result != CogToolResultConstants.Accept)//  {//MessageBox.Show(status.Message);//显示运行状态的提示信息// return;// }//显示运行结果ICogRecord record = toolBlock.CreateLastRunRecord().SubRecords[0];cogRecordDisplay1.Record = record;cogRecordDisplay1.Fit();if (toolBlock.Outputs["R"].Value != null && toolBlock.Outputs["Count"].Value!=null) //这是根据你的vp有多少个输出参数进行判断 可自己设置多个{//更新结果label4.Text = ((double)toolBlock.Outputs["R"].Value).ToString("F2");//第二种写法 VisionPro写法//(工具类型)CogBobTool blob(CogBobTool)toolBlock.Tools["CogBobTool1"]label5.Text = toolBlock.Outputs["Count"].Value.ToString(); ;}}catch (Exception ex) {MessageBox.Show("采集信息识别"+ex.Message);}}//关闭窗体事件 private void Form1_FormClosing(object sender, FormClosingEventArgs e){//保存Vpp 不需要在编辑窗体保存 因为我们整个程序用的是同一个CogSerializer.SaveObjectToFile(acqFifoTool,Settings.CameraPath);CogSerializer.SaveObjectToFile(toolBlock,Settings.TBpath);//释放相机资源//先判断有没有这个对象 不然就会释放不掉 报错acq?.FrameGrabber?.Disconnect(false); //false就是不创建新的}//实时预览private void button3_Click(object sender, EventArgs e){cogRecordDisplay1.StartLiveDisplay(acq);}//保存图片private void button4_Click(object sender, EventArgs e){if (cogRecordDisplay1.Image != null){// 改用绝对路径(或确认相对路径有效),优先推荐系统临时目录/程序可写路径string saveDir = Path.Combine(Application.StartupPath, "Debug");// 确保文件夹存在(关键!)Directory.CreateDirectory(saveDir);string fileName = textBox1.Text.Trim();// 过滤非法字符(避免文件名含 \ / : * ? " < > | 等)fileName = Regex.Replace(fileName, @"[^\w\.]", "");string savePath = Path.Combine(saveDir, $"{fileName}.png");try{cogRecordDisplay1.Image.ToBitmap().Save(savePath);MessageBox.Show("保存成功");this.textBox1.Text = null;}catch (Exception ex){// 详细报错,替代原来的静默异常MessageBox.Show($"保存失败:{ex.Message}\n路径:{savePath}", "错误",MessageBoxButtons.OK, MessageBoxIcon.Error);}}else{MessageBox.Show("图像数据无效,无法保存");}}}
}

http://www.dtcms.com/a/362184.html

相关文章:

  • 【云存储桶安全】怎么满足业务需求,又最大程度上满足信息安全要求呢?
  • 1792. 最大平均通过率
  • 学习:uniapp全栈微信小程序vue3后台-暂时停更
  • 本地没有公网ip?用cloudflare部署内网穿透服务器,随时随地用自定义域名访问自己应用端口资源
  • 液态神经网络:智能制造的新引擎
  • 【跨境电商】上中下游解释,以宠物行业为例
  • 洛谷 c++ P1177 【模板】排序 题解
  • AutoSar RTE介绍
  • 特征增强方法【特征构建】
  • MVC、三层架构
  • RT-DETR网络结构
  • 并发之线程
  • 【思考】WSL是什么
  • 一、SVN与svnbucket.com常见问题解答
  • 从组分到涌现:系统科学视域下结构、功能与层级的辨析及在人工智能中的应用
  • 设备管理软件正在成为制造业企业的战略重点_HawkEye智能运维平台_璞华大数据
  • 对比Mysql理解OceanBase中的租户设计
  • PostgreSQL 从入门到精通:一场与开源数据库的深度对话
  • 时序数据库国产的有哪些?
  • 利用棒棒糖图探索Office (US)的IMDB评分
  • 毕业项目推荐:64-基于yolov8/yolov5/yolo11的蝴蝶种类检测识别系统(Python+卷积神经网络)
  • 如何修复 Vercel 函数超时并大幅降低云函数成本
  • 计组(2)CPU与指令
  • 我的学习经历,个人能力说明书,求职书
  • 伺服器模拟输入控制电机转速
  • 华为云CCE
  • 【计算岗位解析:从代码到产品,这些角色如何“造”出数字世界?】
  • SpringBoot的基础介绍,用法和配置
  • 线上API接口响应慢?一套高效排查与定位问题的心法
  • PyTorch 面试题及详细答案120题(96-105)-- 性能优化与调试