VisionPro二次开发学习笔记1-创建基于QuickBuild的C#应用程序

创建基于QuickBuild的C#应用程序

使用的QuickBuild应用程序位于%VPRO_ROOT%/ Samples / Programming / QuickBuild / advancedAppOne.vpp中。在继续之前,可以在QuickBuild中运行该应用程序。

QuickBuild应用程序使用PatMax查找支架的“耳朵”之一,使用CogFixture工具设置图像的坐标空间,使用Blob工具查找两个中心孔,并使用CogDistancePointToPointTool测量孔之间的距离。最后,结果分析工具通过测试两个孔之间的距离是否在可接受的范围内来确定检查是否通过。

该指南分为四个步骤:

  1. 加载QuickBuild应用程序
  2. 添加GUI并使用线程
  3. 增强GUI并显示结果
  4. 显示影像

1.加载QuickBuild应用程序

1. 打开Visual Studio,创建一个C#.NetFramework的Windows应用程序.
2. 添加以下引用
  • Cognex.VisionPro
  • Cognex.VisionPro.Core
  • Cognex.VisionPro.QuickBuild.Core
3. 打开Form1.cs,添加代码如下:
using Cognex.VisionPro;
using Cognex.VisionPro.QuickBuild;
4. 声明变量
private CogJobManager myJobManager;
private CogJob myJob;
private CogJobIndependent myIndependentJob;
5. 在窗体Load事件中加载QuickBuild 应用程序
/// <summary>
/// 从一个文件中加载作业管理器对象。
/// 获取该管理器中的第一个作业。
/// 从该作业中获取与之关联的独立作业。
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void Form1_Load(object sender, EventArgs e)
        {
            myJobManager = CogSerializer.LoadObjectFromFile(Environment.GetEnvironmentVariable("VPRO_ROOT")+"\\Samples\\Programming\\QuickBuild\\advancedAppOne.vpp") as CogJobManager;

            myJob = myJobManager.Job(0);
            myIndependentJob = myJob.OwnedIndependent;

            //确保队列为空:
            //在加载一个 VisionPro 持久化文件时,需要确保所有队列都是空的。这是因为加载的过程会精确地重建保存时的对象状态。如果在加载过程中队列中仍然保留着未处理的数据,这可能会导致不一致或错误的行为。
            //冲洗队列:
            //“冲洗所有队列”意味着清空所有待处理的数据,以确保系统在加载新的作业或状态时处于一个干净的状态。这种做法是为了避免在处理新数据时与旧数据发生冲突,从而确保系统的稳定性和可靠性。
            myJobManager.UserQueueFlush();
            myJobManager.FailureQueueFlush();
            myJob.ImageQueueFlush();
            myIndependentJob.RealTimeQueueFlush();
        }
6. 关闭

QuickBuild 应用程序的 CogJobManager 对象在运行时会创建多个线程。关闭 CogJobManager 是非常重要的。

当窗体关闭时,将调用 Form1_FormClosing 方法。

private void Form1_FormClosing(object sender, FormClosingEventArgs e)
        {            
            myJobManager.Shutdown();
        }

2. 添加GUI并使用线程

1. 创建一次运行按钮

您将添加的第一个用户界面元素是运行已保存的QuickBuild应用程序的按钮。在Visual Studio工具箱中,将“按钮”从“公共控件”部分拖到Form1。将此按钮命名为RunOnceButton并将其文本设置为Run一次。

双击按钮以创建其Click处理程序,然后键入以下代码:

private void RunOnceButton_Click(object sender, EventArgs e)
        {
            try
            {
                
                myJobManager.Run();
            }
            catch (Exception ex)
            {

                MessageBox.Show(ex.Message);
            }
        }

Run方法在myJobManager中运行所有作业,其中包含已保存的QuickBuild应用程序。按钮的Click处理程序在Try / Catch块内调用Run,以处理QuickBuild应用程序开始运行时可能发生的任何错误。

