0


DALSA工业相机SDK二次开发(图像采集及保存)C#版

一,首先先配置生成项目,根据官方文档步骤来:
在这里插入图片描述

这个没啥好说的,一步步照做就是了,就最后一步,开始我没重视,最后代码写完测试的时候还真的遇到问题了,一直出这样的错:
在这里插入图片描述

查了官方文档才看到最后一条~,然后在项目属性中把这个勾掉了,代码完美运行拉……

在这里插入图片描述
二,功能步骤

其实整个步骤很简单:

1,首先初始化连接相机:点击Init按钮会有MessageBox打印相机名
在这里插入图片描述

2,然后读取配置文件(配置文件是通过官方自带的CamExpert来生成的)读取参数,也可以在程序中配置,本程序有个setting按钮,按一下就可以配置拉,把想配置的参数写在对应的代码块里(当然小编很懒,没做显示的功能,所以按按钮的时候你可能觉得按了个寂寞,但已经配置好了)。还有个读取参数的按钮(当然小编也没做显示的功能,所以也按了个寂寞),但有助于debug的时候查看数据,也可以自己打印出来看看。

3,Snap是快照,可以设置快照的张数,因为写本程序时只有相机没有镜头,所以是黑乎乎一片…但用光源照的时候会呈现白色,所以还是有点反应知道不是卡住的哈哈。
在这里插入图片描述
4,Grab就是连续抓取图像了,Freeze是停止。

5,最后的保存结果(没有镜头只能可怜巴巴的用感光性来测试了T_T)
在这里插入图片描述
PS:程序最重要的是一个回调函数:m_Xfer_XferNotify,每读取一帧图片的时候会调用这个函数,当然回调函数是自己加的,通过这个命令:

m_Xfer.XferNotify += new SapXferNotifyHandler(m_Xfer_XferNotify);

这条命令和m_Xfer_XferNotify函数是精髓!精髓!精髓!

没啥说的,上代码。可运行代码一字不差的放上来咯,注释也尽可能详细了:

