使用Sapera拍摄图像并将数据复制到矢量
Taking image with Sapera and copying data to vector
如何使用Sapera SDK拍摄图像,并将图像数据从SapBuffer
对象传输到矢量?
要使用Sapera处理相机拍摄的图像,您应该专门化用于处理缓冲区的SapProcessing
类。否则,缓冲区将在每帧之后自动清除,并且您将丢失数据。
成像过程如下:
- 您在相机对象上调用
Grab()
以开始成像 - 在获取每个帧之后,调用transfer回调。在这里,您请求您的
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;
}
}
相关文章:
- 在 C++ AMP 数组中复制数据多少次?
- 字符串是否在其构造函数中复制数据
- 在不复制数据的情况下,将double数组转换为只有double成员的structs数组
- 有没有一种方法可以在不复制数据的情况下从string_view创建字符串流
- 如何在不复制数据的情况下将 cv::Mat 转换为 2d 标准::矢量
- C++ 在节点内存储对数据对象的引用,而不复制数据
- 是否可以在不分配内存或复制数据的情况下构造对象?
- 如何在不复制数据的情况下在平面数组和多维数组之间进行转换?
- C 2D char阵列有时会在随机位置复制数据
- 在不复制数据的情况下更改 opencv mat 中的列顺序
- 有没有办法将 EGL 绘制到 /dev/fb1 而不是 /dev/fb0,而无需在树莓派上复制数据
- 使用C 和目标C从原始图像中复制数据
- 给定 myvector.start() 和 myvector.end(),我想在不复制数据的情况下创建 myvector
- 复制数据时出现奇怪错误
- 如何在 C/C++ 中从数组末尾开始复制数据
- glTexImage2D 复制数据或仅指定数据
- 如何在C++中从void指针复制数据
- 在不复制数据的情况下将OpenCV Mat发送到MATLAB工作区的方法
- 如何使用 GPU-DMA 从 GPU-CUDA 代码来复制数据
- 在矢量到矢量中复制数据<float> <Mat> (Opencv/C++)