1 class Camera // 大华相机类
2 {
3 private IDevice m_dev; /* 设备对象 */
4 List<IGrabbedRawData> m_frameList = new List<IGrabbedRawData>(); /* 图像缓存列表 */
5 Thread renderThread = null; /* 显示线程 */
6 bool m_bShowLoop = true; /* 线程控制变量 */
7 Mutex m_mutex = new Mutex(); /* 锁,保证多线程安全 */
8 // public event Action<HObject> NewImage; // 图像显示事件
9
10 public Camera()
11 {
12 if (null == renderThread)
13 {
14 renderThread = new Thread(new ThreadStart(ShowThread));
15 renderThread.IsBackground = true;
16 renderThread.Start();
17 }
18 m_stopWatch.Start();//时间计时开始
19 }
20
21 /* 转码显示线程 */
22 private void ShowThread()
23 {
24 while (m_bShowLoop)//线程控制变量为True
25 {
26 if (m_frameList.Count == 0) //图像缓存列表
27 {
28 Thread.Sleep(10);
29 continue;
30 }
31
32 /* 图像队列取最新帧 */
33 m_mutex.WaitOne();//阻止当前线程,直到当前收到信号
34 IGrabbedRawData frame = m_frameList.ElementAt(0);//返回队列中指定索引处的元素
35 m_frameList.RemoveAt(0);
36 m_frameList.Clear();
37 m_mutex.ReleaseMutex();
38
39 /* 主动调用回收垃圾 */
40 GC.Collect();
41
42 /* 控制显示最高帧率为25FPS */
43 if (false == isTimeToDisplay())
44 {
45 continue;
46 }
47
48 try
49 {
50 /* 图像转码成bitmap图像 */
51 var bitmap = frame.ToBitmap(false);
52
53 // 在这里使用采集的图像
54 //if (NewImage != null)
55 //{
56 // NewImage(image);
57 //}
58 }
59 catch
60 {
61
62 }
63 }
64 }
65
66 const int DEFAULT_INTERVAL = 40;//默认的时间间隔
67 Stopwatch m_stopWatch = new Stopwatch(); /* 时间统计器 */
68
69 /* 判断是否应该做显示操作 */
70 private bool isTimeToDisplay()
71 {
72 m_stopWatch.Stop();
73 long m_lDisplayInterval = m_stopWatch.ElapsedMilliseconds;//获取实例测量出的总时间
74 if (m_lDisplayInterval <= DEFAULT_INTERVAL)
75 {
76 m_stopWatch.Start();
77 return false;
78 }
79 else
80 {
81 m_stopWatch.Reset();
82 m_stopWatch.Start();
83 return true;
84 }
85 }
86
87 /* 相机打开回调 */
88 private void OnCameraOpen(object sender, EventArgs e)
89 {
90 // 在这里记录相机已打开
91 }
92
93 /* 相机关闭回调 */
94 private void OnCameraClose(object sender, EventArgs e)
95 {
96 // 在这里记录相机已关闭
97 }
98
99 /* 相机丢失回调 */
100 private void OnConnectLoss(object sender, EventArgs e)
101 {
102 m_dev.ShutdownGrab();
103 m_dev.Dispose();
104 m_dev = null;
105 }
106
107 /* 码流数据回调 */
108 private void OnImageGrabbed(Object sender, GrabbedEventArgs e)
109 {
110 m_mutex.WaitOne();// m_mutex锁,保证多线程安全
111 m_frameList.Add(e.GrabResult.Clone());/* 图像缓存列表 */
112 m_mutex.ReleaseMutex();
113 }
114
115 /// <summary>
116 /// 打开相机
117 /// </summary>
118 /// <returns>返回字符串为空表示打开成功,不为空表示打开失败,字符串内容为异常信息</returns>
119 /// <param name="triggerSource">触发源选择 软触发或外触发</param>
120 /// <returns></returns>
121 public string Open(string triggerSource)
122 {
123 string sRet = string.Empty;
124 try
125 {
126 /* 设备搜索 */
127 List<IDeviceInfo> li = Enumerator.EnumerateDevices();
128 if (li.Count > 0)
129 {
130 /* 获取搜索到的第一个设备 */
131 m_dev = Enumerator.GetDeviceByIndex(0);
132
133 /* 注册链接事件 */
134 m_dev.CameraOpened += OnCameraOpen;
135 m_dev.ConnectionLost += OnConnectLoss;
136 m_dev.CameraClosed += OnCameraClose;
137
138 /* 打开设备 */
139 if (!m_dev.Open())
140 sRet = "打开相机失败";
141
142 /* 设置TriggerSource 软触发还是外触发*/
143 m_dev.TriggerSet.Open(triggerSource);
144
145 /* 设置图像格式 */
146 using (IEnumParameter p = m_dev.ParameterCollection[ParametrizeNameSet.ImagePixelFormat])
147 {
148 p.SetValue("Mono8");
149 }
150
151 /* 设置缓存个数为8(默认值为16) */
152 m_dev.StreamGrabber.SetBufferCount(8);
153
154 /* 注册码流回调事件 */
155 m_dev.StreamGrabber.ImageGrabbed += OnImageGrabbed;
156
157 /* 开启码流 */
158 if (!m_dev.GrabUsingGrabLoopThread())
159 sRet = "开启码流失败";
160 }
161 else
162 {
163 sRet = "未找到相机设备";
164 }
165 }
166 catch (Exception e)
167 {
168 sRet = e.Message;
169 }
170 return sRet;
171 }
172
173 /// <summary>
174 /// 关闭相机
175 /// </summary>
176 /// <returns>返回字符串为空表示关闭成功,不为空表示关闭失败,字符串内容为异常信息</returns>
177 public string Close()
178 {
179 string sRet = String.Empty;
180 try
181 {
182 if (m_dev == null)
183 {
184 sRet = "Device is invalid";
185 }
186
187 m_dev.StreamGrabber.ImageGrabbed -= OnImageGrabbed; /* 反注册回调 */
188 m_dev.ShutdownGrab(); /* 停止码流 */
189 m_dev.Close(); /* 关闭相机 */
190 }
191 catch (Exception e)
192 {
193 sRet = e.Message;
194 }
195 return sRet;
196 }
197
198 /* 窗口关闭 */
199 public void OnClosed(EventArgs e)
200 {
201 if (m_dev != null)
202 {
203 m_dev.Dispose();
204 m_dev = null;
205 }
206
207 m_bShowLoop = false;
208 renderThread.Join();
209 }
210 /// <summary>
211 /// 设置触发模式 软触发下设置On后自由拉流(连续触发)Off(单次触发)
212 /// </summary>
213 /// <param name="value"></param>
214 public string SetTriggerMode(string value="On")
215 {
216 if (m_dev == null)
217 {
218 return "Device is invalid";
219 }
220 if (!m_dev.IsOpen)
221 {
222 return "相机未打开";
223 }
224 using (IEnumParameter p = m_dev.ParameterCollection[ParametrizeNameSet.TriggerMode])
225 {
226 p.SetValue(value);
227 }
228 return "";
229 }
230 /// <summary>
231 /// 设置曝光
232 /// </summary>
233 /// <param name="value"></param>
234 public string SetExposureTime(float value)
235 {
236 if (m_dev == null)
237 {
238 return "Device is invalid";
239 }
240 if (!m_dev.IsOpen)
241 {
242 return "相机未打开";
243 }
244 double min = GetMinExposureTime();
245 double max = GetMaxExposureTime();
246 if (value < min || value > max)
247 {
248 return string.Format("参数值不在范围内,min:{0},max:{1}", min, max);
249 }
250 using (IFloatParameter p = m_dev.ParameterCollection[ParametrizeNameSet.ExposureTime])
251 {
252 p.SetValue(value);
253 }
254 return "";
255 }
256 /// <summary>
257 /// 设置增益
258 /// </summary>
259 /// <param name="value"></param>
260 public string SetGainRaw(float value)
261 {
262 if (m_dev == null)
263 {
264 return "Device is invalid";
265 }
266 if (!m_dev.IsOpen)
267 {
268 return "相机未打开";
269 }
270 double min = GetMinGainRaw();
271 double max = GetMaxGainRaw();
272 if (value < min || value > max)
273 {
274 return string.Format("参数值不在范围内,min:{0},max:{1}", min, max);
275 }
276 using (IFloatParameter p = m_dev.ParameterCollection[ParametrizeNameSet.GainRaw])
277 {
278 p.SetValue(value);
279 }
280 return "";
281 }
282 /// <summary>
283 /// 设置图像的宽度
284 /// </summary>
285 /// <param name="value"></param>
286 /// <returns></returns>
287 public string SetImageWidth(int value)
288 {
289 if (m_dev == null)
290 {
291 return "Device is invalid";
292 }
293 if (!m_dev.IsOpen)
294 {
295 return "相机未打开";
296 }
297 double min = GetMinImageWidth();
298 double max = GetMaxImageWidth();
299 if (value < min || value > max)
300 {
301 return string.Format("参数值不在范围内,min:{0},max:{1}", min, max);
302 }
303 using (IIntegraParameter p = m_dev.ParameterCollection[ParametrizeNameSet.ImageWidth])
304 {
305 p.SetValue(value);
306 }
307 return "";
308 }
309 /// <summary>
310 /// 设置图像的宽度
311 /// </summary>
312 /// <param name="value"></param>
313 /// <returns></returns>
314 public string SetImageHeight(int value)
315 {
316 if (m_dev == null)
317 {
318 return "Device is invalid";
319 }
320 if (!m_dev.IsOpen)
321 {
322 return "相机未打开";
323 }
324 double min = GetMinImageHeight();
325 double max = GetMaxImageHeight();
326 if (value < min || value > max)
327 {
328 return string.Format("参数值不在范围内,min:{0},max:{1}", min, max);
329 }
330 using (IIntegraParameter p = m_dev.ParameterCollection[ParametrizeNameSet.ImageHeight])
331 {
332 p.SetValue(value);
333 }
334 return "";
335 }
336 /// <summary>
337 /// 设置图像偏移X
338 /// </summary>
339 /// <param name="value"></param>
340 /// <returns></returns>
341 public string SetImageOffsetX(int value)
342 {
343 if (m_dev == null)
344 {
345 return "Device is invalid";
346 }
347 if (!m_dev.IsOpen)
348 {
349 return "相机未打开";
350 }
351 double min = GetMinImageOffsetX();
352 double max = GetMaxImageOffsetX();
353 if (value < min || value > max)
354 {
355 return string.Format("参数值不在范围内,min:{0},max:{1}", min, max);
356 }
357 using (IIntegraParameter p = m_dev.ParameterCollection[ParametrizeNameSet.ImageOffsetX])
358 {
359 p.SetValue(value);
360 }
361 return "";
362 }
363 /// <summary>
364 /// 设置图像偏移Y
365 /// </summary>
366 /// <param name="value"></param>
367 /// <returns></returns>
368 public string SetImageOffsetY(int value)
369 {
370 if (m_dev == null)
371 {
372 return "Device is invalid";
373 }
374 if (!m_dev.IsOpen)
375 {
376 return "相机未打开";
377 }
378 double min = GetMinImageOffsetY();
379 double max = GetMaxImageOffsetY();
380 if (value < min || value > max)
381 {
382 return string.Format("参数值不在范围内,min:{0},max:{1}", min, max);
383 }
384 using (IIntegraParameter p = m_dev.ParameterCollection[ParametrizeNameSet.ImageOffsetY])
385 {
386 p.SetValue(value);
387 }
388 return "";
389 }
390
391 #region 获取相机参数的取值范围
392 public double GetMinExposureTime()
393 {
394 using (IFloatParameter p = m_dev.ParameterCollection[ParametrizeNameSet.ExposureTime])
395 {
396 return p.GetMinimum();
397 }
398 }
399 public double GetMaxExposureTime()
400 {
401 using (IFloatParameter p = m_dev.ParameterCollection[ParametrizeNameSet.ExposureTime])
402 {
403 return p.GetMaximum();
404 }
405 }
406 public double GetMinGainRaw()
407 {
408 using (IFloatParameter p = m_dev.ParameterCollection[ParametrizeNameSet.GainRaw])
409 {
410 return p.GetMinimum();
411 }
412 }
413 public double GetMaxGainRaw()
414 {
415 using (IFloatParameter p = m_dev.ParameterCollection[ParametrizeNameSet.GainRaw])
416 {
417 return p.GetMaximum();
418 }
419 }
420 public long GetMinImageWidth()
421 {
422 using (IIntegraParameter p = m_dev.ParameterCollection[ParametrizeNameSet.ImageWidth])
423 {
424 return p.GetMinimum();
425 }
426 }
427 public long GetMaxImageWidth()
428 {
429 using (IIntegraParameter p = m_dev.ParameterCollection[ParametrizeNameSet.ImageWidth])
430 {
431 return p.GetMaximum();
432 }
433 }
434 public long GetMinImageHeight()
435 {
436 using (IIntegraParameter p = m_dev.ParameterCollection[ParametrizeNameSet.ImageHeight])
437 {
438 return p.GetMinimum();
439 }
440 }
441 public long GetMaxImageHeight()
442 {
443 using (IIntegraParameter p = m_dev.ParameterCollection[ParametrizeNameSet.ImageHeight])
444 {
445 return p.GetMaximum();
446 }
447 }
448 public long GetMinImageOffsetX()
449 {
450 using (IIntegraParameter p = m_dev.ParameterCollection[ParametrizeNameSet.ImageOffsetX])
451 {
452 return p.GetMinimum();
453 }
454 }
455 public long GetMaxImageOffsetX()
456 {
457 using (IIntegraParameter p = m_dev.ParameterCollection[ParametrizeNameSet.ImageOffsetX])
458 {
459 return p.GetMaximum();
460 }
461 }
462 public long GetMinImageOffsetY()
463 {
464 using (IIntegraParameter p = m_dev.ParameterCollection[ParametrizeNameSet.ImageOffsetY])
465 {
466 return p.GetMinimum();
467 }
468 }
469 public long GetMaxImageOffsetY()
470 {
471 using (IIntegraParameter p = m_dev.ParameterCollection[ParametrizeNameSet.ImageOffsetY])
472 {
473 return p.GetMaximum();
474 }
475 }
476 #endregion
477
478 /// <summary>
479 /// bitmap图像转HObject
480 /// </summary>
481 /// <param name="bmp"></param>
482 /// <returns></returns>
483 //private HObject Bitmap2HObjectBpp24(Bitmap bmp)
484 //{
485 // HObject Hobj;
486 // HOperatorSet.GenEmptyObj(out Hobj);
487 // try
488 // {
489 // Rectangle rect = new Rectangle(0, 0, bmp.Width, bmp.Height);
490
491 // BitmapData srcBmpData = bmp.LockBits(rect, ImageLockMode.ReadOnly, PixelFormat.Format24bppRgb);
492 // HOperatorSet.GenImageInterleaved(out Hobj, srcBmpData.Scan0, "bgr", bmp.Width, bmp.Height, 0, "byte", 0, 0, 0, 0, -1, 0);
493 // bmp.UnlockBits(srcBmpData);
494 // }
495 // catch (Exception e)
496 // {
497
498 // }
499 // return Hobj;
500 //}
501 }