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#环境下核心代码如下所示:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using System.IO;
using CSCameraDemo.Properties;
using System.Globalization;
using WindowsFormsApplication1;
using System.Threading.Tasks;
using System.Threading;
using System.Drawing.Imaging;
using BGAPI2;

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

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


如下所示:

SystemList 
Open a System 
Get the InterfaceList and fill it Open an Interface 
Get the DeviceList and fill it 
Open a Device
void mDataStream_NewBufferEvent(object sender, BGAPI2.Events.NewBufferEventArgs mDSEvent)
{
    try
    {
        BGAPI2.Buffer mBufferFilled = null;              
        mBufferFilled = mDSEvent.BufferObj;
        if (mBufferFilled == null)
        {
            MessageBox.Show("Error: Buffer Timeout after 1000 ms!");
        }
        else if (mBufferFilled.IsIncomplete == true)
        {
            //MessageBox.Show("Error: Image is incomplete!");
            //queue buffer again
            mBufferFilled.QueueBuffer();
        }
        else
        {
            #region//获取当前FrameID
            FrameIDInt = (int)mBufferFilled.FrameID;
            OnNotifySetFrameID(FrameIDInt.ToString());
            #endregion
            //将相机内部图像内存数据转为bitmap数据
            System.Drawing.Bitmap bitmap  = new System.Drawing.Bitmap((int)mBufferFilled.Width, (int)mBufferFilled.Height, (int)mBufferFilled.Width,
                System.Drawing.Imaging.PixelFormat.Format8bppIndexed, (IntPtr)((ulong)mBufferFilled.MemPtr + mBufferFilled.ImageOffset));
            #region//Mono图像数据转换。彩色图像数据转换于此不同
            System.Drawing.Imaging.ColorPalette palette = bitmap.Palette;
            int nColors = 256;
            for (int ix = 0; ix < nColors; ix++)
            {
                uint Alpha = 0xFF;
                uint Intensity = (uint)(ix * 0xFF / (nColors - 1));
                palette.Entries[ix] = System.Drawing.Color.FromArgb((int)Alpha, (int)Intensity, (int)Intensity, (int)Intensity);
            }
            bitmap.Palette = palette;
            #endregion
            long currenttime = (long)mBufferFilled.Timestamp;                   
            DateTime sdasd = GetTime(currenttime, true);
            #region//回调函数保存图像功能
            if (bSaveImg)
            {
                //使用bitmap自带函数保存
                string strtime = DateTime.Now.ToString("yyyyMMddhhmmssfff");
                string saveimagepath = pImgFileDir  +"\\"+ strtime + ".jpg";
                // bitmap.Save(saveimagepath, System.Drawing.Imaging.ImageFormat.Bmp);
                //使用opencv进行保存图像
                if (mBufferFilled.PixelFormat == "Mono8")
                {
                    OpenCvSharp.Mat matgray = OpenCvSharp.Extensions.BitmapConverter.ToMat(bitmap);//用bitmap转换为mat                           
                    matgray.SaveImage("opencv_image.png");
                    Cv2.ImWrite("opencvcv_image_Clone.png", matgray);
                    Cv2.ImWrite(saveimagepath, matgray);
                }                      
    //将相机中原始图像数据通过BGAPI SDK直接保存为16位深度的图像
                if (mBufferFilled.PixelFormat.Contains("Mono12"))
                {
        short[] mImageBuffer16Copy = new short[(uint)((uint)mBufferFilled.Width * (uint)mBufferFilled.Height * 1)];
                        Marshal.Copy((IntPtr)mBufferFilled.MemPtr, mImageBuffer16Copy, 0, (int)((int)mBufferFilled.Width * (int)mBufferFilled.Height * 1));
                        //convert Mono12 to Mono16
                        uint length = (uint)((uint)mBufferFilled.Width * (uint)mBufferFilled.Height) * 1;
                        for (uint l = 0; l < length; l++)
                        {
                               mImageBuffer16Copy[l] = (short)(mImageBuffer16Copy[l] << 4);
                        }
                      saveimagepath = pImgFileDir + "\\" + strtime + "-Mono16.png";
                      saveMono16Tiff(saveimagepath , mImageBuffer16Copy, (int)mBufferFilled.Width, (int)mBufferFilled.Height * 1);
                }
                bSaveImg = false;//变量控制单次保存图像
            }
            #endregion
            #region//bitmap的图像数据复制pBitmap
            Bitmap clonebitmap = (Bitmap)bitmap.Clone();
            BitmapData data = clonebitmap.LockBits(new Rectangle(0, 0, clonebitmap.Width, clonebitmap.Height), ImageLockMode.ReadOnly, clonebitmap.PixelFormat);
            clonebitmap.UnlockBits(data);
            pBitmap = clonebitmap;
            #endregion
            #region//将pBitmap图像数据显示在UI界面PictureBox控件上
            prcSource.X = 0;prcSource.Y = 0;
            prcSource.Width = (int)mBufferFilled.Width;prcSource.Height = (int)mBufferFilled.Height;
            System.Drawing.Graphics graph = System.Drawing.Graphics.FromHwnd(pictureBoxA.Handle);
            graph.DrawImage(pBitmap, prcPBox, prcSource, GraphicsUnit.Pixel);
            #endregion
            clonebitmap.Dispose(); //清除临时变量clonebitmap所占内存空间
            mBufferFilled.QueueBuffer();
        }
    }
    catch (BGAPI2.Exceptions.IException ex)
    {
        {
            string str2;
            str2 = string.Format("ExceptionType:{0}! ErrorDescription:{1} in function:{2}", ex.GetType(), ex.GetErrorDescription(), ex.GetFunctionName());
            MessageBox.Show(str2);
        }
    }
    return;
}

