2016年11月29日 星期二

學習如何從emgucv的官方範例去學習滑鼠追蹤控制的程式_part2_學習去分析範例程式寫註解_查字典_問題排除

同學你可以嘗試把程式碼再寫一次

這是官方提供的學習用範例
因為剛剛已經做過執行  而且可成功!!!

很長一大串

如果是我   我會先把這串程式縮短

一個一個加進去   看效果跟執行的狀況不同與演進

原本好大一串程式碼

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 所以可以右鍵 --> 直方圖看差異





色階平等化前
 色階平等化後


有關於色階分布圖的補充
https://helpx.adobe.com/tw/photoshop/using/viewing-histograms-pixel-values.html



(2).學會下中斷點查看細部數值資訊








(3).學會問題排除_看錯誤資訊







(4).學會邊寫邊問自己問題(註解+改寫程式)



喔  因為它是針對  原Color視訊畫的












所以你會發現


我和Lena 的臉 偵測框不會同時出現




針對畫在中央十字架上的分析













最後是  滑鼠座標部分





一個用來獲取滑鼠位置

一個是設置位置(更新位置)


針對在該範圍區塊進行寬、高的移動量設置



沒有留言:

張貼留言