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;
}

每次都会创建新的流

要节省大多时间

相关推荐
JQLvopkk7 小时前
机器视觉为何不用普通相机
人工智能·数码相机
꯭爿꯭巎꯭9 小时前
谷歌相机9.2下载
数码相机
LittroInno10 小时前
AI云台相机系统——从模块到整机的集成架构解析
人工智能·数码相机·架构
RoboWizard12 小时前
初春踏青,无人机、运动相机素材如何用移动固态硬盘“一站式归档”?
数码相机·无人机
unityのkiven12 小时前
如何通过DirectShow用C++实现多台PTZ相机的控制?
开发语言·c++·数码相机
没学上了2 天前
多相机协同拍照原理底层刨析
数码相机
一直在想名3 天前
Flutter 框架跨平台鸿蒙开发 - 胶片相机模拟
数码相机·flutter·华为·harmonyos
CoderIsArt3 天前
半导体加工平台的视觉定位方案
数码相机
格林威3 天前
GigE Vision 多相机同步终极检查清单(可直接用于项目部署)
开发语言·人工智能·数码相机·机器学习·计算机视觉·视觉检测·工业相机
Utopia^3 天前
Flutter 框架跨平台鸿蒙开发 - 闪回相机
数码相机·flutter·华为·harmonyos