Basler相机Sdk采图的演示例程(C#)

勇哥说的这个话题的起因是追求极速的拍图速度。

机器ppm不达标的情况下,往往对视觉的处理速度有变态的要求,为了争取处理时间最短,几十毫秒也要争取。

halcon的接口是通用接口,其速度是比不上相机厂商自己相机配套的SDK的采图速度的。


下面程序运行后,500w的CCD拍图的时间(不算显示时间)达到惊人的32毫秒,如果用halcon接口,最快的我见过是180毫秒。

image.png

using Basler.Pylon;
using HalconDotNet;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Drawing;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace WindowsFormsApplication1
{
    public partial class Form1 : Form
    {
        private PixelDataConverter converter = new PixelDataConverter();
          /// <summary>
        /// 相机ID
        /// </summary>
        public string UserID { get { return userID; } }
        private string userID = string.Empty;

        private Stopwatch sw = new Stopwatch();
        private bool isOkGrab = false;
        private IntPtr latestFrameAddress = IntPtr.Zero;
        public HObject Image { get { return image; } }
        private HObject image = null;
        static Version Sfnc2_0_0 = new Version(2, 0, 0);
        private Camera camera = null;
        HTuple handle;
        public Form1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            var f1=BaslerCameraInit();
            if(f1)
            {
               MessageBox.Show( Open().ToString());
            }
        }

        
        /// <summary>
        /// 实例化第一个找到的相机
        /// </summary>
        public bool BaslerCameraInit()
        {
            try
            {
                camera = new Camera();
                  camera.StreamGrabber.ImageGrabbed -= StreamGrabber_ImageGrabbed;
                camera.StreamGrabber.ImageGrabbed+=StreamGrabber_ImageGrabbed;
                return true;
            }
            catch (Exception ex)
            {
                return false;
              //NotifyG.Error(ex.ToString());
            }
        }


         /// <summary>
        /// 根据相机UserID实例化相机
        /// </summary>
        /// <param name="UserID"></param>
        public bool BaslerCameraInit(string userID)
        {
            try
            {
                // 枚举相机列表
                List<ICameraInfo> allCameraInfos = CameraFinder.Enumerate();
                foreach (ICameraInfo cameraInfo in allCameraInfos)
                {
                    if (userID == cameraInfo[CameraInfoKey.UserDefinedName])
                    {
                        this.userID = userID;
                        camera = new Camera(cameraInfo);
                        camera.StreamGrabber.ImageGrabbed -= StreamGrabber_ImageGrabbed;
                        camera.StreamGrabber.ImageGrabbed += StreamGrabber_ImageGrabbed;
                    }
                }
                if (camera == null)
                {
                    //NotifyG.Error("未识别到UserID为“" + UserID + "”的相机!");
                    return false;
                }
                return true;
            }
            catch (Exception ex)
            {
                return false;
                //NotifyG.Error(ex.ToString());
            }
        }


        void StreamGrabber_ImageGrabbed(object sender, ImageGrabbedEventArgs e)
        {
            try
            {
                // Acquire the image from the camera. Only show the latest image. The camera may acquire images faster than the images can be displayed.

                // Get the grab result.
                IGrabResult grabResult = e.GrabResult;

                // Check if the image can be displayed.
                if (grabResult.IsValid)
                {
                    //grabTime = sw.ElapsedMilliseconds;
                    //if (eventComputeGrabTime != null) eventComputeGrabTime(grabTime);

                    //Reduce the number of displayed images to a reasonable amount if the camera is acquiring images very fast.
                    // ****  降低显示帧率,减少CPU占用率  **** //
                    //if (!stopWatch.IsRunning || stopWatch.ElapsedMilliseconds > 33)
                    {
                        //stopWatch.Restart();
                        // 判断是否是黑白图片格式
                        if (grabResult.PixelTypeValue == PixelType.Mono8)
                        {
                            //allocate the m_stream_size amount of bytes in non-managed environment 
                            if (latestFrameAddress == IntPtr.Zero)
                            {
                                latestFrameAddress = Marshal.AllocHGlobal((Int32)grabResult.PayloadSize);
                            }
                            converter.OutputPixelFormat = PixelType.Mono8;
                            converter.Convert(latestFrameAddress, grabResult.PayloadSize, grabResult);
                            HOperatorSet.GenEmptyObj(out image);
                            image.Dispose();
                            // 转换为Halcon图像显示
                            HOperatorSet.GenImage1(out image, "byte", grabResult.Width, grabResult.Height, latestFrameAddress);
                            HOperatorSet.SetPart(handle, 0, 0, grabResult.Height - 1, grabResult.Width - 1);
                        }
                        else if (grabResult.PixelTypeValue == PixelType.BayerBG8 || grabResult.PixelTypeValue == PixelType.BayerGB8
                                    || grabResult.PixelTypeValue == PixelType.BayerRG8 || grabResult.PixelTypeValue == PixelType.YUV422packed)
                        {
                            int imageWidth = grabResult.Width - 1;
                            int imageHeight = grabResult.Height - 1;
                            HOperatorSet.SetPart(handle, 0, 0, imageHeight, imageWidth);
                            int payloadSize = imageWidth * imageHeight;

                            //allocate the m_stream_size amount of bytes in non-managed environment 
                            if (latestFrameAddress == IntPtr.Zero)
                            {
                                latestFrameAddress = Marshal.AllocHGlobal((Int32)(3 * payloadSize));
                            }
                            converter.OutputPixelFormat = PixelType.RGB8packed;     // 根据下面halcon转换的色彩格式bgr
                            converter.Parameters[PLPixelDataConverter.InconvertibleEdgeHandling].SetValue("Clip");
                            converter.Convert(latestFrameAddress, 3 * payloadSize, grabResult);

                            HOperatorSet.GenImageInterleaved(out image, latestFrameAddress, "bgr",
                                     (HTuple)imageWidth, (HTuple)imageHeight, -1, "byte", (HTuple)imageWidth, (HTuple)imageHeight, 0, 0, -1, 0);
                        }
                        else
                        {
                            //NotifyG.Error(DeviceName + "拍照失败,相机图像格式设置");
                            return;
                        }
                        isOkGrab = true;
                        //MessageBox.Show(isOkGrab.ToString());
                        // 抛出图像处理事件
                        //if (EventGrab != null) EventGrab(this, new CameraGrabEventArgs(image));
                    }
                }
            
            }
            catch (Exception ex)
            {
                //MessageBox.Show(ex.ToString());
                return;
            }
            finally
            {
                // Dispose the grab result if needed for returning it to the grab loop.
                e.DisposeGrabResultIfClone();
            }
        }

        /// <summary>
        /// 打开相机
        /// </summary>
        public bool Open()
        {
            try
            {
                if (camera.IsOpen) camera.Close();
                Thread.Sleep(200);
                camera.Open();
                var imageWidth = camera.Parameters[PLCamera.Width].GetValue();               // 获取图像宽 
                var imageHeight = camera.Parameters[PLCamera.Height].GetValue();              // 获取图像高
                GetMinMaxExposureTime();
                GetMinMaxGain();
                camera.Parameters[PLCamera.AcquisitionMode].SetValue(PLCamera.AcquisitionMode.SingleFrame);
                //NotifyG.Debug(DeviceName + "打开相机成功:" + userID);
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString());
                return false;
            }
            return true;
        }

        /// <summary>
        /// 关闭相机,释放相关资源
        /// </summary>
        public new bool Close()
        {
            try
            {
                camera.Close();
                camera.Dispose();
                if (Image != null)
                {
                    Image.Dispose();
                }
                if (latestFrameAddress != null)
                {
                    Marshal.FreeHGlobal(latestFrameAddress);
                    latestFrameAddress = IntPtr.Zero;
                }
                //NotifyG.Debug(DeviceName + "关闭相机成功:" + userID);
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString());
                return false;
            }
            return true;
        }

        /// <summary>
        /// 单张采集
        /// </summary>
        public bool GrabImage()
        {
            try
            {
                isOkGrab = false;
                sw.Restart();
                if (camera.StreamGrabber.IsGrabbing)
                {
                    //NotifyG.Error("相机当前正处于采集状态!");
                    return false;
                }
                else
                {
                    camera.StreamGrabber.Start(1, GrabStrategy.LatestImages, GrabLoop.ProvidedByStreamGrabber);
                    //while (!isOkGrab)
                    //{
                    //    if (sw.ElapsedMilliseconds > 2000) { isOkGrab = false; return false; }
                    //    Thread.Sleep(1);
                    //}
                    //NotifyG.Debug(DeviceName + "拍照成功:" + sw.ElapsedMilliseconds);
                    return true;
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString());
                return false;
            }
            return true;
        }

        /// <summary>
        /// 开始连续采集
        /// </summary>
        public bool StartGrabbing()
        {
            try
            {
                if (camera.StreamGrabber.IsGrabbing)
                {
                    //NotifyG.Error("相机当前正处于采集状态!");
                    return false;
                }
                else
                {
                    camera.Parameters[PLCamera.AcquisitionMode].SetValue(PLCamera.AcquisitionMode.Continuous);
                    camera.StreamGrabber.Start(GrabStrategy.LatestImages, GrabLoop.ProvidedByStreamGrabber);
                 
                    return true;
                }
            }
            catch (Exception ex)
            {
                //NotifyG.Error(DeviceName + ex.ToString());
                return false;
            }
        }

        /// <summary>
        /// 停止连续采集
        /// </summary>
        public bool StopGrabbing()
        {
            try
            {
                if (camera.StreamGrabber.IsGrabbing)
                {
                    camera.StreamGrabber.Stop();
                }
            }
            catch (Exception ex)
            {
                //NotifyG.Error(DeviceName + ex.ToString());
            }
            return true;
        }


        /// <summary>
        /// 获取最小最大曝光时间
        /// </summary>
        public void GetMinMaxExposureTime()
        {
            try
            {
                if (camera.GetSfncVersion() < Sfnc2_0_0)
                {
                    var minExposureTime = camera.Parameters[PLCamera.ExposureTimeRaw].GetMinimum();
                    var maxExposureTime = camera.Parameters[PLCamera.ExposureTimeRaw].GetMaximum();
                }
                else
                {
                    var minExposureTime = (long)camera.Parameters[PLUsbCamera.ExposureTime].GetMinimum();
                    var maxExposureTime = (long)camera.Parameters[PLUsbCamera.ExposureTime].GetMaximum();
                }
            }
            catch (Exception ex)
            {
                
            }
        }

        /// <summary>
        /// 获取最小最大增益
        /// </summary>
        public void GetMinMaxGain()
        {
            try
            {
                if (camera.GetSfncVersion() < Sfnc2_0_0)
                {
                    var minGain = camera.Parameters[PLCamera.GainRaw].GetMinimum();
                    var maxGain = camera.Parameters[PLCamera.GainRaw].GetMaximum();
                }
                else
                {
                    var minGain = (long)camera.Parameters[PLUsbCamera.Gain].GetMinimum();
                    var maxGain = (long)camera.Parameters[PLUsbCamera.Gain].GetMaximum();
                }
            }
            catch (Exception ex)
            {
                //NotifyG.Error(DeviceName + ex.ToString());
            }
        }

        private void button2_Click(object sender, EventArgs e)
        {
            Stopwatch sw1 = new Stopwatch();
            sw1.Start();
            var f1 = GrabImage();
            sw1.Stop();
            MessageBox.Show(string.Format("grab time:{0}",sw1.ElapsedMilliseconds));
            //if(f1)
            //{
            //    if (null != Image)
            //        HOperatorSet.DispObj(Image, hWindowControl1.Handle);
            //}
        }

        private void Form1_FormClosing(object sender, FormClosingEventArgs e)
        {
            if (null != camera && camera.IsOpen)
                Close();
        }

        private void button6_Click(object sender, EventArgs e)
        {
            try
            {
                if (null != Image && Image.IsInitialized())
                {
                    //HOperatorSet.WriteImage(Image, "bmp", 0, "d:\\123.bmp");
                    HOperatorSet.DispObj(Image, handle);
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            handle = hWindowControl1.HalconWindow;
           
        }

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

        private void button4_Click(object sender, EventArgs e)
        {
            timer1.Stop();
            StopGrabbing();
        }

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


    }
}


