Basler Grab_CameraEvent

本文详细介绍了如何在C#中使用Basler.Pylon库实现相机(如GigE和USB)的ExposureEnd事件处理,包括配置事件触发器、事件处理器以及同步图像抓取。

C# 源码:

using System;
using Basler.Pylon;

namespace Grab_CameraEvents
{
    class EventCamera : Camera
    {
        private static Version Sfnc2_0_0 = new Version(2, 0, 0);

        private IntegerName exposureEndDataName;
        private IntegerName exposureEndFrameID;
        private IntegerName exposureEndTimestamp;

        // This IntegerName can be used for GigE as well as for USB cameras.
        public IntegerName ExposureEndDataName
        {
            get
            {
                return this.exposureEndDataName;
            }
        }

        // This IntegerName selects the frame ID and can be used for GigE as well as for USB cameras.
        public IntegerName ExposureEndFrameID
        {
            get
            {
                return this.exposureEndFrameID;
            }
        }

        // This IntegerName selects the timestamp and can be used for GigE as well as for USB cameras.
        public IntegerName ExposureEndTimestamp
        {
            get
            {
                return this.exposureEndTimestamp;
            }
        }

        public EventCamera()
            : base()
        {
        }


        // Configure camera for event trigger and register exposure end event handler.
        public bool Configure()
        {
            // In this sample, a software trigger is used to demonstrate synchronous processing of the grab results.
            // If you want to react to an event as quickly as possible, you have to use Configuration.AcquireContinuous.
            CameraOpened += Configuration.SoftwareTrigger;

            if (Parameters[PLCameraInstance.GrabCameraEvents].IsWritable)
            {
                Parameters[PLCameraInstance.GrabCameraEvents].SetValue( true );
            }
            else
            {
                throw new Exception( "Can not enable GrabCameraEvents." );
            }

            if (base.Open( 1000, TimeoutHandling.Return ))
            {
                //Check if camera supports waiting for trigger ready
                if (!base.CanWaitForFrameTriggerReady)
                {
                    throw new Exception( "This sample can only be used with cameras that can be queried whether they are ready to accept the next frame trigger." );
                }

                // Features, e.g., 'ExposureEnd', are named according to the GenICam Standard Feature Naming Convention (SFNC).
                // The SFNC defines a common set of features, their behavior, and the related parameter names.
                // This ensures the interoperability of cameras from different camera vendors.
                // Current Basler USB ace and all Basler ace 2 cameras models are based on SFNC version 2.0.
                // Older Basler GigE cameras are based on previous SFNC versions.
                // Accordingly, the behavior of these cameras and some parameters names will be different.
                // The SFNC version can be used to handle differences between camera device models.
                if (this.GetSfncVersion() < Sfnc2_0_0)
                {
                    // The naming convention for ExposureEnd differs between SFNC 2.0 and previous versions.
                    exposureEndDataName = PLGigECamera.ExposureEndEventTimestamp;
                    exposureEndFrameID = PLGigECamera.ExposureEndEventFrameID;
                    exposureEndTimestamp = PLGigECamera.ExposureEndEventTimestamp;
                }
                else // For SFNC 2.0 cameras, e.g. USB3 Vision cameras
                {
                    exposureEndDataName = PLUsbCamera.EventExposureEnd;
                    exposureEndFrameID = PLUsbCamera.EventExposureEndFrameID;
                    exposureEndTimestamp = PLUsbCamera.EventExposureEndTimestamp;
                }

                // Check if the device supports events.
                if (Parameters[PLCamera.EventSelector].CanSetValue( PLCamera.EventSelector.ExposureEnd ) == false)
                {
                    throw new Exception( "The device doesn't support exposure end event." );
                }

                // Add a callback function to receive the changed FrameID value.
                Parameters[exposureEndDataName].ParameterChanged += OnEventExposureEndData;
                // Enable sending of Exposure End events.
                // Select the event to receive.
                Parameters[PLCamera.EventSelector].SetValue( PLCamera.EventSelector.ExposureEnd );
                // Enable it.
                Parameters[PLCamera.EventNotification].SetValue( PLCamera.EventNotification.On );
            }
            return true;
        }

