DALSA網口線掃相機SDK開發詳解例程(C#版)


首先吐槽一句,官方的demos寫的真的不好,坑爹啊。對於小白來說,開發官方demos為我所用太難了。為什么呢?因為它Dalsa的DALSA.SaperaLT.SapClassBasic.dll中,不僅有采圖的代碼庫,還有用於顯示的UI庫(它不是用Winform的PictureBox顯示圖片,而是用它自家的UI顯示圖片),demos把采圖程序和UI庫雜糅在一起,而且隱藏了少部分細節。

 

后來我在網上狂搜資料,搜到了兩個大佬的兩篇好文章:

dalsa 8k線陣網口相機c#開發

https://blog.csdn.net/baidu_30028771/article/details/64628784

 

DALSA相機SDK不完全教程

http://www.cnblogs.com/lgyup/p/4313332.html

文章一的代碼是一個完整的例子,是可以直接采到圖的。文章二的代碼缺少關鍵的GetCameraInfo()方法,是不能直接運行的,但是這篇文章的講解更全面、深入,可以說兩篇都是必備的啦。

 

我為什么要寫這兩篇文章呢?因為我想集合這兩家之長,再加入一點自己的經驗、代碼,並且提供完整的源代碼方便大家開發。很懺愧 ,只做了一點微小的貢獻。

 

我的開發硬件、軟件信息:

操作系統:windows 10、windows 7   64bit都有

線掃相機:Dalsa  Linea Mono 4k  26 kHz GigE (LA-GM-04K08A)

IDE :Visual studio 2013

 

第一篇文章我直接運行代碼報錯了,是到了跟Dalsa相關的dll的語句時報錯的。Win 10系統很扯淡,報錯的提示一點都看不懂,我換Win 7的系統后,也報錯,但是明確把錯誤原因找出來了。其實是Dalsa的dll中有低版本.Net Framework的代碼,導致不兼容。解決的辦法,網上一大推,核心就一句:在app.config的合適位置,加這句話useLegacyV2RuntimeActivationPolicy=”true”。

如果沒有app.config文件,你就需要創建這個文件。

 

我的app.config文件內容如下:

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <startup useLegacyV2RuntimeActivationPolicy="true">
    <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0"/>
  </startup>
</configuration>

 

現在你需要把我上文提到的兩篇博客仔細看一下了。

……

看完了嗎?看完了的話,接着往下看我的文章。

 

首先學習一下相機配置文件(.ccf)如何生成:

① 打開相機軟件Sapera CamExpert,確保相機已經正常工作,然后自己改變到合適的參數;

② 點擊軟件左上角的File——Save As...,選擇文件夾路徑,修改文件名。

 

我的解決方案資源結構如下:

因為我是用Halcon顯示圖片,因此我添加了兩個dll引用。除了app.config之外,我所有自己編寫的代碼全部在Form1.cs中。其實相當於我把全部源代碼一字不漏全告訴你了。

 

我的Form1界面如下:

(點擊Init初始化,會彈出該線陣相機的型號)

 

然后點擊“snap”的話,它會連續采集15張圖,並保存,如下:

 

Form1.cs的全部內容如下:

 1 using System;  2 using System.Collections.Generic;  3 using System.ComponentModel;  4 using System.Data;  5 using System.Drawing;  6 using System.Linq;  7 using System.Text;  8 using System.Windows.Forms;  9 using DALSA.SaperaLT.SapClassBasic;  10 using HalconDotNet;  11 
 12 namespace WinDalsa  13 {  14     public partial class Form1 : Form  15  {  16         private SapLocation m_ServerLocation;   // 設備的連接地址
 17         private SapAcqDevice m_AcqDevice;       // 采集設備
 18         private SapBuffer m_Buffers;            // 緩存對象
 19         private SapAcqDeviceToBuf m_Xfer;       // 傳輸對象
 20 
 21         public Form1()  22  {  23  InitializeComponent();  24  }  25 
 26 
 27         private void Form1_Load(object sender, EventArgs e)  28  {  29             
 30  }  31 
 32         private void Form1_FormClosed(object sender, FormClosedEventArgs e)  33  {  34  DestroyObjects();  35  DisposeObjects();  36  }  37 
 38 
 39         private void btn_init_Click(object sender, EventArgs e)  40  {  41  CreateNewObjects();  42  }  43 
 44         private void btn_setting_Click(object sender, EventArgs e)  45  {  46             //設置曝光值,為了設置的值不超限,需要獲取曝光值的允許范圍(主要是最大值)
 47             double valuetemp = GetMaxValue("ExposureTime");  48             if (valuetemp > 0)  49  {  50                 m_AcqDevice.SetFeatureValue("ExposureTime", valuetemp);  51  }  52 
 53             m_AcqDevice.SetFeatureValue("Gain", "9.9");  54  }  55 
 56 
 57         // 獲得相機部分屬性的值 
 58         private void btn_getValue_Click(object sender, EventArgs e)  59  {  60             string deviceModelName;  61             string deviceUserId;  62             string pixelFormat;  63             string triggerMode;  64 
 65             double acquisitionLineRate;  //行頻和曝光時間不能設置為int類型
 66             double exposureTime;  67             double gain;  68             int width;  69             int height;  70             int sensorWidth;  71             int sensorHeight;  72 
 73 
 74             m_AcqDevice.GetFeatureValue("DeviceModelName", out deviceModelName);  //Linea M4096-7um
 75             m_AcqDevice.GetFeatureValue("DeviceUserID", out deviceUserId);  //
 76             m_AcqDevice.GetFeatureValue("PixelFormat", out pixelFormat);  //Mono8
 77             m_AcqDevice.GetFeatureValue("TriggerMode", out triggerMode);  //Off
 78 
 79             m_AcqDevice.GetFeatureValue("AcquisitionLineRate", out acquisitionLineRate);  //10000.0
 80             m_AcqDevice.GetFeatureValue("ExposureTime", out exposureTime);  //70.0
 81             m_AcqDevice.GetFeatureValue("Gain", out gain);  //9.0 
 82             m_AcqDevice.GetFeatureValue("Width", out width);  //4096
 83             m_AcqDevice.GetFeatureValue("Height", out height);  //2800
 84             m_AcqDevice.GetFeatureValue("SensorWidth", out sensorWidth);  //4096
 85             m_AcqDevice.GetFeatureValue("SensorHeight", out sensorHeight);  //1
 86 
 87  }  88 
 89 
 90         #region 單步采集、連續采集、凍結采集
 91         private void btn_snap_Click(object sender, EventArgs e)  92  {  93 
 94             //Snap()只采集一張,如果是Snap(15)則連續采集15張
 95             m_Xfer.Snap(15);//m_Xfer.Snap(m_Buffers.Count)
 96  }  97 
 98         private void btn_grab_Click(object sender, EventArgs e)  99  { 100  m_Xfer.Grab(); 101  } 102 
103         private void btn_freeze_Click(object sender, EventArgs e) 104  { 105             m_Xfer.Freeze(); //還有m_Xfer.Abort()的用法;
106 
107  } 108 
109         #endregion
110 
111 
112 
113         //得到所有連接的相機信息,並將它們加入到ArrayList里面去
114         public bool GetCameraInfo(out string sCameraName, out int nIndex) 115  { 116             sCameraName = ""; 117             nIndex = 0; 118 
119             int serverCount = SapManager.GetServerCount(); 120             int GenieIndex = 0; 121             System.Collections.ArrayList listServerNames = new System.Collections.ArrayList(); 122 
123             bool bFind = false; 124             string serverName = ""; 125             for (int serverIndex = 0; serverIndex < serverCount; serverIndex++) 126  { 127                 if (SapManager.GetResourceCount(serverIndex, SapManager.ResourceType.AcqDevice) != 0) 128  { 129                     serverName = SapManager.GetServerName(serverIndex); 130  listServerNames.Add(serverName); 131                     GenieIndex++; 132                     bFind = true; 133  } 134  } 135 
136             int count = 1; 137             string deviceName = ""; 138             foreach (string sName in listServerNames) 139  { 140                 deviceName = SapManager.GetResourceName(sName, SapManager.ResourceType.AcqDevice, 0); 141                 count++; 142  } 143 
144             sCameraName = serverName; 145             nIndex = GenieIndex; 146 
147             return bFind; 148  } 149 
150 
151 
152         private bool CreateNewObjects() 153  { 154 
155             string Name; 156             int Index; 157             bool RTemp = GetCameraInfo(out Name, out Index); 158             if (RTemp) 159  { 160  MessageBox.Show(Name); 161  } 162             else
163  { 164                 MessageBox.Show("Get camera info false!"); 165                 return false; 166  } 167             
168 
169             m_ServerLocation = new SapLocation(Name, 0); 170 
171 
172             // 創建采集設備,new SapAcqDevice()的括號中第二個參數既可以寫配置文件路徑,也可以寫false,猜測false是用相機當前的設置 173             //m_AcqDevice = new SapAcqDevice(m_ServerLocation, false);
174             m_AcqDevice = new SapAcqDevice(m_ServerLocation, @"C:\Users\xh6300\Desktop\dalsa_win7_develop\gray\T_Linea_M4096-7um_Default_Default_2800.ccf"); 175             
176 
177             if (m_AcqDevice.Create() == false) 178  { 179  DestroyObjects(); 180  DisposeObjects(); 181                 return false; 182  } 183             // 創建緩存對象
184             if (SapBuffer.IsBufferTypeSupported(m_ServerLocation, SapBuffer.MemoryType.ScatterGather)) 185  { 186                 m_Buffers = new SapBufferWithTrash(2, m_AcqDevice, SapBuffer.MemoryType.ScatterGather); 187  } 188             else
189  { 190                 m_Buffers = new SapBufferWithTrash(2, m_AcqDevice, SapBuffer.MemoryType.ScatterGatherPhysical); 191  } 192             if (m_Buffers.Create() == false) 193  { 194  DestroyObjects(); 195  DisposeObjects(); 196                 return false; 197  } 198 
199             m_AcqDevice.SetFeatureValue("AcquisitionLineRate", 20000.0); //注意:行頻在相機工作時不能設置(曝光、增益可以),最好在初始化階段設置 200 
201             // 創建傳輸對象
202             m_Xfer = new SapAcqDeviceToBuf(m_AcqDevice, m_Buffers); 203             m_Xfer.XferNotify += new SapXferNotifyHandler(m_Xfer_XferNotify); 204             m_Xfer.XferNotifyContext = this; 205             m_Xfer.Pairs[0].EventType = SapXferPair.XferEventType.EndOfFrame; 206             m_Xfer.Pairs[0].Cycle = SapXferPair.CycleMode.NextWithTrash; 207             if (m_Xfer.Pairs[0].Cycle != SapXferPair.CycleMode.NextWithTrash) 208  { 209  DestroyObjects(); 210  DisposeObjects(); 211                 return false; 212  } 213             if (m_Xfer.Create() == false) 214  { 215  DestroyObjects(); 216  DisposeObjects(); 217                 return false; 218  } 219             return true; 220  } 221 
222 
223         private void DestroyObjects() 224  { 225             if (m_Xfer != null && m_Xfer.Initialized) 226  m_Xfer.Destroy(); 227             if (m_Buffers != null && m_Buffers.Initialized) 228  m_Buffers.Destroy(); 229             if (m_AcqDevice != null && m_AcqDevice.Initialized) 230  m_AcqDevice.Destroy(); 231  } 232 
233         private void DisposeObjects() 234  { 235             if (m_Xfer != null) 236             { m_Xfer.Dispose(); m_Xfer = null; } 237             if (m_Buffers != null) 238             { m_Buffers.Dispose(); m_Buffers = null; } 239             if (m_AcqDevice != null) 240             { m_AcqDevice.Dispose(); m_AcqDevice = null; } 241  } 242 
243 
244         private static int picCountNum = 0; //統計采集了多少張圖,有利於理解m_Xfer.Snap(15)中15的意思
245 
246         void m_Xfer_XferNotify(object sender, SapXferNotifyEventArgs argsNotify) 247  { 248             //首先需判斷此幀是否是廢棄幀,若是則立即返回,等待下一幀(但這句話似乎有時候m_Xfer.Snap(n)時會導致丟幀,可以注釋掉試試)
249             if (argsNotify.Trash) return; 250 
251             //獲取m_Buffers的地址(指針),只要知道了圖片內存的地址,其實就能有各種辦法搞出圖片了(例如轉成Bitmap)
252  IntPtr addr; 253             m_Buffers.GetAddress(out addr); 254 
255             //觀察buffer中的圖片的一些屬性值,語句后注釋里面的值是可能的值
256             int count = m_Buffers.Count;  //2
257             SapFormat format = m_Buffers.Format;  //Uint8
258             double rate = m_Buffers.FrameRate;  //30.0,連續采集時,這個值會動態變化
259             int height = m_Buffers.Height;  //2800
260             int weight = m_Buffers.Width;  //4096
261             int pixd = m_Buffers.PixelDepth;  //8 262 
263             //顯示實時幀率
264  UpdateFrameRate(); 265             lbl_FrameRate.BeginInvoke(new Action(() => { lbl_FrameRate.Text = m_Buffers.FrameRate.ToString();})); 266             
267             //利用halcon從內存中采集圖片並保存 
268             HObject ImageTemp = null; 269             HOperatorSet.GenImage1(out ImageTemp, "byte", 4096, 2000, addr);//取內存數據,生成圖像,halcon實現
270 
271             hWindowControl1.HalconWindow.SetPart(0, 0, 2000, 4096); 272  HOperatorSet.DispObj(ImageTemp, hWindowControl1.HalconWindow); 273             picCountNum++; 274             HOperatorSet.WriteImage(ImageTemp, "bmp", 0, "C:\\Users\\xh6300\\Desktop\\tt\\" + picCountNum); 275             
276  } 277 
278 
279         private void UpdateFrameRate() 280  { 281             if (m_Xfer.UpdateFrameRateStatistics()) 282  { 283                 float framerate = 0.0f; 284                 SapXferFrameRateInfo stats = m_Xfer.FrameRateStatistics; 285 
286                 if (stats.IsBufferFrameRateAvailable) 287                     framerate = stats.BufferFrameRate; 288                 else if (stats.IsLiveFrameRateAvailable && !stats.IsLiveFrameRateStalled) 289                     framerate = stats.LiveFrameRate; 290 
291                 m_Buffers.FrameRate = framerate; 292  } 293  } 294 
295 
296 
297         //獲得相機參數的最大值(行頻和曝光時間是近似倒數的關系,獲得參數最大值可以防止設置參數超限)
298         private double GetMaxValue(string featureName) 299  { 300             SapFeature feature = new SapFeature(m_ServerLocation); 301             if (!feature.Create()) 302                 return -1; 303             if (!m_AcqDevice.GetFeatureInfo(featureName, feature)) 304                 return -1; 305             double maxValue = 0; 306             if (!feature.GetValueMax(out maxValue)) 307                 return -1; 308             return maxValue; 309  } 310 
311 
312         //這個一般用得少,最小值一般是很小的數(比如Gain最小0.125,width最小128),我們一般不會設置這樣的數
313         private double GetMinValue(string featureName) 314  { 315             SapFeature feature = new SapFeature(m_ServerLocation); 316             if (!feature.Create()) 317                 return -1; 318             if (!m_AcqDevice.GetFeatureInfo(featureName, feature)) 319                 return -1; 320             int minValue = 0; 321             if (!feature.GetValueMin(out minValue)) 322                 return -1; 323             return minValue; 324  } 325  } 326 }

當你完全理解了這篇文章(以及我提到的兩篇),Dalsa網口線陣相機的開發基本就沒啥問題了,當然這時候你返回去看官方demos會有新的收獲,比如我上面的UpdateFrameRate()就是從官方demos中剝離出來的,該函數可以得到采圖時的實際幀率。

 

有什么問題可以留言詢問。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM