C# 相机Burst模式图像采集:使用相机内存配合OpenCvSharp和Halcon实现短时间的高速采集的方法

C# 相机Burst模式图像采集:使用相机内存配合OpenCvSharp和Halcon实现短时间的高速采集的方法

C# 相机Burst模式图像采集:使用相机内存配合OpenCvSharp和Halcon实现短时间的高速采集的方法

做飞拍项目的时候,经常碰到一种情况:产品一瞬间过去了,相机拍到了,但千兆网带宽不够,图像传不出来,下一帧又来了,直接丢帧。后来换了带Burst模式的相机,问题才解决。

一、Burst模式到底是什么?

简单说就是先存后传

普通模式下,相机拍到一帧就往电脑传一帧。千兆网一秒最多传100多MB,高分辨率高帧率一超,数据就在网口排队,直接丢帧。

Burst模式不一样。收到触发之后,相机不管你传不传得出去,先把一连串图像高速往自己内部内存里塞。塞完了,再从内存往外慢慢传给你。

相当于给相机装了个"临时仓库",先猛拍存起来,再慢慢往外搬。拍的时候不卡你速度,搬的时候不丢你数据。

内部缓存有多大?

不同品牌差异挺大。堡盟QX系列自带2GB图像内存,全分辨率下能缓存169张1200万像素的图。更高端的型号甚至有8GB内存。Basler的ace 2系列也支持高速Burst模式,可以绕过GigE的数据限制。

说白了就是:接口带宽不够,相机内存来凑。

二、什么时候该用Burst?

最典型的场景是高速飞拍。产品在传送带上嗖一下过去,曝光时间只有几十微秒。一帧拍完了,下一帧还不知道什么时候来。Burst模式拍完一批慢慢传,不影响下一批采集。

另一个场景是多相机同时触发。几台相机同时咔嚓一下,每台都往电脑传大图,千兆网瞬间塞满。Burst模式先把图存在各自相机里,再排队往外传,网络压力分散了。

如果相机持续30fps不停拍,Burst模式帮不上忙------内部缓存很快满,满了就只能等传输,最终还是被接口带宽卡住。Burst适合的是"短时间高速抓拍,然后慢慢传"的场景。

以下是丰富后的完整内容,适合发布到 CSDN:


三、怎么配置 Burst 模式?

Basler(pylon .NET API)

Basler 的 Burst 模式分两种:

模式 特点 适用场景
Standard 模式 快速连拍,帧率略低,连拍间隔短 一般高速检测,需要较高 Duty Cycle
HighSpeed 模式 帧率拉到最高,每组连拍后有恢复间隔 极高速瞬态捕捉,如爆炸、冲击测试
csharp 复制代码
using Basler.Pylon;

public class BaslerBurstConfig
{
    /// <summary>
    /// 配置 Basler 相机 Burst 模式(HighSpeed)
    /// </summary>
    public void ConfigureBurstMode(Camera camera, int burstFrameCount = 50)
    {
        // 1. 选择触发源为 Burst 起始触发
        camera.Parameters[PLCamera.TriggerSelector].SetValue(
            PLCamera.TriggerSelector.FrameBurstStart);
        
        // 2. 开启触发模式
        camera.Parameters[PLCamera.TriggerMode].SetValue(
            PLCamera.TriggerMode.On);
        
        // 3. 选择高速 Burst 模式(Standard 或 HighSpeed)
        camera.Parameters[PLCamera.BslAcquisitionBurstMode].SetValue(
            PLCamera.BslAcquisitionBurstModeEnum.HighSpeed);
        
        // 4. 设置每次连拍帧数(相机内部缓存容量决定上限)
        camera.Parameters[PLCamera.AcquisitionBurstFrameCount].SetValue(burstFrameCount);
        
        // 5. 设置触发源(硬触发推荐 Line1,软触发用 Software)
        camera.Parameters[PLCamera.TriggerSource].SetValue(
            PLCamera.TriggerSource.Line1);
        
        // 6. 可选:设置触发极性
        camera.Parameters[PLCamera.TriggerActivation].SetValue(
            PLCamera.TriggerActivation.RisingEdge);
        
        Console.WriteLine($"Burst 模式已配置:每次触发连拍 {burstFrameCount} 帧");
    }
    
