2016年11月23日 星期三

emgucv_滑鼠畫圖(線段、圓圈圈、移動位置的紀錄)功能_貼圖(去背的兩種方法)

同學好


我們再複習一次   基礎配置然後

這次要教

(1)滑鼠移動然後畫出線段

(2)貼圖




兩個

都跟之前一樣使用   2.4.10版本


















一開始一樣獲得   彩色視訊畫面(不停更新!!)

這次我是採用   emgucv 提供的 UI 組件

imageBox  右鍵  --> 可以 檢查 一些資訊


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.Util;
using Emgu.CV.CvEnum;
using Emgu.CV.Structure;
using Emgu.CV.UI;

namespace emgucv_mouseMove_drawLine
{
    public partial class Form1 : Form
    {
        #region global Var
        Capture cap = null;
        Image<Bgr, byte> frame = new Image<Bgr, byte>(450,300);
        #endregion

        public Form1()
        {
            InitializeComponent();            
        }
        //快點兩下  視窗 介面 就可以自動產生此程式區塊
        private void Form1_Load(object sender, EventArgs e)
        {
            cap = new Capture(0);
            Application.Idle += updateFrame;
        }
        //更新畫面的block
        private void updateFrame(object sender, EventArgs e)
        {
            frame = cap.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.Util;
using Emgu.CV.CvEnum;
using Emgu.CV.Structure;
using Emgu.CV.UI;

namespace emgucv_mouseMove_drawLine
{
    public partial class Form1 : Form
    {
        #region global Var
        Capture cap = null;
        Image<Bgr, byte> frame;
        #endregion

        #region Mouse Var
        Image<Bgr, byte> canvas;//畫布
        #endregion

        public Form1()
        {
            InitializeComponent();            
        }
        
        //快點兩下  視窗 介面 就可以自動產生此程式區塊
        //初始化的區塊
        private void Form1_Load(object sender, EventArgs e)
        {
            cap = new Capture(0);

            canvas = new Image<Bgr, byte>(450, 300, new Bgr(255, 255, 255));
            //先創建一個白色畫布
            imageBox2.Image = canvas;

            Application.Idle += updateFrame;
        }
        //更新畫面的block
        private void updateFrame(object sender, EventArgs e)
        {            
            frame = cap.QueryFrame().Resize(450,300, INTER.CV_INTER_LINEAR);            
            imageBox1.Image = frame;
        }

        
    }
}



進入這次第一個課題


(1)滑鼠移動然後畫出線段




我們平常用小畫家的時候

大家有捨麼發現嗎

一個一個的點串連出一條線 對吧!?!

每個點都需要一個二維空間座標來記錄位置
並存起來一個一個存在白色畫面上就形成一條線了優!!!



我們需要兩個   變數 分別用來記錄  x , y 座標 喔!!!
而且平常畫小畫家的時候

好像都是  滑鼠左鍵按著不放拖拉移動才進行畫線的耶!!!!!!


我們好像還需要紀錄是否處在滑鼠左鍵按下不放狀態的  布林值 耶 !!!!


在C#裏頭  要怎麼寫滑鼠事件呢????





滑鼠畫線第一階段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.Util;
using Emgu.CV.CvEnum;
using Emgu.CV.Structure;
using Emgu.CV.UI;

namespace emgucv_mouseMove_drawLine
{
    public partial class Form1 : Form
    {
        #region global Var
        Capture cap = null;
        Image<Bgr, byte> frame;
        #endregion

        #region Mouse Var
        Image<Bgr, byte> canvas;//畫布
        int mX, mY; // 滑鼠座標位置
        bool mousedown = false; // 滑鼠是否處在按下不放階段
        #endregion

        public Form1()
        {
            InitializeComponent();            
        }
        
        //快點兩下  視窗 介面 就可以自動產生此程式區塊
        //初始化的區塊
        private void Form1_Load(object sender, EventArgs e)
        {
            cap = new Capture(0);

            canvas = new Image<Bgr, byte>(450, 300, new Bgr(255, 255, 255));
            //先創建一個白色畫布
            imageBox2.Image = canvas;

            Application.Idle += updateFrame;
        }

        private void imageBox2_MouseDown(object sender, MouseEventArgs e)
        {
            if(e.Button == MouseButtons.Left)
            {
                mousedown = true;
                mX = e.X;
                mY = e.Y;
            }
        }

        //更新畫面的block
        private void updateFrame(object sender, EventArgs e)
        {            
            frame = cap.QueryFrame().Resize(450,300, INTER.CV_INTER_LINEAR);            
            imageBox1.Image = frame;
        }

        
    }
}



可是光是這樣 還不能畫出半條線

這裡多弄一個用來觀察滑鼠目前移動狀態的  textBox 組件





滑鼠畫線第二階段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.Util;
using Emgu.CV.CvEnum;
using Emgu.CV.Structure;
using Emgu.CV.UI;

namespace emgucv_mouseMove_drawLine
{
    public partial class Form1 : Form
    {
        #region global Var
        Capture cap = null;
        Image<Bgr, byte> frame;
        #endregion

        #region Mouse Var
        Image<Bgr, byte> canvas;//畫布
        int mX, mY; // 滑鼠座標位置
        bool mousedown = false; // 滑鼠是否處在按下不放階段
        #endregion

        public Form1()
        {
            InitializeComponent();            
        }
        
        //快點兩下  視窗 介面 就可以自動產生此程式區塊
        //初始化的區塊
        private void Form1_Load(object sender, EventArgs e)
        {
            cap = new Capture(0);

            canvas = new Image<Bgr, byte>(450, 300, new Bgr(255, 255, 255));
            //先創建一個白色畫布
            imageBox2.Image = canvas;

            Application.Idle += updateFrame;
        }

        private void imageBox2_MouseDown(object sender, MouseEventArgs e)
        {
            if(e.Button == MouseButtons.Left)
            {
                mousedown = true;
                mX = e.X;
                mY = e.Y;

                textBox1.AppendText("mouse position = X:"+mX.ToString()+ ",Y:" + mY.ToString()+"\n");
            }
        }

        //更新畫面的block
        private void updateFrame(object sender, EventArgs e)
        {            
            frame = cap.QueryFrame().Resize(450,300, INTER.CV_INTER_LINEAR);            
            imageBox1.Image = frame;
        }

        
    }
}







滑鼠畫線第三階段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.Util;
using Emgu.CV.CvEnum;
using Emgu.CV.Structure;
using Emgu.CV.UI;

namespace emgucv_mouseMove_drawLine
{
    public partial class Form1 : Form
    {
        #region global Var
        Capture cap = null;
        Image<Bgr, byte> frame;
        #endregion

        #region Mouse Var
        Image<Bgr, byte> canvas;//畫布
        int mX, mY; // 滑鼠座標位置
        int preMx, preMy;// 前一個點的座標紀錄
        bool mousedown = false; // 滑鼠是否處在按下不放階段
        #endregion

        public Form1()
        {
            InitializeComponent();            
        }
        
        //快點兩下  視窗 介面 就可以自動產生此程式區塊
        //初始化的區塊
        private void Form1_Load(object sender, EventArgs e)
        {
            cap = new Capture(0);

            canvas = new Image<Bgr, byte>(450, 300, new Bgr(255, 255, 255));
            //先創建一個白色畫布
            imageBox2.Image = canvas;

            Application.Idle += updateFrame;
        }

        private void imageBox2_MouseDown(object sender, MouseEventArgs e)
        {
            if(e.Button == MouseButtons.Left)
            {
                mousedown = true;
                mX = e.X;
                mY = e.Y;

                textBox1.AppendText("mouse position = X:"+mX.ToString()+ ",Y:" + mY.ToString()+"\n");
            }
        }

        private void imageBox2_MouseUp(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left)
                mousedown = false;
        }

        private void imageBox2_MouseMove(object sender, MouseEventArgs e)
        {
            if (mousedown == true)
            {
                mX = e.X;
                mY = e.Y;
                CvInvoke.cvLine(canvas, new Point(preMx, preMy), new Point(mX, mY), new MCvScalar(0, 255, 255), 2 , LINE_TYPE.CV_AA,0);
                preMx = mX;
                preMy = mY;
                imageBox2.Image = canvas;
            }
        }


        //更新畫面的block
        private void updateFrame(object sender, EventArgs e)
        {            
            frame = cap.QueryFrame().Resize(450,300, INTER.CV_INTER_LINEAR);            
            imageBox1.Image = frame;
        }

        
    }
}






剛剛都是一次點擊  紀錄一個位置

但 其實我們是要他畫線的  要隨著滑鼠移動拖拉作畫


注意 !!!!   兩點構成一條線   至少要兩個點座標 !!!!!



畫線



畫圓圈圈
(半徑 3)


畫圓圈圈
(半徑 6)





(2)貼圖


先試試看在 右側 做 貼圖



上次我是用 教 按鈕載入圖片

這次我們用   指定路徑方法





貼圖第一階段_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.Util;
using Emgu.CV.CvEnum;
using Emgu.CV.Structure;
using Emgu.CV.UI;

namespace emgucv_mouseMove_drawLine
{
    public partial class Form1 : Form
    {
        #region global Var
        Capture cap = null;
        Image<Bgr, byte> frame;
        #endregion

