使用 Sapera 拍摄图像并将数据复制到矢量

2024-01-02

我如何拍摄图像萨佩拉SDK https://www.teledynedalsa.com/en/products/imaging/vision-software/sapera-lt/并传输图像数据SapBuffer对象到向量?


要使用 Sapera 处理相机拍摄的图像,您应该专门化SapProcessing类,用于处理缓冲区。否则,缓冲区会在每一帧后自动清除,并且您会丢失数据。

成像过程如下:

  1. 你打电话Grab()在相机对象上开始成像
  2. 拍摄每一帧后,调用传输回调。在这里您请求您的SapProcessing处理下一帧的对象。
  3. Run()你的功能SapProcessing对象被调用。在这里您可以从缓冲区读取数据。
  4. After Run()函数,调用处理回调。
  5. 当您收到足够的帧时,请致电Freeze()停止成像。

此示例代码使用相机上的默认设置拍摄图像(单色 8 位像素格式)。

#include <string>
#include <vector>
#include <memory>
#include <stdexcept>
#include <iostream>
#include <iomanip>
#include <atomic>
#include "SapClassBasic.h"

// Helper function to find the camera by its serial number
SapAcqDevice getDeviceBySN(const std::string& sn)
{
    char serverName[CORSERVER_MAX_STRLEN];
    char serialNumberName[2048];

    const int serverCount = SapManager::GetServerCount();
    for (int i = 0; i < serverCount; i++) {
        if (SapManager::GetResourceCount(i, SapManager::ResourceAcqDevice) != 0)
        {
            SapManager::GetServerName(i, serverName, sizeof(serverName));

            SapAcqDevice camera(serverName);
            if (!camera.Create()) {
                throw std::runtime_error("Failed to create camera object.");
            }
            int featureCount;
            if (camera.GetFeatureCount(&featureCount) && featureCount > 0)
            {
                if (camera.GetFeatureValue("DeviceID", serialNumberName, sizeof(serialNumberName))
                    && serialNumberName == sn)
                {
                    return camera;
                }
            }
            camera.Destroy();
        }
    }
    const auto errorStr = "Camera \"" + sn + "\" was not found.";
    throw std::runtime_error(errorStr.c_str());
}

class SapMyProcessing : public SapProcessing
{
public:
    SapMyProcessing(SapBuffer* pBuffers, SapProCallback pCallback, void* pContext);
    virtual ~SapMyProcessing();

protected:
    virtual BOOL Run();
};

SapMyProcessing::SapMyProcessing(SapBuffer* pBuffers, SapProCallback pCallback, void* pContext)
    : SapProcessing(pBuffers, pCallback, pContext)
{}

SapMyProcessing::~SapMyProcessing()
{
    if (m_bInitOK) Destroy();
}

BOOL SapMyProcessing::Run()
{
    // Get the current buffer index
    const int proIndex = GetIndex();

    // If this is not true, buffer has overflown
    SapBuffer::State state;
    bool goodContent = m_pBuffers->GetState(proIndex, &state)
        && state == SapBuffer::StateFull;

    if (goodContent) {
        void *inAddress = nullptr;
        m_pBuffers->GetAddress(proIndex, &inAddress);
        int inSize = 0;
        m_pBuffers->GetSpaceUsed(proIndex, &inSize);

        // Width, height and pixel format are received from the camera
        const int width = m_pBuffers->GetWidth();
        const int height = m_pBuffers->GetHeight();
        const auto format = m_pBuffers->GetFormat();
        const int outSize = width * height;

        // Skip unexpected pixel format or incomplete frame
        goodContent = format == SapFormatMono8
            && inSize == outSize;

        if (goodContent) {
            // Copy data to vector
            std::vector<uint8_t> outBuffer(outSize);
            std::copy((uint8_t*)inAddress, (uint8_t*)(inAddress) + outSize, outBuffer.begin());

            // Print the first line
            for (int i = 0; i < width; i++) {
                std::cout << std::hex << int(outBuffer[i]);
            }
            std::cout << std::endl << std::endl;
        }
    }

    return TRUE;
}