    /// <summary>
    /// 开始采集并注册回调
    /// </summary>
    public void StartBurstAcquisition(Camera camera, int totalTriggerCount)
    {
        // 配置采集模式为 MultiFrame(总帧数 = 触发次数 × 每次 Burst 帧数)
        int totalFrames = totalTriggerCount * 
            (int)camera.Parameters[PLCamera.AcquisitionBurstFrameCount].GetValue();
        
        camera.Parameters[PLCamera.AcquisitionMode].SetValue(
            PLCamera.AcquisitionMode.MultiFrame);
        camera.Parameters[PLCamera.AcquisitionFrameCount].SetValue(totalFrames);
        
        // 注册图像到达回调
        camera.StreamGrabber.ImageGrabbed += OnImageGrabbed;
        
        // 开始采集
        camera.StreamGrabber.Start(totalFrames);
    }
    
    private void OnImageGrabbed(object sender, ImageGrabbedEventArgs e)
    {
        if (e.GrabResult.GrabSucceeded)
        {
            // 获取图像数据指针和参数
            IntPtr buffer = e.GrabResult.GetBuffer();
            int width = e.GrabResult.Width;
            int height = e.GrabResult.Height;
            PixelType pixelType = e.GrabResult.PixelType;
            
            // 送入处理队列(非阻塞)
            _imageQueue.Enqueue(new RawImageData 
            { 
                Buffer = buffer, 
                Width = width, 
                Height = height,
                PixelType = pixelType,
                Timestamp = e.GrabResult.TimeStamp 
            });
        }
    }
}

/// <summary>
/// 原始图像数据结构
/// </summary>
public class RawImageData
{
    public IntPtr Buffer { get; set; }
    public int Width { get; set; }
    public int Height { get; set; }
    public PixelType PixelType { get; set; }
    public long Timestamp { get; set; }
}

关键注意点 :配置完 TriggerMode 之后,每触发一次,相机就连拍 50 帧存在内部缓存里。如果相机缓存不足(如 200MB),而 50 帧 12MP 图像约 600MB,则必须边拍边取,不能等全部拍完再取。


堡盟(BGAPI SDK)

堡盟 QX 系列相机内置 2GB 高速内存 ,通过 MemoryMode 参数控制内存行为,这是其 Burst 模式的核心优势:

MemoryMode 取值 说明
Off 关闭内存缓存,实时传输
Active 内存激活,用于帧缓冲
Burst 连拍模式,触发后高速写入内存
Config 配置模式,设置内存分区参数
csharp 复制代码
using Baumer.BGAPI;

public class BaumerBurstConfig
{
    private BGAPI.Device _curDevice;
    
    /// <summary>
    /// 配置堡盟 QX 系列 Burst 模式
    /// </summary>
    public void ConfigureBurstMode(int blockCount = 680)
    {
        // 1. 进入内存配置模式(必须先切到 Config 才能改参数)
        _curDevice.RemoteNodeList["MemoryMode"].Value = "Config";
        
        // 2. 设置分区模式:Once = 一次性填满后停止,Circular = 循环覆盖
        _curDevice.RemoteNodeList["MemoryPartMode"].Value = "Once";
        
        // 3. 设置缓存块数(QX 系列 2GB 内存,12MP 约可存 680 张)
        // 计算公式:BlockCount = 总内存(Bytes) / (宽 × 高 × 像素深度)
        _curDevice.RemoteNodeList["MemoryPartBlocks"].Value = blockCount.ToString();
        
        // 4. 启用 Burst 模式
        _curDevice.RemoteNodeList["MemoryMode"].Value = "Burst";
        
        // 5. 配置触发(硬触发或软触发)
        _curDevice.RemoteNodeList["TriggerMode"].Value = "On";
        _curDevice.RemoteNodeList["TriggerSource"].Value = "Line0";
        
        Console.WriteLine($"堡盟 Burst 模式已配置:缓存 {blockCount} 张图像");
    }
    
    /// <summary>
    /// 从内存批量读取图像(Burst 拍完后执行)
    /// </summary>
    public void ReadBurstImagesFromMemory()
    {
        // 切到 Active 模式开始读取
        _curDevice.RemoteNodeList["MemoryMode"].Value = "Active";
        
        // 获取实际存储的图像数量
        int storedCount = int.Parse(_curDevice.RemoteNodeList["MemoryPartBlocksFilled"].Value);
        
        for (int i = 0; i < storedCount; i++)
        {
            // 设置读取索引
            _curDevice.RemoteNodeList["MemoryReadIndex"].Value = i.ToString();
            
            // 取图
            BGAPI.Image image = _curDevice.GetImage(1000); // 1秒超时
            
            if (image != null)
            {
                IntPtr buffer = image.Buffer;
                int width = image.Width;
                int height = image.Height;
                
                // 送入处理队列
                ProcessImage(buffer, width, height);
                
                image.Release();
            }
        }
        
        // 读取完成后重置
        _curDevice.RemoteNodeList["MemoryMode"].Value = "Burst";
    }
}

