基于halcon实现视觉定位框架(C#做主算法,C#、MFC、Qt二次开发)【附源码】

这篇具有很好参考价值的文章主要介绍了基于halcon实现视觉定位框架(C#做主算法,C#、MFC、Qt二次开发)【附源码】。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。


前言

本文主要实现halcon二次开发,基于C#做视觉算法的编辑,已C#做用户空间,然后使用C#、C++(MFC、Qt)分别实现调用,从而实现多相机的使用。
换句话说就是:C#做算法及主界面开发,然后把生成的控件dll移交给C#或者MFC或者QT进行二次调用实现二次开发,这里主要想展示的是多语言之间的调用以及如何跨语言调用控件算法
编程环境:C# .net4.0
MFC
qt5.3
halcon12.0
IDE: VisualStudio 2010
备注:版本都基本不重要,本人测试过用VisualStudio2019 halcon20.05 .net4.7 qt5.15等版本测试过无问题


演示视频

本次项目的效果视频:

Halcon多相机模板匹配,多语言调用


一、项目文件目录讲解

halcon实现),机器视觉-halcon,c#,c++,计算机视觉,视觉检测,开发语言
本工程主要有4个项目:
1、CtuVisionControlLibrary:这里是最基本最终的算法部分,使用C#语言编写,用C#做一个用户控件
2、CtuVisionDLLTest_CSharp:使用C#做主软件的界面,调用上边项目的CtuVisionControlLibrary.dll,可实现多相机的使用
3、CtuVisionDLLTest_MFC:使用C++版的MFC框架做主软件的界面,,调用上边项目的CtuVisionControlLibrary.dll,可实现多相机的使用
4、CtuVisionDLLTest_QT:使用C++版的QT框架做主软件的界面,,调用上边项目的CtuVisionControlLibrary.dll,可实现多相机的使用


1.CtuVisionControlLibrary

halcon实现),机器视觉-halcon,c#,c++,计算机视觉,视觉检测,开发语言
这里是主体框架的目录,其中包括三个类窗体,分别是:
Calibration:标定窗体和算法
Camera:相机设置的主界面
CtuVisionControlLibrary:算法主界面(这里边还需要把C++接口暴露出去)

2.CtuVisionDLLTest_CSharp

halcon实现),机器视觉-halcon,c#,c++,计算机视觉,视觉检测,开发语言
这里的框架内容比较简单,因为主算法在CtuVisionControlLibrary.dll里边,这里可以理解为是基于CtuVisionControlLibrary.dll的二次开发

2.CtuVisionDLLTest_MFC

halcon实现),机器视觉-halcon,c#,c++,计算机视觉,视觉检测,开发语言
这里的框架内容比较简单,因为主算法在CtuVisionControlLibrary.dll里边,这里可以理解为是基于CtuVisionControlLibrary.dll的二次开发,这里主要是MFC对话框,想了解MFC单文档的视觉定位可看我之前写的一篇博客。

2.CtuVisionDLLTest_QT

halcon实现),机器视觉-halcon,c#,c++,计算机视觉,视觉检测,开发语言
这里的框架内容比较简单,因为主算法在CtuVisionControlLibrary.dll里边,这里可以理解为是基于CtuVisionControlLibrary.dll的二次开发,这里主要是MFC对话框,想了解MFC单文档的视觉定位可看我之前写的一篇博客。


二、CtuVisionControlLibrary界面设置

先上图,只需要按照这个来设置即可:

1.CtuVisionControlLibrary.cs主窗体页面

halcon实现),机器视觉-halcon,c#,c++,计算机视觉,视觉检测,开发语言
halcon实现),机器视觉-halcon,c#,c++,计算机视觉,视觉检测,开发语言
halcon实现),机器视觉-halcon,c#,c++,计算机视觉,视觉检测,开发语言
halcon实现),机器视觉-halcon,c#,c++,计算机视觉,视觉检测,开发语言
halcon实现),机器视觉-halcon,c#,c++,计算机视觉,视觉检测,开发语言
halcon实现),机器视觉-halcon,c#,c++,计算机视觉,视觉检测,开发语言

2.Camera.cs主窗体页面

halcon实现),机器视觉-halcon,c#,c++,计算机视觉,视觉检测,开发语言

3.Calibration.cs主窗体页面

halcon实现),机器视觉-halcon,c#,c++,计算机视觉,视觉检测,开发语言


三、调用CtuVisionControlLibrary.dll框架的二次开发页面

1.CtuVisionDLLTest_CSharp主窗体页面

C#界面仅仅做一个label窗体,后续代码引入dll写入控件
halcon实现),机器视觉-halcon,c#,c++,计算机视觉,视觉检测,开发语言

2.CtuVisionDLLTest_CSharp主窗体页面

MFC窗体不需要设置其他,只需要以及个页面即可,后续只需要代码写入位置和大小即可
halcon实现),机器视觉-halcon,c#,c++,计算机视觉,视觉检测,开发语言

3.CtuVisionDLLTest_QT主窗体页面

QT窗体不需要设置其他,只需要给定一个QLabel即可,后续直接把dll控件引入到label中即可
halcon实现),机器视觉-halcon,c#,c++,计算机视觉,视觉检测,开发语言


四、CtuVisionControlLibrary项目解析

这里主要讲解主算法窗体项目的代码解析

1.Camera相机设置算法配置

1.定义基本的类变量

首先定义一系列类变量

bool GetPictureFlag = false;
bool ColorZoneFlag = false;
bool ROIFlag = false;
bool TenFlag = false;
public HTuple hv_AcqHandle;
HWindow HalconWindow;
string CameraType;
string CamreaName;
HObject ho_Image;
HTuple ho_Width, ho_Hight, hvRoi_width, hvRoi_hight;
private readonly object locker1 = new object();
private readonly object locker2 = new object();
public bool ConnectCameraFlag = false;

2.设置窗体关闭时只是隐藏而不是真的关闭

在窗体自带的事件xxx_Close()函数中设置:

private void Camera_FormClosing(object sender, FormClosingEventArgs e)
{
    this.Hide();
    e.Cancel = true;
}

3.搜索相机

这里是搜索相机功能,主要是DirectShow、Gige接口的相机

private void button3_Click(object sender, EventArgs e)
{
      comboBox1.Items.Clear();
      HTuple hv_Information = null, hv_ValueList = null;
      HTuple hv_Length = null;
      string[] deviceNames = { "GigEVision", "DirectShow", "GenICamTL" };

      foreach (string names in deviceNames)
      {
          try
          {
              HOperatorSet.InfoFramegrabber(names, "device", out hv_Information, out hv_ValueList);  // 获取设备信息  放到hv_ValueList
              HOperatorSet.TupleLength(hv_ValueList, out hv_Length);  //TupleLength获取元组的元素的数目 即元组长度
              int length1 = Convert.ToInt32(hv_Length.ToString());

              for (int i = 0; i < length1; i++)
              {
                  string strDevice = hv_ValueList[i].S;
                  if (strDevice.Equals("default"))
                  {
                      break;
                  }
                  strDevice = names + ":" + strDevice;
                  comboBox1.Items.Add(strDevice);
              }
          }
          catch //(System.Exception ex)
          {
          }
      }
      if (comboBox1.Items.Count > 0)
          comboBox1.SelectedIndex = 0;
  }

4.连接相机

根据搜索相机的一些配置参数连接相机

