Emgucv3.1快速配置教學
開發環境 2015
Step1.新增WindowsForm專案
Step2.配置emgucv
Tools
-->NuGet Package Manager
-->Manage NuGet Packages for Solution
會自動幫你添加好相關的dll檔案
而且就連以前我們要自己手動去添加emgucv
提供的四個組件都已經幫我們弄好了喔
四個組件依序是
ImageBox、MatrixBox、HistogramBox、PanAndZoomPictureBox
在30秒內我們完成了配置
是不是很方便不用再捨麼系統環境變數一堆拉哩拉紮的東西
好緊接著我們要先來顯示一張靜態圖片
Unit1.靜態圖片的處理
回到WindowsForm 可視化視窗介面布局 地方
引用三個特定命名空間
圖檔開啟
【程式技巧_按下按鈕將圖片A傳遞至圖片B】
介面部分
Step1.改到外面宣告
Step2.Emgucv Clone方法
Unit2.常見的影像處裡
2-1.灰度(單通道)
2-2.BGR三通道分割及合併
寫法1.直觀寫法
private void button2_Click(object sender, EventArgs e)
{
//寫法1.直觀寫法
Image<Bgr, Byte> imgB, imgG, imgR;
imgB = img1.Clone();
imgG = img1.Clone();
imgR = img1.Clone();
for (int i = 0; i < imgB.Cols; i++)
for (int j = 0; j < imgB.Rows; j++)
{
imgB.Data[j, i, 0] = 255; //B
//imgB.Data[j, i, 1] = 0; //G
//imgB.Data[j, i, 2] = 0; //R
}
for (int i = 0; i < imgG.Cols; i++)
for (int j = 0; j < imgG.Rows; j++)
{
//imgG.Data[j, i, 0] = 0; //B
imgG.Data[j, i, 1] = 255;//G
//imgG.Data[j, i, 2] = 0; //R
}
for (int i = 0; i < imgR.Cols; i++)
for (int j = 0; j < imgR.Rows; j++)
{
//imgR.Data[j, i, 0] = 0; //B
//imgR.Data[j, i, 1] = 0; //G
imgR.Data[j, i, 2] = 255; //R
}
pictureBox2.Image = imgB.ToBitmap();
pictureBox3.Image = imgG.ToBitmap();
pictureBox4.Image = imgR.ToBitmap();
}
寫法2.用Emgucv函數
Step1.用CvInvoke.Split Method
通道分割
Split()可以用上面提到Mat陣列,
也可以用Image<Gray, byte> 陣列去接收
Step2.
通道合併
1. 利用img.Split()先丟到channels
2. 將不感興趣的channel設定為零 【感興趣的channel : COI】
3. 宣告一個VectorofMat資料型態, 可以輸入三個Gray level的資料
經過修改
private void button2_Click(object sender, EventArgs e)
{
Image<Bgr, Byte> imgBgr;
imgBgr = img1.Clone();
Image<Gray, byte>[] imageChannels1 = imgBgr.Split();
//imageChannels1[0] Blue,imageChannels1[1] Green,imageChannels1[2] Red
/* remove Green and Red channels, ie. only Blue channel is saved */
int[] zeroCHs1 = new int[2] { 1, 2 };
for (int i = 0; i < 2; i++)
imageChannels1[zeroCHs1[i]].SetZero();
VectorOfMat c1 = new VectorOfMat();
c1.Push(imageChannels1[0]);
c1.Push(imageChannels1[1]);
c1.Push(imageChannels1[2]);
Image<Bgr, Byte> imgB = new Image<Bgr, byte>(imgBgr.Size);
CvInvoke.Merge(c1, imgB);
pictureBox2.Image = imgB.ToBitmap();//B
Image<Gray, byte>[] imageChannels2 = imgBgr.Split();
//imageChannels1[0] Blue,imageChannels1[1] Green,imageChannels1[2] Red
/*remove Blue and Red channels, ie. only Green channel is saved*/
int[] zeroCHs2 = new int[2] { 0, 2 };
for (int i = 0; i < 2; i++)
imageChannels2[zeroCHs2[i]].SetZero();
VectorOfMat c2 = new VectorOfMat();
c2.Push(imageChannels2[0]);
c2.Push(imageChannels2[1]);
c2.Push(imageChannels2[2]);
Image<Bgr, Byte> imgG = new Image<Bgr, byte>(imgBgr.Size);
CvInvoke.Merge(c2, imgG);
pictureBox3.Image = imgG.ToBitmap();//G
Image<Gray, byte>[] imageChannels3 = imgBgr.Split();
//imageChannels1[0] Blue,imageChannels1[1] Green,imageChannels1[2] Red
/*remove Blue and Green channels, ie. only Red channel is saved*/
int[] zeroCHs3 = new int[2] { 0, 1 };
for (int i = 0; i < 2; i++)
imageChannels3[zeroCHs3[i]].SetZero();
VectorOfMat c3 = new VectorOfMat();
c3.Push(imageChannels3[0]);
c3.Push(imageChannels3[1]);
c3.Push(imageChannels3[2]);
Image<Bgr, Byte> imgR = new Image<Bgr, byte>(imgBgr.Size);
CvInvoke.Merge(c3, imgR);
pictureBox4.Image = imgR.ToBitmap();//R
}
2-3.& 2-4. Canny_高斯模糊
private void button4_Click(object sender, EventArgs e) //Smooth
{
Image<Bgr, Byte> imgBgr;
imgBgr = img1.Clone();
/*convolution(捲積)*/
//Image<Bgr, Byte> blur = imgBgr.SmoothBlur(5,5); // 效果不太明顯
//透過一個5*5的kernek矩陣來計算pixel的值以也就是鄰近25個點的平均值
//每個鄰點都需乘上所對應的權重值然後再加總起來!!
//pictureBox6.Image = blur.ToBitmap();
/*高斯模糊*/
Image<Bgr, Byte> gaussian = imgBgr.SmoothGaussian(7);
pictureBox6.Image = gaussian.ToBitmap();
}
private void button5_Click(object sender, EventArgs e)
{
Image<Bgr, Byte> imgBgr;
imgBgr = img1.Clone();
Image<Gray, byte> canny = imgBgr.Canny(120,180);
pictureBox7.Image = canny.ToBitmap();
}
===============================================================================
如何使用emgucv_基礎技巧_L1(CvInvoke偵錯及使用、視窗文字和標題、文字擺放顏色、圖片物件使用)
Step1.先弄好開發環境
環境 (Emgucv2.2.1 + visual studio 2013)
Step2.
先試著載圖
這裡嘗試用看看Emgucv 中的 介面工具組
加入方式如下
工具 --> 選擇工具箱項目
你已經成功把工具載入了
記得左側工具箱移過去(等一下確認一下版本~~ 之前試過太多版啦 快錯亂了)
先拉一個 imagebox 進去 我們的視窗panel吧!!!!
看他的效果
右鍵 可以直接載入圖片 真方便~
出現 錯誤
錯誤修正兩個程序
【第一】. 確認是在 對應的 x64 系統執行下執行
右擊右方 『方案總管』 選擇最底 『屬性』
這邊我們需要改變一下 是去組態-->組態管理員-->改成x64
【第二.】確認是否有載入opencv dll檔
CvInvoke裡面提供了很多影像處理的基本方法
他們全部都是接自openCV的DLL函式庫
【EmguCV官網架構圖 說明】
立即修正 Emgucv.CV.CvInvoke 錯誤
加入\bin\x64下的opencv dll
(2.2.0為例可加入opencv_core220.dll與opencv_imgproc220.dll,其餘的依需求加入)
這裡考慮到日後需要就全添加了
加入後對DLL右鍵->屬性->複製到輸出目錄改成永遠輸出
範例
來看一 個using 搭配Image<Gray , Single>的例子
先有視窗
指定了 視窗的 寬(600) 和 高(200)
創建的圖片當背景了
code_秀綠背景圖視窗
如何在上面加字?? 並指定字型
使用MCvFont Constructor (type, hscale, vscale)
Namespace: Emgu.CV.Structure
public MCvFont(
FONT type,
double hscale,
double vscale
)
type (FONT)
The type of the font
hscale (Double)
The horizontal scale of the font
vscale (Double)
The vertical scale of the fonr
Create a Font of the specific type, horizontal scale and vertical scale
MCvFont 寫法 (還不會被秀出 只是指定字型、高度、寬度)
通常習慣 讓他在 Image<Tcolor , Tdepth>這個類的 物件上 進行 繪製
因為 Image<Tcolor , Tdepth> 這個類別 提供Draw的 method可協助我們進行文字的秀出
這裡我把它寫在 public Form1() {....}這組括號中
在視窗一初始化後 就會進行
不能秀中文字喔!!
環境 (Emgucv2.2.1 + visual studio 2013)
Step2.
先試著載圖
這裡嘗試用看看Emgucv 中的 介面工具組
加入方式如下
工具 --> 選擇工具箱項目
你已經成功把工具載入了
記得左側工具箱移過去(等一下確認一下版本~~ 之前試過太多版啦 快錯亂了)
先拉一個 imagebox 進去 我們的視窗panel吧!!!!
看他的效果
右鍵 可以直接載入圖片 真方便~
出現 錯誤
錯誤修正兩個程序
【第一】. 確認是在 對應的 x64 系統執行下執行
右擊右方 『方案總管』 選擇最底 『屬性』
這邊我們需要改變一下 是去組態-->組態管理員-->改成x64
【第二.】確認是否有載入opencv dll檔
CvInvoke裡面提供了很多影像處理的基本方法
他們全部都是接自openCV的DLL函式庫
【EmguCV官網架構圖 說明】
立即修正 Emgucv.CV.CvInvoke 錯誤
加入\bin\x64下的opencv dll
(2.2.0為例可加入opencv_core220.dll與opencv_imgproc220.dll,其餘的依需求加入)
這裡考慮到日後需要就全添加了
加入後對DLL右鍵->屬性->複製到輸出目錄改成永遠輸出
再次編譯執行之後,他就會把檔案複製到輸出目錄直接從那邊找到參考路徑,
也就不會有例外發生
成功可秀圖
嘗試其他功能
右鍵屬性 還可以看 各通道色彩直方圖
===================================
用程式碼實現
(1)控制視窗大小
(2)控制視窗背景顏色
(3)視窗標題改變
(4)視窗中秀文字
首先 引用 表頭檔三行
先用字串 宣告 並初始化 我們想在視窗 上標中 呈現的文字
例如 : 「冠羽學長的視窗」 ....「xx的視窗」
CvInvoke 這個類提供cvNamedWindow這個method 來幫助開發者幫視窗命名
public static int cvNamedWindow( string name )
學會使用using 陳述式基本的 C# 語法,在實務開發上經常會使用到
使用 using 最主要的目的是為了讓物件建立的同時能確保該物件所佔用的資源
一定會被完整釋放
如果沒有釋放這些無法自動釋放的資源
就很有可能讓 .NET 應用程式發生 資源耗盡 (Resource Exhausted) 的狀況。
一個簡單的using 陳述式 基本架構
using (System.IO.StreamReader sr = new System.IO.StreamReader(@"C:\test.txt"))
{
string s = null;
while((s = sr.ReadLine()) != null)
{
Console.WriteLine(s);
}
}
被一組using 包起來一個block
using 後頭放的子句 是一個建構子
用 using 陳述式的建議條件,
就是物件被建立的語法必須寫在 using 子句中
否則物件很有可能在被釋放後還有其他物件存取的情況
進而引發例外狀況!
大家都知道
C#中字符串常量可以以@開頭聲名,這樣的優點是轉義序列“不”被處理,
按“原樣”輸出,即我們不需要對轉義字符加上\ (反斜槓) ,就可以輕鬆coding。
string filePath = @" c:\Docs\Source\a.txt " // rather than "c:\\Docs\\Source\\a.txt"
轉義序列
在C語言程序中,常常會看到這樣的語句:
printf(“Welcome to C!\n”);
在最後執行的時候我們發現,語句最後的\n並沒有被打印在屏幕上。反斜槓(\)稱為“轉義字符”,指示printf做一些非正常的事。在碰到反斜槓時,printf把反斜槓和下一個字符結合起來構成“轉義序列”,例如(\n)的意思是“新行”,它使光標定位到下一行的開始位置。下面列出了一些常用的轉義序列:
\n 換行。把光標定位到下一行的開始位置
\t 水平制表符。把光標跳到tab鍵的下一個輸出區
\r 回車。把光標定位在當前行(而不是下一行)的開始位置
\a 響鈴。使系統發聲
\\ 反斜槓。打印一個反斜槓字符
\' 雙引號.打印一個雙引號符號
這裡我們以 Emgucv 來做示範
一組 using
using 後頭放的是 要創立的 圖片物件
.Net會自動完成垃圾回收,對於比較大的圖片,
我們可以使用using關鍵字在不需要的時候自動對其進行回收
使用 Image<Bgr , Byte> 來實現
Namespace: Emgu.CV
關於Image類的使用
Image<TColor, TDepth>用兩個參數定義:Color和Depth
TColor类型 | TDepth类型 |
Gray | Byte |
Bgr (Blue Green Red) | SByte |
Bgra (Blue Green Red Alpha) | Single (float) |
Hsv (Hue Saturation Value) | Double |
Hls (Hue Lightness Saturation) | UInt16 |
Lab (CIE L*a*b*) | Int16 |
Luv (CIE L*u*v*) | Int32 (int) |
Xyz (CIE XYZ.Rec 709 with D65 white point) | |
Ycc (YCrCb JPEG) |
範例
// 創建一張灰度圖
Image<Gray, Byte> imgGray = new Image<Gray, Byte>( 480 , 320 );
// 創建一張藍色的圖片
Image<Bgr, Byte> imgBlue = new Image<Bgr , Byte>( 480 , 320 , new Bgr( 255 , 0 , 0 ));
// 從文件創建Image
Image<Bgr, Byte> imgFile = new Image<Bgr, Byte>( " MyImage.jpg " );
// 從Bitmap創建Image
Bitmap bmp = new Bitmap( " MyImage.jpg " );
Image<Bgr, Byte> imgBmp = new Image<Bgr, Byte>(bmp);來看一 個using 搭配Image<Gray , Single>的例子
using (Image<Gray, Single> image = new Image<Gray, Single>(1000, 800))
{
//對image的操作
}
先有視窗
指定了 視窗的 寬(600) 和 高(200)
創建的圖片當背景了
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.CvEnum;
using Emgu.CV.Structure;
namespace Emgucv_ex_hand_gesture_recognition
{
public partial class Form1 : Form
{
//設定視窗標題文字
String winname = "冠羽學長的視窗";
public Form1()
{
InitializeComponent();
//Create a window with the specific name
CvInvoke.cvNamedWindow(winname);
//Create an image of 600*200 with color green
using ( Image<Bgr, Byte> img1 = new Image<Bgr, byte>(600, 200, new Bgr(0, 255, 0)) )
{
CvInvoke.cvShowImage(winname, img1.Ptr);
CvInvoke.cvWaitKey(0);
//Destory the window
CvInvoke.cvDestroyWindow(winname);
}
}
}
}
如何在上面加字?? 並指定字型
使用MCvFont Constructor (type, hscale, vscale)
Namespace: Emgu.CV.Structure
public MCvFont(
FONT type,
double hscale,
double vscale
)
type (FONT)
The type of the font
hscale (Double)
The horizontal scale of the font
vscale (Double)
The vertical scale of the fonr
Create a Font of the specific type, horizontal scale and vertical scale
MCvFont 寫法 (還不會被秀出 只是指定字型、高度、寬度)
MCvFont f = new MCvFont(FONT.CV_FONT_HERSHEY_TRIPLEX, 1.0, 1.0);
通常習慣 讓他在 Image<Tcolor , Tdepth>這個類的 物件上 進行 繪製
因為 Image<Tcolor , Tdepth> 這個類別 提供Draw的 method可協助我們進行文字的秀出
img.Draw("hello world", ref f, new Point(10, 80), new Bgr(0, 0, 0));
這裡我把它寫在 public Form1() {....}這組括號中
在視窗一初始化後 就會進行
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.CvEnum;
using Emgu.CV.Structure;
namespace Emgucv_ex_hand_gesture_recognition
{
public partial class Form1 : Form
{
//設定視窗標題文字
String winname = "冠羽學長的視窗";
public Form1()
{
InitializeComponent();
//Create a window with the specific name
CvInvoke.cvNamedWindow(winname);
//Create an image of 480x180 with color yellow
using (Image<Bgr, Byte> img1 = new Image<Bgr, byte>(480, 200, new Bgr(0, 255, 255)))
{
//Create a font
MCvFont font = new MCvFont(Emgu.CV.CvEnum.FONT.CV_FONT_HERSHEY_COMPLEX, 1.0, 1.0);
//Draw "Hello, world" on the yellow image;Start point is (25, 100) with color blue
img1.Draw("Hello, world", ref font, new Point(25, 100), new Bgr(255, 0, 0));
//Show the image in the window
CvInvoke.cvShowImage(winname, img1.Ptr);
//A key pressing event
CvInvoke.cvWaitKey(0);
//Destory the window
CvInvoke.cvDestroyWindow(winname);
}
}
}
}
不能秀中文字喔!!
===========================================================================================
沒有留言:
張貼留言