        #region Mouse Var
        Image<Bgr, byte> canvas;//畫布
        int mX, mY; // 滑鼠座標位置
        int preMx, preMy;// 前一個點的座標紀錄
        bool mousedown = false; // 滑鼠是否處在按下不放階段
        #endregion

        #region pasteImage
        Image<Bgr, byte> pasteImg ; // 我們想要貼上去的一個小圖片(png)
        //string imgPath = "C:\\img_res\\Coin.png"; \\前面不加小老鼠寫法
        string imgPath = @"C:\img_res\Coin.png";
        #endregion

        public Form1()
        {
            InitializeComponent();            
        }
        
        //快點兩下  視窗 介面 就可以自動產生此程式區塊
        //初始化的區塊
        private void Form1_Load(object sender, EventArgs e)
        {
            // 攝影機的初始化
            cap = new Capture(0);
            //畫布的初始化
            canvas = new Image<Bgr, byte>(450, 300, new Bgr(255, 255, 255));            
            imageBox2.Image = canvas;
            //貼圖的初始化
            pasteImg = new Image<Bgr, byte>(imgPath);

            Application.Idle += updateFrame;
        }

        private void imageBox2_MouseDown(object sender, MouseEventArgs e)
        {
            if(e.Button == MouseButtons.Left)
            {
                mousedown = true;
                mX = e.X;
                mY = e.Y;

                textBox1.AppendText("mouse position = X:"+mX.ToString()+ ",Y:" + mY.ToString()+"\n");
            }
        }