private void OpenCamrea()
{
    HTuple Information, ValueList;
    string ColorZone = "";
    HalconWindow = hWindowControl1.HalconWindow;
    HalconWindow.SetColor("red");
    string selctCam = comboBox1.SelectedItem.ToString();
    int StrSplit = selctCam.IndexOf(":");
    CameraType = selctCam.Substring(0, StrSplit);
    CamreaName = selctCam.Substring(StrSplit + 1).TrimEnd();

    if (comboBox2.Items.Count <= 0)
    {
        if (CameraType == "DirectShow")
        {
            ColorZone = "gray";
        }
        else if (CameraType == "GigEVision" || CameraType == "GenICamTL")
        {
            ColorZone = "default";
        }
    }
    else
    {
        ColorZone = comboBox2.Text;
    }
    try
    {
        HOperatorSet.InfoFramegrabber(CameraType, "defaults", out Information, out ValueList);
        HOperatorSet.OpenFramegrabber(CameraType, ValueList[0], ValueList[1], ValueList[2], ValueList[3], ValueList[4], ValueList[5], ValueList[6], ValueList[7], ColorZone, ValueList[9], ValueList[10], ValueList[11], CamreaName, 0, ValueList[13], out hv_AcqHandle);
        HOperatorSet.GrabImageStart(hv_AcqHandle, -1);
        HOperatorSet.GrabImageAsync(out ho_Image, hv_AcqHandle, -1);
        HOperatorSet.GetImageSize(ho_Image, out ho_Width, out ho_Hight);
        HalconWindow.SetPart(0, 0, ho_Hight - 1, ho_Width - 1);
        if (button5.Text == "取消ROI")
            button5_Click(null, null);
        GetCarmerInfo(CameraType);
        button1.Text = "断开";
        //trackBar1.Enabled = true;
        trackBar2.Enabled = true;
        button2.Enabled = true;
        ConnectCameraFlag = true;
    }
    catch
    {
        MessageBox.Show("相机连接失败");
        CloseCamera();
    }
}

5.断开相机

既然连接了相机,就有断开相机的说法

private void CloseCamera()
{
     if (button2.Text == "停止预览")
         button2_Click(null, null);
     checkBox2.Checked = false;
     TenFlag = false;
     GetPictureFlag = false;
     checkBox5.Enabled = false;
     trackBar1.Enabled = false;
     trackBar2.Enabled = false;
     Delay(500);
     button2.Enabled = false;
     button1.Text = "连接";
     ConnectCameraFlag = false;
     try
     {
         HOperatorSet.CloseFramegrabber(hv_AcqHandle);
         hv_AcqHandle = null;
     }
     catch { }
 }

6.连接相机后获取相机配置参数

此代码段必须在相机连接后调用获取

private void GetCarmerInfo(string CameraType)
{
    //像素格式
    try
    {
        HTuple hv_Value, hv_Length;
        HOperatorSet.GetFramegrabberParam(hv_AcqHandle, "PixelFormat", out hv_Value);
        HOperatorSet.TupleLength(hv_Value, out hv_Length);
        int length = (int)hv_Length[0];
        for (int i = 0; i < length; i++)
        {
            comboBox3.Items.Add(hv_Value[0].S);
        }
        if (length > 0)
        {
            comboBox3.SelectedIndex = 0;
        }
    }
    catch
    {

    }

    //颜色空间
    try
    {
        if (comboBox2.Items.Count <= 0)
        {
            HTuple Information, ValueList, hv_Length;
            HOperatorSet.InfoFramegrabber(CameraType, "color_space", out Information, out ValueList);

            HOperatorSet.TupleLength(ValueList, out hv_Length);
            int length = (int)hv_Length[0];
            for (int i = 0; i < length; i++)
            {
                comboBox2.Items.Add(ValueList[i].S);
            }
            if (comboBox2.Items.Count > 0)
            {
                ColorZoneFlag = true;
                comboBox2.SelectedIndex = 0;
            }
        }
    }
    catch
    {

    }

    //曝光时间
    try
    {
        HTuple hv_Value;
        //曝光时间
        if (CameraType == "DirectShow")
        {
            trackBar1.Minimum = -13;
            trackBar1.Maximum = -1;
            trackBar1.Value = -1;
            label5.Text = trackBar1.Value.ToString();
            checkBox5.Enabled = true;
            checkBox5.Checked = true;
            trackBar1.Enabled = false;
            HOperatorSet.SetFramegrabberParam(hv_AcqHandle, "exposure", "auto");
        }

        if (CameraType == "GigEVision")
        {
            HOperatorSet.GetFramegrabberParam(hv_AcqHandle, "ExposureTimeRaw", out hv_Value);    //shuoable
            int extime = Convert.ToInt32(hv_Value[0].D);
            trackBar1.Minimum = 0;
            trackBar1.Maximum = 4095;
            trackBar1.Value = extime;
            label5.Text = trackBar1.Value.ToString();
            trackBar1.Enabled = true;
            checkBox5.Checked = false;
            checkBox5.Enabled = false;
        }
    }
    catch
    {

    }

    //增益
    try
    {
        HTuple hv_Value;
        HOperatorSet.GetFramegrabberParam(hv_AcqHandle, "GainRaw", out hv_Value);
        int gain = Convert.ToInt32(hv_Value[0].D);
        trackBar2.Minimum = 8;
        trackBar2.Maximum = 63;
        trackBar2.Value = gain;
        label6.Text = trackBar2.Value.ToString();
        trackBar2.Enabled = true;
    }
    catch
    {

    }
}

7.修改相机参数

修改曝光时间

private void trackBar1_Scroll(object sender, EventArgs e)
{
    if (checkBox5.Checked == false)
    {
        string exposure = trackBar1.Value.ToString();
        label5.Text = exposure;
        try
        {
            if (CameraType == "DirectShow")
            {
                HOperatorSet.SetFramegrabberParam(hv_AcqHandle, "exposure", Convert.ToInt32(exposure));
            }
            if (CameraType == "GigEVision")
            {
                HOperatorSet.SetFramegrabberParam(hv_AcqHandle, "ExposureTimeRaw", Convert.ToInt32(exposure));
            }
        }
        catch
        {

        }
    }
}

修改增益

private void trackBar2_Scroll(object sender, EventArgs e)
{
    string gain = trackBar2.Value.ToString();
    label6.Text = gain;
    try
    {
        HOperatorSet.SetFramegrabberParam(hv_AcqHandle, "GainRaw", Convert.ToInt32(gain));
    }
    catch
    {

    }
}

设置白平衡

private void checkBox1_CheckedChanged(object sender, EventArgs e)
{
     if (checkBox1.Checked == true)
     {
         try
         {
             HOperatorSet.SetFramegrabberParam(hv_AcqHandle, "white_balance", "auto");
         }
         catch
         {

         }
     }
     else
     {
         //HTuple hv_Value;
         //HOperatorSet.GetFramegrabberParam(hv_AcqHandle, "white_balance", out hv_Value);
         //HOperatorSet.SetFramegrabberParam(hv_AcqHandle, "white_balance", Convert.ToInt32(hv_Value.D));
     }
 }

8.线程显示照片,这里使用锁的方式

private void GetImage()
{
     while (GetPictureFlag)
     {
         try
         {
             lock (locker2)
             {
                 ho_Image.Dispose();    //释放
                 HOperatorSet.GrabImageAsync(out ho_Image, hv_AcqHandle, -1);
                 HalconWindow.DispObj(ho_Image);
                 Thread.Sleep(50);
             }
         }
         catch
         {

         }
     }
 }

2.Calibration标定坐标系算法配置

1.标定算法

这里可多点标定,在界面上设置即可,需要三点以上标定

private void AffineTran(int Affine_Num)
{
    HTuple concat = new HTuple(), concat1 = new HTuple(), concat2 = new HTuple(), concat3 = new HTuple();
    try
    {
        concat = concat.TupleConcat(VectorHam2D[Affine_Num].img_x1);
        concat1 = concat1.TupleConcat(VectorHam2D[Affine_Num].img_y1);
        concat2 = concat2.TupleConcat(VectorHam2D[Affine_Num].tar_x1);
        concat3 = concat3.TupleConcat(VectorHam2D[Affine_Num].tar_y1);

        concat = concat.TupleConcat(VectorHam2D[Affine_Num].img_x2);
        concat1 = concat1.TupleConcat(VectorHam2D[Affine_Num].img_y2);
        concat2 = concat2.TupleConcat(VectorHam2D[Affine_Num].tar_x2);
        concat3 = concat3.TupleConcat(VectorHam2D[Affine_Num].tar_y2);

        concat = concat.TupleConcat(VectorHam2D[Affine_Num].img_x3);
        concat1 = concat1.TupleConcat(VectorHam2D[Affine_Num].img_y3);
        concat2 = concat2.TupleConcat(VectorHam2D[Affine_Num].tar_x3);
        concat3 = concat3.TupleConcat(VectorHam2D[Affine_Num].tar_y3);
        RobotHommat[Affine_Num] = new HHomMat2D();
        RobotHommat[Affine_Num].VectorToHomMat2d(concat, concat1, concat2, concat3);
        VectorHam2D[Affine_Num].flag = true;
    }
    catch{}
}

