1、SDK介紹
Dalsa是全球頂尖的CCD/CMOS芯片和相機制造商,總部位於加拿大,我使用的是 Dalsa的 Genie_TS_M1920(黑白)和 Genie_TS_C2048(彩色)兩款工業相機。
打開SDK包,SDK文件和例程在 Sapera文件夾中,SDK分x64和x86兩個版本,x86的版本不能在64位機器上運行,x64的版本不能在32位機器上運行。
打開后
2、C#的使用方法
1)添加類庫的引用,即Components/Net/Bin/DALSA.SaperaLT.SapClassBasic.dll文件的引用,注意x64和x86的版本問題。
2)聲明SaperaLT的對象
我沒有使用SDK中的視圖對象,而是從緩存中取出圖像數據轉為C#的Bitmap,這樣更靈活,所以不需要聲明 SapView。
private SapLocation m_ServerLocation; // 設備的連接地址 private SapAcqDevice m_AcqDevice; // 采集設備 private SapBuffer m_Buffers; // 緩存對象 private SapAcqDeviceToBuf m_Xfer; // 傳輸對象
3)創建對象
private bool CreateNewObjects() { // 創建采集設備 m_AcqDevice = new SapAcqDevice(m_ServerLocation, false); if (m_AcqDevice.Create() == false) { DestroyObjects(); DisposeObjects(); return false; } // 創建緩存對象 if (SapBuffer.IsBufferTypeSupported(m_ServerLocation, SapBuffer.MemoryType.ScatterGather)) { m_Buffers = new SapBufferWithTrash(2, m_AcqDevice, SapBuffer.MemoryType.ScatterGather); } else { m_Buffers = new SapBufferWithTrash(2, m_AcqDevice, SapBuffer.MemoryType.ScatterGatherPhysical); } if (m_Buffers.Create() == false) { DestroyObjects(); DisposeObjects(); return false; } // 創建傳輸對象 m_Xfer = new SapAcqDeviceToBuf(m_AcqDevice, m_Buffers); m_Xfer.XferNotify += new SapXferNotifyHandler(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(); return false; } if (m_Xfer.Create() == false) { DestroyObjects(); DisposeObjects(); return false; } return true; }
4)銷毀對象
private void DestroyObjects() { 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(); } private void DisposeObjects() { 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; } }
5)獲取參數值及最大值、最小值
參數值的類型有string,int,double,bool幾種,需根據參數的可能值類型選擇對應的方法,否則會出錯。
文本型:
string val;
m_AcqDevice.GetFeatureValue(featureName, out val));
整數型:
int val;
m_AcqDevice.GetFeatureValue(featureName, out val));
小數型:
double val;
m_AcqDevice.GetFeatureValue(featureName, out val));
布爾型:
boolean val;
m_AcqDevice.GetFeatureValue(featureName, out val));
常用參數的值類型
中文名 |
參數名 |
值類型 |
圖像X坐標 |
OffsetX |
int |
圖像Y坐標 |
OffsetY |
int |
圖像寬度 |
Width |
int |
圖像高度 |
Height |
int |
采集幀率 |
AcquisitionFrameRate |
double |
曝光時間 |
ExposureTime |
double |
外觸發方式 |
TriggerMode |
bool |
獲取參數最大值,以整數類型舉例:
SapFeature feature = new SapFeature(m_ServerLocation); if (!feature.Create()) return -1; if (!m_AcqDevice.GetFeatureInfo(featureName, feature)) return -1; int maxValue = 0; if (!feature.GetValueMax(out maxValue)) return -1; return maxValue;
獲取參數最小值,以整數類型舉例:
SapFeature feature = new SapFeature(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;
6)設置參數值
設置參數值同樣需要根據參數的值類型,選擇對應的設參方法,否則會出現報錯的情況,我發現使用字符型可以兼容,所以可以把值轉為字符型,再設參。
string value; m_AcqDevice.SetFeatureValue(featureName, value);
根據實際使用發現,曝光時間可以在采集過程中設置,采集幀率在采集過程中設置不能立即生效,需在下次采集方能生效,而X、Y坐標及圖形寬度、高度、外觸發模式需在設備對象創建后,緩存對象創建前進行設置,否則報錯。
7)圖形采集控制
開始采集:
m_Xfer.Grab();
停止采集:
m_Xfer.Freeze();
單張或指定張數抓拍:
m_Xfer.Snap();
8)圖像獲取及顯示
開始采集后,得到每幀圖像時,會觸發XferNotify事件,可在此事件中進行圖像的獲取及顯示工作。
首先需判斷此幀是否是廢棄幀,若是則立即返回,等待下一幀:
if (e.Trash) return;
取得緩存中的圖像數據首地址:
IntPtr addr;
m_Buffers.GetAddress(out addr);
再將數據轉為Bitmap對象:
PixelFormat pf = PixelFormat.Format8bppIndexed; Bitmap bmp = new Bitmap(m_Buffers.Width, m_Buffers.Height, m_Buffers.Pitch, pf, addr); bmp.Palette = m_grayPalette;
以上是8位黑白圖像的轉換方法,創建圖像后需給Bitmap對象賦一個黑白調色板,創建調色板的代碼如下:
using (Bitmap bmp = new Bitmap(1, 1, PixelFormat.Format8bppIndexed)) { m_grayPalette = bmp.Palette; } for (int i = 0; i <= 255; i++) { m_grayPalette.Entries[i] = Color.FromArgb(i, i, i); }
如果是彩色相機,得到的數據是Bayer格式,需用Bayer轉換方法,轉換為24位彩色圖片,我找到Aforge,OpenCV都可以進行Bayer轉換。
Aforge的Bayer轉換代碼:
private BayerFilter m_bayerFilter = new BayerFilter(); m_bayerFilter.BayerPattern = new int[2, 2] { { RGB.G, RGB.B }, { RGB.R, RGB.G } }; bmp = m_bayerFilter.Apply(bmp);
OpenCV的Bayer轉換代碼:
IplImage *frame; frame = cvCreateImage(cvSize(width, height), depth, 1); frame->imageData = (char*)pData; IplImage *bgr = cvCreateImage(cvGetSize(frame),IPL_DEPTH_8U,3); cvCvtColor(frame, bgr, CV_BayerGR2BGR); pDlg->ShowImage(bgr, IDC_PIC1); cvReleaseImage(&frame); cvReleaseImage(&bgr);
如果用Bitmap直接賦給PictureBox的辦法,有時候會有內存泄露的情況,所以可采用GDI+繪圖的方式顯示圖像,缺點是采集停止時,窗體被覆蓋后圖像會消失。
private void DrawImageInPictureBox(PictureBox picBox, Image img) { Graphics g = picBox.CreateGraphics(); g.DrawImage(img, 0, 0, picBox.Width, picBox.Height); g.Dispose(); }
9)采集圖像開窗和面陣做線掃描
圖像開窗通過設置Width和Height兩參數即可,經過實驗發現,橫向開窗對采集幀率最大值沒有影響,而豎向開窗,采集幀率最大值會成比變化,豎向最小可設為2,即可當做線掃描使用,幀率最大可到1~2K。
如果做線掃使用,可以用List鏈表來存儲每幀數據,最后再合成大圖,轉成Bitmap的方法是一樣的,只是注意圖像的高度是每幀高度乘以幀數。