        // Event handler for exposure end. Only very short processing tasks should be performed by this method.
        // Otherwise, the event notification will block the processing of images.
        public void OnEventExposureEndData( Object sender, ParameterChangedEventArgs e )
        {
            if (Parameters[exposureEndFrameID].IsReadable && Parameters[exposureEndTimestamp].IsReadable)
            {
                Console.WriteLine( "OnEventExposureEndData: Camera: {0} EventArgs {1} FrameID {2} TimeStamp {3}"
                        , CameraInfo[CameraInfoKey.ModelName]
                        , e.Parameter.ToString()
                        , Parameters[exposureEndFrameID].ToString()
                        , Parameters[exposureEndTimestamp].ToString() );
            }
        }
    }

    class Grab_CameraEvent
    {
        internal static void Main()
        {
            const int c_countOfImagesToGrab = 10;
            int exitCode = 0;

            try
            {
                // Create a camera object and select the first camera device found.
                using (EventCamera eventCamera = new EventCamera())
                {
                    // Register the ExposureEnd event with the event handler member.
                    eventCamera.Configure();

                    // Register an event handler object with an anonymous method. The object is important if you want to unregister this event.
                    EventHandler<ParameterChangedEventArgs> handlerTimestamp = (s, e) =>
                    {
                        Console.WriteLine("Anonymous method: TimeStamp {0}", e.Parameter.ToString());
                    };

                    eventCamera.Parameters[eventCamera.ExposureEndTimestamp].ParameterChanged += handlerTimestamp;

                    eventCamera.StreamGrabber.Start( c_countOfImagesToGrab );
                    while (eventCamera.StreamGrabber.IsGrabbing)
                    {
                        if (eventCamera.WaitForFrameTriggerReady( 1000, TimeoutHandling.ThrowException ))
                        {
                            eventCamera.ExecuteSoftwareTrigger();
                        }
                        // Wait for an image and then retrieve it. A timeout of 5000 ms is used.
                        IGrabResult grabResult = eventCamera.StreamGrabber.RetrieveResult(5000, TimeoutHandling.ThrowException);
                        using (grabResult)
                        {
                            // Image grabbed successfully?
                            if (grabResult.GrabSucceeded)
                            {
                                ImageWindow.DisplayImage( 0, grabResult );
                            }
                            else
                            {
                                Console.WriteLine( "Error: {0} {1}", grabResult.ErrorCode, grabResult.ErrorDescription );
                            }
                        }
                    }
                    // If events are not required anymore, you should unregister the event handlers.
                    eventCamera.Parameters[eventCamera.ExposureEndDataName].ParameterChanged -= eventCamera.OnEventExposureEndData;
                    eventCamera.Parameters[eventCamera.ExposureEndTimestamp].ParameterChanged -= handlerTimestamp;
                }
            }
            catch (Exception e)
            {
                Console.Error.WriteLine( "Exception: {0}", e.Message );
                exitCode = 1;
            }
            finally
            {
                // Comment the following two lines to disable waiting on exit.
                Console.Error.WriteLine( "\nPress enter to exit." );
                Console.ReadLine();
            }

            Environment.Exit( exitCode );
        }
    }
}