堡盟特色 :2GB 内置内存允许先全部拍完再慢慢取图,适合触发后无法实时处理的场景(如野外高速测试、无 PC 的独立采集)。


海康(MVS SDK)

海康 MVS SDK 中 Burst 功能叫触发帧计数AcquisitionBurstFrameCount),配合触发模式使用:

csharp 复制代码
using MvCamCtrl.NET;

public class HikBurstConfig
{
    private MyCamera _camera;
    private MyCamera.MV_CC_DEVICE_INFO _deviceInfo;
    
    /// <summary>
    /// 配置海康相机 Burst 模式
    /// </summary>
    public int ConfigureBurstMode(uint burstFrameCount = 50)
    {
        int nRet;
        
        // 1. 设置采集模式为 MultiFrame
        nRet = _camera.MV_CC_SetEnumValue_NET("AcquisitionMode", 
            (uint)MyCamera.MV_CAM_ACQUISITION_MODE.MV_ACQ_MODE_MultiFrame);
        if (MyCamera.MV_OK != nRet) return nRet;
        
        // 2. 设置触发帧数(Burst 数量)
        nRet = _camera.MV_CC_SetIntValue_NET("AcquisitionBurstFrameCount", burstFrameCount);
        if (MyCamera.MV_OK != nRet) return nRet;
        
        // 3. 开启触发模式
        nRet = _camera.MV_CC_SetEnumValue_NET("TriggerMode", 
            (uint)MyCamera.MV_CAM_TRIGGER_MODE.MV_TRIGGER_MODE_ON);
        if (MyCamera.MV_OK != nRet) return nRet;
        
        // 4. 设置触发源(软触发或硬触发)
        nRet = _camera.MV_CC_SetEnumValue_NET("TriggerSource", 
            (uint)MyCamera.MV_CAM_TRIGGER_SOURCE.MV_TRIGGER_SOURCE_SOFTWARE);
        if (MyCamera.MV_OK != nRet) return nRet;
        
        // 5. 设置总帧数(触发次数 × Burst 帧数)
        uint totalFrames = burstFrameCount * 10; // 计划触发 10 次
        nRet = _camera.MV_CC_SetIntValue_NET("AcquisitionFrameCount", totalFrames);
        
        Console.WriteLine($"海康 Burst 模式已配置:每次触发 {burstFrameCount} 帧");
        return nRet;
    }
    
    /// <summary>
    /// 执行软触发一次,连拍 50 张
    /// </summary>
    public int TriggerSoftwareBurst()
    {
        return _camera.MV_CC_SetCommandValue_NET("TriggerSoftware");
    }
    
    /// <summary>
    /// 注册图像回调(取图)
    /// </summary>
    public int RegisterImageCallback(cbOutputExdelegate callback)
    {
        // 设置回调函数,Burst 模式下会连续触发回调
        return _camera.MV_CC_RegisterImageCallBackEx_NET(callback, IntPtr.Zero);
    }
}

海康注意点 :触发一次后连续出图,此时系统必须维持稳定的处理流水线。如果处理速度跟不上出图速度,SDK 内部缓冲区会溢出导致丢帧。建议配合大缓冲区 + 生产者-消费者队列使用。


四、拿到缓存图像之后怎么处理?

Burst 模式拍完一批图存在相机内部(或 SDK 缓冲区),应用程序需要持续从缓冲区取图。关键是不能阻塞取图线程,否则相机缓存满后会丢帧或停止采集。

生产者-消费者队列架构

csharp 复制代码
using System.Collections.Concurrent;
using System.Threading;

/// <summary>
/// 线程安全的图像处理队列
/// </summary>
public class ImageProcessingPipeline : IDisposable
{
    private readonly ConcurrentQueue<RawImageData> _imageQueue = new();
    private readonly CancellationTokenSource _cts = new();
    private Thread _consumerThread;
    private int _processedCount = 0;
    private int _droppedCount = 0;
    
