Gige多相机高速拍照模式补充

软件触发(Software Trigger)

  • 代码指令 让相机拍一张
  • 调用:ExecuteSoftwareTrigger()
  • 不需要接线、不需要外部信号

优点:

  • 控制最灵活,想什么时候拍就什么时候拍
  • 多相机可以代码级同步
  • 适合:高精度定时采集(50ms、20ms、10ms)

缺点:

  • PC 忙的时候,触发精度会掉一点
  • 28 个相机一起触发,时序会有几毫秒偏差

硬件触发(Hardware Trigger)

最稳定、最同步、工业标准方案

  • IO 线 给相机一个 3.3V/5V 脉冲
  • 一通电,所有相机同时拍照
  • 同步精度:微秒级

优点:

  • 28 台相机可以做到 完全同时曝光
  • 不受 CPU 占用、系统延迟影响
  • 运动抓拍、高精度同步必用

缺点:

  • 要接线、要 IO 卡、要继电器 / PLC
  • 成本高、布线麻烦

自由运行 / 连续采集(Free Run / Auto)

  • 相机自己按帧率一直拍:25fps、30fps
  • 不用触发,不用指令

优点:

  • 最简单
  • 不用管

缺点:

  • 多相机完全不同步

信号触发(IO 信号、编码器、光耦)

属于硬件触发的分支:

  • 编码器触发(走多少距离拍一张)
  • 光电开关触发(有物体过来拍)
  • PLC 触发

高频单帧取图的陷阱

ExecuteSoftwareTrigger与多次调用PhotoImage

区别在于 ExecuteSoftwareTrigger流启动后,无需触发,可以根据指令触发拍照

但是PhotoImage每次都会走全流程:创建流->推缓冲区->启动采集->取帧->释放流

仅适用于偶尔手动拍一张(如调试、预览)


代码刨析

首先是触发方式是根据官方给的API:arv_camera_set_string决定的

在动态库中添加两个函数

开启软件触发前台调用m_nErrCode = m_cam->SetSoftwareTrigger(true, m_szErrMsg);

m_cam->SetTriggerSelector("FrameStart");(我没有写因为默认开启就是帧触发)

m_cam->OpenStream();启动流

cpp 复制代码
COMMON_ERR CDevice::SetSoftwareTrigger(bool enable, char* szMsg/*= NULL*/)
{

    //校验相机是否有效(m_pGige不为空)
    if (Invalidate()) return ERR_CAMERA_INVALID;

    GError* error = NULL;
    ArvCamera* camera = (ArvCamera*)m_pGige;
    COMMON_ERR nErrCode = COMMON_OK;

    // 设置 TriggerMode
    arv_camera_set_string(camera, "TriggerMode", enable ? "On" : "Off", &error);
    if (error) {
        nErrCode = error->code;
        if (szMsg) memcpy(szMsg, error->message, sizeof(tagErrMsg) - 1);
        g_clear_error(&error);
        return nErrCode;
    }

    // 开启时设置 TriggerSource = Software

    if (enable) {
        arv_camera_set_string(camera, "TriggerSource", "Software", &error);
        if (error) {
            nErrCode = error->code;
            if (szMsg) memcpy(szMsg, error->message, sizeof(tagErrMsg) - 1);
            g_clear_error(&error);
            // 可选回滚
            arv_camera_set_string(camera, "TriggerMode", "Off", nullptr);
            return nErrCode;
        }
    }

    return COMMON_OK;
}

在程序中调用m_nErrCode = m_cam->ExecuteSoftwareTrigger(m_szErrMsg);

cpp 复制代码
// 执行软件触发
COMMON_ERR CDevice::ExecuteSoftwareTrigger(char* szMsg/*= NULL*/)
{
    // 1. 校验相机是否有效(m_pGige不为空)
    if (Invalidate()) return ERR_CAMERA_INVALID;

    GError* error = NULL;
    ArvCamera* camera = (ArvCamera*)m_pGige;

    // 2. 核心调用:向相机发送软件触发指令
    arv_camera_software_trigger(camera, &error);

    COMMON_ERR nErrCode = COMMON_OK;
    if (error) {
        nErrCode = error->code;
        if (szMsg) memcpy(szMsg, error->message, sizeof(tagErrMsg) - 1);
        g_clear_error(&error);
    }

    return nErrCode;
}

