一,首先先配置生成项目,根据官方文档步骤来:
这个没啥好说的,一步步照做就是了,就最后一步,开始我没重视,最后代码写完测试的时候还真的遇到问题了,一直出这样的错:
查了官方文档才看到最后一条~,然后在项目属性中把这个勾掉了,代码完美运行拉……
二,功能步骤
其实整个步骤很简单:
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函数是精髓!精髓!精髓!
没啥说的,上代码。可运行代码一字不差的放上来咯,注释也尽可能详细了:
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.Threading.Tasks; 9 using System.Windows.Forms; 10 using System.Drawing.Imaging; 11 using DALSA.SaperaLT.SapClassBasic; 12 13 namespace dalsaSave 14 { 15 public partial class Form1 : Form 16 { 17 // 全局变量 18 private static int picCountNum = 0; // 统计采集了多少张图,有利于理解m_Xfer.Sanp(15)中15的意思 19 private string configFilePath = @"D:\T_Linea_M4096-7um_Default_Default.ccf"; // 配置文件的路径 20 private string imgPath = @"D:\imgs\"; //采集图片保存地址 21 private SapLocation m_ServerLocation; // 设备的连接地址 22 private SapAcqDevice m_AcqDevice; //采集设备 23 private SapBuffer m_Buffers; // 缓存对象 24 private SapAcqDeviceToBuf m_Xfer; // 传输对象 25 26 27 public Form1() 28 { 29 InitializeComponent(); 30 } 31 32 private void Form1_Load(object sender, EventArgs e) 33 { 34 35 } 36 37 private void Form1_FormClosed(object sender, FormClosedEventArgs e) 38 { 39 DestroyObjects(); 40 DisposeObjects(); 41 } 42 43 // 初始化并连接相机 44 private void btn_init_Click(object sender, EventArgs e) 45 { 46 CreateNewObjects(); 47 } 48 49 private void btn_setting_Click(object sender, EventArgs e) 50 { 51 // 设置曝光值,为了设置的值不超限,需要获取曝光值的允许范围(主要是最大值) 52 double valuetemp = GetMaxValue("ExposureTime"); 53 if (valuetemp > 0) 54 { 55 m_AcqDevice.SetFeatureValue("ExposureTime", valuetemp); 56 } 57 m_AcqDevice.SetFeatureValue("Gain", "9.9"); 58 } 59 60 private void btn_getValue_Click(object sender, EventArgs e) 61 { 62 string deviceModelName; 63 string deviceUserId; 64 string pixelFormat; 65 string triggerMode; 66 67 double acquisitionLineRate; // 行频和曝光时间不能设置为int类型 68 double exposureTime; 69 double gain; 70 int width; 71 int height; 72 int sensorWidth; 73 int sensorHeight; 74 75 m_AcqDevice.GetFeatureValue("DeviceModelName", out deviceModelName); //Linea M4096-7um 76 m_AcqDevice.GetFeatureValue("DeviceUserID", out deviceUserId); //空 77 m_AcqDevice.GetFeatureValue("PixelFormat", out pixelFormat); //Mono8 78 m_AcqDevice.GetFeatureValue("TriggerMode", out triggerMode); //Off 79 80 m_AcqDevice.GetFeatureValue("AcquisitionLineRate", out acquisitionLineRate); //10000.0 81 m_AcqDevice.GetFeatureValue("ExposureTime", out exposureTime); //70.0 82 m_AcqDevice.GetFeatureValue("Gain", out gain); //9.0 83 m_AcqDevice.GetFeatureValue("Width", out width); //4096 84 m_AcqDevice.GetFeatureValue("Height", out height); //2800 85 m_AcqDevice.GetFeatureValue("SensorWidth", out sensorWidth); //4096 86 m_AcqDevice.GetFeatureValue("SensorHeight", out sensorHeight); //1 87 } 88 89 #region 90 private void btn_snap_Click(object sender, EventArgs e) 91 { 92 // Snap() 只采集一张, 如果是Snap(15)则连续采集15张 93 m_Xfer.Snap(15); //m_Xfer.Snap(m_Buffers.Count) 94 } 95 96 private void btn_grab_Click(object sender, EventArgs e) 97 { 98 m_Xfer.Grab(); 99 } 100 101 102 //关闭的时候,执行Freez()停止采集,线程等待5秒, 103 //目的是停止采集后,将还存在内存地址通道中的裸数据都取出来, 104 //如果freeze之后直接释放,就拿不到还在地址上的数据了,缓存对象释放之后,将本次采集所有对象摧毁。 105 106 private void btn_freeze_Click(object sender, EventArgs e) 107 { 108 m_Xfer.Freeze(); 109 } 110 #endregion 111 112 //得到所有连接的相机信息,并将他们加入到ArrayList里面去 113 public bool GetCameraInfo(out string sCameraName, out int nIndex) 114 { 115 Console.WriteLine("开始获取相机信息"); 116 117 sCameraName = ""; 118 nIndex = 0; 119 120 // 查询相机数量 121 int serverCount = SapManager.GetServerCount(); 122 int GenieIndex = 0; 123 124 // 实例化一个list,作为容器 125 System.Collections.ArrayList listServerNames = new System.Collections.ArrayList(); 126 127 bool bFind = false; 128 string serverName = ""; 129 for (int serverIndex = 0; serverIndex < serverCount; serverIndex++) 130 { 131 if (SapManager.GetResourceCount(serverIndex, SapManager.ResourceType.AcqDevice) != 0) 132 { 133 serverName = SapManager.GetServerName(serverIndex); 134 listServerNames.Add(serverName); 135 GenieIndex++; 136 bFind = true; 137 } 138 } 139 140 int count = 1; 141 string deviceName = ""; 142 foreach (string sName in listServerNames) 143 { 144 deviceName = SapManager.GetResourceName(sName, SapManager.ResourceType.AcqDevice, 0); 145 count++; 146 } 147 148 sCameraName = serverName; 149 nIndex = GenieIndex; 150 151 return bFind; 152 153 } 154 155 156 // 初始化并连接相机 157 public bool CreateNewObjects() 158 { 159 Console.WriteLine("相机初始化"); 160 string Name; 161 int Index; 162 163 // 获取相机详细信息 164 bool RTemp = GetCameraInfo(out Name, out Index); 165 if (RTemp) 166 { 167 MessageBox.Show(Name); 168 } 169 else 170 { 171 MessageBox.Show("Get camera info false!"); 172 return false; 173 } 174 175 m_ServerLocation = new SapLocation(Name, 0); 176 177 //创建采集设备,new SapAcqDevice()的括号中第二个参数既可以写配置文件路径,也可以写false,false是用相机当前的设置 178 // 获取相机信息,加载相机配置文件(用相机专家调整好参数后导出ccf文件),加载参数 179 if (configFilePath.Length > 0) 180 m_AcqDevice = new SapAcqDevice(m_ServerLocation, configFilePath); 181 else 182 m_AcqDevice = new SapAcqDevice(m_ServerLocation, false); 183 184 Console.WriteLine(m_AcqDevice.Create()); 185 186 if (m_AcqDevice.Create() == false) 187 { 188 DestroyObjects(); 189 DisposeObjects(); 190 191 return false; 192 } 193 194 // 创建缓存对象 195 if (SapBuffer.IsBufferTypeSupported(m_ServerLocation, SapBuffer.MemoryType.ScatterGather)) 196 { 197 m_Buffers = new SapBufferWithTrash(2, m_AcqDevice, SapBuffer.MemoryType.ScatterGather); 198 } 199 else 200 { 201 m_Buffers = new SapBufferWithTrash(2, m_AcqDevice, SapBuffer.MemoryType.ScatterGatherPhysical); 202 } 203 204 if (m_Buffers.Create() == false) 205 { 206 DestroyObjects(); 207 DisposeObjects(); 208 return false; 209 } 210 211 //设置行频,注意:行频在相机工作时不能设置(曝光、增益可以),最好在初始化阶段设置 212 m_AcqDevice.SetFeatureValue("AcquisitionLineRate", 20000.0); 213 214 //创建传输对象 215 m_Xfer = new SapAcqDeviceToBuf(m_AcqDevice, m_Buffers); 216 217 // 这一句是核心,这是回调函数,就靠它采图了 218 m_Xfer.XferNotify += new SapXferNotifyHandler(m_Xfer_XferNotify); 219 m_Xfer.XferNotifyContext = this; 220 m_Xfer.Pairs[0].EventType = SapXferPair.XferEventType.EndOfFrame; 221 m_Xfer.Pairs[0].Cycle = SapXferPair.CycleMode.NextWithTrash; 222 if (m_Xfer.Pairs[0].Cycle != SapXferPair.CycleMode.NextWithTrash) 223 { 224 DestroyObjects(); 225 DisposeObjects(); 226 return false; 227 } 228 if (m_Xfer.Create() == false) 229 { 230 DestroyObjects(); 231 DisposeObjects(); 232 return false; 233 } 234 235 return true; 236 } 237 238 239 private void DestroyObjects() 240 { 241 if (m_Xfer != null && m_Xfer.Initialized) 242 m_Xfer.Destroy(); 243 if (m_Buffers != null && m_Buffers.Initialized) 244 m_Buffers.Destroy(); 245 if (m_AcqDevice != null && m_AcqDevice.Initialized) 246 m_AcqDevice.Destroy(); 247 } 248 249 250 private void DisposeObjects() 251 { 252 if (m_Xfer != null) 253 { 254 m_Xfer.Dispose(); 255 m_Xfer = null; 256 } 257 if (m_Buffers != null) 258 { 259 m_Buffers.Dispose(); 260 m_Buffers = null; 261 } 262 if (m_AcqDevice != null) 263 { 264 m_AcqDevice.Dispose(); 265 m_AcqDevice = null; 266 } 267 } 268 269 270 void m_Xfer_XferNotify(object sender, SapXferNotifyEventArgs argsNotify) 271 { 272 // 首先判断此帧是否为废弃帧,若是则立即返回,等待下一帧(但这句话有时候m_Xfer.Snap(n)时会导致丢帧,可以注释掉试试) 273 if (argsNotify.Trash) return; 274 275 // 获取m_Buffers的地址(指针),只要知道了图片内存的地址,其实就能有各种办法搞出图片了(例如转成Bitmap) 276 IntPtr addr; 277 m_Buffers.GetAddress(out addr); 278 279 // 观察buffer中的图片的一些属性值,语句后注释里面的值是可能的值 280 int count = m_Buffers.Count; //2 281 SapFormat format = m_Buffers.Format; //Uint8 282 double rate = m_Buffers.FrameRate; //30.0,连续采集时,这个值会动态变化 283 int height = m_Buffers.Height; //2800 284 int weight = m_Buffers.Width; //4096 285 int pixd = m_Buffers.PixelDepth; //8 286 287 //显示实时帧率 288 UpdateFrameRate(); 289 lbl_FrameRate.BeginInvoke(new Action(() => { lbl_FrameRate.Text = m_Buffers.FrameRate.ToString(); })); 290 291 292 picCountNum++; 293 294 // 保存到本地。这个save方法就是从SDK中提取出来的,给上参数,就可以实现图片的保存,不用借助其他任何的技术方法 295 m_Buffers.Save(imgPath + picCountNum + ".bmp", "-format bmp" ); 296 297 298 // 从内存读取图片,并转换成bitmap格式,创建调色板,打印到PictureBox 299 PixelFormat pf = PixelFormat.Format8bppIndexed; 300 Bitmap bmp = new Bitmap(weight, height, m_Buffers.Pitch, pf, addr); 301 ColorPalette m_grayPalette; 302 using (Bitmap tempbmp = new Bitmap(1, 1, PixelFormat.Format8bppIndexed)) 303 { 304 m_grayPalette = tempbmp.Palette; 305 } 306 for (int i = 0; i <= 255; i++) 307 { 308 m_grayPalette.Entries[i] = Color.FromArgb(i, i, i); 309 } 310 311 bmp.Palette = m_grayPalette; 312 313 Image img = Image.FromHbitmap(bmp.GetHbitmap()); 314 picBox.Image = img; 315 } 316 317 private void UpdateFrameRate() 318 { 319 if (m_Xfer.UpdateFrameRateStatistics()) 320 { 321 float framerate = 0.0f; 322 SapXferFrameRateInfo stats = m_Xfer.FrameRateStatistics; 323 324 if (stats.IsBufferFrameRateAvailable) 325 framerate = stats.BufferFrameRate; 326 else if (stats.IsLiveFrameRateAvailable && !stats.IsLiveFrameRateStalled) 327 framerate = stats.LiveFrameRate; 328 329 m_Buffers.FrameRate = framerate; 330 } 331 } 332 333 // 获得相机参数的最大值(行频和曝光时间是近似倒数的关系,获得参数最大值可以防止设置参数超限) 334 private double GetMaxValue(string featureName) 335 { 336 SapFeature feature = new SapFeature(m_ServerLocation); 337 if (!feature.Create()) return -1; 338 if (!m_AcqDevice.GetFeatureInfo(featureName, feature)) return -1; 339 340 double maxValue = 0; 341 if (!feature.GetValueMax(out maxValue)) return -1; 342 return maxValue; 343 } 344 345 // 这个一般用的少,最小值一般是很小的数(比如Gain最小0.125, width最小128),我们一般不会设置这样的数 346 private double GetMinValue(string featureName) 347 { 348 SapFeature feature = new SapFeature(m_ServerLocation); 349 if (!feature.Create()) return -1; 350 if (!m_AcqDevice.GetFeatureInfo(featureName, feature)) return -1; 351 352 int minValue = 0; 353 if (!feature.GetValueMin(out minValue)) return -1; 354 return minValue; 355 } 356 } 357 }
标签:C#,AcqDevice,private,int,DALSA,二次开发,Xfer,Buffers,out From: https://www.cnblogs.com/ybqjymy/p/17089086.html