立即运行程序,然后单击“运行一次”按钮以运行应用程序。(由于此时您未显示任何输出,因此您将看不到任何内容。)尝试尽快重复单击RunOnce按钮。您应该收到一条错误消息。

2. 处理作业事件

快速单击“运行一次”按钮时出现错误的原因是“运行”是立即返回的异步方法。如果在作业运行时再次调用它。您会收到CogNotStoppedException错误。

为避免此问题,您将在作业运行时禁用“运行一次”按钮,并在作业停止时重新启用它。在作业开始时禁用按钮非常容易。您所需要做的就是禁用其Click处理程序中的按钮:

private void RunOnceButton_Click(object sender, EventArgs e)
        {
            try
            {
                RunOnceButton.Enabled = false;
                
                myJobManager.Run();
            }
            catch (Exception ex)
            {

                MessageBox.Show(ex.Message);
            }
        }

在作业停止运行时重新启用按钮会稍微复杂一些。当作业管理器中的所有作业均已完成运行时,CogJobManager会触发Stopped事件。您将把代码重新放入作业管理器的Stopped事件处理程序中的按钮。

在Form1类的末尾,为作业管理器编写Stopped处理程序,如下所示:

private void MyJobManager_Stopped(object sender, CogJobManagerActionEventArgs e)
        {
           
            RunOnceButton.Enabled = true;
            
        }

定义了Stopped事件处理程序后,需要确保作业管理器知道它在哪里。使用AddHandler注册事件的处理程序。AddHandler的第一个参数是事件;第二个参数是处理程序的地址。将以下代码添加到Form1_Load方法的末尾:

 //注册停止事件
            myJobManager.Stopped += MyJobManager_Stopped;

每当您注册事件处理程序时,最好在关闭程序之前将其删除。在此示例中,执行此操作的最佳位置是在关闭作业管理器之前的窗体的FormClosing处理程序中。现在,FormClosing处理程序应如下所示:

 private void Form1_FormClosing(object sender, FormClosingEventArgs e)
        {
            myJobManager.Stopped -= MyJobManager_Stopped;
           
            myJobManager.Shutdown();

        }

如果此时运行程序,则会出现错误:跨线程操作无效。

3.处理跨线程函数调用

请记住,作业管理器会创建多个线程。这些线程之一触发运行已停止事件处理程序的Stopped事件,并最终尝试重新启用“运行一次”按钮。此事件序列是非法的,因为按钮-或任何其他Microsoft Windows Forms控件-只能由创建该控件的线程访问。该按钮不是由任何作业管理器线程创建的。

Microsoft提供了一种对控件进行线程安全调用的方法。

注意:您可以在此MDSN文章中了解有关进行线程安全调用的更多信息。

每个控件都有一个InvokeRequired属性,如果正在从未创建控件的线程中调用它,则该属性返回True。如果为True,则必须创建一个指向将访问该控件的函数的指针,切换到创建该控件的线程,然后使用该指针再次调用该函数。

在.NET中,指向函数的指针是委托。您将声明一个与您要处理的事件具有相同功能签名(参数)的委托。在这种情况下,您的委托人具有与Stopped事件相同的签名。在Stopped事件处理程序之前添加以下代码行:

private delegate void myJobManagerDelegate(object sender,CogJobManagerActionEventArgs e);

现在,在Stopped事件处理程序中,您将检查是否从错误的线程调用了该处理程序。如果是这样,则将使用定义的委托创建指向处理程序的指针,然后使用Invoke方法以递归方式调用它。这是Stopped事件处理程序的外观:

 private void MyJobManager_Stopped(object sender, CogJobManagerActionEventArgs e)
        {
            if (this.InvokeRequired)
            {
                this.Invoke(new myJobManagerDelegate(MyJobManager_Stopped),new object[] { sender,e});
                return;
            }
            RunOnceButton.Enabled = true;
            
        }

