项目场景
Baumer工业相机堡盟相机是一种高性能、高质量的工业相机,可用于各种应用场景,如物体检测、计数和识别、运动分析和图像处理。
Baumer的万兆网相机拥有出色的图像处理性能,可以实时传输高分辨率图像。此外,该相机还具有快速数据传输、低功耗、易于集成以及高度可扩展性等特点。
Baumer工业相机堡盟相机中PixelTransformation功能由BGAPI SDK提供的ImageProcesser函数进行转换的,以方便各种场合所需要的不同格式图像。
技术背景
工业相机SDK开发工具包中的像素转换功能通常用于将来自相机传感器的数据转换成可由计算机处理的格式。该功能将原始像素数据(通常表示为一系列数字)转换为可在计算机屏幕上显示或用于进一步分析和处理的图像。
这个功能的具体细节取决于具体的SDK和正在使用的相机,可能有所不同。不过,一般来说,像素转换功能会考虑到相机传感器的颜色深度、用于传输数据的任何压缩或编码,以及可能影响原始像素数据表示方式的任何其他因素。
总的来说,像素转换功能是任何工业相机SDK开发工具包的一个重要组成部分,因为它允许用户以对广泛的应用有用和实用的方式处理相机产生的数据。
工业相机从环境中捕捉图像并将其转换为数字数据。像素转换功能是在模拟信号转换为数字信号的过程中发生的,其中每个像素的特征被修改,以优化所产生的图像的质量。
在mono8和mono12像素格式的情况下,该数字表示每个像素的比特深度。单8相机捕获的灰度图像有256级亮度,而单12相机捕获的灰度图像有4096级亮度。
在转换过程中,像素值根据各种算法进行转换,包括伽玛校正、色彩校正和数字增益,以确保图像准确地表现所拍摄的场景。例如,伽马校正,调整每个像素的亮度值,以补偿相机响应的非线性。
CameraExplorer使用像素转换功能
Baumer BGAPI SDK使用像素转换功能
Baumer工业相机堡盟相机SDK示例中005_PixelTransformation.cpp详细介绍了如何配置像素转换功能。
软件SDK示例地址如下所示:Baumer_GAPI_SDK_2.12.0_win_x86_64_cpp\examples\src\0_Common\005_PixelTransformation\005_PixelTransformation.cpp
下面代码Demo演示如何通过相机SDK中的Buffer转换Mono8和彩色像素转换为BGR8。
如下所示为C++的部分核心代码:
SystemList Open a System Get the InterfaceList and fill it Open an Interface Get the DeviceList and fill it Open a Device // CAPTURE 8 IMAGES std::cout << " " << std::endl; std::cout << "CAPTURE & TRANSFORM 4 IMAGES" << std::endl; std::cout << "############################" << std::endl << std::endl; BGAPI2::Buffer * pBufferFilled = NULL; try { BGAPI2::Image* pImage = imgProcessor->CreateImage(); BGAPI2::Node* pPixelFormatInfoSelector = imgProcessor->GetNode("PixelFormatInfoSelector"); BGAPI2::Node* pBytesPerPixel = imgProcessor->GetNode("BytesPerPixel"); for (int i = 0; i < 4; i++) { pBufferFilled = pDataStream->GetFilledBuffer(1000); // timeout 1000 msec if (pBufferFilled == NULL) { std::cout << "Error: Buffer Timeout after 1000 msec" << std::endl << std::endl; } else if (pBufferFilled->GetIsIncomplete() == true) { std::cout << "Error: Image is incomplete" << std::endl << std::endl; // queue buffer again pBufferFilled->QueueBuffer(); } else { std::cout << " Image " << std::setw(5) << pBufferFilled->GetFrameID() << " received in memory address " << std::hex << pBufferFilled->GetMemPtr() << std::dec << std::endl; // create an image object from the filled buffer and convert it BGAPI2::Image * pTransformImage = NULL; pImage->Init(pBufferFilled); BGAPI2::String sPixelFormat = pImage->GetPixelformat(); std::cout << " pImage.Pixelformat: " << pImage->GetPixelformat() << std::endl; std::cout << " pImage.Width: " << pImage->GetWidth() << std::endl; std::cout << " pImage.Height: " << pImage->GetHeight() << std::endl; std::cout << " pImage.Buffer: " << std::hex << pImage->GetBuffer() << std::dec << std::endl; pPixelFormatInfoSelector->SetValue(sPixelFormat); double fBytesPerPixel = pBytesPerPixel->GetAvailable() ? pBytesPerPixel->GetDouble() : 0.0; std::cout << " Bytes per image: " << static_cast<unsigned int>((pImage->GetWidth())*(pImage->GetHeight())*fBytesPerPixel) << std::endl; std::cout << " Bytes per pixel: " << fBytesPerPixel << std::endl; // display first 6 pixel values of first 6 lines of the image // ======================================================================== unsigned char* imageBuffer = (unsigned char *)pImage->GetBuffer(); std::cout << " Address" << std::endl; // set display for uppercase hex numbers filled with '0' std::cout << std::uppercase << std::setfill('0') << std::hex; for (int j = 0; j < 6; j++) { // first 6 lines void* imageBufferAddress = &imageBuffer[static_cast<int>(pImage->GetWidth()*j*fBytesPerPixel)]; std::cout << " " << std::setw(8) << imageBufferAddress << " "; for (int k = 0; k < static_cast<int>(6 * fBytesPerPixel); k++) { // bytes of first 6 pixels std::cout << " " << std::setw(2) << static_cast<int>(imageBuffer[static_cast<int>(pImage->GetWidth()*j*fBytesPerPixel)+k]); } std::cout << " ..." << std::endl; } // set display for lowercase dec numbers filled with ' ' std::cout << std::nouppercase << std::setfill(' ') << std::dec; // if pixel format starts with "Mono" if (std::string(pImage->GetPixelformat()).substr(0, 4) == "Mono") { // transform to Mono8 pTransformImage = imgProcessor->CreateTransformedImage(pImage, "Mono8"); std::cout << " Image " << std::setw(5) << pBufferFilled->GetFrameID() << " transformed to Mono8" << std::endl; std::cout << " pTransformImage.Pixelformat: " << pTransformImage->GetPixelformat() << std::endl; std::cout << " pTransformImage.Width: " << pTransformImage->GetWidth() << std::endl; std::cout << " pTransformImage.Height: " << pTransformImage->GetHeight() << std::endl; std::cout << " pTransformImage.Buffer: " << std::hex << pTransformImage->GetBuffer() << std::dec << std::endl; std::cout << " Bytes per image: " << pTransformImage->GetWidth() * pTransformImage->GetHeight() * 1 << std::endl; std::cout << " Bytes per pixel: " << 1.0 << std::endl; unsigned char* transformBuffer = (unsigned char *)pTransformImage->GetBuffer(); // display first 6 pixel values of first 6 lines of the transformed image // ======================================================================== std::cout << " Address Y Y Y Y Y Y " << std::endl; // set display for uppercase hex numbers filled with '0' std::cout << std::uppercase << std::setfill('0') << std::hex; for (int j = 0; j < 6; j++) { // first 6 lines void* transformBufferAddress = &transformBuffer[pTransformImage->GetWidth() * 1 * j]; std::cout << " " << std::setw(8) << std::setfill('0') << std::hex << transformBufferAddress << " "; for (int k = 0; k < 6; k++) { // first 6 Pixel with Mono8 (1 Byte per Pixel) // value of pixel std::cout << " " << std::setw(2) << static_cast<int>(transformBuffer[pTransformImage->GetWidth()*j + k]); } std::cout << " ..." << std::endl; } // set display for lowercase dec numbers filled with ' ' std::cout << std::nouppercase << std::setfill(' ') << std::dec; std::cout << " " << std::endl; } else { // if color format // transform to BGR8 pTransformImage = imgProcessor->CreateTransformedImage(pImage, "BGR8"); std::cout << " Image " << std::setw(5) << pBufferFilled->GetFrameID() << " transformed to BGR8" << std::endl; std::cout << " pTransformImage.Pixelformat: " << pTransformImage->GetPixelformat() << std::endl; std::cout << " pTransformImage.Width: " << pTransformImage->GetWidth() << std::endl; std::cout << " pTransformImage.Height: " << pTransformImage->GetHeight() << std::endl; std::cout << " pTransformImage.Buffer: " << std::hex << pTransformImage->GetBuffer() << std::dec << std::endl; std::cout << " Bytes per image: " << pTransformImage->GetWidth() * pTransformImage->GetHeight() * 3 << std::endl; std::cout << " Bytes per pixel: " << 3.0 << std::endl; unsigned char* transformBuffer = (unsigned char *)pTransformImage->GetBuffer(); // display first 6 pixel values of first 6 lines of the transformed image // ======================================================================== std::cout << " Address B G R B G R B G R B G R B G R B G R" << std::endl; // set display for uppercase hex numbers filled with '0' std::cout << std::uppercase << std::setfill('0') << std::hex; for (int j = 0; j < 6; j++) { // 6 lines void* transformBufferAddress = &transformBuffer[pTransformImage->GetWidth() * 3 * j]; std::cout << " " << std::setw(8) << std::setfill('0') << std::hex << transformBufferAddress << " "; for (int k = 0; k < 6; k++) { // first 6 Pixel with BGR8 (3 Bytes per Pixel) // Value of Blue pixel std::cout << " " << std::setw(2) << static_cast<int>(transformBuffer[pTransformImage->GetWidth() * 3 * j + k * 3 + 0]); // Value of Green pixel std::cout << " " << std::setw(2) << static_cast<int>(transformBuffer[pTransformImage->GetWidth() * 3 * j + k * 3 + 1]); // Value of Red pixel std::cout << " " << std::setw(2) << static_cast<int>(transformBuffer[pTransformImage->GetWidth() * 3 * j + k * 3 + 2]); } std::cout << " ..." << std::endl; } // set display for lowercase dec numbers filled with ' ' std::cout << std::nouppercase << std::setfill(' ') << std::dec; std::cout << " " << std::endl; } pTransformImage->Release(); // delete [] transformBuffer; // QUEUE BUFFER AFTER USE pBufferFilled->QueueBuffer(); } } if (pImage != NULL) { pImage->Release(); pImage = NULL; } } catch (BGAPI2::Exceptions::IException& ex) { returncode = (returncode == 0) ? 1 : returncode; std::cout << "ExceptionType: " << ex.GetType() << std::endl; std::cout << "ErrorDescription: " << ex.GetErrorDescription() << std::endl; std::cout << "in function: " << ex.GetFunctionName() << std::endl; } std::cout << " " << std::endl; std::cout << "CAMERA STOP" << std::endl; std::cout << "###########" << std::endl << std::endl;
图像转换的优势
工业相机的像素变换功能有几个优点,例如。
1. 提高图像质量。像素变换有助于纠正图像的失真和非线性,从而使图像更清晰、明确。
2. 提高准确性和精确性。通过纠正图像的失真和非线性,像素变换有助于提高测量和分析的准确性和精确度。
3. 不同相机之间的一致性。像素变换可用于校准不同的相机,以产生一致和准确的结果。
4. 提高效率。通过校正失真和非线性,像素转换消除了对额外的后处理步骤的需要,节省了时间和精力。
5. 更大的灵活性。像素转换可以定制,以适应特定的应用,使图像采集和分析更加灵活。
图像转换的行业应用
工业相机的像素转换功能可用于各种场景,如。
1. 图像校正。像素变换功能可用于纠正图像失真和其他由相机镜头引起的缺陷,如色差、晕影和透视变形。
2. 色彩校正。该功能可用于调整图像的色彩平衡、饱和度和其他与色彩有关的参数。
3. 图像增强。该功能可用于增强图像的对比度、锐度和其他视觉特征,以提高图像的质量。
4. 图像处理。该功能可用于转换图像格式或数据类型,调整图像大小,裁剪图像,或应用其他图像处理技术。
5. 机器视觉。该函数可用于预处理图像数据,然后再将其输入计算机视觉算法,用于物体检测、识别、跟踪或其他机器视觉任务。
总的来说,像素变换函数在图像处理和分析中起着至关重要的作用,它在制造业、机器人、汽车、医疗和其他行业的应用非常广泛。