        private void imageBox2_MouseUp(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left)
                mousedown = false;
        }

        private void imageBox2_MouseMove(object sender, MouseEventArgs e)
        {
            if (mousedown == true)
            {
                mX = e.X;
                mY = e.Y;
                //畫線
                /*CvInvoke.cvLine(canvas, 
                                    new Point(preMx, preMy), 
                                    new Point(mX, mY), 
                                    new MCvScalar(0, 255, 255), 
                                    2 , 
                                    LINE_TYPE.CV_AA,0);*/
                //畫圓  
                CvInvoke.cvCircle(canvas,
                                   new Point(mX, mY),
                                   6,
                                   new MCvScalar(255, 0, 0),
                                   2,
                                   LINE_TYPE.CV_AA, 0);
                preMx = mX;
                preMy = mY;
                imageBox2.Image = canvas;
            }
        }


        //更新畫面的block
        private void updateFrame(object sender, EventArgs e)
        {            
            frame = cap.QueryFrame().Resize(450,300, INTER.CV_INTER_LINEAR);            
            imageBox1.Image = frame;

            //貼圖--> canvas 是指 寬:450/高:300較大的母圖 
            //Step1.設置好要貼上去的位置 (感興趣區域:你想針對局部影像做處裡的範圍)
            canvas.ROI = new Rectangle(0,0,pasteImg.Width,pasteImg.Height);
            pasteImg.CopyTo(canvas);
            canvas.ROI = new Rectangle();
            imageBox2.Image = canvas;
        }

        
    }
}





同學注意 這一個部份

我是把  貼圖寫在  updateFrame那個區塊

所以假如你去對剛剛貼上去的範圍作畫會立刻消逝





影片解釋:





圖貼上了是貼上了但是太大了


我們來縮小一下

剛剛寬 : 245 高:291


縮小寬、高兩倍




然後是針對這張 png圖片的黑色背景處理

是一張png但感覺沒有去被的feel

藉由  imageBox 右鍵  --> 查看 像素資訊





我們把背景轉粉色



判斷 pixel 數值 是 0 的 然後 設置成跟 背景顏色 相同粉色




這樣就是一個簡單去背小技巧了優

去背方法一、 就把 貼圖被景色設置跟母圖背景顏色一樣

在一開始介紹通道分割的時候有教大家怎麼指定不同顏色喔!!!!!

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.Util;
using Emgu.CV.CvEnum;
using Emgu.CV.Structure;
using Emgu.CV.UI;

namespace emgucv_mouseMove_drawLine
{
    public partial class Form1 : Form
    {
        #region global Var
        Capture cap = null;
        Image<Bgr, byte> frame;
        #endregion