另外勇哥说一个问题:

当这个程序被强行在进程中关闭后,你会发现再启动程序就初始化相机失败。

这是因为相机的句柄没有被关闭。上面的演示例程中,关闭句柄被放在了form窗口正常关闭的时候。

你重启电脑可以解决这个问题,或者你也可以等个几分钟,再启动程序也可以连上相机。

这是因为相机内部自己会超时复位,但是这个超时具体是几分钟勇哥也没统计过。



下面附上常见工业相机的SDK开发资料网址:


Basler相机

Basler pylon相机软件套装是一款包含易于使用的SDK、驱动程序和工具的软件套装,您可通过Windows、Linux PC或Mac来操作任何一款Basler相机。pylon采用最新GenICam技术,可无限制访问最新型号的相机并使用相关功能。

https://www.baslerweb.com/cn/

https://www.baslerweb.com/cn/sales-support/downloads/software-downloads/


MvCameraControl海康相机

https://www.hikrobotics.com/vision/visionlist.htm

https://www.hikrobotics.com/service/soft.htm

机器视觉工业相机客户端MVS V3.1.0

软件版本:MVS3.1.0 build20181229



TIS映美精工业相机,映美精IC Imageing Control.net

https://www.theimagingsource.com/support/downloads-for-windows/

https://www.theimagingsource.com/support/downloads-for-windows/software-development-kits-sdks/icimagingcontrol/