之后相机会自己拍照,我们只需要读他拍照后反馈的流就可以

相比

COMMON_ERR CGige::PhotoImage(char* szMsg/*= NULL*/)中

cpp 复制代码
COMMON_ERR CGige::PhotoImage(char* szMsg/*= NULL*/)
{
    if (Invalidate()) return ERR_CAMERA_INVALID;
    COMMON_ERR nErrCode = COMMON_OK;

    GError* error = NULL;
    ArvCamera* camera =(ArvCamera*)m_pGige;

    int bits = GetBitCount();
    m_nBitCount = (bits >= 24) ? bits : 8;

    int width = arv_camera_get_integer(camera, "Width", NULL);
    int height = arv_camera_get_integer(camera, "Height", NULL);

    arv_camera_gv_select_stream_channel(camera, 0, NULL);
    arv_camera_set_acquisition_mode(camera, ARV_ACQUISITION_MODE_SINGLE_FRAME, NULL);

    guint payload = arv_camera_get_payload(camera, NULL);
    ArvStream* stream = arv_camera_create_stream(camera, NULL, NULL, &error);
    if (stream && payload > 0)
    {
        for (int i = 0; i < 1; i++)
            arv_stream_push_buffer(stream, arv_buffer_new(payload, NULL));

        InitRateSpeed();
        arv_camera_start_acquisition(camera, &error);
        if (!error)
        {
            ArvBuffer* buffer = arv_stream_pop_buffer(stream);
            if (buffer && arv_buffer_get_status(buffer) == ARV_BUFFER_STATUS_SUCCESS)
            {
                size_t buffer_size = 0;
                const uint8_t* data = reinterpret_cast<const uint8_t*>(arv_buffer_get_data(buffer, &buffer_size));
                int nWidth = arv_buffer_get_image_width(buffer);
                int nHeight = arv_buffer_get_image_height(buffer);
                SaveBuffer(data, buffer_size, nWidth, nHeight);
            }
            if (buffer) g_clear_object(&buffer);
        }
        arv_camera_stop_acquisition(camera, NULL);
    }
    if (error)
    {
        nErrCode = error->code; //ERR_CREATE_STREAM;
        if (szMsg) memcpy(szMsg, error->message, sizeof(tagErrMsg) - 1);
        g_clear_error(&error);
    }
    if (stream) g_clear_object(&stream);

    return nErrCode;
}

每次都会创建新的流

要节省大多时间

相关推荐
LabVIEW开发18 小时前
LabVIEW 机器视觉 让 FDM 3D 打印缺陷检出率达到 100%
数码相机·labview·labview知识·labview功能·labview程序
小白不白11119 小时前
Invoke的用法
开发语言·人工智能·数码相机·计算机视觉·c#
博图光电21 小时前
梅卡曼德工业相机代理 | 专业工业视觉解决方案 - 助力智能制造
数码相机·制造
拓朗工控2 天前
视觉检测行业工控机选型指南:核心要素与避坑策略
人工智能·数码相机·视觉检测·工控机·工业电脑
小宋加油啊2 天前
对于工业相机的认识(对机械臂的,工业方面的也可以参考)
数码相机
暂未成功人士!2 天前
相机标定---张正友相机标定和手眼标定
数码相机·手眼标定·相机标定
大江东去浪淘尽千古风流人物3 天前
【VGGT】统一3D重建:单网络同时预测相机位姿、深度图、点云与3D轨迹的前馈Transformer架构深度解析
网络·数码相机·3d·transformer·slam·3d重建·cvpr2025
CG_MAGIC3 天前
摄像机与渲染输出:焦距、景深与Cycles/Eevee渲染设置
数码相机·3d·贴图·效果图·建模教程·渲云渲染
蝈蝈Tjguo3 天前
opencv 与摄影测量 相机坐标系的区别
人工智能·数码相机·opencv
埃科光电5 天前
打通全场景检测痛点UB系列相机赋能多元智造场景
图像处理·数码相机·计算机视觉·制造·相机