        #region Mouse Var
        Image<Bgr, byte> canvas;//畫布
        int mX, mY; // 滑鼠座標位置
        int preMx, preMy;// 前一個點的座標紀錄
        bool mousedown = false; // 滑鼠是否處在按下不放階段
        #endregion

        #region pasteImage
        Image<Bgr, byte> pasteImg ; // 我們想要貼上去的一個小圖片(png)
        //string imgPath = "C:\\img_res\\Coin.png"; \\前面不加小老鼠寫法
        string imgPath = @"C:\img_res\Coin.png";
        Image<Gray, byte> grayImg;
        #endregion

        public Form1()
        {
            InitializeComponent();            
        }
        
        //快點兩下  視窗 介面 就可以自動產生此程式區塊
        //初始化的區塊
        private void Form1_Load(object sender, EventArgs e)
        {
            // 攝影機的初始化
            cap = new Capture(0);
            //畫布的初始化
            canvas = new Image<Bgr, byte>(450, 300, new Bgr(255, 0, 255));            
            imageBox2.Image = canvas;
            //貼圖的初始化
            //可以是指定縮放倍數 或者特定 寬、高數值        
            pasteImg = new Image<Bgr, byte>(imgPath).Resize(0.5, INTER.CV_INTER_LINEAR);
            //grayImg = pasteImg.Convert<Gray, byte>();

            //pasteImg
            //貼上去動作只做一次    (初始化區塊)
            //canvas.ROI = new Rectangle(0, 0, pasteImg.Width, pasteImg.Height);
            //pasteImg.CopyTo(canvas);
            //canvas.ROI = new Rectangle();
            //imageBox2.Image = canvas;
            Application.Idle += updateFrame;
        }

        private void imageBox2_MouseDown(object sender, MouseEventArgs e)
        {
            if(e.Button == MouseButtons.Left)
            {
                mousedown = true;
                mX = e.X;
                mY = e.Y;

                textBox1.AppendText("mouse position = X:"+mX.ToString()+ ",Y:" + mY.ToString()+"\n");
            }
        }

        private void imageBox2_MouseUp(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left)
                mousedown = false;
        }