    // 队列长度限制(防止内存无限增长)
    private const int MAX_QUEUE_SIZE = 100;
    
    public void Start()
    {
        _consumerThread = new Thread(ConsumerLoop);
        _consumerThread.IsBackground = true;
        _consumerThread.Start();
    }
    
    /// <summary>
    /// 生产者:相机回调中调用,快速入队
    /// </summary>
    public bool EnqueueImage(RawImageData image)
    {
        if (_imageQueue.Count >= MAX_QUEUE_SIZE)
        {
            // 队列满,丢弃最旧帧或当前帧(根据策略)
            Interlocked.Increment(ref _droppedCount);
            return false;
        }
        
        _imageQueue.Enqueue(image);
        return true;
    }
    
    /// <summary>
    /// 消费者:后台线程持续处理
    /// </summary>
    private void ConsumerLoop()
    {
        while (!_cts.Token.IsCancellationRequested)
        {
            if (_imageQueue.TryDequeue(out RawImageData image))
            {
                try
                {
                    ProcessImage(image);
                    Interlocked.Increment(ref _processedCount);
                }
                finally
                {
                    // 释放非托管内存
                    if (image.Buffer != IntPtr.Zero)
                    {
                        // 根据 SDK 要求释放
                        // Marshal.FreeHGlobal(image.Buffer); 
                    }
                }
            }
            else
            {
                // 队列为空,短暂休眠避免 CPU 空转
                Thread.Sleep(1);
            }
        }
    }
    
    /// <summary>
    /// 图像处理逻辑(可替换为 OpenCvSharp 或 Halcon)
    /// </summary>
    private void ProcessImage(RawImageData image)
    {
        // 根据像素格式选择处理方式
        switch (image.PixelFormat)
        {
            case PixelType.Mono8:
                ProcessMono8(image);
                break;
            case PixelType.BayerRG8:
                ProcessBayerRG8(image);
                break;
            case PixelType.RGB8:
                ProcessRGB8(image);
                break;
        }
    }
    
    private void ProcessMono8(RawImageData image)
    {
        // OpenCvSharp 零拷贝处理
        using (Mat mat = new Mat(image.Height, image.Width, MatType.CV_8UC1, image.Buffer))
        {
            // 高斯滤波去噪
            using Mat blurred = new Mat();
            Cv2.GaussianBlur(mat, blurred, new Size(3, 3), 0);
            
            // 边缘检测
            using Mat edges = new Mat();
            Cv2.Canny(blurred, edges, 50, 150);
            
            // 保存结果
            string filename = $"frame_{image.Timestamp}.png";
            Cv2.ImWrite(filename, edges);
        }
    }
    
    public void Stop()
    {
        _cts.Cancel();
        _consumerThread?.Join(2000);
    }
    
    public void Dispose()
    {
        Stop();
        _cts.Dispose();
    }
    
    public (int Processed, int Dropped) GetStatistics() => 
        (_processedCount, _droppedCount);
}

OpenCvSharp 处理思路(零拷贝 + 批量处理)

csharp 复制代码
using OpenCvSharp;
using System;
using System.IO;

public class OpenCvSharpBurstProcessor
{
    private readonly string _outputDir;
    
    public OpenCvSharpBurstProcessor(string outputDir)
    {
        _outputDir = outputDir;
        Directory.CreateDirectory(outputDir);
    }
    
    /// <summary>
    /// 处理 Burst 单帧(零拷贝包装)
    /// </summary>
    public void ProcessBurstFrame(IntPtr pData, int width, int height, 
        PixelType pixelType, long timestamp)
    {
        // 根据像素格式确定 MatType
        MatType matType = ConvertPixelType(pixelType);
        
        // 零拷贝包装(注意:pData 生命周期由相机 SDK 管理)
        using (Mat mat = new Mat(height, width, matType, pData))
        {
            // 如果是 Bayer 格式,先转 RGB
            if (pixelType == PixelType.BayerRG8)
            {
                using Mat rgb = new Mat();
                Cv2.CvtColor(mat, rgb, ColorConversionCodes.BayerRG2BGR);
                ProcessAndSave(rgb, timestamp);
            }
            else
            {
                ProcessAndSave(mat, timestamp);
            }
        }
    }
    