3. 增强GUI并显示结果

1. 添加连续运行按钮

您将添加的下一个用户界面元素是“运行连续”按钮。当您单击此按钮时,它将保持按下状态,并且该应用程序将运行,直到再次单击该按钮。若要获得此行为,本示例使用一个复选框并将其外观更改为按钮。

确保Form1.cs [设计]选项卡处于活动状态。从Visual Studio工具箱的“公共控件”部分中,将一个CheckBox控件拖到窗体上。将其文本更改为“连续运行”。将其名称更改为RunContCheckBox。最后,将其外观更改为Button。

双击新的“连续运行”按钮以创建其Check_Changed处理程序,并添加以下代码:

private void RunContentCheckBox_CheckedChanged(object sender, EventArgs e)
        {
            if (RunContentCheckBox.Checked)
            {
                try
                {
                    
                    myJobManager.RunContinuous();
                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.Message);
                }
            }
            else
            {
                try
                {
                    
                    myJobManager.Stop();
                }
                catch (Exception ex)
                {

                    MessageBox.Show(ex.Message);
                }
            }
            
        }

RunContinuous方法重复运行myJobManager中的所有作业,该作业包含您保存的QuickBuild应用程序,直到Stop停止它们为止。CheckedChanged处理程序负责在作业开始时禁用“运行一次”按钮,并在等待作业停止时禁用“连续运行”按钮。

将以下代码行添加到“已停止”处理程序中,以在所有作业停止后重新启用“连续运行”按钮。

 private void MyJobManager_Stopped(object sender, CogJobManagerActionEventArgs e)
        {
            if (this.InvokeRequired)
            {
                this.Invoke(new myJobManagerDelegate(MyJobManager_Stopped),new object[] { sender,e});
                return;
            }
            RunOnceButton.Enabled = true;
            RunContentCheckBox.Enabled = true;
        }

并将以下代码行添加到“运行一次”按钮的单击处理程序,以在作业运行一次时禁用“连续运行”按钮。

RunContentCheckBox.Enabled = false;

如果此时运行程序,则会在适当的时间看到按钮变为启用和禁用状态。您也可以单击窗口的关闭框以退出应用程序,即使该应用程序正在运行。

2. 显示程序结果

当用户队列中有新结果可用时,作业管理器将触发UserResultAvailable事件。在那儿,您将从工作中提取数据并将其显示在表单中。

确保Form1.cs [设计]选项卡处于活动状态。从Visual Studio工具箱的“公共控件”部分中,将一个TextBox拖到您的窗体上。将其名称更改为RunStatusTextBox。在这里您将显示应用程序的运行状态。

在Form1类的末尾,添加以下UserResultAvailable事件处理程序。请注意,由于它修改了用户界面项(文本框),因此您需要使用之前学习的Invoke习惯用法。

 private void MyJobManager_UserResultAvailable(object sender, CogJobManagerActionEventArgs e)
        {
            if (this.InvokeRequired)
            {
                this.Invoke(new myJobManagerDelegate(MyJobManager_UserResultAvailable), new object[] { sender, e });
                return;
            }
            ICogRecord topRecord = myJobManager.UserResult();
            RunStatusTextBox.Text = topRecord.SubRecords["UserResultTag"].Content + ":" + topRecord.SubRecords["JobName"].Content + "-->" + topRecord.SubRecords["RunStatus"].Content.ToString();

           
        }

UserResult方法从作业管理器的用户队列中删除并返回最早的结果记录。该记录包含“已发布项目”列表中每个项目的子记录。它还包含这些其他子记录:

UserResultTag

作业运行的序列号
职位名称

返回结果的作业的名称
运行状态

作业的RunStatus

在运行程序之前,您需要在窗体的Load处理程序中注册UserResultsAvailable处理程序,然后在其FormClosing处理程序中注销它。现在,Load处理程序应如下所示:

