使用Sapera拍摄图像并将数据复制到矢量 [英] Taking image with Sapera and copying data to vector

查看:206
本文介绍了使用Sapera拍摄图像并将数据复制到矢量的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如何使用 Sapera SDK a>并将图像数据从SapBuffer对象传输到矢量?

How do I take images with Sapera SDK and transfer the image data from the SapBuffer object to vector?

推荐答案

要处理使用Sapera相机拍摄的图像,您应该对SapProcessing类进行特殊处理,该类用于处理缓冲区.否则,在每一帧之后将自动清除缓冲区,并且您会丢失数据.

To handle images taken by camera using Sapera, you should make specialization of SapProcessing class, which is used to process buffers. Otherwise the buffer is cleared automatically after each frame, and you lose the data.

成像过程如下:

  1. 您在相机对象上调用Grab()开始成像
  2. 拍摄完每一帧后,将调用传输回调.在这里,您请求SapProcessing对象处理下一帧.
  3. 调用SapProcessing对象的
  4. Run()函数.在这里,您可以从缓冲区读取数据.
  5. Run()函数之后,将调用处理回调.
  6. 收到足够的帧后,请致电Freeze()停止成像.
  1. You call Grab() on the camera object to start imaging
  2. After each frame has been taken, transfer callback is called. Here you request your SapProcessing object to process the next frame.
  3. Run() function of your SapProcessing object is called. Here you can read data from the buffer.
  4. After Run() function, processing callback is called.
  5. When you have received enough frames, call Freeze() to stop imaging.

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

This example code takes images using default settings on the camera (monochrome 8-bit pixel format).

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

这篇关于使用Sapera拍摄图像并将数据复制到矢量的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