Baumer工业相机堡盟工业相机如何通过BGAPI SDK实现Raw格式的图像保存(C++)

简介: Baumer工业相机堡盟工业相机如何通过BGAPI SDK实现Raw格式的图像保存(C++)

Baumer工业相机


Baumer工业相机堡盟相机是一种高性能、高质量的工业相机,可用于各种应用场景,如物体检测、计数和识别、运动分析和图像处理。


Baumer的万兆网相机拥有出色的图像处理性能,可以实时传输高分辨率图像。此外,该相机还具有快速数据传输、低功耗、易于集成以及高度可扩展性等特点。


Baumer RAW文件是一种记录了工业相机传感器的原始信息,同时记录了由相机拍摄所产生的一些原数据(Metadata,如ISO的设置、快门速度、光圈值、白平衡等)的文件。RAW是未经处理、也未经压缩的格式,可以把RAW概念化为“原始图像编码数据”。


Baumer工业相机的Camera Explorer软件功能强大,内容丰富,通过该软件可以有效的获取相机相关的全部信息,在对于相机检测项目的开发中,有时需要获取相机中图像Buffer信息和相关的数据流信息,而Camera Explorer软件可以有效的显示相关的信息。


Baumer工业相机通过SDK实现Raw格式的图像保存的技术背景


Baumer工业相机通常通过SDK(Software Development Kit)实现Raw格式的图像保存时,会利用其专门的图像处理模块和数据传输接口来处理原始图像数据。这种方式的技术背景涉及以下几个方面:


  1. 数据采集和传输:Baumer工业相机的SDK会提供用于高速数据采集和传输的接口和功能,以确保从相机传感器捕获到的Raw图像数据可以高效地传输给计算机或其他设备进行处理。


  1. 图像处理和编程接口:Baumer的SDK会提供图像处理的API和工具,以便开发人员可以在采集到的Raw图像数据上进行各种处理操作,包括像素值的访问、图像增强、颜色校正等,从而满足不同应用的需求。


  1. 校准和配置:Baumer的SDK还可以提供各种配置选项和校准工具,以便开发人员可以对相机进行校准和配置,确保从相机获取的Raw图像数据质量和准确性。


  1. 文件格式和保存:Baumer的SDK会支持将处理后的图像数据保存为Raw格式的文件,同时可能也提供其他格式的转换工具和API,以便用户能够导出不同格式的图像数据。


总的来说,Baumer工业相机通过SDK实现Raw格式的图像保存是建立在高速数据传输、图像处理和API支持的基础上,以满足工业和科学领域对高质量图像数据处理的需求。


通过SDK获取相机信息的代码分析


本文介绍使用BGAPI SDK对Baumer工业相机进行开发时,通过BGAPI SDK实现Raw格式的图像保存,从而能够做对应的参数设置和功能开发。