2.调用标定数据

这里是标定数据的转换步骤

 public bool PixelToRobot(int Affine_Num, double img_x, double img_y, out double robot_x, out double robot_y)
{
    robot_x = robot_y = -1.0;
    if (VectorHam2D[Affine_Num].flag == true)
    {
        try
        {
            robot_x = RobotHommat[Affine_Num].AffineTransPoint2d(img_x, img_y, out robot_y);
            return true;
        }
        catch //(Exception e)
        {
            return false;
        }
    }
    return false;
}

3.CtuVisionControlLibrary主窗体算法配置

1.这里先配置主结构体,后续会用到的结构体

public struct VisionPoint
{
     public double x;
     public double y;
     public double r;
     public double score;
     public VisionPoint(double imgx, double imgy, double imgr, double s)
     {
         x = imgx;
         y = imgy;
         r = imgr;
         score = s;
     }
 }
 public struct CurrentControl
 {
     public int CurrentROIType;             //当前ROI的绘制方法
     public int CurrentRunROIType;          //当前ROI的运算方法
     public HObject H_CurrentROI;           //当前绘制的ROI
     public int TemplateAlgorithm;          //当前的模板算法
     public int CurrentModelNum;            //当前的模板编号
     public int Image_Width; 
     public int Image_Height;
     public CurrentControl(int a, int b, HObject c,int d,int e,int f,int g)
     {
         CurrentROIType = a;
         CurrentRunROIType = b;
         H_CurrentROI = c;
         TemplateAlgorithm = d;
         CurrentModelNum = e;
         Image_Width = f;
         Image_Height = g;
     }
 }
 public struct ModelCom
 {
     public bool EffectiveFlag;            //改模板是否有效 -
     public int modelNum;                  //模板号 -
     public int TemplateAlgorithm;         //匹配算法 -
     public HObject h_img;                 //创建模板的原图
     public HObject h_roi;                 //创建模板的ROI
     
     public int startAngle;             //起始角度 -
     public int endAngle;               //角度范围 -
     public int Level;                  //对比度 -
     public bool AutoContrast;          //自动对比度 -
     public int Score;               //匹配分数 -
     public int DeformationNum;         //允许变形 -
     public int MatchNum;               //期待匹配数,0代表全部匹配 -
     public HTuple hv_ModelID;          //模板ID
     public int FindModelTimeOut;       //模板匹配超时 -
     public HObject ShapeModelRegions;  //模板轮廓
     public HTuple hv_Orgin_Row;        //模板锚点的行 -
     public HTuple hv_Orgin_Column;     //模板锚点的列 -
     public HTuple hv_Orgin_Angle;      //模板锚点的角度 -
     public HTuple hv_Target_Row;       //锚点的行 -
     public HTuple hv_Target_Column;    //锚点的列 -
     public bool TargetFlag;            //设置锚点的标志 -
     public HObject h_SearchROI;        //搜索区域
     public bool SearchROIFlag;         //拥有搜索区域的标志 -
 }
 public struct BarCode
 {
     public HObject BarCodeROI;
     public bool BarCodeROIFlag;
     public HObject QRCodeROI;
     public bool QRCodeROIFlag;
     public HObject OCRROI;
     public bool OCRROIFlag;
 }

2.设置C++接口的函数

设置的c++接口代表外露的函数部分
Guid用IDE生成

public struct COPYDATASTRUCT
{
    public IntPtr dwData; //可以是任意值
    public int cbData;    //指定lpData内存区域的字节数
    [MarshalAs(UnmanagedType.LPStr)]
    public string lpData; //发送给目录窗口所在进程的数据
}
[InterfaceType(ComInterfaceType.InterfaceIsDual)]
[Guid("147C71DB-62EE-44D9-9D5D-0D8D78A7F093")]
public interface VisionLibrary
{
    void SetAdapterDllPtr(IntPtr i_AdapterDllPtr,int num);
    void StringTest(string str1, out string str2);
    void GetImage(out bool res);
    void FindModel(int ModelNum,out double x,out double y,out double angle);
    void AffineVector2Hom(int Num, double image_x, double image_y, out double robot_x, out double robot_y);
    void ReadBarCode(out string Code);
    void ReadQRCode(out string Code);
    void ReadOCRCode(out string Code);
}

3.在构造函数上方编写此段话

[ProgId("CtuVisionControlLibrary.VisionLibrary")]
[ClassInterface(ClassInterfaceType.None)]
[Guid("37518F8E-21C9-4F51-9777-EFAD6B76ED63")]
public partial class CtuVisionControlLibrary : UserControl, VisionLibrary
{
	xxxx
}

4.对C++外露函数进行实现

弄完此处基本C++接口配置完成

public void SetAdapterDllPtr(IntPtr i_AdapterDllPtr,int num)
{
    AdapterDllPtr = i_AdapterDllPtr;
    VisionNum = num;
    //初始化数据
    filePath = string.Format("./VisionModel{0}", VisionNum);
    if (!Directory.Exists(filePath))
    {
        Directory.CreateDirectory(filePath);
    }

   // HOperatorSet.SetSystem("clip_region", "fasle");
    ReadModel(0, MaxModelNum);
    ReadCodeROI();
    VisionCamera = new Camera();
    ctuPosition = new Calibration(filePath);
    HalconWindow = hWindowControl1.HalconWindow;
    HDevWindowStack.Push(HalconWindow);
    HOperatorSet.SetDraw(HDevWindowStack.GetActive(), "margin");

    updateModelComboBox(0);
    comboBox3.SelectedIndex = 0;
    comboBox4.SelectedIndex = 1;

}

public void StringTest(string str1, out string str2)
{
    str2 = str1;
    byte[] sarr = System.Text.Encoding.Default.GetBytes(str2);
    int len = sarr.Length;
    COPYDATASTRUCT cds;
    cds.dwData = (IntPtr)0;
    cds.cbData = len + 1;
    cds.lpData = str2;
    SendMessage(AdapterDllPtr.ToInt32(), DOT_NET_BUTTON_PRESSED, 0,ref cds);
}

public void GetImage(out bool res)
{
    if (VisionCamera.ConnectCameraFlag == true)
    {
        AcquisitionFlag = false;
        bool Res = VisionCamera.HDevImg(out ho_img);
        if (Res)         //采集单张图像成功
        {
            HOperatorSet.GetImageSize(ho_img, out ho_Width, out ho_Hight);
            MySetPart();
            //HalconWindow.SetPart(0, 0, ho_Hight - 1, ho_Width - 1);
            //hWindowControl1.ImagePart = new System.Drawing.Rectangle((int)0, (int)0, (int)ho_Width[0].I, (int)ho_Hight[0].I);
            MyCurrentControl.Image_Height = (int)ho_Hight[0].I;
            MyCurrentControl.Image_Width = (int)ho_Width[0].I;
            HalconWindow.DispObj(ho_img);
            res = true;
        }
        else
        {
            HalconWindow.ClearWindow();
            res = false;
        }
    }
    else
    {
        HalconWindow.ClearWindow();
        res = false;
    }
}

public void FindModel(int ModelNum, out double x, out double y, out double angle)
{
    if (ModelNum < 0 || ModelNum >= MaxModelNum)
    {
        x = y = angle = -1;
        return;
    }
    string mes = RunFindModel(ModelNum);
    string[] meslist = mes.Split(',');
    x = Convert.ToDouble(meslist[0]);
    y = Convert.ToDouble(meslist[1]);
    angle = Convert.ToDouble(meslist[2]);
    return;
}