// Information to pass to callbacks
struct TransferContext {
    std::atomic_int frameGrabCount = 0, frameProcessingCount = 0;
    std::shared_ptr<SapMyProcessing> processing;
};

void transferCallback(SapXferCallbackInfo *info)
{
    auto context = (TransferContext*)info->GetContext();

    context->frameGrabCount++;
    if (!info->IsTrash()) {
        // Execute Run() for this frame
        context->processing->ExecuteNext();
    }
}

// Processing callback is called after Run()
void processingCallback(SapProCallbackInfo* info)
{
    auto context = (TransferContext*)info->GetContext();

    // Processing has finished
    context->frameProcessingCount++;
}

// The main imaging function
void grab(const std::string& serialNumber)
{
    // Number of frames to receive from the camera
    const int maxFrameCount = 10;

    TransferContext context;

    auto camera = getDeviceBySN(serialNumber);
    std::unique_ptr<SapBuffer> buffer
        = std::make_unique<SapBufferWithTrash>(maxFrameCount, &camera);
    std::unique_ptr<SapTransfer> transfer
        = std::make_unique<SapAcqDeviceToBuf>(&camera, buffer.get(), transferCallback, &context);
    context.processing = std::make_shared<SapMyProcessing>(buffer.get(), processingCallback, &context);

    auto cleanup = [&]() {
            if (context.processing) context.processing->Destroy();
            if (transfer) transfer->Destroy();
            if (buffer) buffer->Destroy();
            camera.Destroy();
        };

    try {
        if (!buffer->Create()) {
            throw std::runtime_error("Failed to create buffer object.");
        }
        if (!transfer->Create()) {
            throw std::runtime_error("Failed to create transfer object.");
        }
        if (!context.processing->Create()) {
            throw std::runtime_error("Failed to create processing object.");
        }
        transfer->SetAutoEmpty(false);
        context.processing->SetAutoEmpty(true);
        context.processing->Init();

        transfer->Grab();

        // Wait for the camera to grab all frames
        while (context.frameGrabCount < maxFrameCount);

        transfer->Freeze();
        if (!transfer->Wait(5000)) {
            throw std::runtime_error("Failed to stop grab.");
        }

        // Wait for processing to complete
        while (context.frameProcessingCount < maxFrameCount);

        cleanup();
    }
    catch (...) {
        cleanup();
        throw;
    }
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

使用 Sapera 拍摄图像并将数据复制到矢量 的相关文章

随机推荐

  • Anylogic 中的时间分布和处理所花费的时间

    我正在研究生产模型 其中原材料的输入按小时计算 我运行该模型 8 小时 1 个班次 所以基本上有 16 小时资源闲置 当我没有使用计划部分并运行模型 8 7 小时 56 小时 时 每个作业的时间测量都很好 但现在当我计划输出时 它也包括空闲
  • 用户没有访问该对象的权限。 Firebase 存储 Android

    我是 firebase 存储的新手 为了学习它 我制作了一个简单的应用程序 其中有一个按钮和一个ImageView 当我点击按钮时 会出现一张图片 from drawable 显示在 ImageView 上 我还编写了在Firebase上上
  • 部署 Gen2 Cloud Function 时出现权限被拒绝错误

    我们根据给定的需求开发了云功能 并使用第一代进行了初步验证 一切顺利 但需要进行的修改很少 因此需要额外的处理时间 因此我们必须切换到 gen2 以下是 gcloud 函数部署命令 gcloud functions deploy gen2
  • ServiceStack Swagger UI 和 API 版本号

    有没有办法将版本号输入到 swagger UI 中 那么我们可以让开发者知道每个部署是什么版本吗 这在最新版本的 ServiceStack 中是可能的 您只需在 AppHost 中设置 ServiceStack API 版本即可 publi
  • 根据内容将输入拆分为多个输出?

    假设有一个如下所示的文件 xxxx aa whatever yyyy bb whatever zzzz aa whatever 我想将其分成 2 个文件 其中包含 first xxxx aa whatever zzzz aa whateve
  • 如何迭代 getElementByClassName 返回

    我读过几篇关于 GetElementsByClassName 的文章 但我很难理解如何迭代它返回的内容 我正在编写纯 JavaScript 代码 以便当用户滚动时我的导航栏将采用 固定 位置 但是 当发生此更改时 导航栏列表项需要更改格式
  • 如何获取jenkins管道插件作业的工作区(WorkflowRun对象java API)

    在java API中 我可以从Run java对象访问工作空间路径 直到今天 所有对象都是 hudson model AbstractBuild 的实例 hudson model AbstractBuild getWorkspace hud
  • 内存屏障/栅栏的开销

    我目前正在编写 C 代码 并在代码中使用大量内存屏障 栅栏 我知道 MB 告诉编译器和硬件不要重新排序围绕它的写入 读取 但我不知道这个操作对于处理器在运行时有多复杂 我的问题是 这种屏障的运行时开销是多少 我用谷歌没有找到任何有用的答案
  • pymongo:删除重复项(映射减少?)

    我确实有一个包含多个集合的数据库 总共约 1500 万个文档 文档如下所示 简化 Text blabla ID 101 Text Whuppppyyy ID 102 Text Abrakadabraaa ID 103 Text olalal
  • Gorm 一对多搜索

    有以下问题 我有 Bookmaker 和 Users 域类 一个博彩公司有许多用户 class Bookmaker static hasMany users User 并且 User 域类不包含对 Bookmaker 的引用 我的目标是创建
  • 来自 JSON 字符串的打字稿“enum”

    有没有办法让 TypeScript 枚举与 JSON 中的字符串兼容 例如 enum Type NEW OLD interface Thing type Type let thing Thing JSON parse type NEW al
  • Python 3 中 str.translate 的自定义表

    如果我运行这段代码 s translate str maketrans as dfg 1234 qw 我会得到 ValueError string keys in translate table must be of length 1 有没
  • 获取控制台句柄

    如何获取外部应用程序的控制台句柄 我有一个程序作为控制台运行 我有一个第二个程序将调用 GetConsoleScreenBufferInfo 但为此我需要第一个程序的控制台句柄 给定第一个程序的 HWND 是否有可能我可以获得它的控制台句柄
  • 使用 withColumnRenamed 重命名多列

    我想使用 Spark withColumnRenamed 函数更改两列的名称 当然 我可以写 data sqlContext createDataFrame 1 2 3 4 x1 x2 data data withColumnRenamed
  • 如何使用 codeigniter 锁定表?

    我必须在模型中运行这个 sql 例程 this gt db gt query LOCK TABLE orders WRITE this gt db gt query TRUNCATE TABLE orders this gt db gt q
  • 从 master 分支构建到 gh-pages 分支

    我想做的事 我正在使用github 我有两个分支机构 主页面和 gh 页面 我的 master 分支上有一个 unity3d 项目 当我运行它时 它将生成一个网页 我想在 gh pages 分支上显示网页的内容 我认为这意味着我必须在存储库
  • 如何通过区分类型来隔离枚举?

    下面的代码定义了两个枚举 class Insect BEE 0x00 WASP 0x01 BUMBLEBEE 0x02 class Breakfast HAM 0x00 EGGS 0x01 PANCAKES 0x02 b Insect WA
  • 如何根据 R 中其他行和列中的值来填充数据框

    假设我有一个如下所示的数据框 ID T X Y Z 1 1 A A NA 1 2 B A NA 1 3 B B NA 1 4 B A NA 2 1 A B NA 2 2 A A NA 2 3 B A NA 2 4 A B NA 3 1 B
  • Java 中埃拉托斯特尼的并行筛法

    我正在尝试并行实现埃拉托斯特尼筛法 我创建了一个布尔列表 其中填充了给定大小的 true 值 每当找到素数时 该素数的所有倍数都会在布尔列表中标记为 false 我尝试使该算法并行的方法是启动一个新线程 同时仍然过滤初始素数 例如 该算法以
  • 使用 Sapera 拍摄图像并将数据复制到矢量

    我如何拍摄图像萨佩拉SDK https www teledynedalsa com en products imaging vision software sapera lt 并传输图像数据SapBuffer对象到向量 要使用 Sapera