Baumer工业相机堡盟工业相机如何通过BGAPI SDK直接实现Mono16位深度的图像保存(C++)

简介: Baumer工业相机堡盟工业相机如何通过BGAPI SDK直接实现Mono16位深度的图像保存(C++)

Baumer工业相机

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


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

Baumer工业相机通过使用BGAPI SDK进行开发时,在C++环境可以直接实现位深度为16的图像保存。


Baumer工业相机保存位深度12/16位图像的技术背景

工业相机通常用于需要高质量图像的分析和检查的专业环境中。这些相机被设计用来捕捉16比特的高比特深度的图像,与低比特深度的图像相比,可以捕捉到更大范围的色彩和细节。


保存位深16位图像的工业相机的技术背景涉及几个关键部分。首先,相机的图像传感器必须能够捕捉到高比特深度的图像。这是通过使用高质量的图像传感器来实现的,该传感器能够以每像素16比特的分辨率捕获数据。


其次,相机的电子设备必须能够处理和存储高比特深度的图像数据。这意味着相机需要有一个高速处理器和足够的内存来处理所产生的大量图像数据。


第三,相机的软件必须能够支持16位图像的保存。这意味着相机的固件和软件接口必须被设计成能够处理16位图像所产生的更大的文件尺寸,并且还能与工业标准文件格式如TIFF和RAW兼容。


总的来说,保存16位深度图像的工业相机的技术背景涉及高质量的图像传感器、强大的电子器件和专门的软件的组合,这些都是为了处理捕捉和存储高位深度图像的独特需求。


这里主要描述如何在C#的平台下通过BGAPI SDK直接实现Mono16图像格式的保存功能的核心代码


代码案例分享

本文介绍使用BGAPI SDK对Baumer的工业相机进行开发时,直接实现Mono12或者Mono16图像格式的保存功能


如下为核心代码实现步骤:


1:引用合适的类文件

C++环境下核心代码如下所示:

#include <stdio.h>
#include <iostream>
#include <iomanip>
#include <set>
#include <vector>
#include <algorithm>
#include <string>
#include "bgapi2_genicam/bgapi2_genicam.hpp"
#include <string>
#include <sstream>
#include <fstream>
#include <iostream>
#include <iomanip>

2:通过BGAPI SDK直接转换保存Mono12/16图像

下面为在在C++环境开启相机连接相机后通过转换图像格式实现Mono12或者Mono16图像格式保存的核心代码。


如下所示:

