『エッジ画像』つまり 画像内の輪郭を求めるには OpenCvSharpにはSobel・Laplace・Cannyの3つのメソッドがあります。入力画像はカラー画像でも問題ありませんが 説明を簡単にするためグレースケールを入力画像とします。
- Sobel 一次微分(差分)を用いてエッジ検出を行います。
一次微分のため 黒⇒白 の変化を検出します。白⇒黒の 変化は検出されません。
メソッドの呼び出し形式
Cv.Sobel(CvArr src,CvArr dst,int xorder, int yorder, ApertureSize aperture_size)
CvArr src:入力画像 カラー画像可
CvArr dst:出力画像 サイズ・ビット深度・チャネル数は入力画像と同じにします。
int xorder,int yorder:X方向、Y方向の微分次数 0にするとその方向の変化は検出されません。
ApertureSize aperture_size:拡張 Sobel カーネルのサイズ。
列挙型定数 ApertureSizeで1・3・5・7および-1(Scharr)から選択します。
ドキュメントによると一般に(xorder, yorder, aperture_size)の組み合わせは (1,0,3)または(0,1,3)で呼ばれることが多いとあります。ここでもこの組み合わせと aperture_sizeに特殊な値Scharrを指定した場合を試します。 - Laplace 二次微分(差分)を用いてエッジ検出を行います。
二次微分のため 黒⇒白・白⇒黒 双方の変化が検出されます。
メソッドの呼び出し形式
Cv.Laplace(CvArr src,CvArr dst, ApertureSize aperture_size)
CvArr src:入力画像 カラー画像可
CvArr dst:出力画像 サイズ・ビット深度・チャネル数は入力画像と同じにします。
ApertureSize aperture_size:2次微分フィルタを求めるために利用される領域のサイズ。
これは正の奇数でなければいけません。列挙型定数 ApertureSizeから1・3・5・7を選択します。 - Canny ドキュメントによれば 上記2つのメソッドが出力画像は 勾配画像となるのに対し Cannyメソッドの出力画像はエッジであるか無いかの2値画像になると 書いてあります。
メソッドの呼び出し形式
Cv.Canny(CvArr src,CvArr dst, double threashold1,double threashold2,ApertureSize aperture_size)
CvArr src:入力画像 カラー画像可
CvArr dst:出力画像 サイズ・ビット深度は入力画像と同じ チャネル数は必ず1にしてください。
double threashold1,double threashold2:閾値1・2
小さい方の値がエッジの接続に利用され、
大きい方の値が明確なエッジの初期セグメントを検出するのに利用されます。
詳しくは ここを参照してください。
ApertureSize aperture_size: sobel演算用の領域のサイズ。
列挙型定数 ApertureSizeから3・5・7を選択します。(デフォルト3)
実験は 以前使用した 詰碁の本を自分で撮影した画像を透視変換した画像をテストデータとし、以下の6個のボタンを準備して行いました。
- Sobel (xorder, yorder, aperture_size)= (1,0,3)
- Sobel (xorder, yorder, aperture_size)= (0,1,3)
- Sobel (xorder, yorder, aperture_size)= (1,0,Scharr)
- Sobel (xorder, yorder, aperture_size)= (0,1,Scharr)
- Laplace aperture_size=3
- Canny aperture_size=3
コーディング |
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Text; using System.Windows.Forms; using OpenCvSharp; namespace OpenCvShp { public partial class Form1 : Form { private IplImage src; private IplImage dst; private Boolean flg = false; public Form1() { InitializeComponent(); } //初期処理(画像データ読み込み・表示) private void timer1_Tick(object sender, EventArgs e) { timer1.Enabled = false; src = new IplImage(@"C:\OpenCvTest\Data\goban320_240.jpg", LoadMode.GrayScale); // 透視変換 中略 flg = true; dst = src.Clone(); pictureBox1.Invalidate(); } private void btnSobel013_Click(object sender, EventArgs e) { Cv.Sobel(src, dst, 0, 1, ApertureSize.Size3); pictureBox1.Invalidate(); } private void btnSobel103_Click(object sender, EventArgs e) { Cv.Sobel(src, dst, 1, 0, ApertureSize.Size3); pictureBox1.Invalidate(); } private void btnSobel01Scharr_Click(object sender, EventArgs e) { Cv.Sobel(src, dst, 0, 1, ApertureSize.Scharr); pictureBox1.Invalidate(); } private void btnSobel10Scharr_Click(object sender, EventArgs e) { Cv.Sobel(src, dst, 1, 0, ApertureSize.Scharr); pictureBox1.Invalidate(); } private void btnLaplace_Click(object sender, EventArgs e) { Cv.Laplace(src, dst, ApertureSize.Size3); pictureBox1.Invalidate(); } private void btnCanny_Click(object sender, EventArgs e) { Cv.Canny(src, dst, 100, 200, ApertureSize.Size3); pictureBox1.Invalidate(); } //描画処理 private void pictureBox1_Paint(object sender, PaintEventArgs e) { if (flg) { Bitmap bmp = new Bitmap(dst.Width, dst.Height); bmp = dst.ToBitmap(); e.Graphics.DrawImage(bmp, 0, 0, bmp.Width, bmp.Height); bmp.Dispose(); } } } }
処理結果 |
元画像
Sobel (xorder, yorder, aperture_size)= (1,0,3)
X方向のみ反応していることが わかります。
Sobel (xorder, yorder, aperture_size)= (0,1,3)
Y方向のみ反応していることがわかります。
aperture_sizeをScharrにするとざわざわ感が増してくる感じがします。
Sobel (xorder, yorder, aperture_size)= (1,0,Scharr)
Sobel (xorder, yorder, aperture_size)= (0,1,Scharr)
Laplace aperture_size=3
縦横きれいに拾っていますが白石・黒石の区別がつきません。
Canny aperture_size=3
なぜか 罫線・白石は2重線になっています感度が高いのかも
Windows7 Vs2008 OpenCv2.4 And OpenCvSharp |