public void AffineVector2Hom(int Num, double image_x, double image_y, out double robot_x, out double robot_y)
{
    int PositionDataNum = Calibration.PositionDataNum;
    if (Num < 0 || Num >= PositionDataNum)
    {
        robot_x = robot_y = -1;
        return;
    }
    ctuPosition.PixelToRobot(Num, image_x, image_y, out robot_x, out robot_y);
}

public void ReadBarCode(out string Code)
{
    Code = FindBarCode();
    if (Code != "-1")
    {
        toolStripStatusLabel1.Text = Code;
    }
    else
    {
        toolStripStatusLabel1.Text = "读码失败!";
    }
}

public void ReadQRCode(out string Code)
{
    Code = FindQRCode();
    if (Code != "-1")
    {
        toolStripStatusLabel1.Text = Code;
    }
    else
    {
        toolStripStatusLabel1.Text = "读码失败!";
    }
}

public void ReadOCRCode(out string Code)
{
    Code = ReadOCR();
    if (Code != "-1")
    {
        toolStripStatusLabel1.Text = Code;
    }
    else
    {
        toolStripStatusLabel1.Text = "读码失败!";
    }
}

5.开始具体的算法实现

先定义类变量

private Camera VisionCamera;
private Calibration ctuPosition;
HWindow HalconWindow;
HObject ho_img;          //图像用于显示(原图)
HTuple ho_Width, ho_Hight;     //原图的长宽
bool AcquisitionFlag = false;       //连续采集变量
private readonly object locker1 = new object();       //线程加锁
private bool ChangeImageFlag = false;     //图片缩放功能
private bool ShowTenFlag = false;    //显示十字线功能
private bool MouseDownFlag = false;   //移动的过程中是否按下
CurrentControl MyCurrentControl = new CurrentControl(0, 0, null, 0, 0, 0, 0);
private static int MaxModelNum = 40;
ModelCom[] MyModel = new ModelCom[MaxModelNum];
BarCode MyBarCode = new BarCode();
string filePath = "";
private static int EraserSize = 40;
HObject brush_region1 = new HObject();   //画笔:用于画区域
HObject brush_region2 = new HObject();   //画笔:用于擦除区域

6.打开图像

这里是打开图像的按钮功能

private void toolStripSplitButton2_ButtonClick(object sender, EventArgs e)
{
    string strFilePath = null;
    OpenFileDialog fd = new OpenFileDialog();
    fd.Filter = "All files(*.*)|*.*|图片(*.bmp)|*.bmp";
    if (fd.ShowDialog() != DialogResult.OK)
    {
        return;
    }
    strFilePath = fd.FileName;
    HOperatorSet.ReadImage(out ho_img, strFilePath);
    HOperatorSet.GetImageSize(ho_img, out ho_Width, out ho_Hight);
    MySetPart();
    //HalconWindow.SetPart(0, 0, ho_Hight - 1, ho_Width - 1);
    //hWindowControl1.ImagePart = new System.Drawing.Rectangle((int)0, (int)0, (int)ho_Width[0].I, (int)ho_Hight[0].I);
    MyCurrentControl.Image_Height = (int)ho_Hight[0].I;
    MyCurrentControl.Image_Width = (int)ho_Width[0].I;
    HalconWindow.DispObj(ho_img);
}

7.保存图像

这里是保存图像的按钮功能

private void 保存图像ToolStripMenuItem_Click(object sender, EventArgs e)
{
    if (ho_img == null)
        return;
    SaveFileDialog sfd = new SaveFileDialog();
    sfd.Filter = "图片(*.bmp)|*.bmp|图片(*.tif)|*.tif";
    sfd.FilterIndex = 1;
    sfd.RestoreDirectory = true;
    if (sfd.ShowDialog().ToString() == "OK")
    {
        string FILE_NAME = sfd.FileName.ToString();         //获得文件路径 
        string[] mes = FILE_NAME.Split('.');
        if (mes[mes.Length - 1] == "bmp" || mes[mes.Length - 1] == "tif")
        {
            if (mes[mes.Length - 1] == "bmp")
            {
                HOperatorSet.WriteImage(ho_img, "bmp", 0, FILE_NAME);
            }
            if (mes[mes.Length - 1] == "tif")
            {
                HOperatorSet.WriteImage(ho_img, "tif", 0, FILE_NAME);
            }
        }
    }
    
}

8.ROI绘制及运算规则设置

这里包括ROI绘制方式以及运算规则设置

private void toolStripSplitButton3_ButtonClick(object sender, EventArgs e)
{
    if (ho_img == null)
        return;
    HObject ROITemp = new HObject();
    HTuple hv_Row1 = null, hv_Column1 = null, hv_Row2 = null, hv_Column2 = null, hv_Phi1 = null, hv_Length1 = null, hv_Length2 = null, hv_Radius1 = null, hv_Radius2 = null, hv_Area = null;
    HOperatorSet.SetColor(HalconWindow, "red");
    toolStrip1.Enabled = false;
    switch (MyCurrentControl.CurrentROIType)
    {
        case 0:      //绘制矩形
            HOperatorSet.DrawRectangle1(HalconWindow, out hv_Row1, out hv_Column1, out hv_Row2, out hv_Column2);
            HOperatorSet.GenRectangle1(out ROITemp, hv_Row1, hv_Column1, hv_Row2, hv_Column2);
            break;
        case 1:      //绘制旋转矩形
            HOperatorSet.DrawRectangle2(HalconWindow, out hv_Row1, out hv_Column1, out hv_Phi1, out hv_Length1, out hv_Length2);
            HOperatorSet.GenRectangle2(out ROITemp, hv_Row1, hv_Column1, hv_Phi1, hv_Length1, hv_Length2);
            break;
        case 2:      //绘制圆形
            HOperatorSet.DrawCircle(HalconWindow, out hv_Row1, out hv_Column1, out hv_Radius1);
            HOperatorSet.GenCircle(out ROITemp, hv_Row1, hv_Column1, hv_Radius1);
            break;
        case 3:      //绘制椭圆
            HOperatorSet.DrawEllipse(HalconWindow, out hv_Row1, out hv_Column1, out hv_Phi1, out hv_Radius1, out hv_Radius2);
            HOperatorSet.GenEllipse(out ROITemp, hv_Row1, hv_Column1, hv_Phi1, hv_Radius1, hv_Radius2);
            break;
        case 4:      //绘制任意区域
            HOperatorSet.DrawRegion(out ROITemp, HalconWindow);
            break;
    }
    if (MyCurrentControl.H_CurrentROI == null)
    {
        MyCurrentControl.H_CurrentROI = ROITemp;
    }
    else 
    {
        switch (MyCurrentControl.CurrentRunROIType)
        {
            case 0:
                HOperatorSet.Union2(MyCurrentControl.H_CurrentROI, ROITemp, out MyCurrentControl.H_CurrentROI);
                break;
            case 1:
                HOperatorSet.Intersection(MyCurrentControl.H_CurrentROI, ROITemp, out MyCurrentControl.H_CurrentROI);
                break;
            case 2:
                HOperatorSet.Difference(MyCurrentControl.H_CurrentROI, ROITemp, out MyCurrentControl.H_CurrentROI);
                break;
        }
    }
    
    HOperatorSet.AreaCenter(MyCurrentControl.H_CurrentROI, out hv_Area, out hv_Row1, out hv_Column1);
    HalconWindow.ClearWindow();
    HalconWindow.DispObj(ho_img);
    HalconWindow.DispObj(MyCurrentControl.H_CurrentROI);
    HOperatorSet.SetColor(HalconWindow, "blue");
    HOperatorSet.DispCross(HalconWindow, hv_Row1, hv_Column1, MyCurrentControl.Image_Width == 0 ? 20 : MyCurrentControl.Image_Width / 24, 0);
    toolStrip1.Enabled = true;
}

9.创建模板

创建模板主入口