3:使用BGAPI SDK的图像直接转换Mono12/16图像并保存的功能

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


如下所示:

public static void saveMono16Tiff(string fileName, short[] shortarray, int imagewidth, int imageheight)
{
    FileStream FileST = new FileStream(fileName, FileMode.Create);
    // Create the writer for data.
    BinaryWriter binWriter = new BinaryWriter(FileST);
    // Write data to Test.data.
    ushort data16 = 0;
    uint data32 = 0;
    uint sizeX = (uint)imagewidth;
    uint sizeY = (uint)imageheight;
    int imagelength2 = imagewidth * imageheight;
    // TIFF identifier and count of directory entries
    //================================================
    data16 = 0x4949;  // identifier "II" for little-endian byte order
    binWriter.Write(data16);
    data16 = 42;  // tiff identifier 42
    binWriter.Write(data16);
    data32 = 8;   // offset for the first IFD
    binWriter.Write(data32);
    data16 = 12;  // number of directory entries
    binWriter.Write(data16);
    // 1. entry: ImageWidth (number of columns)
    //==========================================
    data16 = 0x100;  // tag:   100.H
    binWriter.Write(data16);
    data16 = 4;   // type:  LONG
    binWriter.Write(data16);
    data32 = 1;   // count: 1
    binWriter.Write(data32);
    data32 = sizeX;  // value: horizontal image size
    binWriter.Write(data32);
    // 2. entry: ImageLength (number of rows)
    //=======================================
    data16 = 0x101;  // tag:   101.H 
    binWriter.Write(data16);
    data16 = 4;   // type:  LONG
    binWriter.Write(data16);
    data32 = 1;   // count: 1
    binWriter.Write(data32);
    data32 = sizeY;  // value: horizontal image size
    binWriter.Write(data32);
    // 3. entry: BitsPerSample
    //=========================
    data16 = 0x102;  // tag:   102.H 
    binWriter.Write(data16);
    data16 = 3;   // type:  SHORT
    binWriter.Write(data16);
    data32 = 1;   // count: 1 == SamplesPerPixel Mono16
    binWriter.Write(data32);
    data32 = 16;   // SamplesPerPixel == 1 => value: 16    (16 bps => NOT BASELINE!)
    binWriter.Write(data32);
    // 4. entry: Compression
    //=======================
    data16 = 0x103;  // tag:   103.H 
    binWriter.Write(data16);
    data16 = 3;   // type:  SHORT
    binWriter.Write(data16);
    data32 = 1;   // count: 1 
    binWriter.Write(data32);
    data32 = 1;   // value: 1 (no compression)
    binWriter.Write(data32);
    // 5. entry: PhotometricInterpretation
    //======================================
    data16 = 0x106;  // tag:   106.H 
    binWriter.Write(data16);
    data16 = 3;   // type:  SHORT
    binWriter.Write(data16);
    data32 = 1;   // count: 1 
    binWriter.Write(data32);
    data32 = 1;   // SamplesPerPixel == 1 => value: 1 (BlackIsZero)
    binWriter.Write(data32);
    // 6. entry: StripOffsets
    //========================
    data16 = 0x111;  // tag:   111.H 
    binWriter.Write(data16);
    data16 = 4;   // type:  LONG
    binWriter.Write(data16);
    data32 = 1;   // count: 1 == StripsPerImage
    binWriter.Write(data32);
    data32 = 174;  // value = 8 + 2 + 12*12 + 4 + 8 + 8 = 174
    binWriter.Write(data32);
    // 7. entry: SamplesPerPixel
    //===========================
    data16 = 0x115;  // tag:   115.H 
    binWriter.Write(data16);
    data16 = 3;   // type:  SHORT
    binWriter.Write(data16);
    data32 = 1;   // count: 1 
    binWriter.Write(data32); ;
    data32 = 1;   // SamplesPerPixel == 1 Mono16
    binWriter.Write(data32);
    // 8. entry: RowsPerStrip
    //========================
    data16 = 0x116;  // tag:   116.H 
    binWriter.Write(data16);
    data16 = 4;   // type:  LONG
    binWriter.Write(data16);
    data32 = 1;   // count: 1
    binWriter.Write(data32);
    data32 = sizeY;  // value: vertical image size (one strip only)
    binWriter.Write(data32);
    // 9. entry: StripByteCounts (For each strip, the number of bytes in the strip after compression.)
    //================================================================================================
    data16 = 0x117;  // tag:   117.H 
    binWriter.Write(data16);
    data16 = 4;   // type:  LONG
    binWriter.Write(data16);
    data32 = 1;   // count: 1 == StripsPerImage
    binWriter.Write(data32);
    data32 = 2 * 1 * sizeX * sizeY;  // value = 2* 1 * SizeX * SizeY
    binWriter.Write(data32);
    // 10. entry: XResolution (The number of pixels per ResolutionUnit in the ImageWidth direction.)
    //================================================================================================
    data16 = 0x11A;  // tag:   11A.H 
    binWriter.Write(data16);
    data16 = 5;   // type:  RATIONAL
    binWriter.Write(data16);
    data32 = 1;   // count: 1 
    binWriter.Write(data32);
    data32 = 158;  // offset to value = 8 + (2 + 12*12 + 4) = 158
    binWriter.Write(data32);
    // 11. entry: YResolution (The number of pixels per ResolutionUnit in the ImageLength direction.)
    //================================================================================================
    data16 = 0x11B;  // tag:   11B.H 
    binWriter.Write(data16);
    data16 = 5;   // type:  RATIONAL
    binWriter.Write(data16);
    data32 = 1;   // count: 1 
    binWriter.Write(data32);
    data32 = 166;  // offset to value = 8 + (2 + 12*12 + 4) + 8 = 166
    binWriter.Write(data32);
    // 12. entry: ResolutionUnit (The unit of measurement for XResolution and YResolution.)
    //=====================================================================================
    data16 = 0x128;  // tag:   128.H 
    binWriter.Write(data16);
    data16 = 3;   // type:  SHORT
    binWriter.Write(data16);
    data32 = 1;   // count: 1 
    binWriter.Write(data32);
    data32 = 2;   // value: 2 (Inch) => dpi
    binWriter.Write(data32);
    data32 = 0;   // offset of next IFD: none
    binWriter.Write(data32);
    //  write IFD values longer than 4 byte
    //======================================
    data32 = 72;  // XResolution numerator: 72 => 72 dpi (a common value..)
    binWriter.Write(data32);
    data32 = 1;   // XResolution denominator: 1
    binWriter.Write(data32);
    data32 = 72;  // YResolution numerator: 72 => 72 dpi (a common value..)
    binWriter.Write(data32);
    data32 = 1;   // YResolution denominator: 1
    binWriter.Write(data32);
    // end of header save to file
    // save image data (converted from Mono12 to Mono16) to file
    for (int i = 0; i < imagelength2; i++)
    {
        data16 = (ushort)shortarray[i];
        binWriter.Write(data16);
    }
    // close file
    binWriter.Close();
    FileST.Close();
    return;
}   // end of saveMono16Tiff()