void saveMono16Tiff(char *filename, unsigned char **imagebuffer, int sizeX, int sizeY)
{
  // TIFFSPEC: Adobe TIFF 6.0 specification (June 3, 1992) 
  //           http://partners.adobe.com/public/developer/en/tiff/TIFF6.pdf
  unsigned char * headerdata = NULL;
  FILE * file = NULL;
  int tiffMono16HeaderLength = 174; // Mono16 = 174; see 12 entries below
  unsigned short data16 = 0;
  unsigned int data32 = 0;
  // create file with the given name (with .tif)
  file = fopen(filename, "wb");
  //filesize = tiffMono16HeaderLength + sizeX*sizeY*2; // header[bytes] + image[bytes]
  // create tiff header for Mono16
  //===============================
  headerdata = (unsigned char*) new unsigned char[tiffMono16HeaderLength];
  memset(headerdata, 0, tiffMono16HeaderLength);
  int pos = 0;  // write position inside headerdata
  // TIFF identifier and count of directory entries
  //================================================
  data16 = 0x4949;  // identifier "II" for little-endian byte order
  memcpy(&headerdata[pos], &data16, 2);
  pos = pos + 2;
  data16 = 42;  // tiff identifier 42
  memcpy(&headerdata[pos], &data16, 2);
  pos = pos + 2;
  data32 = 8;   // offset for the first IFD
  memcpy(&headerdata[pos], &data32, 4);
  pos = pos + 4;
  data16 = 12;  // number of directory entries
  memcpy(&headerdata[pos], &data16, 2);
  pos = pos + 2;
  // 1. entry: ImageWidth (number of columns)
  //==========================================
  data16 = 0x100;  // tag:   100.H 
  memcpy(&headerdata[pos], &data16, 2);
  pos = pos + 2;
  data16 = 4;   // type:  LONG
  memcpy(&headerdata[pos], &data16, 2);
  pos = pos + 2;
  data32 = 1;   // count: 1
  memcpy(&headerdata[pos], &data32, 4);
  pos = pos + 4;
  data32 = sizeX;  // value: horizontal image size
  memcpy(&headerdata[pos], &data32, 4);
  pos = pos + 4;
  // 2. entry: ImageLength (number of rows)
  //=======================================
  data16 = 0x101;  // tag:   101.H 
  memcpy(&headerdata[pos], &data16, 2);
  pos = pos + 2;
  data16 = 4;   // type:  LONG
  memcpy(&headerdata[pos], &data16, 2);
  pos = pos + 2;
  data32 = 1;   // count: 1
  memcpy(&headerdata[pos], &data32, 4);
  pos = pos + 4;
  data32 = sizeY;  // value: horizontal image size
  memcpy(&headerdata[pos], &data32, 4);
  pos = pos + 4;
  // 3. entry: BitsPerSample
  //=========================
  data16 = 0x102;  // tag:   102.H 
  memcpy(&headerdata[pos], &data16, 2);
  pos = pos + 2;
  data16 = 3;   // type:  SHORT
  memcpy(&headerdata[pos], &data16, 2);
  pos = pos + 2;
  data32 = 1;   // count: 1 == SamplesPerPixel Mono16
  memcpy(&headerdata[pos], &data32, 4);
  pos = pos + 4;
  data32 = 16;   // SamplesPerPixel == 1 => value: 16    (16 bps => NOT BASELINE!)
  memcpy(&headerdata[pos], &data32, 4);
  pos = pos + 4;
  // 4. entry: Compression
  //=======================
  data16 = 0x103;  // tag:   103.H 
  memcpy(&headerdata[pos], &data16, 2);
  pos = pos + 2;
  data16 = 3;   // type:  SHORT
  memcpy(&headerdata[pos], &data16, 2);
  pos = pos + 2;
  data32 = 1;   // count: 1 
  memcpy(&headerdata[pos], &data32, 4);
  pos = pos + 4;
  data32 = 1;   // value: 1 (no compression)
  memcpy(&headerdata[pos], &data32, 4);
  pos = pos + 4;
  // 5. entry: PhotometricInterpretation
  //======================================
  data16 = 0x106;  // tag:   106.H 
  memcpy(&headerdata[pos], &data16, 2);
  pos = pos + 2;
  data16 = 3;   // type:  SHORT
  memcpy(&headerdata[pos], &data16, 2);
  pos = pos + 2;
  data32 = 1;   // count: 1 
  memcpy(&headerdata[pos], &data32, 4);
  pos = pos + 4;
  data32 = 1;   // SamplesPerPixel == 1 => value: 1 (BlackIsZero)
  memcpy(&headerdata[pos], &data32, 4);
  pos = pos + 4;
  // 6. entry: StripOffsets
  //========================
  data16 = 0x111;  // tag:   111.H 
  memcpy(&headerdata[pos], &data16, 2);
  pos = pos + 2;
  data16 = 4;   // type:  LONG
  memcpy(&headerdata[pos], &data16, 2);
  pos = pos + 2;
  data32 = 1;   // count: 1 == StripsPerImage
  memcpy(&headerdata[pos], &data32, 4);
  pos = pos + 4;
  data32 = 174;  // value = 8 + 2 + 12*12 + 4 + 8 + 8 = 174
  memcpy(&headerdata[pos], &data32, 4);
  pos = pos + 4;
  // 7. entry: SamplesPerPixel
  //===========================
  data16 = 0x115;  // tag:   115.H 
  memcpy(&headerdata[pos], &data16, 2);
  pos = pos + 2;
  data16 = 3;   // type:  SHORT
  memcpy(&headerdata[pos], &data16, 2);
  pos = pos + 2;
  data32 = 1;   // count: 1 
  memcpy(&headerdata[pos], &data32, 4);
  pos = pos + 4;
  data32 = 1;   // SamplesPerPixel == 1 Mono16
  memcpy(&headerdata[pos], &data32, 4);
  pos = pos + 4;
  // 8. entry: RowsPerStrip
  //========================
  data16 = 0x116;  // tag:   116.H 
  memcpy(&headerdata[pos], &data16, 2);
  pos = pos + 2;
  data16 = 4;   // type:  LONG
  memcpy(&headerdata[pos], &data16, 2);
  pos = pos + 2;
  data32 = 1;   // count: 1
  memcpy(&headerdata[pos], &data32, 4);
  pos = pos + 4;
  data32 = sizeY;  // value: vertical image size (one strip only)
  memcpy(&headerdata[pos], &data32, 4);
  pos = pos + 4;
  // 9. entry: StripByteCounts (For each strip, the number of bytes in the strip after compression.)
  //================================================================================================
  data16 = 0x117;  // tag:   117.H 
  memcpy(&headerdata[pos], &data16, 2);
  pos = pos + 2;
  data16 = 4;   // type:  LONG
  memcpy(&headerdata[pos], &data16, 2);
  pos = pos + 2;
  data32 = 1;   // count: 1 == StripsPerImage
  memcpy(&headerdata[pos], &data32, 4);
  pos = pos + 4;
  data32 = 2 * 1 * sizeX*sizeY;  // value = 2* 1 * SizeX * SizeY
  memcpy(&headerdata[pos], &data32, 4);
  pos = pos + 4;
  // 10. entry: XResolution (The number of pixels per ResolutionUnit in the ImageWidth direction.)
  //================================================================================================
  data16 = 0x11A;  // tag:   11A.H 
  memcpy(&headerdata[pos], &data16, 2);
  pos = pos + 2;
  data16 = 5;   // type:  RATIONAL
  memcpy(&headerdata[pos], &data16, 2);
  pos = pos + 2;
  data32 = 1;   // count: 1 
  memcpy(&headerdata[pos], &data32, 4);
  pos = pos + 4;
  data32 = 158;  // offset to value = 8 + (2 + 12*12 + 4) = 158
  memcpy(&headerdata[pos], &data32, 4);
  pos = pos + 4;
  // 11. entry: YResolution (The number of pixels per ResolutionUnit in the ImageLength direction.)
  //================================================================================================
  data16 = 0x11B;  // tag:   11B.H 
  memcpy(&headerdata[pos], &data16, 2);
  pos = pos + 2;
  data16 = 5;   // type:  RATIONAL
  memcpy(&headerdata[pos], &data16, 2);
  pos = pos + 2;
  data32 = 1;   // count: 1 
  memcpy(&headerdata[pos], &data32, 4);
  pos = pos + 4;
  data32 = 166;  // offset to value = 8 + (2 + 12*12 + 4) + 8 = 166
  memcpy(&headerdata[pos], &data32, 4);
  pos = pos + 4;
  // 12. entry: ResolutionUnit (The unit of measurement for XResolution and YResolution.)
  //=====================================================================================
  data16 = 0x128;  // tag:   128.H 
  memcpy(&headerdata[pos], &data16, 2);
  pos = pos + 2;
  data16 = 3;   // type:  SHORT
  memcpy(&headerdata[pos], &data16, 2);
  pos = pos + 2;
  data32 = 1;   // count: 1 
  memcpy(&headerdata[pos], &data32, 4);
  pos = pos + 4;
  data32 = 2;   // value: 2 (Inch) => dpi
  memcpy(&headerdata[pos], &data32, 4);
  pos = pos + 4;
  data32 = 0;   // offset of next IFD: none
  memcpy(&headerdata[pos], &data32, 4);
  pos = pos + 4;
  //  write IFD values longer than 4 byte
  //======================================
  data32 = 72;  // XResolution numerator: 72 => 72 dpi (a common value..)
  memcpy(&headerdata[pos], &data32, 4);
  pos = pos + 4;
  data32 = 1;   // XResolution denominator: 1
  memcpy(&headerdata[pos], &data32, 4);
  pos = pos + 4;
  data32 = 72;  // YResolution numerator: 72 => 72 dpi (a common value..)
  memcpy(&headerdata[pos], &data32, 4);
  pos = pos + 4;
  data32 = 1;   // YResolution denominator: 1
  memcpy(&headerdata[pos], &data32, 4);
  pos = pos + 4;
  // save header to file
  //======================
  fwrite(headerdata, tiffMono16HeaderLength, 1, file);
  // save image data (converted from Mono12 to Mono16) to file 
  //===========================================================
  fwrite(*imagebuffer, sizeX*sizeY * 2, 1, file); //*2 --> 2 bytes = 16 bit
  fclose(file);
  delete[] headerdata;
  return;
} // end of saveMono16Tiff()

