一、前期创建工程和设计UI界面
三个Button按钮以及一个从halcon导入的窗口。
二、实现思路及代码
1.首先要获得相机句柄,这里要打开halcon软件去获取当前使用的相机参数,例如下图可供参考
open_framegrabber ('GigEVision2', 0, 0, 0, 0, 0, 0, 'progressive', -1, 'default', -1, 'false', 'default', 'QT1-023-A-CAM2', 0, -1, AcqHandle)
我们想要打开相机,就需要将这句Halcon软件中的语句转化为C#语句,来获取相机的打开。
具体代码如下:
HOperatorSet.OpenFramegrabber("GigEVision2", 0, 0, 0, 0, 0, 0, "progressive", -1, "default", -1, "false", "default", "QT1-023-A-CAM2", 0, -1,out AcqHandle);
因为在语句的最后,我们要注意语法规则,自己去定义窗口输出的名称,并且在其前面加上“out”字符。
2.在获得相机的打开后,我们要能进行获取图像的操作。我们继续观察刚才Halcon中的语句,发现这个语句所执行的功能正是抓取图像。因此我们在第二个按钮,可以转化下面的C#语句
HOperatorSet.GrabImageAsync(out ImageA, AcqHandle, -1);
注意,ImageA是输出的结果,即相机所抓取图像的变量名。
在抓取后,我们需要将图片与窗口进行匹配,因此我们需要添加以下代码让抓取的图片可以展示在窗口。
HTuple width, height;
HOperatorSet.GetImageSize(ImageA, out width, out height);
HOperatorSet.SetPart(hWindowControl1.HalconWindow, 0, 0, width - 1, height - 1);
HOperatorSet.DispObj(ImageA, hWindowControl1.HalconWindow);
第三行中,width-1,height-1是为了让图片可以平铺在窗口。如果不了解的朋友,可以去试一下别的或者搜索相关内容。
3.当我们抓取完图片后,应当写入关闭相机的代码,因此我们在第三个按钮中添加以下代码来实现相关功能。
HOperatorSet.CloseFramegrabber(AcqHandle);
4.当我们完成前三步操作后,发现虽然可以实现相机的打开,抓取图片以及关闭。但无法实现连续的操作,因此,我们需要添加简单的多线程,来使得我们的相机可以多次使用。除此之外,我们也要考虑一定的防呆功能,减少功能的错误操作。下面是完整代码:
using HalconDotNet;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace _20240822_class
{
public partial class Form2 : Form
{
public Form2()
{
InitializeComponent();
button2.Enabled = false;
button_closeAcqHandle.Enabled = false;
}
HTuple AcqHandle;
Thread GrabRun;
private void button1_Click(object sender, EventArgs e)
{
button2.Enabled = true;
/// <summary>
/// 相机句柄
/// </summary>
HOperatorSet.OpenFramegrabber("GigEVision2", 0, 0, 0, 0, 0, 0, "progressive", -1, "default", -1, "false", "default", "QT1-023-A-CAM2", 0, -1,out AcqHandle);
}
private void Run()
{
while (! isStop)
{
HOperatorSet.GrabImageAsync(out ImageA, AcqHandle, -1);
HTuple width, height;
HOperatorSet.GetImageSize(ImageA, out width, out height);
HOperatorSet.SetPart(hWindowControl1.HalconWindow, 0, 0, width - 1, height - 1);
HOperatorSet.DispObj(ImageA, hWindowControl1.HalconWindow);
}
}
HObject ImageA;
private void button2_Click(object sender, EventArgs e)
{
button_closeAcqHandle.Enabled = true;
isStop = false;
GrabRun = new Thread(Run);
GrabRun.Start();
}
bool isStop=false;
private void button_closeAcqHandle_Click(object sender, EventArgs e)
{
isStop=true;
GrabRun.Abort();
GrabRun = null;
HOperatorSet.CloseFramegrabber(AcqHandle);
button2.Enabled = false;
button_closeAcqHandle.Enabled = false;
}
}
}
首先,将照片的展示功能封装到一个Run函数方法中,可以简化别的按钮中的代码行数,起到简洁化和模块化。其次,通过设置GrabRun这个变量,其属性便是多线程,通过调用它来实现多线程。为了减少错误操作,当我们第一次启动时,只能点击获取相机按钮。当“获取相机”的代码运行完后,在启用“抓取图片”的功能按钮,同时“获取相机”按钮关闭。同理下一个“关闭按钮”。