C# + Basler 相机图像采集实战解析

454 阅读4分钟

前言

在工业自动化、医疗成像和科研检测等领域,工业相机是视觉系统的核心组件。

Basler作为全球领先的工业相机品牌,其产品以高帧率、高分辨率和稳定性著称。然而,对于C#开发者而言,如何快速调用Basler SDK实现图像采集仍面临接口适配、性能优化等挑战。

本文将以Basler相机为例,结合官方文档与开发经验,详解从环境配置到代码实现的完整流程,并提供多线程采集、回调函数等高效方案,帮助大家开发可靠的图像采集系统。

项目说明

每个相机基本都有自己带的SDK 初学者看一下自己后期需要使用到什么相机就学那个列:海康、巴勒斯......前提是相机方提供的sdk里有C#的接口。

调用巴勒斯的相机使用sdk

Basler产品文档

zh.docs.baslerweb.com/

通用套路

1、初始化相机

2、打开相机

3、设置配置

4、图像抓取

5、停止抓取

6、图片保存

采集相机的几种方式

1、多线程采集

2、setTime 定时器采集

3、回调函数 等等

环境配置

1、下载安装 Basler 程序

2、安装好之后里面有对应的Basler.Pylon.dll文件需要在vs中引入这个dll文件大致路径是这样的D:\Basler\Development\Assemblies\Basler.Pylon\x64\Basler.Pylon.dll 这个是我电脑上的路径仅供参考。

代码展示

1、后台代码

using Basler.Pylon;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Imaging;
using System.Linq;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace CSharpAndSDK
{
    static class Program
    {
        /// <summary>
        /// 应用程序的主入口点。
        /// </summary>
        [STAThread]
        static void Main()
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            Application.Run(new Form1());
        }

    }
    public  class baslerCamcs 
    {
        //连接相机的个数
        public int CameraNumber = CameraFinder.Enumerate().Count;

        //委托+事件=回调函数,用于传递相机抓取的图像
        public delegate void CameraImage(Bitmap bmp);
        public event CameraImage CameraImageEvent;

        //放出一个Camera
        Camera camera;

        //basler里将相机采集到的图像转换成位图
        PixelDataConverter pxConvert = new PixelDataConverter();

        //控制相机采集图片的过程!
        bool Graber = true;

        //第一步初始化相机  所用的全是camera里的事件然后绑定自己写好的事件
        public void CameraInit()
        {
            //相当于初始化了一下相机的动态链接库 可以调用Camera里面的东西了
            camera = new Camera();

            //自由连接模式     
            //当连接到相机时自动应用此配置
            //打开后,将其添加到Basler.Pylon.ICamera中。在打电话之前,摄像头打开了活动
            camera.CameraOpened += Configuration.AcquireContinuous;

            //断开连接事件
            camera.ConnectionLost += Camera_ConnectionLost;

            //抓取开始事件
            camera.StreamGrabber.GrabStarted += StreamGrabber_GrabStarted;

            //抓取图片事件
            camera.StreamGrabber.ImageGrabbed += StreamGrabber_ImageGrabbed;

            //抓取结束事件
            camera.StreamGrabber.GrabStopped += StreamGrabber_GrabStopped;
            //打开相机
            //StreamGrabber_GrabStarted
            //StreamGrabber_GrabStopped
            camera.Open();
        }
       
        /// <summary>
        /// 停止抓取
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void StreamGrabber_GrabStopped(object sender, GrabStopEventArgs e)
        {
            Graber = false;
        }

        /// <summary>
        /// 抓取图片
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void StreamGrabber_ImageGrabbed(object sender, ImageGrabbedEventArgs e)
        {
            IGrabResult grabResult = e.GrabResult;
            if (grabResult.IsValid)
            {
                if (Graber)
                {
                    //委托就用到了!
                    CameraImageEvent(GrabResult2Bmp(grabResult));
                }
            }
          
        }

        /// <summary>
        /// 开始抓取
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void StreamGrabber_GrabStarted(object sender, EventArgs e)
        {
            Graber = true;
        }

        /// <summary>
        /// 断开连接
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void Camera_ConnectionLost(object sender, EventArgs e)
        {
            try
            {
                //停止连接
                camera.StreamGrabber.Stop();
                //释放相机资源
                DestroyCamera();
            }
            catch (Exception)
            {
                return;
            }
        }

        /// <summary>
        /// 释放相机
        /// </summary>
        public void DestroyCamera()
        {
            if (camera != null)
            {
                camera.Close();
                camera.Dispose();
                camera = null;
            }
            else
            {
                return;
            }
        }

        /// <summary>
        /// 将相机转换成图像转成Bitmap
        /// </summary>
        /// <param name="grabResult"></param>
        /// <returns></returns>
        Bitmap GrabResult2Bmp(IGrabResult grabResult)
        {
            //   PixelFormat   format:新的像素格式 System.Drawing.Bitmap。 这必须指定一个值,开头 Format。(参1:图宽,参2:图高,参3:像素格式)
            Bitmap b = new Bitmap(grabResult.Width, grabResult.Height, PixelFormat.Format32bppArgb);

            //BitmapData:指定位图像的属性
            BitmapData bitmapData = b.LockBits(new Rectangle(0, 0, b.Width, b.Height), ImageLockMode.ReadWrite, b.PixelFormat);
            //PixelType.BGRA8packed:抓取结果返回像素类型,由图像处理支持类使用
            pxConvert.OutputPixelFormat = PixelType.BGRA8packed;
            IntPtr bmpIntpr = bitmapData.Scan0;
            pxConvert.Convert(bmpIntpr, bitmapData.Stride * b.Height, grabResult);
            b.UnlockBits(bitmapData);
            return b;
        }


        public void OneShot()
        {
            if (Graber)
            {
                //PLCamera:所有可用于basler摄像机设备dByStre的参数名称列表  SingleFrame:启用单帧采集模式。
                camera.Parameters[PLCamera.AcquisitionMode].SetValue(PLCamera.AcquisitionMode.SingleFrame);

                camera.StreamGrabber.Start(1, GrabStrategy.OneByOne, GrabLoop.ProvidedByStreamGrabber);
                
            }
        }

        public void KeepShot()
        {
            //Continuous:启用连续采集模式。
            camera.Parameters[PLCamera.AcquisitionMode].SetValue(PLCamera.AcquisitionMode.Continuous);
            //GrabStrategy.OneByOne:默认的抓取策略
            //GrabLoop.ProvidedByStreamGrabber:定义了额外线程的使用
            camera.StreamGrabber.Start( GrabStrategy.OneByOne, GrabLoop.ProvidedByStreamGrabber);
        }

        public void Stop()
        {
            if (camera != null)
            {
                //流抓取停止
                camera.StreamGrabber.Stop();
            }
            else
            {
                MessageBox.Show("该相机已停止抓取");
            }
        }
    }
}