Baumer工业相机转换保存位深度12/16位图像的优点

Baumer工业相机转换保存位深度12/16位图像的优点如下:


更高的图像质量:12/16位图像可以更精确地捕捉每个像素的亮度和颜色值,相较于8位图像,捕捉更丰富的颜色层次和更详细的图像信息。


强大的动态范围:12/16位图像具有更广泛的动态范围,意味着它们可以比8位图像更好地区分明暗区域的细节,提高图像中细节的呈现。


更好的信噪比:12/16位图像的信噪比较高,噪声水平更低。这有助于提供更清晰、更干净的图像,尤其是在低光环境下。


更佳的色彩再现:12/16位图像可提供更准确的颜色表现,从而使得在色彩敏感的应用中具有更高水平视觉效果,如医疗、影像、半导体与食品等产业。


更强大的后期处理能力:12/16位图像的深度提供了更大的调整空间,这使得后期处理图像时具有更好的操控性,可以避免数据丢失或异常。


更适合需求严格的领域:对于对图像精度和质量要求非常高的应用场景(如科研、医学影像和制造等行业),12/16位图像具有明显优势。


总之,Baumer工业相机具有能力转换和保存12/16位图像数据,能满足各种行业对图像精度和质量的高需求,提供更高质量的图像输出和分析,从而提高整体系统的稳定性和性能表现。