private void Form1_Load(object sender, EventArgs e)
        {
            myJobManager = CogSerializer.LoadObjectFromFile(Environment.GetEnvironmentVariable("VPRO_ROOT")+"\\Samples\\Programming\\QuickBuild\\advancedAppOne.vpp") as CogJobManager;

            myJob = myJobManager.Job(0);
            myIndependentJob = myJob.OwnedIndependent;

            //确保队列为空:
            //在加载一个 VisionPro 持久化文件时,需要确保所有队列都是空的。这是因为加载的过程会精确地重建保存时的对象状态。如果在加载过程中队列中仍然保留着未处理的数据,这可能会导致不一致或错误的行为。
            //冲洗队列:
            //“冲洗所有队列”意味着清空所有待处理的数据,以确保系统在加载新的作业或状态时处于一个干净的状态。这种做法是为了避免在处理新数据时与旧数据发生冲突,从而确保系统的稳定性和可靠性。
            myJobManager.UserQueueFlush();
            myJobManager.FailureQueueFlush();
            myJob.ImageQueueFlush();
            myIndependentJob.RealTimeQueueFlush();

            //注册停止事件
            myJobManager.Stopped += MyJobManager_Stopped;
            myJobManager.UserResultAvailable += MyJobManager_UserResultAvailable;

            


        }

FormClosing处理程序如下所示:

//取消注册与 myJobManager 相关的事件处理程序,以避免在窗体关闭后接收事件。
        //调用 Application.DoEvents() 来处理任何挂起的消息,确保在执行后续操作(如关闭作业管理器)时,应用程序不会冻结。
        //调用 myJobManager.Shutdown() 方法以正确清理资源和停止后台任务。
        //使用 DoEvents() 可以确保在执行 Shutdown 操作之前,所有与用户界面相关的事件都得到处理,从而提高用户体验。尽管 DoEvents() 在某些情况下有其用途,但在大多数情况下,过度使用可能会导致复杂性增加,因此应谨慎使用。
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void Form1_FormClosing(object sender, FormClosingEventArgs e)
        {
            myJobManager.Stopped -= MyJobManager_Stopped;
            myJobManager.UserResultAvailable -= MyJobManager_UserResultAvailable;
            Application.DoEvents();
            myJobManager.Shutdown();

           
        }

除了删除UserResultAvailable处理程序外,FormClosing方法还调用Application.DoEvents()来清除Windows消息队列。它可以防止在单击表单的关闭框之后但未注册UserResultAvailable处理程序之前,如果有新的用户结果可用,则可能发生死锁。

3. 运行应用程序

运行应用程序时,您将在文本框中看到结果。在下一步中,您将在应用程序中添加一个显示。

4. 显示图像

  • 使用显示控件显示结果记录
  • 访问适当的记录以显示
  • 将显示状态栏连接到显示器
1. 显示控件概述

VisionPro提供了四种显示控件,可用于显示图像和图形。

显示控制描述
CogToolDisplay这是您在QuickBuild和视觉工具中看到的显示控件。您可以将VisionPro工具连接到显示控件,并直接从该工具提取记录。它使用下拉列表选择要显示的图像记录。
CogRecordsDisplay此控件类似于CogToolDisplay控件。它使用户可以从下拉列表中选择图像记录,并显示图像的任何图形子记录。与CogToolDisplay不同,此控件对VisionPro工具一无所知。您必须提供要显示的记录。
CogRecordDisplay该控件显示单个图像记录及其图形子记录。它没有下拉列表框,并且不允许用户选择图像。
CogDisplay这是所有其他显示控件用作基础的最低级别的显示控件。此控件显示单个图像和一组图形,这些图形必须直接提供给该控件。

在此示例中,您将使用CogRecordDisplay控件显示LastRun.CogFixtureTool1.OutputImage记录,其中包含括号的图像以及显示孔之间距离的图形。