usingSystem;usingSystem.Collections.Generic;usingSystem.ComponentModel;usingSystem.Data;usingSystem.Drawing;usingSystem.Linq;usingSystem.Text;usingSystem.Threading.Tasks;usingSystem.Windows.Forms;usingSystem.Drawing.Imaging;usingDALSA.SaperaLT.SapClassBasic;namespacedalsaSave{publicpartialclassForm1:Form{// 全局变量privatestaticint picCountNum =0;// 统计采集了多少张图,有利于理解m_Xfer.Sanp(15)中15的意思privatestring configFilePath =@"D:\T_Linea_M4096-7um_Default_Default.ccf";// 配置文件的路径privatestring imgPath =@"D:\imgs\";  //采集图片保存地址
        private SapLocation m_ServerLocation; // 设备的连接地址
        private SapAcqDevice m_AcqDevice; //采集设备
        private SapBuffer m_Buffers; // 缓存对象
        private SapAcqDeviceToBuf m_Xfer; // 传输对象

        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {

        }

        private void Form1_FormClosed(object sender, FormClosedEventArgs e)
        {
            DestroyObjects();
            DisposeObjects();
        }

        // 初始化并连接相机
        private void btn_init_Click(object sender, EventArgs e)
        {
            CreateNewObjects();
        }

    private void btn_setting_Click(object sender, EventArgs e)
    {
            // 设置曝光值,为了设置的值不超限,需要获取曝光值的允许范围(主要是最大值)
            double valuetemp = GetMaxValue("ExposureTime");if(valuetemp >0){
                m_AcqDevice.SetFeatureValue("ExposureTime", valuetemp);}
            m_AcqDevice.SetFeatureValue("Gain","9.9");}privatevoidbtn_getValue_Click(object sender,EventArgs e){string deviceModelName;string deviceUserId;string pixelFormat;string triggerMode;double acquisitionLineRate;// 行频和曝光时间不能设置为int类型double exposureTime;double gain;int width;int height;int sensorWidth;int sensorHeight;

            m_AcqDevice.GetFeatureValue("DeviceModelName",out deviceModelName);//Linea M4096-7um
            m_AcqDevice.GetFeatureValue("DeviceUserID",out deviceUserId);//空
            m_AcqDevice.GetFeatureValue("PixelFormat",out pixelFormat);//Mono8
            m_AcqDevice.GetFeatureValue("TriggerMode",out triggerMode);//Off

            m_AcqDevice.GetFeatureValue("AcquisitionLineRate",out acquisitionLineRate);//10000.0
            m_AcqDevice.GetFeatureValue("ExposureTime",out exposureTime);//70.0
            m_AcqDevice.GetFeatureValue("Gain",out gain);//9.0          
            m_AcqDevice.GetFeatureValue("Width",out width);//4096
            m_AcqDevice.GetFeatureValue("Height",out height);//2800
            m_AcqDevice.GetFeatureValue("SensorWidth",out sensorWidth);//4096
            m_AcqDevice.GetFeatureValue("SensorHeight",out sensorHeight);//1}#regionprivatevoidbtn_snap_Click(object sender,EventArgs e){// Snap() 只采集一张, 如果是Snap(15)则连续采集15张
            m_Xfer.Snap(15);//m_Xfer.Snap(m_Buffers.Count)}privatevoidbtn_grab_Click(object sender,EventArgs e){
            m_Xfer.Grab();}//关闭的时候,执行Freez()停止采集,线程等待5秒,//目的是停止采集后,将还存在内存地址通道中的裸数据都取出来,//如果freeze之后直接释放,就拿不到还在地址上的数据了,缓存对象释放之后,将本次采集所有对象摧毁。privatevoidbtn_freeze_Click(object sender,EventArgs e){
            m_Xfer.Freeze();}#endregion//得到所有连接的相机信息,并将他们加入到ArrayList里面去publicboolGetCameraInfo(outstring sCameraName,outint nIndex){
            Console.WriteLine("开始获取相机信息");

            sCameraName ="";
            nIndex =0;// 查询相机数量int serverCount = SapManager.GetServerCount();int GenieIndex =0;// 实例化一个list,作为容器System.Collections.ArrayList listServerNames =newSystem.Collections.ArrayList();bool bFind =false;string serverName ="";for(int serverIndex =0; serverIndex < serverCount; serverIndex++){if(SapManager.GetResourceCount(serverIndex, SapManager.ResourceType.AcqDevice)!=0){
                    serverName = SapManager.GetServerName(serverIndex);
                    listServerNames.Add(serverName);
                    GenieIndex++;
                    bFind =true;}}int count =1;string deviceName ="";foreach(string sName in listServerNames){
                deviceName = SapManager.GetResourceName(sName, SapManager.ResourceType.AcqDevice,0);
                count++;}

            sCameraName = serverName;
            nIndex = GenieIndex;return bFind;}// 初始化并连接相机publicboolCreateNewObjects(){
            Console.WriteLine("相机初始化");string Name;int Index;// 获取相机详细信息bool RTemp =GetCameraInfo(out Name,out Index);if(RTemp){
                MessageBox.Show(Name);}else{
                MessageBox.Show("Get camera info false!");returnfalse;}

            m_ServerLocation =newSapLocation(Name,0);//创建采集设备,new SapAcqDevice()的括号中第二个参数既可以写配置文件路径,也可以写false,false是用相机当前的设置// 获取相机信息,加载相机配置文件(用相机专家调整好参数后导出ccf文件),加载参数if(configFilePath.Length >0)
                m_AcqDevice =newSapAcqDevice(m_ServerLocation, configFilePath);else
                m_AcqDevice =newSapAcqDevice(m_ServerLocation,false);

            Console.WriteLine(m_AcqDevice.Create());if(m_AcqDevice.Create()==false){DestroyObjects();DisposeObjects();returnfalse;}// 创建缓存对象if(SapBuffer.IsBufferTypeSupported(m_ServerLocation, SapBuffer.MemoryType.ScatterGather)){
                m_Buffers =newSapBufferWithTrash(2, m_AcqDevice, SapBuffer.MemoryType.ScatterGather);}else{
                m_Buffers =newSapBufferWithTrash(2, m_AcqDevice, SapBuffer.MemoryType.ScatterGatherPhysical);}if(m_Buffers.Create()==false){DestroyObjects();DisposeObjects();returnfalse;}//设置行频,注意:行频在相机工作时不能设置(曝光、增益可以),最好在初始化阶段设置
            m_AcqDevice.SetFeatureValue("AcquisitionLineRate",20000.0);//创建传输对象
            m_Xfer =newSapAcqDeviceToBuf(m_AcqDevice, m_Buffers);// 这一句是核心,这是回调函数,就靠它采图了
            m_Xfer.XferNotify +=newSapXferNotifyHandler(m_Xfer_XferNotify);
            m_Xfer.XferNotifyContext =this;
            m_Xfer.Pairs[0].EventType = SapXferPair.XferEventType.EndOfFrame;
            m_Xfer.Pairs[0].Cycle = SapXferPair.CycleMode.NextWithTrash;if(m_Xfer.Pairs[0].Cycle != SapXferPair.CycleMode.NextWithTrash){DestroyObjects();DisposeObjects();returnfalse;}if(m_Xfer.Create()==false){DestroyObjects();DisposeObjects();returnfalse;}returntrue;}privatevoidDestroyObjects(){if(m_Xfer !=null&& m_Xfer.Initialized)
                m_Xfer.Destroy();if(m_Buffers !=null&& m_Buffers.Initialized)
                m_Buffers.Destroy();if(m_AcqDevice !=null&& m_AcqDevice.Initialized)
                m_AcqDevice.Destroy();}privatevoidDisposeObjects(){if(m_Xfer !=null){
                m_Xfer.Dispose();
                m_Xfer =null;}if(m_Buffers !=null){
                m_Buffers.Dispose();
                m_Buffers =null;}if(m_AcqDevice !=null){
                m_AcqDevice.Dispose();
                m_AcqDevice =null;}}voidm_Xfer_XferNotify(object sender,SapXferNotifyEventArgs argsNotify){// 首先判断此帧是否为废弃帧,若是则立即返回,等待下一帧(但这句话有时候m_Xfer.Snap(n)时会导致丢帧,可以注释掉试试)if(argsNotify.Trash)return;// 获取m_Buffers的地址(指针),只要知道了图片内存的地址,其实就能有各种办法搞出图片了(例如转成Bitmap)IntPtr addr;
            m_Buffers.GetAddress(out addr);// 观察buffer中的图片的一些属性值,语句后注释里面的值是可能的值int count = m_Buffers.Count;//2SapFormat format = m_Buffers.Format;//Uint8double rate = m_Buffers.FrameRate;//30.0,连续采集时,这个值会动态变化int height = m_Buffers.Height;//2800int weight = m_Buffers.Width;//4096int pixd = m_Buffers.PixelDepth;//8//显示实时帧率UpdateFrameRate();
            lbl_FrameRate.BeginInvoke(newAction(()=>{ lbl_FrameRate.Text = m_Buffers.FrameRate.ToString();}));

            picCountNum++;// 保存到本地。这个save方法就是从SDK中提取出来的,给上参数,就可以实现图片的保存,不用借助其他任何的技术方法
            m_Buffers.Save(imgPath + picCountNum +".bmp","-format bmp");// 从内存读取图片,并转换成bitmap格式,创建调色板,打印到PictureBoxPixelFormat pf = PixelFormat.Format8bppIndexed;Bitmap bmp =newBitmap(weight, height, m_Buffers.Pitch, pf, addr);ColorPalette m_grayPalette;using(Bitmap tempbmp =newBitmap(1,1, PixelFormat.Format8bppIndexed)){
                m_grayPalette = tempbmp.Palette;}for(int i =0; i <=255; i++){
                m_grayPalette.Entries[i]= Color.FromArgb(i, i, i);}

            bmp.Palette = m_grayPalette;Image img = Image.FromHbitmap(bmp.GetHbitmap());
            picBox.Image = img;}privatevoidUpdateFrameRate(){if(m_Xfer.UpdateFrameRateStatistics()){float framerate =0.0f;SapXferFrameRateInfo stats = m_Xfer.FrameRateStatistics;if(stats.IsBufferFrameRateAvailable)
                    framerate = stats.BufferFrameRate;elseif(stats.IsLiveFrameRateAvailable &&!stats.IsLiveFrameRateStalled)
                    framerate = stats.LiveFrameRate;

                m_Buffers.FrameRate = framerate;}}// 获得相机参数的最大值(行频和曝光时间是近似倒数的关系,获得参数最大值可以防止设置参数超限)privatedoubleGetMaxValue(string featureName){SapFeature feature =newSapFeature(m_ServerLocation);if(!feature.Create())return-1;if(!m_AcqDevice.GetFeatureInfo(featureName, feature))return-1;double maxValue =0;if(!feature.GetValueMax(out maxValue))return-1;return maxValue;}// 这个一般用的少,最小值一般是很小的数(比如Gain最小0.125, width最小128),我们一般不会设置这样的数privatedoubleGetMinValue(string featureName){SapFeature feature =newSapFeature(m_ServerLocation);if(!feature.Create())return-1;if(!m_AcqDevice.GetFeatureInfo(featureName, feature))return-1;int minValue =0;if(!feature.GetValueMin(out minValue))return-1;return minValue;}}}
标签: c# 开发语言 ui

本文转载自: https://blog.csdn.net/weixin_45499836/article/details/126312422
版权归原作者 Pass_Time_ 所有, 如有侵权,请联系我们删除。

“DALSA工业相机SDK二次开发(图像采集及保存)C#版”的评论:

还没有评论