Baumer工业相机转换保存位深度12/16位图像的行业应用

Baumer工业相机能够抓取和保存12/16位图像,为各种行业提供更高质量和精度的图像,以下为一些典型的行业应用:


医学影像:在医学影像领域,如X光成像、超声检查、内窥镜检查等,高质量的图像数据对于诊断具有关键性作用,12/16位图像能够提供更准确的色彩和细节表现。


半导体制造:半导体制造需要对芯片进行精确的检测,以确保其功能不受缺陷影响。12/16位图像能够提供更细致的图像,用于检查和识别问题部分。


机器视觉:例如,在质量检测、自动化装配线和供应链管理等领域中,12/16位图像可以实现更高精度和辨识度的目标检测和跟踪。


汽车制造:汽车制造中,精确的检测和监控对于组装和质量测试至关重要。12/16位图像能提供足够的细节来确保零部件之间的准确配缺陷识别。


食品制造与农业:在食品制造和农业领域,需要精确区分植物或食品的颜色和纹理,以确保出售给消费者的产品质量。12/16位图像能够提供更准确的色彩再现,有助于区分和识别目标物品。


安全监控:在安防行业中,12/16位图像可提供更清晰可识别的图像,有助于监控区域举动或情况,确保生产过程工作顺利和安全无虞。


能源行业:在太阳能电池板制造、风力涡轮机等设备上进行质量检测时,12/16位图像可以提供更多细节,用以分析和评估设备的性能。


生物科技:例如,在显微镜、生物检测、细胞成像等应用中,12/16位图像可以捕捉到更准确、更细致的生物标本信息,从而为研究和开发提供更丰富的数据。


无损检测:例如,利用红外检测等技术对建筑物、飞机、管道等进行缺陷检测,12/16位图像可提供更高质量的图像数据,以确保检测的准确性和可靠性。


通过Baumer工业相机的12/16位图像捕捉功能,用户可以在众多行业领域获得更高质量、更具可靠性的图像数据,从而提高工作效率和准确性。