        private void imageBox2_MouseMove(object sender, MouseEventArgs e)
        {
            if (mousedown == true)
            {
                mX = e.X;
                mY = e.Y;
                //畫線
                /*CvInvoke.cvLine(canvas, 
                                    new Point(preMx, preMy), 
                                    new Point(mX, mY), 
                                    new MCvScalar(0, 255, 255), 
                                    2 , 
                                    LINE_TYPE.CV_AA,0);*/
                //畫圓  
                CvInvoke.cvCircle(canvas,
                                   new Point(mX, mY),
                                   6,
                                   new MCvScalar(255, 0, 0),
                                   2,
                                   LINE_TYPE.CV_AA, 0);
                preMx = mX;
                preMy = mY;
                imageBox2.Image = canvas;
            }
        }


        //更新畫面的block
        private void updateFrame(object sender, EventArgs e)
        {            
            frame = cap.QueryFrame().Resize(450,300, INTER.CV_INTER_LINEAR);            
            imageBox1.Image = frame;

            //貼圖--> canvas 是指 寬:450/高:300較大的母圖 
            //不停貼圖 不停更新
            //Step1.設置好要貼上去的位置 (感興趣區域:你想針對局部影像做處裡的範圍)
            //pasteImg.Resize(0.5,INTER.CV_INTER_LINEAR);
            canvas.ROI = new Rectangle(0,0,pasteImg.Width,pasteImg.Height);
            
            for (int i=0;i<pasteImg.Rows;i++)
                for(int j=0;j<pasteImg.Cols;j++)
                {
                    if(pasteImg.Data[i,j,0] == 0 && 
                        pasteImg.Data[i, j, 1] == 0 && 
                        pasteImg.Data[i, j, 2] == 0)
                    {
                        pasteImg.Data[i, j, 0] = 255;
                        pasteImg.Data[i, j, 1] = 0;
                        pasteImg.Data[i, j, 2] = 255;
                    }
                }
                
            pasteImg.CopyTo(canvas);        

            canvas.ROI = new Rectangle();//這句用來幹嘛的???? --->用來持續更新用
            //更新ROI的初始化
            imageBox2.Image = canvas;
        }        
    }
}




可是我的背景不一定都是純色呀 !!!!

如果是貼在  照片 或是   視訊  那又該如何才好???


這裡介紹一個方法


首先 針對 你要貼上去的小張貼圖

轉灰階

-->二值化它(讓他為黑背景白色前景)







使用

CvInvoke.cvCopy   取代  copyTo




程式碼


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.Util;
using Emgu.CV.CvEnum;
using Emgu.CV.Structure;
using Emgu.CV.UI;

namespace emgucv_mouseMove_drawLine
{
    public partial class Form1 : Form
    {
        #region global Var
        Capture cap = null;
        Image<Bgr, byte> frame;
        #endregion

        #region Mouse Var
        Image<Bgr, byte> canvas;//畫布
        int mX, mY; // 滑鼠座標位置
        int preMx, preMy;// 前一個點的座標紀錄
        bool mousedown = false; // 滑鼠是否處在按下不放階段
        #endregion

        #region pasteImage
        Image<Bgr, byte> pasteImg ; // 我們想要貼上去的一個小圖片(png)        
        //string imgPath = "C:\\img_res\\Coin.png"; \\前面不加小老鼠寫法
        string imgPath = @"C:\img_res\Coin.png";
        Image<Gray, byte> grayImg;        
        #endregion

        public Form1()
        {
            InitializeComponent();            
        }
        
