C#和halcon的混编程序出现长时间拍照时程序崩溃问题的解决经验


勇哥项目中有下面这个拍照函数GrabOneImage()。

在其它十几台设备上面运行没发现有什么问题,但是最近发现有一台设备上长时间运行不到半小时,程序就报告崩溃。错误原因是内存不足。


  public bool GrabOneImage(bool isDebug)
   {
            try
            {
                //如果未初始化,先初始化相机
                if (acqHandle == null)
                {
                    HTuple handle = new HTuple();
                    //初始化相机有时会报错,多初始化几次就成功了,这样搞不太好,有待解决
                    int num = 0;
                Again:
                    try
                    {
                        HOperatorSet.OpenFramegrabber(new HTuple("GigEVision2"),
                                                      new HTuple(0),
                                                      new HTuple(0),
                                                      new HTuple(0),
                                                      new HTuple(0),
                                                      new HTuple(0),
                                                      new HTuple(0),
                                                      new HTuple("progressive"),
                                                      new HTuple(-1),
                                                      new HTuple("default"),
                                                      new HTuple(-1),
                                                      new HTuple("false"),
                                                      new HTuple("default"),
                                                      Work.Instance.cameraStr,
                                                      new HTuple(0),
                                                      new HTuple(-1),
                                                      out handle);
                        Work.acqHandle = handle;
                    }
                    catch
                    {
                        num++;
                        if (num < 5)
                            goto Again;
                    }
                    if (acqHandle == null) return false;
                    HTuple minExposure, maxExposure, temp, curExposure;
                    //HOperatorSet.GetFramegrabberParam(Work.acqHandle, "ExposureTimeAbs", out temp);
                    HOperatorSet.SetFramegrabberParam(Work.acqHandle, "ExposureTimeAbs", Work.Instance.exposure);
                    HOperatorSet.GetFramegrabberParam(Work.acqHandle, "ExposureTimeAbs", out curExposure);//"exposure"
                    minExposure = 1000;// temp[0];
                    maxExposure = 100000;
                    Frm_ImageAcq.Instance.tck_exposure.Minimum = 1000;
                    Frm_ImageAcq.Instance.tck_exposure.Maximum = 200000;
                    Frm_ImageAcq.Instance.tck_exposure.Value = (int)curExposure.D;
                    Frm_ImageAcq.Instance.lbl_exposure.Text = curExposure.ToString();
                    Work.Instance.exposure = (int)curExposure.D;
                    HOperatorSet.SetFramegrabberParam(Work.acqHandle, "ExposureTimeAbs", Work.Instance.exposure);
                }
                if(null!=inputImage)
                {
                    inputImage.Dispose();
                }
                HOperatorSet.GrabImage(out inputImage, acqHandle);
                if (isDebug)
                    Frm_Main.Instance.hwc_imageWindow.HobjectToHimage(inputImage);
                else
                {
                    DisplayAndFitImage(inputImage, produceWindow.HalconWindow);
                }
                return true;
            }
            catch (Exception ex)
            {
                //MessageBox.Show(ex.ToString());
                return false;
            }
   }

下图是在崩溃时的屏幕截图。

其中句柄数正常时应该为600多个,现在有近1900个了。

内存占用1.5个G。而这台IPC总共才4G内存。

崩溃时,拍照函数中的halcon算子开始抛出异常。

image.png


为了对比,勇哥用halcon导入一段拍照的代码,整理了一下,写成一个小程序。

运行了20个小时,发现内存没涨,句柄也没持续增加,一切正常没死掉。


image.png

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using HalconDotNet;

namespace WindowsFormsApplication1
{
    public partial class xiangji : Form
    {
       

        public xiangji()
        {
            InitializeComponent();
        }
        HTuple hv_AcqHandle = null, newHandle=null,hv_Width = new HTuple();
        HTuple hv_Height = new HTuple();
        HObject ho_Image = null;
        private void button1_Click(object sender, EventArgs e)
        {
            
            HOperatorSet.OpenFramegrabber("GigEVision2", 0, 0, 0, 0, 0, 0, "progressive",
        -1, "default", -1, "false", "default", "a0bd1d0f6037_MachineVisionSzAcx_MVA3A20MG8onSzAcx",
        0, -1, out hv_AcqHandle);
            MessageBox.Show("OK");
        }

        private void button4_Click(object sender, EventArgs e)
        {
            grab();
        }

        private void button3_Click(object sender, EventArgs e)
        {
            timer1.Start();
        }

        private void timer1_Tick(object sender, EventArgs e)
        {
            grab();
        }

        private void grab()
        {
            
            if (null != ho_Image)
                ho_Image.Dispose();
            HOperatorSet.GrabImage(out ho_Image, hv_AcqHandle);
            HOperatorSet.GetImageSize(ho_Image, out hv_Width, out hv_Height);
            HOperatorSet.SetPart(hWindowControl1.HalconWindow, 0, 0, hv_Height-1, hv_Width-1);
            HOperatorSet.DispObj(ho_Image, hWindowControl1.HalconWindow);
            if (null != ho_Image)
                ho_Image.Dispose();
        }

