同學你可以嘗試把程式碼再寫一次
這是官方提供的學習用範例
因為剛剛已經做過執行 而且可成功!!!
很長一大串
如果是我 我會先把這串程式縮短
一個一個加進去 看效果跟執行的狀況不同與演進
原本好大一串程式碼
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using Emgu.CV;
using Emgu.CV.Structure;
using Emgu.Util;
using System.Runtime.InteropServices;
namespace faceMouseControl_example
{
public partial class Form1 : Form
{
private Capture _capture;
private HaarCascade _face;
public Form1()
{
InitializeComponent();
//Read the HaarCascade object
_face = new HaarCascade("haarcascade_frontalface_default.xml");
if (_capture == null)
{
try
{
_capture = new Capture();
}
catch (NullReferenceException excpt)
{
MessageBox.Show(excpt.Message);
return;
}
}
Application.Idle += updateFrame;
}
private void updateFrame(object sender, EventArgs e)
{
Image<Bgr, Byte> frame = _capture.QueryFrame();
Image<Gray, Byte> grayImage = frame.Convert<Gray, Byte>();
grayImage._EqualizeHist();
Rectangle imageArea = grayImage.ROI;
Rectangle mouseStableArea =
new Rectangle((int)(imageArea.Width * 0.4), (int)(imageArea.Height * 0.4),
(int)(imageArea.Width * 0.2), (int)(imageArea.Height * 0.2));
//draw the stable area where the face will not trigger a movement;
frame.Draw(mouseStableArea, new Bgr(255, 0, 0), 1);
MCvAvgComp[] faces = grayImage.DetectHaarCascade(_face)[0];
if (faces.Length > 0)
{ //if there is at least one face
#region find the biggest face
MCvAvgComp biggestFace = faces[0];
for (int i = 1; i < faces.Length; i++)
{
if (faces[i].rect.Width * faces[i].rect.Height > biggestFace.rect.Width * biggestFace.rect.Height)
biggestFace = faces[i];
}
#endregion
//draw a yellow rectangle around the face
frame.Draw(biggestFace.rect, new Bgr(255, 255, 0.0), 1);
Point biggestFaceCenter = new Point(biggestFace.rect.X + biggestFace.rect.Width / 2, biggestFace.rect.Y + biggestFace.rect.Height / 2);
Point imageAreaCenter = new Point(imageArea.X + imageArea.Width / 2, imageArea.Y + imageArea.Height / 2);
//draw a green cross at the center of the biggest face
frame.Draw(
new Cross2DF(biggestFaceCenter, biggestFace.rect.Width * 0.1f, biggestFace.rect.Height * 0.1f),
new Bgr(0, 255, 0), 1);
if (!mouseStableArea.Contains(biggestFaceCenter))
{ //the point is far enough from the center to triger a movement
//horizontal fraction is a value in [-0.5, 0.5] where
//-0.5 refer to the far left and
//0.5 refer to the far right
double horizontalFraction = (double)(biggestFaceCenter.X - imageAreaCenter.X) / imageArea.Width;
//do the same for vertical fraction
double verticalFraction = (double)(biggestFaceCenter.Y - imageAreaCenter.Y) / imageArea.Height;
Rectangle rect = System.Windows.Forms.Screen.PrimaryScreen.Bounds;
int maxMouseSpeed = rect.Width / 20;
System.Drawing.Point p;
GetCursorPos(out p);
p.X = Math.Min(Math.Max(0, p.X + (int)((maxMouseSpeed / 2) * horizontalFraction)), rect.Width);
p.Y = Math.Min(Math.Max(0, p.Y + (int)((maxMouseSpeed / 2) * verticalFraction)), rect.Height);
SetCursorPos(p.X, p.Y);
}
}
imageBox1.Image = frame;
}
[DllImport("user32.dll")]
private static extern bool GetCursorPos(out System.Drawing.Point lpPoint);
[DllImport("user32.dll")]
private static extern bool SetCursorPos(int X, int Y);
}
}
首先我們把程式刪減到
打開視訊畫面的階段(這是基本的)
官方的開視訊顯示的Code
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using Emgu.CV;
using Emgu.CV.Structure;
using Emgu.Util;
using System.Runtime.InteropServices;
namespace faceMouseControl_example
{
public partial class Form1 : Form
{
private Capture _capture;
public Form1()
{
InitializeComponent();
if (_capture == null)
{
try
{
_capture = new Capture();
}
catch (NullReferenceException excpt)
{
MessageBox.Show(excpt.Message);
return;
}
}
Application.Idle += updateFrame;
}
private void updateFrame(object sender, EventArgs e)
{
Image<Bgr, Byte> frame = _capture.QueryFrame();
imageBox1.Image = frame;
}
}
}
我習慣的寫法(喜歡寫短一些....簡潔俐落一點 、功能先達到、但比較不嚴謹也較暴力)
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using Emgu.CV;
using Emgu.CV.Structure;
using Emgu.Util;
using System.Runtime.InteropServices;
namespace faceMouseControl_example
{
public partial class Form1 : Form
{
Capture _capture = null;
Image<Bgr, byte> frame;
public Form1()
{
InitializeComponent();
_capture = new Capture(0);
Application.Idle += updateFrame;
}
private void updateFrame(object sender, EventArgs e)
{
frame = _capture.QueryFrame();
imageBox1.Image = frame;
}
}
}
官方的轉灰階
宣告寫在update中 一直新空間產生
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using Emgu.CV;
using Emgu.CV.Structure;
using Emgu.Util;
using System.Runtime.InteropServices;
namespace faceMouseControl_example
{
public partial class Form1 : Form
{
private Capture _capture;
public Form1()
{
InitializeComponent();
if (_capture == null)
{
try
{
_capture = new Capture();
}
catch (NullReferenceException excpt)
{
MessageBox.Show(excpt.Message);
return;
}
}
Application.Idle += updateFrame;
}
private void updateFrame(object sender, EventArgs e)
{
Image<Bgr, Byte> frame = _capture.QueryFrame();
Image<Gray, Byte> grayImage = frame.Convert<Gray, Byte>();
imageBox1.Image = grayImage;
}
}
}
轉灰階我的普通寫法
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using Emgu.CV;
using Emgu.CV.Structure;
using Emgu.Util;
using System.Runtime.InteropServices;
namespace faceMouseControl_example
{
public partial class Form1 : Form
{
Capture _capture = null;
Image<Bgr, byte> frame;
Image<Gray, Byte> grayImage;
public Form1()
{
InitializeComponent();
_capture = new Capture(0);
Application.Idle += updateFrame;
}
private void updateFrame(object sender, EventArgs e)
{
frame = _capture.QueryFrame();
grayImage = frame.Convert<Gray, Byte>();
imageBox1.Image = grayImage;
}
}
}
寫裡面跟寫外面差別在哪?????
寫外面
寫裡面
感覺沒差多少
官方範例寫法記憶體測試
Visual Studio --> Performance Profiler --> Memory Usage
在update中 宣告多次
在外圍宣告一次
無聊順便測試的
一些參考
請問迴圈中使用之變數宜宣告於何處?
https://social.msdn.microsoft.com/Forums/zh-TW/9abf11cc-af5f-45ab-a410-a812bc498bf0?forum=233
Creating objects in Loop C#
http://stackoverflow.com/questions/2321388/creating-objects-in-loop-c-sharp
感覺偏題了 好 繼續
後續我先用一種簡單寫法
就好
(1).學會查字典
到底這個 _EqualizeHist() 做了捨麼神奇的事情 ????
(這句可省--->有無做都可以偵測到喔)
滑鼠一上去查看一下
右鍵 --> Go to Definition --> 上移
接著去查字典了優
http://www.emgu.com/wiki/files/2.4.10/document/
點選左側 Emgu.CV 的 namespace
Ctrl + F --> Image
Ctrl + F --> member --> 點進去
The algorithm inplace normalizes brightness and increases contrast of the image.
For color images, a HSV representation of the image is first obtained and the V (value) channel is histogram normalized
講白話一點 這個主要是作色階分布平等化(均勻化)
用來改善影像對比喔!!!
由於我們是用 emgucv 提供的 UI 套件 中 imageBox 所以可以右鍵 --> 直方圖看差異