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

Posted

技术标签:

【中文标题】使用 Sapera 拍摄图像并将数据复制到矢量【英文标题】:Taking image with Sapera and copying data to vector 【发布时间】:2019-02-08 11:19:25 【问题描述】:

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

【问题讨论】:

【参考方案1】:

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

成像过程如下:

    您在相机对象上调用Grab() 以开始成像 拍摄完每一帧后,调用传输回调。在这里,您请求您的 SapProcessing 对象来处理下一帧。 调用 SapProcessing 对象的 Run() 函数。在这里您可以从缓冲区中读取数据。 在Run()函数之后,调用处理回调。 当您收到足够的帧时,请致电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;
    

【讨论】:

以上是关于使用 Sapera 拍摄图像并将数据复制到矢量的主要内容,如果未能解决你的问题,请参考以下文章

如何上传图像并将其保存在数据库中? [复制]

急求,arcgis中,如何求每个独立的栅格块的平均值,并将平均值赋予到对应的矢量图块上???

使用相机拍摄,在图像视图中显示并保存到图片中

在 Sapera ++ 中使用相机配置文件

sh 将给定文件夹内的所有图像从彩色转换为灰度,调整它的黑白抖动级别并将其追踪到SVG矢量f

使用C ++修改EXIF数据