C# 联合 VisionPro 进行相机采集

一、前置条件

  1. 硬件 / 软件准备
    • 工业相机(支持 GenICam/ GigE/ USB3 Vision 协议,如 Basler、Hikvision、Keyence 等)
    • 已安装相机厂商驱动和 VisionPro 相机适配包(Cognex FrameGrabber)
    • 确保 VisionPro 的Cognex.VisionPro.FrameGrabber.dll已添加到项目引用
  2. 核心概念
    • CogFrameGrabber:VisionPro 中管理相机的核心类,用于枚举、连接相机
    • CogAcqFifo:采集队列,用于控制相机的单次 / 连续采图
    • CogImageData:采集到的图像数据对象

二、完整相机采集代码示例

以下示例包含枚举相机、连接相机、单次采图、连续采图、释放资源等核心功能,可直接运行:

cs 复制代码
using System;
using System.Linq;
using Cognex.VisionPro;
using Cognex.VisionPro.FrameGrabber;
using Cognex.VisionPro.Display;
using System.Threading;

namespace VisionProCameraCapture
{
    class CameraCaptureDemo
    {
        // 相机核心对象
        private CogFrameGrabber _frameGrabber; // 帧采集器(相机)
        private CogAcqFifo _acqFifo;           // 采集队列
        private CogDisplay _cogDisplay;         // 图像显示控件(WinForm用)
        private bool _isContinuousCapture = false; // 是否连续采集
        private Thread _captureThread;          // 连续采集线程

        // WinForm窗体(示例用,可替换为你的窗体)
        private System.Windows.Forms.Form _mainForm;

        static void Main(string[] args)
        {
            CameraCaptureDemo demo = new CameraCaptureDemo();
            
            try
            {
                // 1. 初始化窗体和显示控件(可选,用于可视化)
                demo.InitDisplayForm();

                // 2. 枚举并连接相机
                if (!demo.ConnectCamera())
                {
                    Console.WriteLine("相机连接失败!");
                    return;
                }

                // 示例1:单次采图
                Console.WriteLine("开始单次采图...");
                var singleImage = demo.CaptureSingleImage();
                if (singleImage != null)
                {
                    Console.WriteLine("单次采图成功!");
                    demo.ShowImage(singleImage); // 显示图像
                }

                // 示例2:连续采图(运行5秒后停止)
                Console.WriteLine("开始连续采图(5秒后停止)...");
                demo.StartContinuousCapture();
                Thread.Sleep(5000); // 采集5秒
                demo.StopContinuousCapture();
                Console.WriteLine("连续采图已停止!");
            }
            catch (Exception ex)
            {
                Console.WriteLine($"程序异常:{ex.Message}");
                Console.WriteLine($"异常详情:{ex.StackTrace}");
            }
            finally
            {
                // 3. 释放所有资源
                demo.DisposeAllResources();
            }

            Console.WriteLine("按任意键退出...");
            Console.ReadLine();
        }

        /// <summary>
        /// 初始化显示窗体和CogDisplay控件(WinForm)
        /// </summary>
        private void InitDisplayForm()
        {
            _mainForm = new System.Windows.Forms.Form();
            _mainForm.Text = "VisionPro相机采集预览";
            _mainForm.Size = new System.Drawing.Size(800, 600);

            // 创建VisionPro图像显示控件
            _cogDisplay = new CogDisplay();
            _cogDisplay.Dock = System.Windows.Forms.DockStyle.Fill;
            _mainForm.Controls.Add(_cogDisplay);

            // 显示窗体
            _mainForm.Show();
        }

        /// <summary>
        /// 枚举相机并建立连接
        /// </summary>
        /// <returns>是否连接成功</returns>
        public bool ConnectCamera()
        {
            try
            {
                // 1. 获取所有可用的帧采集器(相机)
                CogFrameGrabber[] frameGrabbers = CogFrameGrabber.Show(true);
                if (frameGrabbers == null || frameGrabbers.Length == 0)
                {
                    Console.WriteLine("未检测到任何相机!");
                    return false;
                }

                // 2. 选择第一个相机(也可根据相机名称/ID筛选)
                _frameGrabber = frameGrabbers[0];
                Console.WriteLine($"已找到相机:{_frameGrabber.Name}");

                // 3. 创建采集队列(AcqFifo)
                // VideoFormat:相机分辨率/像素格式(可通过相机配置工具预设)
                _acqFifo = _frameGrabber.CreateAcqFifo("Default", CogAcqFifoPixelFormatConstants.Mono8, 1, false);
                _acqFifo.Start(); // 启动采集队列
                Console.WriteLine("相机连接成功!");
                return true;
            }
            catch (Exception ex)
            {
                Console.WriteLine($"相机连接异常:{ex.Message}");
                return false;
            }
        }

        /// <summary>
        /// 单次采图
        /// </summary>
        /// <returns>采集到的图像对象</returns>
        public CogImage8Grey CaptureSingleImage()
        {
            if (_acqFifo == null || !_acqFifo.Running)
            {
                Console.WriteLine("采集队列为空或未启动!");
                return null;
            }

            try
            {
                // 等待采集图像(超时时间5000ms)
                CogImageData imageData = _acqFifo.Acquire(5000, out bool timedOut);
                if (timedOut)
                {
                    Console.WriteLine("单次采图超时!");
                    return null;
                }

                // 转换为8位灰度图(工业视觉常用)
                CogImage8Grey greyImage = new CogImage8Grey(imageData);
                imageData.Dispose(); // 释放原始图像数据
                return greyImage;
            }
            catch (Exception ex)
            {
                Console.WriteLine($"单次采图失败:{ex.Message}");
                return null;
            }
        }