Software Development Kits (SDKs)

IC Imaging Control .NET Component for C#, VB.NET, C++ Class Library for C++ projects

ic_setup_3.4.0.2744.exe



Teledyne DALSA

Sapera LT SDK是一款图像采集与控制软件的开发工具包(SDK),用于Teledyne DALSA相机与采集卡。Sapera LT支持从相机与采集卡中采集图像,依据的标准包括GigE Vision;CameraLink与CameraLink HS。GigE Vision是一种基于千兆以太网通信协议开发的相机接口标准。

https://www.teledynedalsa.com/en/products/imaging/vision-software/sapera-lt/

www.lustervision.com/dalsa-linea/

http://51camera.com.cn/show-34-10-1.html



大恒相机

http://www.daheng-imaging.com/


Point Grey相机


FlyCapture SDK是加拿大Point Grey(灰点)公司开发的功能丰富,最稳定的软件套件。

https://www.flir.com/products/flycapture-sdk

https://www.flir.com/iis/machine-vision/




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

作者:hackpig

来源:www.skcircle.com

版权声明:本文为博主原创文章,转载请附上博文链接!


本文出自勇哥的网站《少有人走的路》wwww.skcircle.com,转载请注明出处!讨论可扫码加群:
  • 评论列表:
  •  访客
     发布于 2020-04-22 10:28:15  回复该评论
  • 我用500万的basler相机,用你整理的sdk,取图时间是102ms,难道时型号不一样,我的型号:acA3800-10gm
    •  勇哥,很想停止
       发布于 2020-04-22 15:01:26  回复该评论
    • 检查一下网线,质量不好的网线会降速运行。
      再检查一下网卡设置相关,特别是过滤器。
      最后检查相机本身的默认设置,如曝光之类的。
      还不行那就奇怪了。
  •  访客
     发布于 2020-10-22 08:36:50  回复该评论
  • 楼上acA3800显然不是500万,acA2500才是500万相机
    •  访客
       发布于 2020-10-22 08:38:35  回复该评论
    • 想问在处理彩色图那里宽和高为什么要-1,我没-1反而对,然后rgb是不是反了
  •  王晓飞
     发布于 2022-01-11 13:37:52  回复该评论
  • Basler相机获取图像后如何转换为NIVision的图像VisionImage
    // 转换为NI图像显示(以下方法正确否)
    VisionImage vPylonImage;
    byte[,] data;
    data = new byte[grabResult.Height, grabResult.Width];
    var temp = Marshal.UnsafeAddrOfPinnedArrayElement(data, 0);
    byte[] buffer = grabResult.PixelData as byte[];
    Marshal.Copy(buffer, 0, temp, buffer.Length);
    vPylonImage.ArrayToImage(new PixelValue2D(data));

发表评论:

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

会员中心
搜索
«    2024年4月    »
1234567
891011121314
15161718192021
22232425262728
2930
网站分类
标签列表
最新留言
    热门文章 | 热评文章 | 随机文章
文章归档
友情链接
  • 订阅本站的 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