        private void xiangji_Load(object sender, EventArgs e)
        {

        }
    }
}


对比下两段程序,其实,问题就在于划线这里。

image.png

在halcon里,HObject变量在用之前与使用完之后,都要释放(Dispose)。


因为inputImage是个全局变量,不能用完后立刻Dispose,因此,勇哥写了两个函数

Get_inputImage() 读取inputImage,而Set_inputImage()用于给inputImage赋值。

改完后的代码如下:

HObject Get_inputImage()
  {
     return inputImage;
  }
 
  void Set_inputImage(HObject obj)
  {
      if (inputImage != null)
      inputImage.Dispose();
      inputImage = obj.CopyObj(1, -1); //如果直接liveImage=obj是不可以的,因为当Dispose后全局变量变量也会被注销。
  }



 /// <summary>
        /// 采图
        /// </summary>
        public bool GrabOneImage(bool isDebug)
        {
            try
            {
                //如果未初始化,先初始化相机
                if (acqHandle == null)
                {
                    HTuple handle = new HTuple();
                    //初始化相机有时会报错,多初始化几次就成功了,这样搞不太好,有待解决
                    int num = 0;
                Again:
                    try
                    {
                        HOperatorSet.OpenFramegrabber(new HTuple("GigEVision2"),
                                                      new HTuple(0),
                                                      new HTuple(0),
                                                      new HTuple(0),
                                                      new HTuple(0),
                                                      new HTuple(0),
                                                      new HTuple(0),
                                                      new HTuple("progressive"),
                                                      new HTuple(-1),
                                                      new HTuple("default"),
                                                      new HTuple(-1),
                                                      new HTuple("false"),
                                                      new HTuple("default"),
                                                      Work.Instance.cameraStr,
                                                      new HTuple(0),
                                                      new HTuple(-1),
                                                      out handle);
                        Work.acqHandle = handle;
                    }
                    catch
                    {
                        num++;
                        if (num < 5)
                            goto Again;
                    }

                    HTuple minExposure, maxExposure, temp, curExposure;
                    //HOperatorSet.GetFramegrabberParam(Work.acqHandle, "ExposureTimeAbs", out temp);
                    HOperatorSet.GetFramegrabberParam(Work.acqHandle, "ExposureTimeAbs", out curExposure);//"exposure"
                    minExposure = 1000;// temp[0];
                    maxExposure = 100000;
                    Frm_ImageAcq.Instance.tck_exposure.Minimum = 1000;
                    Frm_ImageAcq.Instance.tck_exposure.Maximum = 800000;
                    Frm_ImageAcq.Instance.tck_exposure.Value = (int)curExposure.D;
                    Frm_ImageAcq.Instance.lbl_exposure.Text = curExposure.ToString();
                    Work.Instance.exposure = (int)curExposure.D;
                }
                HObject img=null;
                HOperatorSet.GrabImage(out img, acqHandle);
                Set_inputImage(img);
                if (isDebug)
                    Frm_Main.Instance.hwc_imageWindow.HobjectToHimage(img);
                else
                {
                    DisplayAndFitImage(img, produceWindow.HalconWindow);
                }

                if (null != img)
                    img.Dispose();
                return true;
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString());
                return false;
            }
        }


问题解决了!!


注: 这个问题的怪异之处是,这个GrabOneImage()函数,虽然之前的写法不严谨。但是在十几台设备上都没什么问题,偏偏在这一台问题机上出现内存和句柄的问题。

而且这些机器从操作系统到CCD型号、halcon版本均是一模一样,甚至IPC的配置都是一样的。

之前只是见过有设备的程序换了速度更慢或者更快的IPC就表现异常,这因为那个设备的程序中有多个线程协作的逻辑,这时会跟CPU有直接关系。

而本例勇哥只能叹一声,怪哉!


--------------------- 

作者:hackpig
来源:
www.skcircle.com
版权声明:本文为博主原创文章,转载请附上博文链接!


本文出自勇哥的网站《少有人走的路》wwww.skcircle.com,转载请注明出处!讨论可扫码加群:

发表评论:

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

会员中心
搜索
«    2025年4月    »
123456
78910111213
14151617181920
21222324252627
282930
网站分类
标签列表
最新留言
    热门文章 | 热评文章 | 随机文章
文章归档
友情链接
  • 订阅本站的 RSS 2.0 新闻聚合
  • 扫描加本站机器视觉QQ群,验证答案为:halcon勇哥的机器视觉
  • 点击查阅微信群二维码
  • 扫描加勇哥的非标自动化群,验证答案:C#/C++/VB勇哥的非标自动化群
  • 扫描加站长微信:站长微信:abc496103864
  • 扫描加站长QQ:
  • 扫描赞赏本站:
  • 留言板:

Powered By Z-BlogPHP 1.7.2

Copyright Your skcircle.com Rights Reserved.

鄂ICP备18008319号


站长QQ:496103864 微信:abc496103864