添加对以下程序集的引用:

  • Cognex.VisionPro.Controls
  • Cognex.VisionPro.Display.Controls

确保Form1.cs [设计]选项卡处于活动状态。从Visual Studio工具箱的VisionPro显示控件部分中,将CogRecordDisplay控件拖到窗体上。

注意:如果在工具箱中看不到CogRecordDisplay,请在工具箱中单击鼠标右键,然后选择“选择项目”。在出现的“选择工具箱项”对话框中,向下滚动直到找到CogRecordDisplay并确保已选中该复选框。

在FormClosing方法的末尾,添加以下代码以在应用程序关闭时处置控件:

private void Form1_FormClosing(object sender, FormClosingEventArgs e)
        {
            myJobManager.Stopped -= MyJobManager_Stopped;
            myJobManager.UserResultAvailable -= MyJobManager_UserResultAvailable;
            Application.DoEvents();
            myJobManager.Shutdown();

            cogDisplayStatusBarV21.Dispose();
            cogRecordDisplay1.Dispose();
        }

然后在Load方法的末尾添加以下代码,以将显示状态栏与显示器链接起来。

private void Form1_Load(object sender, EventArgs e)
        {
            myJobManager = CogSerializer.LoadObjectFromFile(Environment.GetEnvironmentVariable("VPRO_ROOT")+"\\Samples\\Programming\\QuickBuild\\advancedAppOne.vpp") as CogJobManager;

            myJob = myJobManager.Job(0);
            myIndependentJob = myJob.OwnedIndependent;

            //确保队列为空:
            //在加载一个 VisionPro 持久化文件时,需要确保所有队列都是空的。这是因为加载的过程会精确地重建保存时的对象状态。如果在加载过程中队列中仍然保留着未处理的数据,这可能会导致不一致或错误的行为。
            //冲洗队列:
            //“冲洗所有队列”意味着清空所有待处理的数据,以确保系统在加载新的作业或状态时处于一个干净的状态。这种做法是为了避免在处理新数据时与旧数据发生冲突,从而确保系统的稳定性和可靠性。
            myJobManager.UserQueueFlush();
            myJobManager.FailureQueueFlush();
            myJob.ImageQueueFlush();
            myIndependentJob.RealTimeQueueFlush();

            //注册停止事件
            myJobManager.Stopped += MyJobManager_Stopped;
            myJobManager.UserResultAvailable += MyJobManager_UserResultAvailable;

            cogDisplayStatusBarV21.Display = cogRecordDisplay1;


        }

获取记录以显示在CogRecordDisplay控件中的代码位于UserResultAvailable处理程序的末尾:

private void MyJobManager_UserResultAvailable(object sender, CogJobManagerActionEventArgs e)
        {
            if (this.InvokeRequired)
            {
                this.Invoke(new myJobManagerDelegate(MyJobManager_UserResultAvailable), new object[] { sender, e });
                return;
            }
            ICogRecord topRecord = myJobManager.UserResult();
            RunStatusTextBox.Text = topRecord.SubRecords["UserResultTag"].Content + ":" + topRecord.SubRecords["JobName"].Content + "-->" + topRecord.SubRecords["RunStatus"].Content.ToString();

            ICogRecord tmpRecord = topRecord.SubRecords["ShowLastRunRecordForUserQueue"];
            tmpRecord = tmpRecord.SubRecords["LastRun"];
            tmpRecord = tmpRecord.SubRecords["CogFixtureTool1.OutputImage"];
            cogRecordDisplay1.Record = tmpRecord;
            cogRecordDisplay1.Fit(true);
        }

对SubRecords的连续调用遵循子记录路径,以获取QuickBuild应用程序的Fixture工具的输出图像。Record属性指定要显示的记录。Fit方法缩放图像及其图形以适合显示控件。

界面设计如下:

在这里插入图片描述