工业相机使用位深度12/16位图像的优点

更好的图像细节:12/16位图像可以捕捉到更多的细节和颜色深度,提供更高的图像质量。


更广泛的动态范围:12/16位图像允许在明暗变化很大的场景中捕捉到更多的细节和颜色,以及更好的光线控制。


更低的噪声:采用12/16位图像可以减少噪声,使得图像更加清晰。


更好的后期处理:12/16位图像可以在后期处理中更灵活地进行平滑、增加对比度和其他调整。


因此,工业相机使用12/16位图像可以提供更高质量的图像,更好的细节和颜色控制,并为后期处理提供更多的灵活性。


工业相机使用位深度12/16位图像的行业应用

医疗成像:工业相机可用于各种医疗成像应用,例如X射线成像,MRI和CT扫描。这些应用需要16位图像位深度来提供高质量的成像结果。


汽车制造:工业相机可以用于汽车制造中的各种应用,例如质量控制和检查。这些应用需要高分辨率和16位图像位深度,以检测并处理微小的缺陷或问题。


机器人视觉:工业相机的高速度和高精度对于机器人视觉应用非常重要。机器人需要能够识别和定位目标,同时能够处理16位图像位深度的高质量图像。


智能交通系统:工业相机也可以用于智能交通系统中。例如,交通监控摄像机需要高质量的图像以便能够识别和跟踪车辆,行人和其他交通标志。