private void 创建模板ToolStripMenuItem_Click(object sender, EventArgs e)
{
    if (MyModel[MyCurrentControl.CurrentModelNum].EffectiveFlag == true)
    {
        DialogResult result = MessageBox.Show("已经存在模板是否替换?", "提示", MessageBoxButtons.OKCancel, MessageBoxIcon.Information);
        if (result == DialogResult.Cancel)
        {
            MyCurrentControl.H_CurrentROI = null;
            return;
        }
    }
    if (MyCurrentControl.H_CurrentROI == null || ho_img == null)
    {
        MessageBox.Show("无原图或者ROI");
        return;
    }
    InitMyModel(MyCurrentControl.CurrentModelNum, MyCurrentControl.CurrentModelNum + 1);    //删除当前模板
    //把当前的参数保存下来
    MyModel[MyCurrentControl.CurrentModelNum].h_img = ho_img.Clone();
    MyModel[MyCurrentControl.CurrentModelNum].h_roi = MyCurrentControl.H_CurrentROI.Clone();
    MyModel[MyCurrentControl.CurrentModelNum].startAngle = Convert.ToInt32(slider2.Value.ToString());
    MyModel[MyCurrentControl.CurrentModelNum].endAngle = Convert.ToInt32(slider3.Value.ToString());
    MyModel[MyCurrentControl.CurrentModelNum].Level = Convert.ToInt32(slider4.Value.ToString());
    MyModel[MyCurrentControl.CurrentModelNum].AutoContrast = checkBox2.Checked;
    MyModel[MyCurrentControl.CurrentModelNum].FindModelTimeOut = Convert.ToInt32(textBox6.Text);
    MyModel[MyCurrentControl.CurrentModelNum].Score = Convert.ToInt32(slider5.Value.ToString());
    MyModel[MyCurrentControl.CurrentModelNum].MatchNum = Convert.ToInt32(comboBox4.Text);
    MyModel[MyCurrentControl.CurrentModelNum].DeformationNum = Convert.ToInt32(comboBox3.Text);
    MyModel[MyCurrentControl.CurrentModelNum].TemplateAlgorithm = MyCurrentControl.TemplateAlgorithm;
    MyModel[MyCurrentControl.CurrentModelNum].modelNum = MyCurrentControl.CurrentModelNum;

    bool Res = false;
    if (MyCurrentControl.TemplateAlgorithm == 0)
        Res = CreateShapeModel();
    else if (MyCurrentControl.TemplateAlgorithm == 1)
        Res = CreateGrayModel();
    else if (MyCurrentControl.TemplateAlgorithm == 2)
        Res = CreateNCCModel();
    else if (MyCurrentControl.TemplateAlgorithm == 3)
        Res = CreateChangeShapeModel();
    else
    { }
    if (Res == false)
    {
        //模板创建失败
        InitMyModel(MyCurrentControl.CurrentModelNum, MyCurrentControl.CurrentModelNum + 1);    //删除当前模板
        MyCurrentControl.H_CurrentROI = null;
        toolStripStatusLabel1.Text = "模板创建失败!";
        return;
    }
    else {
        toolStripStatusLabel1.Text = "模板创建成功!";
    }

    updateModelComboBox(MyCurrentControl.CurrentModelNum);

    WriteData(MyCurrentControl.CurrentModelNum);
    WriteImageROI(MyCurrentControl.CurrentModelNum);
}

以创建灰度模板为例

private bool CreateGrayModel()
{
    if (MyCurrentControl.H_CurrentROI == null || ho_img == null)
        return false;

    toolStripStatusLabel1.Text = "正在创建模板...";
    HObject hv_ImageReduced;
    HTuple hv_pi = ((new HTuple(0.0)).TupleAcos()) * 2;
    HOperatorSet.ReduceDomain(MyModel[MyCurrentControl.CurrentModelNum].h_img, MyModel[MyCurrentControl.CurrentModelNum].h_roi, out hv_ImageReduced);
    //创建灰度模板
    try
    {
        HOperatorSet.CreateTemplateRot(hv_ImageReduced, 4, (new HTuple(MyModel[MyCurrentControl.CurrentModelNum].startAngle)).TupleRad(), (new HTuple(MyModel[MyCurrentControl.CurrentModelNum].endAngle)).TupleRad(), 0.0982, "sort", "original", out MyModel[MyCurrentControl.CurrentModelNum].hv_ModelID);
    }
    catch { return false; }
    
    //清除显示
    HalconWindow.ClearWindow();
    HalconWindow.DispObj(MyModel[MyCurrentControl.CurrentModelNum].h_img);
    HOperatorSet.AreaCenter(MyModel[MyCurrentControl.CurrentModelNum].h_roi, out MyModel[MyCurrentControl.CurrentModelNum].hv_Orgin_Angle, out MyModel[MyCurrentControl.CurrentModelNum].hv_Orgin_Row, out MyModel[MyCurrentControl.CurrentModelNum].hv_Orgin_Column);
    HalconWindow.SetColor("blue");
    HalconWindow.DispObj(MyModel[MyCurrentControl.CurrentModelNum].h_roi);
    HalconWindow.SetColor("green");
    HOperatorSet.DispCross(HalconWindow, MyModel[MyCurrentControl.CurrentModelNum].hv_Orgin_Row, MyModel[MyCurrentControl.CurrentModelNum].hv_Orgin_Column, MyCurrentControl.Image_Width == 0 ? 20 : MyCurrentControl.Image_Width / 24, 0);
    MyCurrentControl.H_CurrentROI = null;
    MyModel[MyCurrentControl.CurrentModelNum].EffectiveFlag = true;
    return true;
}

10.查找模板

查找模板主入口

private void 执行ToolStripMenuItem_Click(object sender, EventArgs e)
{
    if (!MyModel[MyCurrentControl.CurrentModelNum].EffectiveFlag)
    {
        MessageBox.Show("当前模板号无模板");
        return;
    }
    Queue<VisionPoint> pp = new Queue<VisionPoint>();
    if (MyModel[MyCurrentControl.CurrentModelNum].TemplateAlgorithm == 0)
        pp = FindModel_Shape(MyCurrentControl.CurrentModelNum);
    else if (MyModel[MyCurrentControl.CurrentModelNum].TemplateAlgorithm == 1)
        pp = FindModel_Gray(MyCurrentControl.CurrentModelNum);
    else if (MyModel[MyCurrentControl.CurrentModelNum].TemplateAlgorithm == 2)
        pp = FindModel_NCC(MyCurrentControl.CurrentModelNum);
    else if (MyModel[MyCurrentControl.CurrentModelNum].TemplateAlgorithm == 3)
        pp = FindModel_ChangeShape(MyCurrentControl.CurrentModelNum);

    if (pp.Count() != 0)
    {
        string mes = "";
        toolStripStatusLabel1.Text = "";
        while (pp.Count() != 0)
        {
            VisionPoint p = pp.Dequeue();
            mes = mes + p.x.ToString("0.000") + "," + p.y.ToString("0.000") + "," + p.r.ToString("0.000") + ":" + p.score.ToString("0.000") + ";";
        }
        string[] visionTargets = mes.Split(';');
        toolStripStatusLabel1.Text = "模板匹配成功:" + visionTargets[0];
    }
    else
    {
        toolStripStatusLabel1.Text = "模板匹配失败!";
    }
}

以查找灰度模板为例