    private void ProcessAndSave(Mat image, long timestamp)
    {
        // 1. 预处理:灰度转换(如果是彩色图)
        using Mat gray = image.Channels() == 3 
            ? image.CvtColor(ColorConversionCodes.BGR2GRAY) 
            : image.Clone();
        
        // 2. 滤波去噪
        using Mat blurred = new Mat();
        Cv2.GaussianBlur(gray, blurred, new Size(5, 5), 0);
        
        // 3. 二值化
        using Mat binary = new Mat();
        Cv2.Threshold(blurred, binary, 0, 255, ThresholdTypes.Otsu);
        
        // 4. 形态学操作
        using Mat kernel = Cv2.GetStructuringElement(MorphShapes.Rect, new Size(3, 3));
        using Mat morphed = new Mat();
        Cv2.MorphologyEx(binary, morphed, MorphTypes.Open, kernel);
        
        // 5. 轮廓提取与筛选
        Cv2.FindContours(morphed, out Point[][] contours, out HierarchyIndex[] hierarchy, 
            RetrievalModes.External, ContourApproximationModes.Simple);
        
        // 6. 绘制结果
        using Mat result = image.Channels() == 1 
            ? Cv2.CvtColor(image, null, ColorConversionCodes.GRAY2BGR) 
            : image.Clone();
        
        foreach (var contour in contours)
        {
            double area = Cv2.ContourArea(contour);
            if (area > 100) // 面积过滤
            {
                Rect rect = Cv2.BoundingRect(contour);
                Cv2.Rectangle(result, rect, new Scalar(0, 255, 0), 2);
            }
        }
        
        // 7. 保存结果
        string path = Path.Combine(_outputDir, $"burst_{timestamp}.png");
        Cv2.ImWrite(path, result);
    }
    
    /// <summary>
    /// 批量处理 Burst 序列(适合事后分析)
    /// </summary>
    public void ProcessBurstSequence(IntPtr[] buffers, int width, int height, 
        PixelType pixelType, long[] timestamps)
    {
        // 使用 Parallel.For 多线程处理已缓存的 Burst 序列
        Parallel.For(0, buffers.Length, i =>
        {
            ProcessBurstFrame(buffers[i], width, height, pixelType, timestamps[i]);
        });
    }
    
    private MatType ConvertPixelType(PixelType pt)
    {
        return pt switch
        {
            PixelType.Mono8 => MatType.CV_8UC1,
            PixelType.RGB8 => MatType.CV_8UC3,
            PixelType.Mono16 => MatType.CV_16UC1,
            _ => MatType.CV_8UC1
        };
    }
}

Halcon 处理思路(原生算子 + HDevEngine 集成)

csharp 复制代码
using HalconDotNet;

public class HalconBurstProcessor : IDisposable
{
    private readonly HWindow _window;
    private readonly string _outputDir;
    
    public HalconBurstProcessor(string outputDir)
    {
        _outputDir = outputDir;
        _window = new HWindow();
        System.IO.Directory.CreateDirectory(outputDir);
    }
    
    /// <summary>
    /// 处理 Burst 单帧(从指针创建 HImage)
    /// </summary>
    public void ProcessBurstFrame(IntPtr pData, int width, int height, 
        string pixelType, long timestamp)
    {
        // 从原始指针创建 Halcon 图像(零拷贝或浅拷贝,取决于 SDK)
        // 注意:Halcon 的 GenImage1Extern 需要管理内存生命周期
        HImage image = new HImage(pixelType, width, height, pData);
        
        try
        {
            // 1. 高斯滤波
            HImage smoothed = image.GaussFilter(5.0);
            
            // 2. 边缘提取(亚像素精度)
            HXLDCont edges = smoothed.EdgesSubPix("canny", 1.0, 20, 40);
            
            // 3. 分割区域
            HRegion region = smoothed.Threshold(128, 255);
            HRegion connected = region.Connection();
            
            // 4. 形状筛选
            HRegion selected = connected.SelectShape("area", "and", 100, 999999);
            
            // 5. 获取特征
            HTuple areas, row, column;
            selected.AreaCenter(out areas, out row, out column);
            
            // 6. 绘制结果
            _window.SetColor("green");
            _window.DispObj(image);
            _window.SetColor("red");
            _window.DispObj(selected);
            
            // 7. 保存结果
            string path = System.IO.Path.Combine(_outputDir, $"halcon_burst_{timestamp}.tif");
            image.WriteImage("tiff", 0, path);
            
            // 8. 释放资源
            edges.Dispose();
            region.Dispose();
            connected.Dispose();
            selected.Dispose();
        }
        finally
        {
            image.Dispose();
        }
    }
    