        /// <summary>
        /// 开始连续采图
        /// </summary>
        public void StartContinuousCapture()
        {
            if (_isContinuousCapture || _acqFifo == null)
                return;

            _isContinuousCapture = true;
            // 启动后台线程采集(避免阻塞UI)
            _captureThread = new Thread(ContinuousCaptureLoop)
            {
                IsBackground = true // 后台线程,程序退出时自动终止
            };
            _captureThread.Start();
        }

        /// <summary>
        /// 连续采图循环
        /// </summary>
        private void ContinuousCaptureLoop()
        {
            while (_isContinuousCapture)
            {
                var image = CaptureSingleImage();
                if (image != null)
                {
                    ShowImage(image); // 实时显示图像
                    image.Dispose();  // 释放图像资源(避免内存暴涨)
                }
                Thread.Sleep(10); // 控制采集频率(可根据需求调整)
            }
        }

        /// <summary>
        /// 停止连续采图
        /// </summary>
        public void StopContinuousCapture()
        {
            _isContinuousCapture = false;
            // 等待线程结束
            if (_captureThread != null && _captureThread.IsAlive)
            {
                _captureThread.Join(1000);
            }
        }

        /// <summary>
        /// 在CogDisplay控件中显示图像
        /// </summary>
        /// <param name="image">要显示的图像</param>
        public void ShowImage(CogImage8Grey image)
        {
            if (_cogDisplay == null || image == null)
                return;

            // 跨线程访问UI控件需用Invoke
            _cogDisplay.Invoke(new Action(() =>
            {
                _cogDisplay.Image = image;
                _cogDisplay.Fit(true); // 自适应显示
            }));
        }

        /// <summary>
        /// 释放所有资源(关键!)
        /// </summary>
        public void DisposeAllResources()
        {
            // 停止连续采集
            StopContinuousCapture();

            // 释放采集队列
            if (_acqFifo != null)
            {
                if (_acqFifo.Running)
                    _acqFifo.Stop();
                _acqFifo.Dispose();
                _acqFifo = null;
            }

            // 释放帧采集器
            if (_frameGrabber != null)
            {
                _frameGrabber.Dispose();
                _frameGrabber = null;
            }

            // 释放显示控件和窗体
            if (_cogDisplay != null)
            {
                _cogDisplay.Dispose();
                _cogDisplay = null;
            }

            if (_mainForm != null)
            {
                _mainForm.Close();
                _mainForm.Dispose();
            }

            // 强制垃圾回收
            GC.Collect();
            GC.WaitForPendingFinalizers();
            Console.WriteLine("资源已全部释放!");
        }
    }
}

三、关键代码解释

  1. 相机枚举与连接

    • CogFrameGrabber.Show(true):弹出相机选择窗口,让用户选择要连接的相机(也可通过CogFrameGrabber.FrameGrabbers静默枚举)。
    • CreateAcqFifo:创建采集队列,参数说明:
      • "Default":相机配置文件名称(可在 VisionPro 中预设);
      • CogAcqFifoPixelFormatConstants.Mono8:像素格式(8 位灰度,工业场景首选);
      • 1:队列长度(单次采图设 1 即可);
      • false:非共享模式。
  2. 单次采图核心

    • _acqFifo.Acquire(5000, out bool timedOut):阻塞式采图,第一个参数是超时时间(ms),超时后timedOuttrue
    • CogImage8Grey(imageData):将原始采集数据转换为 VisionPro 可处理的灰度图像对象。
  3. 连续采图核心

    • 必须使用后台线程Thread)执行连续采图,避免阻塞 UI 线程导致界面卡死。
    • 每次采图后需调用image.Dispose()释放图像资源,否则会导致内存持续上涨。
  4. 图像显示

    • CogDisplay是 VisionPro 官方的图像显示控件,支持缩放、标注、ROI 显示等功能。
    • 跨线程更新 UI 需使用Invoke方法,否则会抛出跨线程访问异常。
相关推荐
格林威2 小时前
印刷电路板阻焊层缺失识别:防止短路风险的 7 个核心策略,附 OpenCV+Halcon 实战代码!
人工智能·数码相机·opencv·机器学习·计算机视觉·视觉检测·工业相机
中达瑞和-高光谱·多光谱5 小时前
MAX-S810机载多光谱相机在草地森林覆盖面统计中的应用
数码相机
_李小白5 小时前
【Android 美颜相机】第一天:认识Android-GPUImage项目
android·数码相机
努力犯错6 小时前
Qwen-Image-Edit-2511-Multiple-Angles LoRA:多角度AI图像生成完全指南
人工智能·数码相机·计算机视觉
格林威6 小时前
基于灰度投影的快速图像配准:适用于产线在线对位的 5 个核心方法,附 OpenCV+Halcon 实战代码!
人工智能·数码相机·opencv·机器学习·计算机视觉·视觉检测·工业相机
qianbo_insist1 天前
基于图像尺寸的相机内参拼接视频
数码相机·音视频·拼接
双翌视觉2 天前
深入解析远心镜头的工作原理与选型
人工智能·数码相机·机器学习
Hi202402173 天前
如何通过选择正确的畸变模型解决相机标定难题
人工智能·数码相机·计算机视觉·自动驾驶
线束线缆组件品替网3 天前
Bulgin 防水圆形线缆在严苛环境中的工程实践
人工智能·数码相机·自动化·软件工程·智能电视
kylezhao20193 天前
工业 2D 相机与镜头选型详解
数码相机