private Queue<VisionPoint> FindModel_Gray(int ModelNum)
{
    Queue<VisionPoint> pp = new Queue<VisionPoint>();
    if (ho_img == null || MyModel[ModelNum].hv_ModelID == null)
        return pp;

    HTuple hv_RowCheck = null, hv_ColumnCheck = null, hv_AngleCheck = null, hv_Error = null;
    HTuple hMat2D = null;
    HObject ho_ImageAffinTrans;

    double Score = MyModel[ModelNum].Score / 100.0;

    HObject hv_img = ho_img;
    if (MyModel[ModelNum].SearchROIFlag)
        HOperatorSet.ReduceDomain(hv_img, MyModel[ModelNum].h_SearchROI, out hv_img);

    HOperatorSet.BestMatchRotMg(hv_img, MyModel[ModelNum].hv_ModelID, (new HTuple(MyModel[ModelNum].startAngle)).TupleRad(), (new HTuple(MyModel[ModelNum].endAngle)).TupleRad(), 100 - Score, "true", 4, out hv_RowCheck, out hv_ColumnCheck, out hv_AngleCheck, out hv_Error);
    if (0 < (int)((new HTuple(hv_Error.TupleLength()))))
    {
        try
        {
            if (Score > (100 - hv_Error[0].D))
                return pp;
            if (MyModel[ModelNum].TargetFlag == true)
            {
                HTuple RowTrans = null, ColumnTrans = null;

                HOperatorSet.VectorAngleToRigid(MyModel[ModelNum].hv_Orgin_Row, MyModel[ModelNum].hv_Orgin_Column, 0, hv_RowCheck[0].D, hv_ColumnCheck[0].D, hv_AngleCheck[0].D, out hMat2D);
                HOperatorSet.AffineTransPixel(hMat2D, MyModel[ModelNum].hv_Target_Row, MyModel[ModelNum].hv_Target_Column, out RowTrans, out ColumnTrans);
                HalconWindow.SetColor("green");
                HOperatorSet.DispCross(HalconWindow, RowTrans[0].D, ColumnTrans[0].D, MyCurrentControl.Image_Width / 24, hv_AngleCheck[0].D);
                HOperatorSet.AffineTransRegion(MyModel[ModelNum].h_roi, out ho_ImageAffinTrans, hMat2D, "constant");
                HalconWindow.SetColor("blue");
                HalconWindow.DispObj(ho_ImageAffinTrans);
                pp.Enqueue(new VisionPoint(RowTrans[0].D, ColumnTrans[0].D, hv_AngleCheck[0].D * 57.3, 100 - hv_Error[0].D));
            }
            else
            {
                HalconWindow.SetColor("green");
                HOperatorSet.DispCross(HalconWindow, hv_RowCheck[0].D, hv_ColumnCheck[0].D, MyCurrentControl.Image_Width / 24, hv_AngleCheck[0].D);
                HOperatorSet.VectorAngleToRigid(MyModel[ModelNum].hv_Orgin_Row, MyModel[ModelNum].hv_Orgin_Column, 0, hv_RowCheck[0].D, hv_ColumnCheck[0].D, hv_AngleCheck[0].D, out hMat2D);
                HOperatorSet.AffineTransRegion(MyModel[ModelNum].h_roi, out ho_ImageAffinTrans, hMat2D, "constant");
                HalconWindow.SetColor("blue");
                HalconWindow.DispObj(ho_ImageAffinTrans);
                pp.Enqueue(new VisionPoint(hv_RowCheck[0].D, hv_ColumnCheck[0].D, hv_AngleCheck[0].D * 57.3, 100 - hv_Error[0].D));
            }
            if (MyModel[ModelNum].SearchROIFlag)
            {
                HalconWindow.SetColor("orange");
                HalconWindow.DispObj(MyModel[ModelNum].h_SearchROI);
            }
        }
        catch { }
    }
    return pp;
}

11.条形码识别

识别条形码,也就是一维码

private string FindBarCode()
{
     if (ho_img == null)
         return "-1";
     HTuple hv_BarCodeHandle = null, hv_DecodedDataStrings = null, hv_BarCodeResults1 = null;
     HObject ho_SymbolRegions;

     HObject hv_img = ho_img;
     if (MyBarCode.BarCodeROIFlag)
         HOperatorSet.ReduceDomain(hv_img, MyBarCode.BarCodeROI, out hv_img);

     HOperatorSet.CreateBarCodeModel(new HTuple(), new HTuple(), out hv_BarCodeHandle);
     HOperatorSet.SetBarCodeParam(hv_BarCodeHandle, "element_size_min", 1);
     HOperatorSet.FindBarCode(hv_img, out ho_SymbolRegions, hv_BarCodeHandle, "auto", out hv_DecodedDataStrings);
     HOperatorSet.GetBarCodeResult(hv_BarCodeHandle, "all", "orientation", out hv_BarCodeResults1);
     HOperatorSet.ClearBarCodeModel(hv_BarCodeHandle);

     if (MyBarCode.BarCodeROIFlag)
     {
         HalconWindow.SetColor("orange");
         HalconWindow.DispObj(MyBarCode.BarCodeROI);
     }

     HalconWindow.SetColor("green");
     HalconWindow.DispObj(ho_SymbolRegions);

     if ((int)((new HTuple(hv_DecodedDataStrings.TupleLength()))) > 0)
     {
         HTuple hv_Area = null, hv_Row1 = null, hv_Column1 = null;
         string barCode = hv_DecodedDataStrings[0].S;
         double Angle = hv_BarCodeResults1[0].D;
         HOperatorSet.AreaCenter(ho_SymbolRegions, out hv_Area, out hv_Row1, out hv_Column1);
         double BaseLength = MyCurrentControl.Image_Width == 0 ? 50 : MyCurrentControl.Image_Width / 10;
         double BaseArrow = MyCurrentControl.Image_Width == 0 ? 50 : MyCurrentControl.Image_Width / 320;
         HalconWindow.SetColor("red");
         HOperatorSet.DispArrow(HalconWindow, hv_Row1, hv_Column1, hv_Row1 - (((((hv_BarCodeResults1 / 57.3) - 1.57)).TupleCos()) * BaseLength), hv_Column1 - (((((hv_BarCodeResults1 / 57.3) - 1.57)).TupleSin()) * BaseLength), BaseArrow);
         return string.Format("{0}:{1}", barCode, Angle.ToString());
     }
     else
         return "-1";
 }

12.二维码识别

识别二维码

private string FindQRCode()
{
    if (ho_img == null)
        return "-1";

    HObject ho_SymbolXLDs;
    HTuple hv_DataCodeHandle = null, hv_ResultHandles = null, hv_DecodedDataStrings = null;
    HObject hv_img = ho_img;
    if (MyBarCode.QRCodeROIFlag)
        HOperatorSet.ReduceDomain(hv_img, MyBarCode.QRCodeROI, out hv_img);
    
    HOperatorSet.CreateDataCode2dModel("QR Code", new HTuple(), new HTuple(), out hv_DataCodeHandle);
    HOperatorSet.FindDataCode2d(hv_img, out ho_SymbolXLDs, hv_DataCodeHandle, new HTuple(), new HTuple(), out hv_ResultHandles, out hv_DecodedDataStrings);
    HOperatorSet.ClearDataCode2dModel(hv_DataCodeHandle);

    if (MyBarCode.QRCodeROIFlag)
    {
        HalconWindow.SetColor("orange");
        HalconWindow.DispObj(MyBarCode.QRCodeROI);
    }

    if ((int)((new HTuple(hv_DecodedDataStrings.TupleLength()))) > 0)
    {
        string Code = hv_DecodedDataStrings[0].S;
        HalconWindow.SetColor("green");
        HalconWindow.DispObj(ho_SymbolXLDs);
        return Code;
    }
    else 
    {
        return "-1";
    }
}

13.OCR识别

识别OCR