目录
打赏
0
1
1
1
9
分享
相关文章
Baumer工业相机堡盟工业相机如何通过NEOAPI SDK获取每张图像的微秒时间和FrameID功能(C#)
Baumer工业相机堡盟工业相机如何通过NEOAPI SDK获取每张图像的微秒时间和FrameID功能(C#)
129 0
Baumer工业相机堡盟工业相机如何通过NEOAPI SDK使用Force IP强制修改网口IP功能(C++)
Baumer工业相机堡盟工业相机如何通过NEOAPI SDK使用Force IP强制修改网口IP功能(C++)
76 0
Baumer工业相机堡盟工业相机如何通过NEOAPI SDK使用ForceIP强制修改网口IP功能(C#)
Baumer工业相机堡盟工业相机如何通过NEOAPI SDK使用ForceIP强制修改网口IP功能(C#)
75 0
Baumer工业相机堡盟工业相机如何通过NEOAPI SDK使用Binning像素合并功能(C++)
Baumer工业相机堡盟工业相机如何通过NEOAPI SDK使用Binning像素合并功能(C++)
113 0
海康威视工业相机SDK+Python+PyQt开发数据采集系统(支持软件触发、编码器触发)
该系统基于海康威视工业相机SDK,使用Python与PyQt开发,支持Gige与USB相机设备的搜索及双相机同时显示。系统提供软件触发与编码器触发模式,并可在数据采集过程中实时保存图像。此外,用户可以调节曝光时间和增益,并进行信息输入,这些信息将被保存至配置文件以便下次自动加载。参数调节与实时预览等功能进一步增强了系统的实用性。
461 1
Baumer工业相机堡盟工业相机如何通过NEOAPI SDK获取每张图像的微秒时间和FrameID功能(C++)
Baumer工业相机堡盟工业相机如何通过NEOAPI SDK获取每张图像的微秒时间和FrameID功能(C++)
99 0
【08】flutter完成屏幕适配-重建Android,增加GetX路由,屏幕适配,基础导航栏-多版本SDK以及gradle造成的关于fvm的使用(flutter version manage)-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
【08】flutter完成屏幕适配-重建Android,增加GetX路由,屏幕适配,基础导航栏-多版本SDK以及gradle造成的关于fvm的使用(flutter version manage)-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
166 20
【08】flutter完成屏幕适配-重建Android,增加GetX路由,屏幕适配,基础导航栏-多版本SDK以及gradle造成的关于fvm的使用(flutter version manage)-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
[Android][Framework]系统jar包,sdk的制作及引用
[Android][Framework]系统jar包,sdk的制作及引用
175 0
|
4月前
|
Android SDK
【10月更文挑战第21天】
150 1
Android|使用阿里云推流 SDK 实现双路推流不同画面
本文记录了一种使用没有原生支持多路推流的阿里云推流 Android SDK,实现同时推送两路不同画面的流的方法。
96 7

热门文章

最新文章

  • 1
    【Azure Storage Account】利用App Service作为反向代理, 并使用.NET Storage Account SDK实现上传/下载操作
    12
  • 2
    【04】鸿蒙实战应用开发-华为鸿蒙纯血操作系统Harmony OS NEXT-正确安装鸿蒙SDK-结构目录介绍-路由介绍-帧动画(ohos.animator)书写介绍-能够正常使用依赖库等-ArkUI基础组件介绍-全过程实战项目分享-从零开发到上线-优雅草卓伊凡
    44
  • 3
    CompreFace:Star6.1k,Github上火爆的轻量化且强大的人脸识别库,api,sdk都支持
    34
  • 4
    【Azure Developer】编写Python SDK代码实现从China Azure中VM Disk中创建磁盘快照Snapshot
    21
  • 5
    【02】鸿蒙实战应用开发-华为鸿蒙纯血操作系统Harmony OS NEXT-项目开发实战-准备工具安装-编译器DevEco Studio安装-arkts编程语言认识-编译器devco-鸿蒙SDK安装-模拟器环境调试-hyper虚拟化开启-全过程实战项目分享-从零开发到上线-优雅草卓伊凡
    28
  • 6
    【11】flutter进行了聊天页面的开发-增加了即时通讯聊天的整体页面和组件-切换-朋友-陌生人-vip开通详细页面-即时通讯sdk准备-直播sdk准备-即时通讯有无UI集成的区别介绍-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
    163
  • 7
    【08】flutter完成屏幕适配-重建Android,增加GetX路由,屏幕适配,基础导航栏-多版本SDK以及gradle造成的关于fvm的使用(flutter version manage)-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
    166
  • 8
    【01】完整开发即构美颜sdk的uni官方uts插件—让所有开发者可以直接使用即构美颜sdk的能力-优雅草卓伊凡
    77
  • 9
    AutoTalk第十三期-应知必会的自动化工具-阿里云SDK支持策略(一)
    58
  • 10
    自动化AutoTalk第十期:应知必会的自动化工具-阿里云SDK
    58
  • AI助理

    你好,我是AI助理

    可以解答问题、推荐解决方案等