2、界面代码

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

namespace CSharpAndSDK
{
    public partial class Form1 : Form
    {
        public baslerCamcs camera { get; set; } = new baslerCamcs();
        public Form1()
        {
            InitializeComponent();
            //委托
            camera.CameraImageEvent += Camera_CameraImageEvent;
        }

        private void Camera_CameraImageEvent(Bitmap bmp)
        {
            //使用委托进行跨线程交互 防止线程卡死状态在Invoke前面加一个Begin
            pictureBox1.BeginInvoke(new  MethodInvoker(delegate
            {
                Bitmap old = pictureBox1.Image as Bitmap;
                pictureBox1.Image = bmp;
                if (old != null)
                    old.Dispose();
            }));
        }
        //拍一张
        private void button1_Click(object sender, EventArgs e)
        {
            camera.OneShot();
        }

        //停止
        private void button2_Click(object sender, EventArgs e)
        {
            camera.Stop();
        }

      
        /// 连续拍
        private void button3_Click(object sender, EventArgs e)
        {
            camera.KeepShot();
        }

        //当前窗体关闭的时候引发的释放相机
        private void Form1_FormClosed(object sender, FormClosedEventArgs e)
        {
            camera.DestroyCamera();
        }

        void Unanble()
        {
            this.button1.Enabled = false;
            this.button2.Enabled = false;
            this.button3.Enabled = false;
        }
        private void Form1_Load(object sender, EventArgs e)
        {
            //如果连接相机个数大于0的话 初始化之前写的CameraInit();
            if (camera.CameraNumber > 0)
            {
                camera.CameraInit();
            }
            else
            {
                MessageBox.Show("未连接到相机");
                Unanble();
            }
        }
    }
}

总结

通过Basler Pylon SDK,C#开发可快速实现工业相机的图像采集与处理。

本文提供的多线程与回调方案,兼顾实时性与资源效率,适用于高速检测、流水线监控等场景。

最后

如果你觉得这篇文章对你有帮助,不妨点个赞支持一下!你的支持是我继续分享知识的动力。如果有任何疑问或需要进一步的帮助,欢迎随时留言。

也可以加入微信公众号 [DotNet技术匠] 社区,与其他热爱技术的同行一起交流心得,共同成长!

优秀是一种习惯,欢迎大家留言学习!

作者:寻梦人i

出处:cnblogs.com/xunmengrenli/p/13392514.html

声明:网络内容,仅供学习,尊重版权,侵权速删,歉意致谢!