這裡給自己準備一張 用 小畫家畫的一張圖
寬、高 設置 200*200
上下按看看可以查詢到 可放一個路徑字串資訊載圖
設置 寬高各為200
右鍵點開做資訊查看符合 剛才的 小畫家 獲得之資訊
Stage1. 一張原影像載入
Canny邊緣偵測 實驗
寫法1. 獲取 255的白色邊緣資訊(其餘黑為0)
查個字典
Find the edges on this image and marked them in the returned image.
參數說明 link
http://www.emgu.com/wiki/files/2.4.10/document/html/9547d8d7-dd5d-ef91-4cee-7d0544a1fe58.htm
一個邊緣(Edge)的定義
可以想像成是一個急速下滑的山谷
如果我們針對一張影像中間為較深黑色(接近0)區塊
旁邊兩側為地勢較高的(較白接近255的)區域
我們從左側至右側就會形成類似山谷的曲線~~~
或是一個水溝(中間凹下去一般)
寫法1. Image<Gray, byte> Canny(double thresh, double threshLinking);
這裡用的參數是來自官方範例給定的
大(高)門檻值用來控制強邊緣的初始分割
如果一個像素的梯度大於上限值,則被認為是邊緣像素
如果小於下限閾值,則被拋棄
如果該點的梯度在兩者之間則當這個點與高於上限值的像素點連接時我們才保留
否則刪除。
第二個參數 threshLinking
小(低)門檻值(thresh)用來控制邊緣連接
通常高低閾值比在2:1 到3:1之間
這裡我用的此張範例不是很好清楚得知參數條動差異
因此改用自己照片
關於 Canny 邊緣偵測器的解釋
Canny Edge Detection
寫法2. 關鍵函數
CvInvoke.cvCanny 設計等於下方架構
public static void cvCanny(
IntPtr image,
IntPtr edges,
double threshold1,
double threshold2,
int apertureSize
)
第一個參數image,Input image
表示輸入圖像,必須為單通道灰度圖
第二個參數edges,Image to store the edges found by the function
表示輸出的邊緣圖像,為單通道黑白圖
第三個參數threshold1,The first threshold
第四個參數threshold2,The second threshold.
第三個參數和第四個參數表示閾值,這二個閾值中當中的小閾值用來控制邊緣連接,大的閾值用來控制強邊緣的初始分割,即如果一個像素的梯度大於上限值,則被認為是邊緣像素,如果小於下限閾值,則被拋棄。如果該點的梯度在兩者之間則當這個點與高於上限值的像素點連接時我們才保留,否則刪除。
第五個參數aperture,Aperture parameter for Sobel operator
表示Sobel算子大小,默認為3即表示一個3*3的矩陣。
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;
namespace emgucv_canny_basic
{
public partial class Form1 : Form
{
#region variable
//Image<Bgr, byte> img = new Image<Bgr, byte>(200, 200);
string imgPath = @"C:\img_res\Myphoto.jpg";
Image<Bgr, byte> img;
#endregion
public Form1()
{
InitializeComponent();
img = new Image<Bgr, byte>(imgPath);
}
private void Form1_Load(object sender, EventArgs e)
{
//寫法1.
//imageBox1.Image = img.Canny(400, 250);
//寫法2.
imageBox1.Image = img;
Image<Gray, byte> grayImg = img.Convert<Gray, byte>(); //灰階
imageBox2.Image = grayImg;
Image<Gray, byte> binaryImg = grayImg.ThresholdToZero(new Gray(200));
imageBox3.Image = binaryImg;
Image<Gray, byte> edgeResult = new Image<Gray, byte>(img.Size);
CvInvoke.cvCanny(binaryImg, edgeResult ,300,100,3);
imageBox4.Image = edgeResult;
}
}
}