        //快點兩下  視窗 介面 就可以自動產生此程式區塊
        //初始化的區塊
        private void Form1_Load(object sender, EventArgs e)
        {
            // 攝影機的初始化
            cap = new Capture(0);
            //畫布的初始化
            canvas = new Image<Bgr, byte>(450, 300, new Bgr(255, 0, 255));            
            imageBox2.Image = canvas;
            //貼圖的初始化
            //可以是指定縮放倍數 或者特定 寬、高數值        
            //pasteImg = new Image<Bgr, byte>(imgPath).Resize(0.5,INTER.CV_INTER_LINEAR);
            pasteImg = new Image<Bgr, byte>(imgPath);
            CvInvoke.cvNamedWindow("彩圖");
            CvInvoke.cvShowImage("彩圖", pasteImg);
            //grayImg = new Image<Gray, byte>(imgPath).Resize(0.5, INTER.CV_INTER_LINEAR);
            grayImg = new Image<Gray, byte>(imgPath);
            CvInvoke.cvNamedWindow("灰圖");
            CvInvoke.cvShowImage("灰圖", grayImg);

            CvInvoke.cvThreshold(grayImg, grayImg, 0, 255, THRESH.CV_THRESH_BINARY);
            CvInvoke.cvShowImage("二值圖", grayImg);

            //CvInvoke.cvShowImage("二值圖取反", grayImg.Not());
            //mask = 255 - grayImg;
            //CvInvoke.cvShowImage("相減後", mask);



            //pasteImg.CopyTo(pasteTmp);
            //pasteImg = new Image<Bgra, byte>(120, 160, new Bgra(255, 0, 255, 150));

            //grayImg = pasteImg.Convert<Gray, byte>();

            //pasteImg
            //貼上去動作只做一次    (初始化區塊)
            //canvas.ROI = new Rectangle(0, 0, pasteImg.Width, pasteImg.Height);
            //pasteImg.CopyTo(canvas);
            //canvas.ROI = new Rectangle();
            //imageBox2.Image = canvas;
            Application.Idle += updateFrame;
        }

        private void imageBox2_MouseDown(object sender, MouseEventArgs e)
        {
            if(e.Button == MouseButtons.Left)
            {
                mousedown = true;
                mX = e.X;
                mY = e.Y;

                textBox1.AppendText("mouse position = X:"+mX.ToString()+ ",Y:" + mY.ToString()+"\n");
            }
        }

        private void imageBox2_MouseUp(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left)
                mousedown = false;
        }

        private void imageBox2_MouseMove(object sender, MouseEventArgs e)
        {
            if (mousedown == true)
            {
                mX = e.X;
                mY = e.Y;
                //畫線
                /*CvInvoke.cvLine(canvas, 
                                    new Point(preMx, preMy), 
                                    new Point(mX, mY), 
                                    new MCvScalar(0, 255, 255), 
                                    2 , 
                                    LINE_TYPE.CV_AA,0);*/
                //畫圓  
                CvInvoke.cvCircle(canvas,
                                   new Point(mX, mY),
                                   6,
                                   new MCvScalar(255, 0, 0),
                                   2,
                                   LINE_TYPE.CV_AA, 0);
                preMx = mX;
                preMy = mY;
                imageBox2.Image = canvas;
            }
        }


        //更新畫面的block
        private void updateFrame(object sender, EventArgs e)
        {            
            frame = cap.QueryFrame().Resize(450,300, INTER.CV_INTER_LINEAR);            
            imageBox1.Image = frame;

            //貼圖--> canvas 是指 寬:450/高:300較大的母圖 
            //不停貼圖 不停更新
            //Step1.設置好要貼上去的位置 (感興趣區域:你想針對局部影像做處裡的範圍)
            //pasteImg.Resize(0.5,INTER.CV_INTER_LINEAR);
            canvas.ROI = new Rectangle(0,0,pasteImg.Width,pasteImg.Height);           

            CvInvoke.cvCopy(pasteImg , canvas, grayImg);

            canvas.ROI = new Rectangle();//這句用來幹嘛的???? --->用來持續更新用
            //更新ROI的初始化
            imageBox2.Image = canvas;
        }        
    }
}






貼在視訊  乾淨版本的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.Util;
using Emgu.CV.CvEnum;
using Emgu.CV.Structure;
using Emgu.CV.UI;

namespace emgucv_mouseMove_drawLine
{
    public partial class Form1 : Form
    {
        #region global Var
        Capture cap = null;
        Image<Bgr, byte> frame;
        #endregion

        #region Mouse Var
        Image<Bgr, byte> canvas;//畫布
        int mX, mY; // 滑鼠座標位置
        int preMx, preMy;// 前一個點的座標紀錄
        bool mousedown = false; // 滑鼠是否處在按下不放階段
        #endregion

        #region pasteImage
        Image<Bgr, byte> pasteImg ; // 我們想要貼上去的一個小圖片(png)        
        //string imgPath = "C:\\img_res\\Coin.png"; \\前面不加小老鼠寫法
        string imgPath = @"C:\img_res\Coin.png";
        Image<Gray, byte> grayImg;        
        #endregion

        public Form1()
        {
            InitializeComponent();            
        }
        
        //快點兩下  視窗 介面 就可以自動產生此程式區塊
        //初始化的區塊
        private void Form1_Load(object sender, EventArgs e)
        {
            // 攝影機的初始化
            cap = new Capture(0);
            //畫布的初始化
            canvas = new Image<Bgr, byte>(450, 300, new Bgr(255, 0, 255));            
            imageBox2.Image = canvas;
            //貼圖的初始化
            //可以是指定縮放倍數 或者特定 寬、高數值        
            //pasteImg = new Image<Bgr, byte>(imgPath).Resize(0.5,INTER.CV_INTER_LINEAR);

            pasteImg = new Image<Bgr, byte>(imgPath);
            //CvInvoke.cvNamedWindow("彩圖");
            //CvInvoke.cvShowImage("彩圖", pasteImg);
            ////grayImg = new Image<Gray, byte>(imgPath).Resize(0.5, INTER.CV_INTER_LINEAR);
            grayImg = new Image<Gray, byte>(imgPath);
            Application.Idle += updateFrame;
        }

        private void imageBox2_MouseDown(object sender, MouseEventArgs e)
        {
            if(e.Button == MouseButtons.Left)
            {
                mousedown = true;
                mX = e.X;
                mY = e.Y;

                textBox1.AppendText("mouse position = X:"+mX.ToString()+ ",Y:" + mY.ToString()+"\n");
            }
        }

        private void imageBox2_MouseUp(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left)
                mousedown = false;
        }

        private void imageBox2_MouseMove(object sender, MouseEventArgs e)
        {
            if (mousedown == true)
            {
                mX = e.X;
                mY = e.Y;
                //畫線
                /*CvInvoke.cvLine(canvas, 
                                    new Point(preMx, preMy), 
                                    new Point(mX, mY), 
                                    new MCvScalar(0, 255, 255), 
                                    2 , 
                                    LINE_TYPE.CV_AA,0);*/
                //畫圓  
                CvInvoke.cvCircle(canvas,
                                   new Point(mX, mY),
                                   6,
                                   new MCvScalar(255, 0, 0),
                                   2,
                                   LINE_TYPE.CV_AA, 0);
                preMx = mX;
                preMy = mY;
                imageBox2.Image = canvas;
            }
        }


        //更新畫面的block
        private void updateFrame(object sender, EventArgs e)
        {            
            frame = cap.QueryFrame().Resize(450,300, INTER.CV_INTER_LINEAR);            
            imageBox1.Image = frame;

            //貼圖--> canvas 是指 寬:450/高:300較大的母圖 
            //不停貼圖 不停更新
            //Step1.設置好要貼上去的位置 (感興趣區域:你想針對局部影像做處裡的範圍)
            //pasteImg.Resize(0.5,INTER.CV_INTER_LINEAR);

            //canvas.ROI = new Rectangle(0,0,pasteImg.Width,pasteImg.Height);


            frame.ROI = new Rectangle(0, 0, pasteImg.Width, pasteImg.Height);
            //CvInvoke.cvCopy(pasteImg , canvas, grayImg);
            CvInvoke.cvCopy(pasteImg, frame, grayImg);

            canvas.ROI = new Rectangle();//這句用來幹嘛的???? --->用來持續更新用
            //更新ROI的初始化
            imageBox2.Image = canvas;
        }        
    }
}

















沒有留言:

張貼留言