    /// <summary>
    /// 使用 HDevEngine 执行 HDevelop 脚本处理 Burst 序列
    /// </summary>
    public void ProcessWithHDevEngine(IntPtr[] buffers, int width, int height, 
        string pixelType, long[] timestamps, string hdevPath)
    {
        HDevEngine engine = new HDevEngine();
        engine.SetProcedurePath(System.IO.Path.GetDirectoryName(hdevPath));
        
        HDevProgram program = new HDevProgram(hdevPath);
        HDevProgramCall call = new HDevProgramCall(program);
        
        for (int i = 0; i < buffers.Length; i++)
        {
            // 创建 HImage 并传入 HDevelop 程序
            HImage image = new HImage(pixelType, width, height, buffers[i]);
            
            call.SetInputIconicParamImage("Image", image);
            call.SetInputCtrlParamTuple("Timestamp", timestamps[i]);
            call.SetInputCtrlParamTuple("OutputDir", _outputDir);
            
            call.Execute();
            
            // 获取结果
            HTuple defectCount = call.GetOutputCtrlParamTuple("DefectCount");
            Console.WriteLine($"Frame {i}: 缺陷数 = {defectCount}");
            
            image.Dispose();
        }
        
        engine.Dispose();
    }
    
    /// <summary>
    /// 批量保存原始 Burst 数据(用于事后 Halcon 分析)
    /// </summary>
    public void SaveRawBurstData(IntPtr[] buffers, int width, int height, 
        int bytesPerPixel, long[] timestamps)
    {
        int frameSize = width * height * bytesPerPixel;
        
        for (int i = 0; i < buffers.Length; i++)
        {
            string path = System.IO.Path.Combine(_outputDir, $"raw_{timestamps[i]}.bin");
            byte[] data = new byte[frameSize];
            System.Runtime.InteropServices.Marshal.Copy(buffers[i], data, 0, frameSize);
            System.IO.File.WriteAllBytes(path, data);
        }
    }
    
    public void Dispose()
    {
        _window?.Dispose();
    }
}

性能对比与选型建议

处理方式 优点 缺点 适用场景
OpenCvSharp 零拷贝 免费开源,社区活跃,Bitmap 互转方便 工业相机 SDK 支持不如 Halcon 完善 中小型项目,预算有限
Halcon 原生算子 工业级稳定,算子优化极致,3D/深度学习原生支持 商业授权费用高 高精度工业检测,大规模部署
HDevEngine 脚本 快速原型,算法可热更新,非程序员也能调参 脚本执行有额外开销 算法频繁迭代,多项目复用
C# 多线程 + 队列 充分利用多核,解耦采集与处理 线程同步复杂,调试困难 高帧率、大数据量场景

CSDN 发布建议 :可补充实际测试数据(如 Basler acA2500 在 Burst 模式下的帧率-CPU 占用曲线图),增加说服力。标签:#C# #机器视觉 #Burst模式 #工业相机 #OpenCvSharp #Halcon

五、几个容易踩的坑

坑一:缓存满了自动丢帧。相机内部缓存满了之后,新拍的图会直接丢弃。在高速Burst模式下,连拍结束后的传输间隙要预留够。

坑二:Burst模式和普通触发混用。确认触发源配置正确,FrameBurstStart触发和普通FrameStart触发是两套独立的触发通道。

坑三:存图速度跟不上取图速度。Burst模式解决了"拍得快",没解决"存得快"。内部缓存满了之后,如果电脑取图太慢,新图一样会丢。后端的异步处理线程必须足够快,或者队列足够大。

坑四:不同品牌参数名不一样 。Basler叫BslAcquisitionBurstModeAcquisitionBurstFrameCount。海康叫AcquisitionBurstFrameCount。堡盟叫MemoryModeMemoryPartBlocks。换品牌的时候别照着抄。

六、什么时候该用,什么时候别用

该用:高速瞬态抓拍(碰撞测试、跌落分析)、多相机同时触发但网络带宽不够、需要短时间密集采样的场景。

不该用:24×7连续采集、相机内存容量小于单批图像总大小、对实时性要求极高(Burst模式有传输延迟)。

