Baumer工业相机堡盟相机是一种高性能、高质量的工业相机,可用于各种应用场景,如物体检测、计数和识别、运动分析和图像处理。
Baumer的万兆网相机拥有出色的图像处理性能,可以实时传输高分辨率图像。此外,该相机还具有快速数据传输、低功耗、易于集成以及高度可扩展性等特点。
Baumer工业相机通过使用BGAPI SDK进行开发时,在C++环境可以直接实现位深度为16的图像保存。
工业相机通常用于需要高质量图像的分析和检查的专业环境中。这些相机被设计用来捕捉16比特的高比特深度的图像,与低比特深度的图像相比,可以捕捉到更大范围的色彩和细节。
保存位深16位图像的工业相机的技术背景涉及几个关键部分。首先,相机的图像传感器必须能够捕捉到高比特深度的图像。这是通过使用高质量的图像传感器来实现的,该传感器能够以每像素16比特的分辨率捕获数据。
其次,相机的电子设备必须能够处理和存储高比特深度的图像数据。这意味着相机需要有一个高速处理器和足够的内存来处理所产生的大量图像数据。
第三,相机的软件必须能够支持16位图像的保存。这意味着相机的固件和软件接口必须被设计成能够处理16位图像所产生的更大的文件尺寸,并且还能与工业标准文件格式如TIFF和RAW兼容。
总的来说,保存16位深度图像的工业相机的技术背景涉及高质量的图像传感器、强大的电子器件和专门的软件的组合,这些都是为了处理捕捉和存储高位深度图像的独特需求。
这里主要描述如何在C#的平台下通过BGAPI SDK直接实现Mono16图像格式的保存功能的核心代码
本文介绍使用BGAPI SDK对Baumer的工业相机进行开发时,直接实现Mono12或者Mono16图像格式的保存功能
如下为核心代码实现步骤:
C++环境下核心代码如下所示:
#include
#include
#include
#include
#include
#include
#include
#include "bgapi2_genicam/bgapi2_genicam.hpp"
#include
#include
#include
#include
#include
下面为在在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位图像的优点如下:
更高的图像质量:12/16位图像可以更精确地捕捉每个像素的亮度和颜色值,相较于8位图像,捕捉更丰富的颜色层次和更详细的图像信息。
强大的动态范围:12/16位图像具有更广泛的动态范围,意味着它们可以比8位图像更好地区分明暗区域的细节,提高图像中细节的呈现。
更好的信噪比:12/16位图像的信噪比较高,噪声水平更低。这有助于提供更清晰、更干净的图像,尤其是在低光环境下。
更佳的色彩再现:12/16位图像可提供更准确的颜色表现,从而使得在色彩敏感的应用中具有更高水平视觉效果,如医疗、影像、半导体与食品等产业。
更强大的后期处理能力:12/16位图像的深度提供了更大的调整空间,这使得后期处理图像时具有更好的操控性,可以避免数据丢失或异常。
更适合需求严格的领域:对于对图像精度和质量要求非常高的应用场景(如科研、医学影像和制造等行业),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位图像捕捉功能,用户可以在众多行业领域获得更高质量、更具可靠性的图像数据,从而提高工作效率和准确性。