有关于Baumer工业相机堡盟工业相机如何通过BGAPI SDK实现Raw格式的图像保存(C#)的介绍,之前已经有相关的技术博客可以参考:


Baumer工业相机堡盟工业相机如何通过BGAPI SDK实现Raw格式的图像保存(C#)


Baumer工业相机回调函数里保存原始图像数据


C++环境下在回调函数里保存Raw图像代码如下所示:

void BGAPI2CALL BufferHandler( void * callBackOwner, Buffer * pBufferFilled )
{
  CGigeDemoDlg* pDlg = (CGigeDemoDlg*)callBackOwner;
  unsigned char* imagebuffer = NULL;
  BGAPI2::Image* pImageSrc = NULL;
  bo_uchar* pMemDst = NULL;
  bo_uint64 memSizeDst = 0;
  USES_CONVERSION;
  try
  {
    if(pBufferFilled == NULL)
    {
    }
    else if(pBufferFilled->GetIsIncomplete() == true)
    {
      // queue buffer again
      pBufferFilled->QueueBuffer();
    }
    else
    {
      pDlg->FrameID= pBufferFilled->GetFrameID();                                                 //获取当前图像FrameID显示帧率
      int width = 0, height = 0;
      width = (int)pBufferFilled->GetWidth();height = (int)pBufferFilled->GetHeight();      //获取当前图像像素长宽
      CString PixelFormat1 = (CString)pBufferFilled->GetPixelFormat();              //获取当前图像像素格式
      imagebuffer = (BYTE*)((bo_int64)pBufferFilled->GetMemPtr()+pBufferFilled->GetImageOffset());//获取当前图像数据
      const bo_uint w = static_cast<bo_uint>(pBufferFilled->GetWidth());
      const bo_uint h = static_cast<bo_uint>(pBufferFilled->GetHeight());
      void* const pMemSrc = pBufferFilled->GetMemPtr();
      BGAPI2::String sBufferPixelFormat = pBufferFilled->GetPixelFormat();
      const bo_uint64 memSizeSrc = pBufferFilled->GetMemSize();
      if (pImageSrc == NULL) 
      {
        pImageSrc = pDlg->m_imgProcessor->CreateImage(w, h, sBufferPixelFormat, pMemSrc, memSizeSrc);
      } 
      else 
      {
        pImageSrc->Init(w, h, sBufferPixelFormat, pMemSrc, memSizeSrc);
      }
      if (pImageSrc != NULL&PixelFormat1.FindOneOf((_T("Bayer")))!=-1) 
      {
        //如果选用格式为Bayer
        BGAPI2::String sPixelFormatDst ="BGR8";             
        bo_uint64 bufferLength = pImageSrc->GetTransformBufferLength(sPixelFormatDst);
        if (bufferLength > memSizeDst) 
        {
          if (pMemDst != NULL) 
          {
            delete[] pMemDst;
            pMemDst = NULL;
            memSizeDst = 0;
          }
          pMemDst = new bo_uchar[static_cast<size_t>(bufferLength)];
          memSizeDst = bufferLength;
        }       
        pDlg->m_imgProcessor->TransformImageToBuffer(pImageSrc, sPixelFormatDst, pMemDst, bufferLength);
      }
      #pragma region //保存图像功能
      if(pDlg->m_bSaveImage &&!pDlg->m_strDirectory.IsEmpty())
      {
        CTime time = CTime::GetCurrentTime(); 
        CString strtime;
        strtime.Format(_T("\\%4d%2d%2d%2d%2d%2d"),time.GetYear(),time.GetMonth(),time.GetDay(),time.GetHour(),time.GetMinute(),time.GetSecond());
        CString  strpath = pDlg->m_strDirectory+strtime+".jpg";
        //使用Baumer自定义Raw格式保存
        BGAPI2::Image* pBufferFilledImage;
        CString filename = pDlg->m_strDirectory+strtime+".brw"; 
        BGAPI2::String filenamestr = pDlg->m_strDirectory+strtime+".brw";
        pImageSrc->GetNode("SaveBrw")->SetValue(filenamestr);
        pDlg->m_bSaveImage = false;
      }
      #pragma endregion 
      Gdiplus::Rect rc = Gdiplus::Rect(0,0,width,height);
      #pragma region 黑白相机代码:像素格式为mono时转Bitmap的代码,彩色相机此处代码不同
      if(pDlg->m_pBitmap == NULL)
      {
        pDlg->m_pBitmap = new Gdiplus::Bitmap(width,height,PixelFormat8bppIndexed);
      }
      Gdiplus::BitmapData lockedbits;
      Gdiplus::ColorPalette * pal = (Gdiplus::ColorPalette*)new BYTE[sizeof(Gdiplus::ColorPalette)+255*sizeof(Gdiplus::ARGB)];
      pal->Count=256;
      for(UINT i=0;i<256;i++)
      {
        UINT color=i*65536+i*256+i;
        color= color|0xFF000000;
        pal->Entries[i]=color;
      }
      pDlg->m_pBitmap->SetPalette(pal);
      Gdiplus::Status ret = pDlg->m_pBitmap->LockBits(&rc,Gdiplus::ImageLockModeWrite,PixelFormat8bppIndexed,&lockedbits);
      BYTE* pixels = (BYTE*)lockedbits.Scan0;
      BYTE* src = (BYTE*)imagebuffer;
      for (int row = 0; row < height; ++row) 
      {
        CopyMemory(pixels, src, lockedbits.Stride);
        pixels += width;
        src += width;
      }
      pDlg->m_pBitmap->UnlockBits(&lockedbits);
      #pragma endregion 
      #pragma region //将图像显示在PictureControl控件上
      HDC hDC = ::GetDC(pDlg->m_stcPicture.m_hWnd);
      Gdiplus::Graphics GdiplusDC(hDC);
      CRect rcControl;
      pDlg->m_stcPicture.GetWindowRect(&rcControl);
      Gdiplus::Rect rtImage(0,0,rcControl.Width(),rcControl.Height());
      GdiplusDC.DrawImage(pDlg->m_pBitmap,rtImage,0,0,width,height, Gdiplus::UnitPixel);
      delete []pal;
      ::ReleaseDC(pDlg->m_stcPicture.m_hWnd,hDC);
      delete pDlg->m_pBitmap ;
      pDlg->m_pBitmap =NULL;
      #pragma endregion 
      // queue buffer again
      pBufferFilled->QueueBuffer();
    }
  }
  catch (BGAPI2::Exceptions::IException& ex)
  {
    CString str;
    str.Format(_T("ExceptionType:%s! ErrorDescription:%s in function:%s"),ex.GetType(),ex.GetErrorDescription(),ex.GetFunctionName());    
  } 
}


Baumer保存Raw图像格式重要核心代码

BGAPI2::Image* pImageSrc = NULL;
const bo_uint w = static_cast<bo_uint>(pBufferFilled->GetWidth());
const bo_uint h = static_cast<bo_uint>(pBufferFilled->GetHeight());
void* const pMemSrc = pBufferFilled->GetMemPtr();
BGAPI2::String sBufferPixelFormat = pBufferFilled->GetPixelFormat();
const bo_uint64 memSizeSrc = pBufferFilled->GetMemSize();
//将相机内部图像内存数据转为BGAPI2.Image数据,方便后续直接保存未BRW对应的BRW格式
if (pImageSrc == NULL) 
{
  pImageSrc = pDlg->m_imgProcessor->CreateImage(w, h, sBufferPixelFormat, pMemSrc, memSizeSrc);
} 
else 
{
  pImageSrc->Init(w, h, sBufferPixelFormat, pMemSrc, memSizeSrc);
}
#pragma region //保存图像功能
if(pDlg->m_bSaveImage &&!pDlg->m_strDirectory.IsEmpty())
{
  CTime time = CTime::GetCurrentTime(); 
  CString strtime;
  strtime.Format(_T("\\%4d%2d%2d%2d%2d%2d"),time.GetYear(),time.GetMonth(),time.GetDay(),time.GetHour(),time.GetMinute(),time.GetSecond());
  CString  strpath = pDlg->m_strDirectory+strtime+".jpg";
  pDlg->SaveImageMono(strpath, imagebuffer,width,height);
  //使用Baumer自定义Raw格式保存
  BGAPI2::Image* pBufferFilledImage;
  CString filename = pDlg->m_strDirectory+strtime+".brw"; 
  BGAPI2::String filenamestr = pDlg->m_strDirectory+strtime+".brw";
  pImageSrc->GetNode("SaveBrw")->SetValue(filenamestr);
  pDlg->m_bSaveImage = false;
}
#pragma endregion 


Baumer工业相机保存Raw图像格式的测试



Baumer工业相机通过SDK实现Raw格式的图像保存的优势


通过SDK实现Raw格式的图像保存有几个优势:


  1. 灵活性:使用SDK保存图像的原始Raw格式可以保留数据的完整性,而不会出现由JPEG等压缩格式所带来的数据损失。这使得用户可以在后期处理过程中更加灵活地进行调整和编辑,从而获得更高质量的图像。


  1. 捕获更多细节:Raw格式通常能够捕获更多的图像细节和动态范围,使得在后期处理中可以更好地进行曝光和颜色校正,以及减少噪点等工作。


  1. 自定义处理:通过SDK保存Raw格式图像,用户可以利用相机制造商提供的原始数据以及自定义的图像处理算法进行更精细的图像处理,满足特定的应用需求。


Raw格式图像的保存使得用户能够获得更高质量的图像数据,但同时也需要更多的后期处理工作。因此,选择是否保存Raw格式图像取决于具体的应用需求和后期处理能力。


Baumer工业相机通过SDK实现Raw格式的图像保存的行业应用


工业相机通过SDK实现Raw格式的图像保存在许多行业应用中发挥重要作用,包括但不限于:


  1. 检测和测量应用:在制造业中,工业相机通过SDK保存Raw格式的图像可用于精确的检测和测量应用,例如缺陷检测、尺寸测量、外观质量控制等。Raw格式图像的高质量和完整性有助于确保实时检测和测量的准确性。


  1. 医学成像:医疗领域也常常利用工业相机进行医学成像,比如X射线、CT扫描、核磁共振成像等。通过SDK保存Raw格式的图像能够保留更多的图像细节和动态范围,有助于医学图像的后期处理和分析。


  1. 智能交通:在智能交通系统中,工业相机通过SDK保存Raw格式的图像可用于车牌识别、交通监控等应用。Raw格式的图像数据能提供更多细节,有助于提高识别的准确性和可靠性。


  1. 机器视觉:在自动化生产线和机器视觉系统中,工业相机通过SDK保存Raw格式的图像可用于产品检测、识别和定位等应用。Raw格式图像保留了更多的信息,有助于提高机器视觉系统的准确性和稳定性。


总的来说,工业相机通过SDK实现Raw格式的图像保存在需要高质量图像数据、精确测量和复杂分析的行业应用中具有广泛的应用前景。

目录
相关文章
|
监控 API 开发工具
Baumer工业相机堡盟工业相机如何通过NEOAPI SDK获取每张图像的微秒时间和FrameID功能(C#)
Baumer工业相机堡盟工业相机如何通过NEOAPI SDK获取每张图像的微秒时间和FrameID功能(C#)
386 0
|
监控 API 开发工具
Baumer工业相机堡盟工业相机如何通过NEOAPI SDK获取每张图像的微秒时间和FrameID功能(C++)
Baumer工业相机堡盟工业相机如何通过NEOAPI SDK获取每张图像的微秒时间和FrameID功能(C++)
255 0
|
编译器 C++ 开发者
【C++篇】深度解析类与对象(下)
在上一篇博客中,我们学习了C++的基础类与对象概念,包括类的定义、对象的使用和构造函数的作用。在这一篇,我们将深入探讨C++类的一些重要特性,如构造函数的高级用法、类型转换、static成员、友元、内部类、匿名对象,以及对象拷贝优化等。这些内容可以帮助你更好地理解和应用面向对象编程的核心理念,提升代码的健壮性、灵活性和可维护性。
|
12月前
|
编译器 C++ 容器
【c++11】c++11新特性(上)(列表初始化、右值引用和移动语义、类的新默认成员函数、lambda表达式)
C++11为C++带来了革命性变化,引入了列表初始化、右值引用、移动语义、类的新默认成员函数和lambda表达式等特性。列表初始化统一了对象初始化方式,initializer_list简化了容器多元素初始化;右值引用和移动语义优化了资源管理,减少拷贝开销;类新增移动构造和移动赋值函数提升性能;lambda表达式提供匿名函数对象,增强代码简洁性和灵活性。这些特性共同推动了现代C++编程的发展,提升了开发效率与程序性能。
459 12
|
10月前
|
人工智能 机器人 编译器
c++模板初阶----函数模板与类模板
class 类模板名private://类内成员声明class Apublic:A(T val):a(val){}private:T a;return 0;运行结果:注意:类模板中的成员函数若是放在类外定义时,需要加模板参数列表。return 0;
250 0
|
10月前
|
存储 编译器 程序员
c++的类(附含explicit关键字,友元,内部类)
本文介绍了C++中类的核心概念与用法,涵盖封装、继承、多态三大特性。重点讲解了类的定义(`class`与`struct`)、访问限定符(`private`、`public`、`protected`)、类的作用域及成员函数的声明与定义分离。同时深入探讨了类的大小计算、`this`指针、默认成员函数(构造函数、析构函数、拷贝构造、赋值重载)以及运算符重载等内容。 文章还详细分析了`explicit`关键字的作用、静态成员(变量与函数)、友元(友元函数与友元类)的概念及其使用场景,并简要介绍了内部类的特性。
389 0
|
编译器 C语言 C++
类和对象的简述(c++篇)
类和对象的简述(c++篇)
|
设计模式 安全 C++
【C++进阶】特殊类设计 && 单例模式
通过对特殊类设计和单例模式的深入探讨,我们可以更好地设计和实现复杂的C++程序。特殊类设计提高了代码的安全性和可维护性,而单例模式则确保类的唯一实例性和全局访问性。理解并掌握这些高级设计技巧,对于提升C++编程水平至关重要。
231 16
|
编译器 C++
类和对象(中 )C++
本文详细讲解了C++中的默认成员函数,包括构造函数、析构函数、拷贝构造函数、赋值运算符重载和取地址运算符重载等内容。重点分析了各函数的特点、使用场景及相互关系,如构造函数的主要任务是初始化对象,而非创建空间;析构函数用于清理资源;拷贝构造与赋值运算符的区别在于前者用于创建新对象,后者用于已存在的对象赋值。同时,文章还探讨了运算符重载的规则及其应用场景,并通过实例加深理解。最后强调,若类中存在资源管理,需显式定义拷贝构造和赋值运算符以避免浅拷贝问题。
|
存储 编译器 C++
类和对象(上)(C++)
本篇内容主要讲解了C++中类的相关知识,包括类的定义、实例化及this指针的作用。详细说明了类的定义格式、成员函数默认为inline、访问限定符(public、protected、private)的使用规则,以及class与struct的区别。同时分析了类实例化的概念,对象大小的计算规则和内存对齐原则。最后介绍了this指针的工作机制,解释了成员函数如何通过隐含的this指针区分不同对象的数据。这些知识点帮助我们更好地理解C++中类的封装性和对象的实现原理。