private string ReadOCR()
{
     if (ho_img == null)
         return "-1";
     HObject ho_Region2, ho_ConnectedRegions1, ho_SelectedRegions1, ho_SortedRegions;
     HTuple hv_UsedThreshold2, hv_OCRHandle, hv_Class, hv_Confidence;

     HObject hv_img = ho_img;
     if (MyBarCode.OCRROIFlag)
         HOperatorSet.ReduceDomain(hv_img, MyBarCode.OCRROI, out hv_img);

     HOperatorSet.BinaryThreshold(hv_img, out ho_Region2, "max_separability", "dark", out hv_UsedThreshold2);
     HOperatorSet.Connection(ho_Region2, out ho_ConnectedRegions1);
     HOperatorSet.SelectShape(ho_ConnectedRegions1, out ho_SelectedRegions1, "area", "and", 150, 99999);
     HOperatorSet.SortRegion(ho_SelectedRegions1, out ho_SortedRegions, "character", "true", "row");
     HOperatorSet.ReadOcrClassMlp("./genicam/Industrial.omc",out hv_OCRHandle);
     HOperatorSet.DoOcrMultiClassMlp(ho_SortedRegions, hv_img, hv_OCRHandle, out hv_Class, out hv_Confidence);
     HOperatorSet.ClearOcrClassMlp(hv_OCRHandle);

     if (MyBarCode.OCRROIFlag)
     {
         HalconWindow.SetColor("orange");
         HalconWindow.DispObj(MyBarCode.OCRROI);
     }

     if ((int)((new HTuple(hv_Class.TupleLength()))) > 0)
     {
         string OCRCode = hv_Class[0].S;
         return OCRCode;
     }
     else
     {
         return "-1";
     }
 }

4.CtuVisionDLLTest_CSharp主窗体调用算法控件dll

1.定义指针结构体

public struct COPYDATASTRUCT
{
    public IntPtr dwData; //可以是任意值
    public int cbData;    //指定lpData内存区域的字节数
    [MarshalAs(UnmanagedType.LPStr)]
    public string lpData; //发送给目录窗口所在进程的数据
}

2.定义事件ID

private static uint DOT_NET_BUTTON_PRESSED = 0x0800;

3.构造函数引入dll

这里就是通过代码把dll的窗体引入到界面中

public CtuVisionDLLTest_CSharp()
{
    InitializeComponent();
    IntPtr intPtr = this.Handle;
    ctuVisionControlLibrary1.SetAdapterDllPtr(intPtr, 0);
    ctuVisionControlLibrary2.SetAdapterDllPtr(intPtr, 1);
}

4.调用方法:以模板匹配为例

这里只使用其中一个调用方法,其他方法调用方式一样,里面包含了标定转换

 private void 模板匹配ToolStripMenuItem_Click(object sender, EventArgs e)
 {
     int ModelNum = 0;
     double image_x ,image_y ,image_angle;
     ctuVisionControlLibrary1.FindModel(ModelNum, out image_x, out image_y, out image_angle);   //调用外露函数,模板匹配

     double robot_x, robot_y;
     int PositionNum = 0;
     ctuVisionControlLibrary1.AffineVector2Hom(PositionNum, image_x, image_y, out robot_x, out robot_y);   //调用外露函数,坐标转换
 }

5.CtuVisionDLLTest_MFC主窗体调用算法控件dll

1.MFC注册dll

BOOL CCtuVisionDLLTest_MFCDlg::OnInitDialog()
{
	CDialogEx::OnInitDialog();

	// 设置此对话框的图标。当应用程序主窗口不是对话框时,框架将自动
	//  执行此操作
	SetIcon(m_hIcon, TRUE);			// 设置大图标
	SetIcon(m_hIcon, FALSE);		// 设置小图标

	// TODO: 在此添加额外的初始化代码

	
	char filePath[MAX_PATH];
	GetModuleFileNameA(GetModuleHandle(0), filePath, MAX_PATH);
	char* pos = strrchr(filePath, '\\');
	if(NULL != pos)
		*pos = 0;
	
	char dllPath[MAX_PATH]="";
	sprintf(dllPath, "%s\\CtuVisionControlLibrary.dll", filePath);

	//注册ActiveX
	char bufGUIDModel[1024];
	memset(bufGUIDModel, 0, sizeof(bufGUIDModel));
	GUIDToString(CtuVisionControlLibrary::CLSID_CtuVisionControlLibrary, bufGUIDModel);
	RegisterActiveX(dllPath, bufGUIDModel);

	CRect rectModel;
	GetDlgItem(IDC_Vision)->GetWindowRect(&rectModel);
	ScreenToClient(&rectModel);

	LoadActiveX(this->m_hWnd,TEXT("CtuVisionControlLibrary.VisionLibrary"), __uuidof(CtuVisionControlLibrary::VisionLibrary), rectModel.left, rectModel.top, rectModel.Width(), rectModel.Height());

	return TRUE;  // 除非将焦点设置到控件,否则返回 TRUE
}

2.编写加载ActiveX的函数

void CCtuVisionDLLTest_MFCDlg::LoadActiveX(HWND hParentWnd, LPCTSTR strActiveXName, REFIID riidOfActiveX, int x, int y, int nWidth, int nHeight)
{
	//Initialize ATL control containment code.
	BOOL (WINAPI *m_AtlAxWinInit)();
	m_AtlAxWinInit = (BOOL (WINAPI *)(void))::GetProcAddress(hATLLib, "AtlAxWinInit");
	m_AtlAxWinInit();
	// Get the dimensions of the main window's client
	// area, and enumerate the child windows. Pass the
	// dimensions to the child windows during enumeration.
	m_hActiveXSelf = ::CreateWindowEx(WS_EX_CLIENTEDGE,TEXT("AtlAxWin"),strActiveXName,WS_CHILD | WS_VISIBLE | WS_EX_RTLREADING,x, y, nWidth, nHeight,hParentWnd,NULL,NULL,NULL);
	if (!m_hActiveXSelf)
	{
		::MessageBox( NULL, TEXT("Can not load AtlAxWin!"),TEXT(""), MB_OK | MB_ICONSTOP);
		throw int(106901);
	}
	HRESULT (WINAPI *m_AtlAxGetControl) (HWND h, IUnknown** pp);
	m_AtlAxGetControl = (HRESULT (WINAPI *)(HWND, IUnknown**))::GetProcAddress(hATLLib, "AtlAxGetControl");
	m_AtlAxGetControl(m_hActiveXSelf, &m_pUnk);
	m_pUnk->QueryInterface(riidOfActiveX, (LPVOID *) &m_pDotNetCOMPtr);
	if (m_pDotNetCOMPtr != NULL)
	{
		m_pDotNetCOMPtr->SetAdapterDllPtr((long)hParentWnd,0);
	}
	else
	{
	// Get the dimensions of the main window's client
	// area, and enumerate the child windows. Pass the
	// dimensions to the child windows during enumeration.
	::DestroyWindow(m_hActiveXSelf);
	m_hActiveXSelf = ::CreateWindowEx(WS_EX_CLIENTEDGE,TEXT("AtlAxWin"),TEXT("MSHTML:Please register ActiveX control before using this plugin."),WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN |WS_EX_RTLREADING,x, y, nWidth, nHeight,hParentWnd,NULL,NULL,NULL);
	}
}

3.注意控件的加载函数

CRect rectModel;
GetDlgItem(IDC_Vision)->GetWindowRect(&rectModel);
ScreenToClient(&rectModel);

LoadActiveX(this->m_hWnd,TEXT("CtuVisionControlLibrary.VisionLibrary"), __uuidof(CtuVisionControlLibrary::VisionLibrary), rectModel.left, rectModel.top, rectModel.Width(), rectModel.Height());

4.接口调用

这里以StringTest外部接口进行展示

void CCtuVisionDLLTest_MFCDlg::OnBnClickedButton1()
{
	// TODO: 在此添加控件通知处理程序代码
	char *strColumn_ID = "ctu"; 
	_bstr_t bstrColumn_ID(strColumn_ID);
	BSTR pDataCode = NULL;
	m_pDotNetCOMPtr->StringTest(bstrColumn_ID, &pDataCode);
	_bstr_t bDataCode = pDataCode;
	char buf[128];
	sprintf_s(buf, "%s", (char*)bDataCode);
}

6.CtuVisionDLLTest_QT主窗体调用算法控件dll

由于Qt与MFC都是基于C++的,因此调用方法与MFC类似

1.构造函数加载dll控件并且支持多控件加载,代表多相机使用

