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位图像捕捉功能,用户可以在众多行业领域获得更高质量、更具可靠性的图像数据,从而提高工作效率和准确性。

目录
相关文章
|
算法 开发工具 计算机视觉
【零代码研发】OpenCV实验大师工作流引擎C++ SDK演示
【零代码研发】OpenCV实验大师工作流引擎C++ SDK演示
407 1
|
监控 API 开发工具
Baumer工业相机堡盟工业相机如何通过NEOAPI SDK获取每张图像的微秒时间和FrameID功能(C++)
Baumer工业相机堡盟工业相机如何通过NEOAPI SDK获取每张图像的微秒时间和FrameID功能(C++)
248 0
|
开发工具 对象存储 Android开发
对象存储oss使用问题之C++使用OSS SDK时遍历OSS上的文件时崩溃如何解决
《对象存储OSS操作报错合集》精选了用户在使用阿里云对象存储服务(OSS)过程中出现的各种常见及疑难报错情况,包括但不限于权限问题、上传下载异常、Bucket配置错误、网络连接问题、跨域资源共享(CORS)设定错误、数据一致性问题以及API调用失败等场景。为用户降低故障排查时间,确保OSS服务的稳定运行与高效利用。
824 0
|
编译器 C++ 开发者
【C++篇】深度解析类与对象(下)
在上一篇博客中,我们学习了C++的基础类与对象概念,包括类的定义、对象的使用和构造函数的作用。在这一篇,我们将深入探讨C++类的一些重要特性,如构造函数的高级用法、类型转换、static成员、友元、内部类、匿名对象,以及对象拷贝优化等。这些内容可以帮助你更好地理解和应用面向对象编程的核心理念,提升代码的健壮性、灵活性和可维护性。
|
11月前
|
编译器 C++ 容器
【c++11】c++11新特性(上)(列表初始化、右值引用和移动语义、类的新默认成员函数、lambda表达式)
C++11为C++带来了革命性变化,引入了列表初始化、右值引用、移动语义、类的新默认成员函数和lambda表达式等特性。列表初始化统一了对象初始化方式,initializer_list简化了容器多元素初始化;右值引用和移动语义优化了资源管理,减少拷贝开销;类新增移动构造和移动赋值函数提升性能;lambda表达式提供匿名函数对象,增强代码简洁性和灵活性。这些特性共同推动了现代C++编程的发展,提升了开发效率与程序性能。
438 12
|
9月前
|
人工智能 机器人 编译器
c++模板初阶----函数模板与类模板
class 类模板名private://类内成员声明class Apublic:A(T val):a(val){}private:T a;return 0;运行结果:注意:类模板中的成员函数若是放在类外定义时,需要加模板参数列表。return 0;
233 0
|
9月前
|
存储 编译器 程序员
c++的类(附含explicit关键字,友元,内部类)
本文介绍了C++中类的核心概念与用法,涵盖封装、继承、多态三大特性。重点讲解了类的定义(`class`与`struct`)、访问限定符(`private`、`public`、`protected`)、类的作用域及成员函数的声明与定义分离。同时深入探讨了类的大小计算、`this`指针、默认成员函数(构造函数、析构函数、拷贝构造、赋值重载)以及运算符重载等内容。 文章还详细分析了`explicit`关键字的作用、静态成员(变量与函数)、友元(友元函数与友元类)的概念及其使用场景,并简要介绍了内部类的特性。
372 0
|
设计模式 安全 C++
【C++进阶】特殊类设计 && 单例模式
通过对特殊类设计和单例模式的深入探讨,我们可以更好地设计和实现复杂的C++程序。特殊类设计提高了代码的安全性和可维护性,而单例模式则确保类的唯一实例性和全局访问性。理解并掌握这些高级设计技巧,对于提升C++编程水平至关重要。
220 16
|
编译器 C语言 C++
类和对象的简述(c++篇)
类和对象的简述(c++篇)
|
12月前
|
编译器 C++
类和对象(中 )C++
本文详细讲解了C++中的默认成员函数,包括构造函数、析构函数、拷贝构造函数、赋值运算符重载和取地址运算符重载等内容。重点分析了各函数的特点、使用场景及相互关系,如构造函数的主要任务是初始化对象,而非创建空间;析构函数用于清理资源;拷贝构造与赋值运算符的区别在于前者用于创建新对象,后者用于已存在的对象赋值。同时,文章还探讨了运算符重载的规则及其应用场景,并通过实例加深理解。最后强调,若类中存在资源管理,需显式定义拷贝构造和赋值运算符以避免浅拷贝问题。