总之,工业相机使用16位图像位深度的行业应用范围非常广泛,它们可以用于各种不同的应用,以提供高质量的成像结果和精确的图像处理功能。

目录
相关文章
|
3月前
|
监控 API 开发工具
Baumer工业相机堡盟工业相机如何通过NEOAPI SDK获取每张图像的微秒时间和FrameID功能(C#)
Baumer工业相机堡盟工业相机如何通过NEOAPI SDK获取每张图像的微秒时间和FrameID功能(C#)
73 0
|
3月前
|
数据采集 API 开发工具
Baumer工业相机堡盟工业相机如何通过NEOAPI SDK使用Force IP强制修改网口IP功能(C++)
Baumer工业相机堡盟工业相机如何通过NEOAPI SDK使用Force IP强制修改网口IP功能(C++)
44 0
|
7天前
|
机器人 API 开发工具
大恒相机 - Python SDK 调试记录
大恒相机 - Python SDK 调试记录
13 1
|
2月前
|
并行计算 算法 C#
C# Mandelbrot和Julia分形图像生成程序更新到2010-9-14版 支持多线程计算 多核处理器
此文档是一个关于分形图像生成器的介绍,作者分享了个人开发的M-J算法集成及色彩创新,包括源代码和历史版本。作者欢迎有兴趣的读者留言交流,并提供了邮箱(delacroix_xu@sina.com)以分享资源。文中还展示了程序的发展历程,如增加了真彩色效果、圈选放大、历史记录等功能,并分享了几幅精美的分形图像。此外,还提到了程序的新特性,如导入ini文件批量输出图像和更新一批图片的功能。文档末尾附有多张程序生成的高分辨率分形图像示例。
|
2月前
|
存储 编解码 算法
C#.NET逃逸时间算法生成分形图像的毕业设计完成!晒晒功能
该文介绍了一个使用C#.NET Visual Studio 2008开发的程序,包含错误修复的Julia、Mandelbrot和优化过的Newton三种算法,生成色彩丰富的分形图像。作者改进了原始算法的效率,将内层循环的画点操作移至外部,提升性能。程序提供五种图形模式,支持放大缩小及颜色更新,并允许用户自定义画布大小以调整精度。还具备保存为高质JPG的功能。附有四张示例图片展示生成的分形效果。
424 3
|
3月前
|
监控 API 开发工具
Baumer工业相机堡盟工业相机如何通过NEOAPI SDK获取每张图像的微秒时间和FrameID功能(C++)
Baumer工业相机堡盟工业相机如何通过NEOAPI SDK获取每张图像的微秒时间和FrameID功能(C++)
59 0
|
3月前
|
存储 传感器 监控
工业相机如何实现实时和本地Raw格式图像和Bitmap格式图像的保存和相互转换(C#代码,UI界面版)
工业相机如何实现实时和本地Raw格式图像和Bitmap格式图像的保存和相互转换(C#代码,UI界面版)
79 0
|
3月前
|
开发框架 前端开发 .NET
C#编程与Web开发
【4月更文挑战第21天】本文探讨了C#在Web开发中的应用,包括使用ASP.NET框架、MVC模式、Web API和Entity Framework。C#作为.NET框架的主要语言,结合这些工具,能创建动态、高效的Web应用。实际案例涉及企业级应用、电子商务和社交媒体平台。尽管面临竞争和挑战,但C#在Web开发领域的前景将持续拓展。
150 3
|
3月前
|
SQL 开发框架 安全
C#编程与多线程处理
【4月更文挑战第21天】探索C#多线程处理,提升程序性能与响应性。了解C#中的Thread、Task类及Async/Await关键字,掌握线程同步与安全,实践并发计算、网络服务及UI优化。跟随未来发展趋势,利用C#打造高效应用。
162 3
|
15天前
|
存储 C#
揭秘C#.Net编程秘宝:结构体类型Struct,让你的数据结构秒变高效战斗机,编程界的新星就是你!
【8月更文挑战第4天】在C#编程中,结构体(`struct`)是一种整合多种数据类型的复合数据类型。与类不同,结构体是值类型,意味着数据被直接复制而非引用。这使其适合表示小型、固定的数据结构如点坐标。结构体默认私有成员且不可变,除非明确指定。通过`struct`关键字定义,可以包含字段、构造函数及方法。例如,定义一个表示二维点的结构体,并实现计算距离原点的方法。使用时如同普通类型,可通过实例化并调用其成员。设计时推荐保持结构体不可变以避免副作用,并注意装箱拆箱可能导致的性能影响。掌握结构体有助于构建高效的应用程序。
39 7