CtuVisionDLLTest_QT::CtuVisionDLLTest_QT(QWidget *parent)
	: QMainWindow(parent)
{
	ui.setupUi(this);

	char filePath[MAX_PATH];
	GetModuleFileNameA(GetModuleHandle(0), filePath, MAX_PATH);
	char* pos = strrchr(filePath, '\\');
	if(NULL != pos)
		*pos = 0;
	
	char dllPath[MAX_PATH]="";
	sprintf(dllPath, "%s\\CtuVisionControlLibrary.dll", filePath);

	//注册ActiveX
	char bufGUIDModel[1024];
	memset(bufGUIDModel, 0, sizeof(bufGUIDModel));
	GUIDToString(CtuVisionControlLibrary::CLSID_CtuVisionControlLibrary, bufGUIDModel);
	RegisterActiveX(dllPath, bufGUIDModel);

	HWND h_Wnd[CameraNum];
	QRect rect[CameraNum];
	h_Wnd[0] = (HWND)ui.VisionLab1->winId();
	h_Wnd[1] = (HWND)ui.VisionLab2->winId();
	h_Wnd[2] = (HWND)ui.VisionLab3->winId();
	rect[0] = ui.VisionLab1->frameGeometry();
	rect[1] = ui.VisionLab2->frameGeometry();
	rect[2] = ui.VisionLab3->frameGeometry();

	for(int i=0;i<CameraNum;i++)
	{
		LoadActiveX(h_Wnd[i],m_pDotNetCOMPtr[i],i,TEXT("CtuVisionControlLibrary.VisionLibrary"), __uuidof(CtuVisionControlLibrary::VisionLibrary), 0, 0, rect[i].width(), rect[i].height());
	}
}

2.调用方式

这里以模板匹配+坐标转换为例子展示

void CtuVisionDLLTest_QT::on_pushButton_2_clicked()
{
	int ModelNum = ui.lineEdit->text().toInt();
	double image_x,image_y,r;
	image_x = image_y = r = 0.0;
	m_pDotNetCOMPtr[0]->FindModel(ModelNum,&image_x,&image_y,&r);
	QString mes = QString("%1,%2,%3").arg(image_x).arg(image_y).arg(r);
	if(image_x !=-1.0)
	{
		int CaliNum = ui.lineEdit_4->text().toInt();
		double robot_x,robot_y;
		robot_x=robot_y = 0.0;
		VARIANT_BOOL res = VARIANT_FALSE;
		m_pDotNetCOMPtr[0]->AffineVector2Hom(CaliNum,image_x,image_y,&robot_x,&robot_y);
		if(robot_x!=-1.0)
		{
			mes = QString("%1,%2,%3").arg(robot_x).arg(robot_y).arg(r);
		}
	}
	ui.statusBar->showMessage(mes);
}

总结

该工程篇幅比较多,不过具体的函数在文章中已经表标明,具体的查看源码使用。
C#做算法及主界面开发,然后把生成的控件dll移交给C#或者MFC或者QT进行二次调用实现二次开发,这里主要想展示的是多语言之间的调用以及如何跨语言调用控件算法文章来源地址https://www.toymoban.com/news/detail-805369.html

到了这里,关于基于halcon实现视觉定位框架(C#做主算法,C#、MFC、Qt二次开发)【附源码】的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 基于C#调用halcon实现模板匹配【附部分源码】

    本文主要实现基于C#实现视觉定位的基础框架,与前面的python版、MFC版、Qt版一样,可供不同的开发者进行学习使用。 本文也是包括多模板算法匹配:基于形状、基于灰度、基于相关性、基于可变比例等。 编程环境:dotnet4.7 halcon20.05 IDE: VisualStudio 2022 本次项目的效果视频:

    2024年02月06日
    浏览(83)
  • 在C#中使用Halcon开发视觉检测程序

    本文的初衷是希望帮助那些有其它平台视觉算法开发经验的人能快速转入Halcon平台下,通过文中的示例开发者能快速了解一个Halcon项目开发的基本步骤,让开发者能把精力完全集中到算法的开发上面。 首先,你需要安装Halcon, HALCON 18.11.0.1 的安装包会放在文章末尾。安装包分

    2024年02月03日
    浏览(46)
  • 基于康耐视cognexVisionpro用C#二次开发的多相机视觉对位框架

    基于康耐视cognexVisionpro用C#二次开发的多相机视觉对位框架 支持1:多相机对位逻辑运算,旋转标定坐标关联运算(可供参考学习)可以协助理解做对位贴合项目思路。 支持2:直接连接运动控制卡,控制UVW平台运动(可供参考学习) 支持3:自动标定程序设定(可供参考学习

    2024年04月15日
    浏览(40)
  • 【halcon 实现模板匹配,定位,找线,找点,找圆】

    c#联合halcon 链接: https://www.bilibili.com/video/BV1aR4y1473b/. halcon函数速查 链接: https://pan.baidu.com/s/1rbxf62bMh61Ie0pB4t3AHw . 提取码:0000 图片链接 链接: https://pan.baidu.com/s/1f0ld6nHcqzblvTnekEoSiQ . 0000 读取 选择模板 将模板从原图中截取出来 然后就可以开始找目标定位了 得到 x, y, angle, 分数 通

    2024年02月05日
    浏览(75)
  • c#,dotnet, DataMatrix 类型二维码深度识别,OCR,(基于 Halcon)

    代码中部分调用的 c++ 函数参数,具体说明自行研究~(我也是参考的其他资源,还没研究透彻) 例如:HOperatorSet.GenRectangle2() , 2000, 2000, 0, 2000, 2000 这些数字应该是选取的图片解析范围、尺寸(长、宽),2000 更改成 100 后可能只会识别到部分二维码。 效果图: 链接:https:

    2024年02月20日
    浏览(43)
  • C#语言的机器视觉5个框架

    C#语言的机器视觉框架有多种选择,以下是其中几个常用的: OpenCVSharp:OpenCVSharp是OpenCV的C#封装,提供了一系列的图像处理和计算机视觉算法,包括图像处理、特征检测、目标跟踪、人脸识别等。 AForge.NET:AForge.NET是一个开源的计算机视觉和人工智能框架,提供了一系列的图

    2024年02月11日
    浏览(48)
  • 视觉定位系统怎么实现定位及引导贴合的应用?视觉定位系统案例详解

    视觉定位系统采用先进的图像视觉检测技术,实现对高速运动的工业产品进行实时全面的视觉定位分析。机器视觉系统可以起到人类视觉的作用,利用自动化科技来替代人眼,使质量进一步升级,不仅可以提高工作效率,而且减少了人工产生的不确定因素对质量控制效果的影响

    2024年02月11日
    浏览(50)
  • HALCON的综合应用案例【01】: 3D 算法处理在 Visual Studio 2019 C# 环境中的集成实例

    HALCON 为一款比较流行的商业视觉处理软件,他提供了多种开发的模式,可以在HALCON中开发,也可以将HALCON的设计通过导出库的形式集成到其他开发环境里面,以方便系统集成。本文为笔者自己的一个3D 视觉检测项目,利用HALCON的3D 库开发算法,然后,将算法集成到 MS-VS-C#的环

    2024年02月06日
    浏览(49)
  • 基于视觉语义信息的建图与定位综述

    点云PCL免费知识星球,点云论文速读。 文章:Semantic Visual Simultaneous Localization and Mapping: A Survey 作者:Kaiqi Chen, Jianhua Zhang, Jialing Liu, Qiyi Tong, Ruyu Liu, Shengyong Chen 编辑:点云PCL 来源:arXiv 2022 欢迎各位加入免费知识星球,获取PDF论文,欢迎转发朋友圈。文章仅做学术分享,如有

    2023年04月18日
    浏览(47)
  • C#通用框架源码 增加了机器人 流程框架 多任务流程 机器视觉源码框架

    C#通用框架源码 增加了机器人 流程框架 多任务流程 机器视觉源码框架,算法使用的是halcon,有C#基础和Halcon基础学习这个很好提升快。 标题:C#通用框架源码及机器视觉应用分析 摘要:本文将就C#通用框架源码的新增内容进行详细分析,并深入探讨其中包括的机器人流程框

    2024年02月03日
    浏览(49)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包