新增專案名稱 “CameraCapture”
加入 references Emgu.CV Emgu.CV.UI Emgu.Util from directory
C:\Emgu\emgucv-windows-universal-cuda 3.0.0.2158\bin
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:
10: using Emgu.CV;
11: using Emgu.CV.CvEnum;
12: using Emgu.CV.Structure;
13: using Emgu.Util;
Add variables
1: private Capture m_capture;
2: private bool m_captureInProgress;
3: private int m_camIndex = 1;
專案新增x64目錄並加入C:\Emgu\emgucv-windows-universal-cuda 3.0.0.2158\bin\x64目錄下所有dll檔案
輸入*.dll按下Enter鍵, 複選全部檔案(方法1:CTRL+a鍵;
方法2:滑鼠點選第一個dll檔案, 按下Shift鍵不放, 點選最後一個dll檔案)
設定剛才加入的dll檔案屬性(複製到輸出目錄 = 有更新時才複製)
加入x64目錄下dll有個好處, 可以將Release目錄複製到一台沒有安裝Emgu電腦下執行,
缺點是每一個專案都會自己一份dll, 占用不少硬體空間(600多MB)
另一種方式是增加系統變數方式, 讓系統找得到對應的dll檔案即可
==========================================================
設定攝影機FrameGrabber副程式, 框架如下
1: private void FrameGrabber(object sender, EventArgs e)
2: {
3: }
定義5張Mat格式變數colorFrame, grayFrame, smallGrayFrame, smoothGrayFrame, cannyFrame
1: private void FrameGrabber(object sender, EventArgs e)
2: {
3: using(Mat colorFrame = new Mat())
4: using(Mat grayFrame = new Mat())
5: using(Mat smallGrayFrame = new Mat())
6: using (Mat smoothGrayFrame = new Mat())
7: using (Mat cannyFrame = new Mat())
8: {
9: m_capture.Retrieve(colorFrame, 0);
10: CvInvoke.CvtColor(colorFrame, grayFrame, ColorConversion.Bgr2Gray);
11: CvInvoke.PyrDown(grayFrame, smallGrayFrame);
12: CvInvoke.PyrUp(smallGrayFrame, smoothGrayFrame);
13: CvInvoke.Canny(smoothGrayFrame, cannyFrame, 100, 60);
14:
15: captureImageBox.Image = colorFrame;
16: grayscaleImageBox.Image = grayFrame;
17: smoothedGrayscaleImageBox.Image = smoothGrayFrame;
18: cannyImageBox.Image = cannyFrame;
19: }
20: }
上述local變數使用using會有一個問題, 當該物件被資源釋放時(IDISPOSABLE),
有可能同時又被指派至imageBox, 這時候就會跳出錯誤訊息
測試後改以下列方式(不使用using)
1:
2: Mat colorFrame = new Mat();
3: Mat grayFrame = new Mat();
4: Mat smallGrayFrame = new Mat();
5: Mat smoothGrayFrame = new Mat();
6: Mat cannyFrame = new Mat();
7: {
8: m_capture.Retrieve(colorFrame, 0);
9: CvInvoke.CvtColor(colorFrame, grayFrame, ColorConversion.Bgr2Gray);
10: CvInvoke.PyrDown(grayFrame, smallGrayFrame);
11: CvInvoke.PyrUp(smallGrayFrame, smoothGrayFrame);
12: CvInvoke.Canny(smoothGrayFrame, cannyFrame, 100, 60);
13: try
14: {
15: captureImageBox.Image = colorFrame;
16: grayscaleImageBox.Image = grayFrame;
17: smoothedGrayscaleImageBox.Image = smoothGrayFrame;
18: cannyImageBox.Image = cannyFrame;
19: }
20: catch (Exception exception)
21: {
22: MessageBox.Show(exception.Message);
23: }
24: GC.Collect();
25: }
使用using版本,CameraCapture記憶體固定大概33~35MB,
如果不使用using版本, 記憶體可能會飆高到500~700MB甚至更高, 然後才被釋放,
建議可以加入GC.Collect();記憶體固定大概也可以維持在33~35MB
附帶一提, GC.Release會花一些時間, 不如將這些變數拉高至Form1成員變數
這樣就不會一直創建/釋放物件
1: public partial class Form1 : Form
2: {
3: private Capture m_capture;
4: private bool m_captureInProgress;
5: private int m_camIndex = 1;
6: Mat colorFrame = new Mat();
7: Mat grayFrame = new Mat();
8: Mat smallGrayFrame = new Mat();
9: Mat smoothGrayFrame = new Mat();
10: Mat cannyFrame = new Mat();
DoubleBufferOn
1: private void DoubleBufferOn()
2: {
3: SetStyle(ControlStyles.AllPaintingInWmPaint, true);
4: SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
5: UpdateStyles();
6: }
Form1 Constructor
1: public Form1()
2: {
3: InitializeComponent();
4: DoubleBufferOn();
5:
6: CvInvoke.UseOpenCL = false;
7: try
8: {
9: m_capture = new Capture(m_camIndex);
10: this.DoubleBuffered = true;
11: m_capture.ImageGrabbed += new EventHandler(FrameGrabber);
12: }
13: catch (Exception exception)
14: {
15: MessageBox.Show(exception.Message);
16: }
17: }
Start/Stop Camera
1: private void captureButton_Click(object sender, EventArgs e)
2: {
3: if (m_capture != null)
4: {
5: if (m_captureInProgress)
6: {
7: captureButton.Text = "Start Capture";
8: m_capture.Pause();
9: }
10: else
11: {
12: captureButton.Text = "Stop Capture";
13: m_capture.Start();
14: }
15: m_captureInProgress = !m_captureInProgress;
16: }
17: }
Flip Horizontally
1: private void flipHorizontalButton_Click(object sender, EventArgs e)
2: {
3: m_capture.FlipHorizontal = !m_capture.FlipHorizontal;
4: }
Flip Virtically
1: private void flipVerticalButton_Click(object sender, EventArgs e)
2: {
3: m_capture.FlipVertical = !m_capture.FlipVertical;
4: }
範例程式: CameraCapture
參考資料
2. OpenCL
留言列表