七、核心优势

优势维度 具体说明
高速连续捕获 以极高帧率连续采集多帧图像,数据暂存于相机内部高速缓存,避免实时传输瓶颈
零丢帧保障 规避常规连续采集中因总线带宽不足或 OS 调度延迟导致的丢帧问题,确保关键帧完整捕获
总线带宽优化 批量传输而非逐帧实时传输,降低对 GigE/USB3 等接口的持续带宽压力
CPU 占用降低 配合异步回调或零拷贝传输,减少 C# 应用层线程阻塞与上下文切换开销
触发响应精准 外部硬触发信号启动 Burst,实现微秒级同步,适合与产线 PLC/编码器联动
C# 集成友好 主流 SDK(Basler Pylon、Baumer、Halcon)均提供 GrabImageBurst 等托管接口,异步编程模型成熟

八、行业应用

应用领域 典型场景 Burst 模式价值
半导体检测 晶圆表面缺陷扫描、Die 级 AOI 高速旋转/平移中捕获数百帧,不遗漏细微瑕疵
锂电池制造 极片涂布缺陷检测、极耳尺寸测量 配合频闪光源冻结运动模糊,获取清晰边缘轮廓
3C 电子 手机屏幕跌落测试、按键寿命测试 连续记录高速冲击/回弹过程,逐帧回溯分析失效机理
汽车安全 安全气囊点爆形态分析、碰撞测试 毫秒级捕捉气囊展开全过程,验证设计参数
食品/医药包装 高速灌装液位检测、封膜完整性检查 产线 600+ 瓶/分钟速度下,确保每瓶都有独立检测帧
高速运动分析 弹道轨迹追踪、机械振动模态分析 高帧率序列支持慢动作回放与运动学参数提取

九、选型建议速查

场景特征 推荐配置
帧率 > 500fps 选择 Camera Link / CoaXPress 接口 + 大容量相机缓存
多相机同步 外触发 + PTP(IEEE 1588)精确时间协议
长时间 Burst 关注相机缓存容量(如 4GB DDR),或配合 RAID 阵列实时落盘
C# 低延迟处理 使用 unsafe 代码或 Span<byte> 避免 Bitmap 拷贝开销

CSDN 发布建议 :可配合实际项目截图(如 Halcon HSmartWindow 显示 Burst 序列、Basler Pylon Viewer 参数配置界面),增加阅读体验。标签建议:#C# #机器视觉 #工业相机 #Burst模式 #图像采集

十、总结

Burst模式的核心就一句话:拍的时候只管往内存里塞,传的时候慢慢往外倒。相机内部缓存越大的话,那么能扛的爆发速度越高。

把Burst模式和普通连续采集区分开------前者解决的是"短时间拍得快",后者解决的是"长时间传得稳"。两个场景不同,别混着用。

小提示:第一次用Burst模式,先用MVS或pylon Viewer手动触发一次,看相机内部缓存能存多少张、传完需要多久,心里有个底再写代码。不同分辨率下缓存张数不一样,ROI开得越小,能存的张数越多。

相关推荐
轮到我狗叫了21 分钟前
Slurm如何使用
人工智能·python·深度学习·机器学习
chen<>24 分钟前
C++ 六种 memory_order:从原子性到线程间可见性.md
java·linux·开发语言·c++
AI创界者26 分钟前
【开源硬核】comfyUI MiniMax H3 融合模型本地部署一键整合包!单卡撬动 2K 影音全模态输出,附避坑指南
人工智能·aigc
一直C26 分钟前
Linux系统编程|进程间通信IPC全套详解(1)(管道、信号)
linux·c语言·开发语言·网络·青少年编程·visual studio code
2601_9637491029 分钟前
越华环保集团|河湖工况下数字化污水治理云边协同采集架构实现
人工智能·架构
闪学it34 分钟前
小滴课堂-AI大模型小龙虾-OpenClaw-0基础从入门到实战
人工智能
代码方舟34 分钟前
零信任架构实战:基于天远手机携号转网V即时版构建自动化营销风控网关
人工智能·智能手机·架构·自动化
会周易的程序员34 分钟前
企业私有 AI 算力服务器架构设计:异构四节点 + QUIC 微服务
运维·服务器·c++·人工智能·微服务·架构
闪学it37 分钟前
AE影视后期特效-遮罩/调色/抠像/MG动画/3D/Vlog制作
人工智能