public abstract class CameraBase : ICamera, IDisposable { #region 字段 private bool _disposed = false; private long _frameCounter = 0; #endregion #region ICamera 接口实现 - 属性 /// <summary> /// 相机连接状态 /// </summary> public virtual bool IsConnected { get; protected set; } /// <summary> /// 相机唯一标识 /// </summary> public string CameraId { get; protected set; } /// <summary> /// 图像宽度(像素) /// </summary> public virtual int Width { get; protected set; } = 1920; /// <summary> /// 图像高度(像素) /// </summary> public virtual int Height { get; protected set; } = 1200; /// <summary> /// 曝光时间(微秒) /// </summary> public virtual double ExposureTimeUs { get; set; } = 10000; /// <summary> /// 增益值 /// </summary> public virtual double Gain { get; set; } = 1.0; /// <summary> /// 图像接收事件 /// </summary> public virtual event Action<Bitmap, DateTime, long> ImageReceived; #endregion #region 构造函数和初始化 /// <summary> /// 构造函数 /// </summary> /// <param name="cameraId">相机唯一标识</param> /// <param name="width">图像宽度</param> /// <param name="height">图像高度</param> protected CameraBase(string cameraId, int width = 1920, int height = 1200) { CameraId = cameraId ?? throw new ArgumentNullException(nameof(cameraId)); Width = width > 0 ? width : throw new ArgumentException("宽度必须大于0", nameof(width)); Height = height > 0 ? height : throw new ArgumentException("高度必须大于0", nameof(height)); IsConnected = false; } /// <summary> /// 静态工厂方法:创建指定类型的相机实例(供后续扩展) /// </summary> public static ICamera Create(string cameraType, string cameraId) { // 这里可以后续扩展,通过反射动态创建具体相机实例 throw new NotImplementedException("需要通过具体相机工厂创建实例"); } #endregion #region ICamera 接口实现 - 方法(提供默认实现) /// <summary> /// 连接相机 - 默认实现 /// </summary> /// <returns>总是返回true,子类可重写</returns> public virtual bool Connect() { IsConnected = true; return true; } /// <summary> /// 断开相机连接 - 默认实现 /// </summary> public virtual void Disconnect() { StopGrabbing(); IsConnected = false; } /// <summary> /// 设置触发模式 - 默认实现 /// </summary> /// <param name="mode">触发模式</param> /// <param name="source">触发源</param> /// <returns>总是返回true,子类可重写</returns> public virtual bool SetTriggerMode(TriggerMode mode, string source = null) { // 记录触发模式设置,具体生效由子类实现 return true; } /// <summary> /// 软触发拍照 - 默认实现 /// 通过调用 GrabImage 并触发事件模拟软触发 /// </summary> /// <returns>触发是否成功</returns> public virtual bool Trigger() { if (!IsConnected) { return false; } try { var image = GrabImage(1000); if (image != null) { OnImageReceived(image); return true; } } catch (Exception ex) { // 记录日志 System.Diagnostics.Debug.WriteLine($"软触发失败: {ex.Message}"); } return false; } #endregion #region ICamera 接口实现 - 抽象方法(子类必须实现) /// <summary> /// 采集单帧图像(阻塞方式) /// </summary> /// <param name="timeout">超时时间(毫秒)</param> /// <returns>采集到的图像,失败返回null</returns> public abstract Bitmap GrabImage(int timeout = 5000); /// <summary> /// 开始连续采集 /// </summary> /// <returns>启动是否成功</returns> public abstract bool StartGrabbing(); /// <summary> /// 停止连续采集 /// </summary> public abstract void StopGrabbing(); #endregion #region 保护方法(供子类使用) /// <summary> /// 触发图像接收事件 /// </summary> /// <param name="image">采集到的图像</param> protected virtual void OnImageReceived(Bitmap image) { if (image == null) return; Interlocked.Increment(ref _frameCounter); ImageReceived?.Invoke(image, DateTime.Now, _frameCounter); } /// <summary> /// 验证相机连接状态 /// </summary> /// <param name="operationName">操作名称(用于错误信息)</param> /// <returns>是否已连接</returns> protected bool ValidateConnection(string operationName) { if (!IsConnected) { System.Diagnostics.Debug.WriteLine($"无法执行 {operationName}:相机未连接"); return false; } return true; } /// <summary> /// 安全执行相机操作(异常处理) /// </summary> /// <typeparam name="T">返回类型</typeparam> /// <param name="operation">要执行的操作</param> /// <param name="defaultValue">失败时的默认值</param> /// <param name="operationName">操作名称(用于日志)</param> /// <returns>操作结果</returns> protected T SafeExecute<T>(Func<T> operation, T defaultValue, string operationName) { try { return operation(); } catch (Exception ex) { System.Diagnostics.Debug.WriteLine($"{operationName} 执行失败: {ex.Message}"); return defaultValue; } } #endregion #region IDisposable 实现 /// <summary> /// 释放资源 /// </summary> public void Dispose() { Dispose(true); GC.SuppressFinalize(this); } /// <summary> /// 释放托管和非托管资源 /// </summary> /// <param name="disposing">是否释放托管资源</param> protected virtual void Dispose(bool disposing) { if (!_disposed) { if (disposing) { // 释放托管资源 } // 释放非托管资源 Disconnect(); _disposed = true; } } /// <summary> /// 析构函数 /// </summary> ~CameraBase() { Dispose(false); } #endregion #region 重写方法 /// <summary> /// 返回相机信息字符串 /// </summary> public override string ToString() { return $"Camera: {CameraId}, Connected: {IsConnected}, Resolution: {Width}x{Height}"; } #endregion }这个代码如何
最新发布
10-31
public interface ICamera : IDisposable { /// <summary> /// 相机是否已连接并就绪 /// </summary> bool IsConnected { get; } /// <summary> /// 相机唯一标识(如 serial number) /// </summary> string CameraId { get; } /// <summary> /// 当前分辨率宽度 /// </summary> int Width { get; } /// <summary> /// 当前分辨率高度 /// </summary> int Height { get; } /// <summary> /// 曝光时间(微秒) /// </summary> double ExposureTimeUs { get; set; } /// <summary> /// 增益(dB 或 raw value,依设备而定) /// </summary> double Gain { get; set; } /// <summary> /// 连接相机 /// </summary> /// <returns>是否成功</returns> bool Connect(); /// <summary> /// 断开连接 /// </summary> void Disconnect(); /// <summary> /// 开始连续采集图像(自由运行模式) /// 图像通过 ImageReceived 事件返回 /// </summary> /// <returns>是否启动成功</returns> bool StartGrabbing(); /// <summary> /// 停止采集 /// </summary> void StopGrabbing(); /// <summary> /// 软触发一次拍照(单帧) /// </summary> /// <returns>是否触发成功</returns> bool Trigger(); /// <summary> /// 获取最近一帧图像(阻塞等待结果) /// </returns> /// <param name="timeout">超时时间(毫秒)</param> /// <returns>位图图像,失败返回 null</returns> Bitmap GrabImage(int timeout = 5000); /// <summary> /// 设置触发模式 /// </summary> /// <param name="mode">触发类型</param> /// <param name="source">触发源(可选,如 Line1, Software)</param> /// <returns>是否设置成功</returns> bool SetTriggerMode(TriggerMode mode, string source = null); /// <summary> /// 图像采集完成后的回调事件 /// 参数: (capturedImage, timestamp, frameId) /// </summary> event Action<Bitmap, DateTime, long> ImageReceived; } /// <summary> /// 触发模式枚举 /// </summary> public enum TriggerMode { /// <summary> /// 自由运行:持续采集 /// </summary> FreeRun, /// <summary> /// 外部硬触发:由 IO 信号触发 /// </summary> HardwareTrigger, /// <summary> /// 软件触发:由程序调用 Trigger() 方法触发 /// </summary> SoftwareTrigger, /// <summary> /// 编码器同步触发(用于线扫飞拍) /// </summary> EncoderTrigger }这个为何没有打开相机和关闭相机,需要吗
10-31
### 回答1: basler_pylon_5.2.0.13457是巴斯勒公司开发的一个相机软件开发包(SDK),用于与其相机产品进行通信和控制。这个版本的软件包是在巴斯勒的前一个版本基础上进行的更新和改进。 这个软件包提供了一系列的函数和工具,使开发人员能够轻松地与巴斯勒相机进行交互。它支持主要的操作系统,如Windows和Linux,并提供了多种编程语言的接口,如C++、C#和Python。 使用basler_pylon_5.2.0.13457,开发人员可以很容易地获取相机的图像数据,调整相机的参数,如曝光时间、增益和白平衡,并控制相机的触发方式。此外,它还提供了一些高级功能,如图像处理和相机校准,以改善相机的性能和图像质量。 除了基本的相机控制功能,basler_pylon_5.2.0.13457还为用户提供了一些扩展功能。例如,它支持相机的远程访问和控制,允许用户通过网络来控制相机。此外,它还提供了一些工具,用于相机的固件升级和配置。 总之,basler_pylon_5.2.0.13457是一个功能强大的相机软件开发包,可用于与巴斯勒相机进行集成和开发。它提供了丰富的功能和接口,使开发人员能够轻松地控制和操作相机,从而满足不同应用场景的需求。 ### 回答2: basler_pylon_5.2.0.13457是一个摄像头驱动程序的版本号。Basler是一家专门从事工业摄像机的生产的公司,他们的相机广泛应用于工业视觉和机器视觉领域。 Pylon是Basler提供的一个软件包,用于控制和操作他们的摄像头产品。而版本号5.2.0.13457代表了这个软件包的特定版本。 每个版本的软件包都会有一些改进和更新,以提高摄像头的性能和功能。对于basler_pylon_5.2.0.13457这个版本,具体的改进和更新内容需要查阅Basler的官方文档或者联系他们的技术支持团队来获取。 通常,更新摄像头驱动程序的版本可以带来更好的相机性能、更稳定的操作以及更多的功能选项。用户可以根据自己的需求和使用情况,决定是否升级到新版本。 总结来说,basler_pylon_5.2.0.13457是Basler公司提供的摄像头控制软件包的特定版本号,通过更新软件版本,用户可以享受到更好的相机性能和更多的功能选项。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值