如果立即运行该程序,您将看到CogRecordDisplay控件中显示的每个图像。

在这里插入图片描述

在这里插入图片描述

  • 11
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: VisionPro是一款视觉系统开发平台,提供了丰富的工具和功能,用于图像处理和分析。VisionPro二次开发是指在VisionPro的基础上进行个性化定制和扩展,以满足特定应用需求。 VisionPro二次开发可以通过编写自定义的算法和脚本来实现。用户可以使用VisionPro提供的算法库和API,根据自己的需求进行算法的扩展和修改,以达到更好的图像处理效果。 此外,VisionPro还提供了友好的界面和工具,可以通过拖拽、配置等方式,快速定制图像处理的流程。用户可以根据自己的需求,选择合适的工具和参数配置,来完成特定的图像处理任务。 VisionPro二次开发也涉及到与其他系统的集成。用户可以通过编写插件或接口,将VisionPro与其他设备或软件进行连接,实现数据的共享和交互。通过与其他系统的集成,可以扩展VisionPro的应用范围,提高系统的整体效能。 总之,VisionPro二次开发是一项在原来基础上进行个性化定制和扩展的工作,通过算法的扩展、界面的定制以及与其他系统的集成,来实现更灵活、更高效的图像处理和分析功能。 ### 回答2: VisionPro是一款先进的机器视觉软件,广泛用于工业自动化领域。visionpro二次开发是指在VisionPro软件基础上进行二次开发,根据实际需求进行定制化的开发工作。 VisionPro二次开发的目的是为了满足特定的需求或解决特定的问题。通过二次开发,可以添加新的图像处理算法、优化现有的功能、增加用户界面、集成外部设备或应用程序等。这样可以提高VisionPro的适用性和灵活性,使其更好地适应各种不同的应用场景。 在进行VisionPro二次开发时,首先需要了解和熟悉VisionPro的基本功能和特性。然后根据需要,进行软件开发、算法设计、界面设计等工作。开发完成后,还需要进行测试和调试,确保开发的功能符合要求并且可以稳定运行。 VisionPro二次开发的好处是可以根据实际需求进行定制化开发,使其更好地适应特定的应用场景。这样可以提高生产效率、降低生产成本,并且提供更好的产品质量控制。此外,VisionPro二次开发还可以提供更多的功能和选择,提高系统的灵活性和扩展性。 总之,VisionPro二次开发是一项重要的工作,可以定制化开发机器视觉应用程序,提高生产效率和质量控制的能力。这需要专业的技术团队和广泛的行业经验,以确保开发的软件能够满足实际需求并可靠运行。 ### 回答3: VisionPro是一款强大的图像处理软件,可用于实现机器视觉应用。VisionPro二次开发是指在基础软件上进行定制开发,以满足特定的应用需求。 VisionPro二次开发可以通过以下几个步骤实施: 首先,需要对应用需求进行详细的调研和分析。了解客户的具体需求,明确所需实现的功能和目标。 其次,根据需求分析的结果,制定开发方案和计划。确定所需功能的开发方式和技术手段,以及开发的时间和资源投入。 接下来,进行软件定制开发。根据方案和计划,对VisionPro软件进行二次开发。根据具体的需求,可以通过编写脚本、开发插件或接口等方式,实现所需的功能扩展或定制。 在开发过程中,需要对功能进行测试和调试,确保软件的稳定性和可靠性。可以利用模拟数据或实际图像数据进行测试,对开发的功能进行验证和优化。 最后,进行部署和应用集成。将二次开发VisionPro应用集成到实际的生产环境中,与其他设备或系统进行连接和交互。并对系统进行使用培训,使用户能够熟练操作和维护该应用。 VisionPro二次开发的好处在于可以根据需求进行定制开发,满足特定的应用场景和功能要求。通过二次开发,可以扩展和增强VisionPro的功能,提高图像处理的精确度和效率。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值