2016年12月15日 星期四

emgucv_Canny邊緣偵測介紹

首先我們準備好程式工作環境











這裡給自己準備一張  用  小畫家畫的一張圖

寬、高 設置 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);


這裡用的參數是來自官方範例給定的

第一個參數  thresh
大(高)門檻值用來控制強邊緣的初始分割
The threshhold to find initial segments of strong edges

如果一個像素的梯度大於上限值,則被認為是邊緣像素

如果小於下限閾值,則被拋棄

如果該點的梯度在兩者之間則當這個點與高於上限值的像素點連接時我們才保留
否則刪除。




第二個參數  threshLinking
小(低)門檻值(thresh)用來控制邊緣連接
The threshold used for edge Linking



通常高低閾值比在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;
        }
    }
}












沒有留言:

張貼留言