円を検出する

円を検出するメソッドは HoughCirclesになります。

CvSeq HoughCircles(CvArr image,CvMemStorage circle_storage,
HoughCirclesMethod method,double dp,double min_dist,double param1,double param2,
int min_radius,int max_radius)

CvArr image : 8ビット,シングルチャンネル,グレースケールの入力画像。
直線の検出は 2値化画像を入力にしますが 円の検出は グレースケール画像を入力にし 内部で2値化(Canny)を行います。
CvMemStorage circle_storage : 作業用領域
HoughCirclesMethod method : 2値化手法 現在のところ, Gradient メソッドのみが実装されています。 
double dp : 画像分解能に対する投票分解能の比率の逆数。
 例えば, dp=1 の場合は,投票空間は入力画像と同じ分解能をもち 処理は重くなります。
 また dp=2 の場合は,投票空間の幅と高さは半分になります。
double min_dist: 検出される円の中心同士の最小距離。
 このパラメータが小さすぎると,正しい円の周辺に別の円が複数誤って検出されることになります。
 逆に大きすぎると,検出できない円がでてくる可能性があります。
double param1 : 2値化手法ごとに指定するパラメータの 1 番目。
Canny() エッジ検出に渡される2つの閾値の内,大きい方の閾値を表します。(小さい閾値は,この値の半分になります)。
double param2 : 2値化手法ごとに指定するパラメータの 2 番目。
円の中心を検出する際の投票数の閾値を表します。
これが小さくなるほど,より多くの誤検出が起こる可能性があります。より多くの投票を獲得した円が,最初に出力されます。
int minRadius : 円の半径の最小値。
int maxRadius : 円の半径の最大値。

 コーディング 

Android版と同じデータ 同じ引数で実験しました。

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 Boolean flg = false;
        public Form1()
        {
            InitializeComponent();
        }
        //初期処理(画像データ読み込み・表示)
        private void timer1_Tick(object sender, EventArgs e)
        {
            timer1.Enabled = false;
            src = new IplImage(@"C:\OpenCvTest\Data\a640_480.jpg", LoadMode.Color);
            flg = true;
            pictureBox1.Invalidate();
        }
        private void btnHough_Click(object sender, EventArgs e)
        {
            CvMemStorage storage = new CvMemStorage();
            IplImage gray = new IplImage(src.Size, BitDepth.U8, 1);
            Cv.CvtColor(src, gray, ColorConversion.BgrToGray);
            CvSeq circl = Cv.HoughCircles(gray, storage, HoughCirclesMethod.Gradient, 2, 10, 160, 50, 10, 20);
            foreach (CvCircleSegment crcl in circl)
            {
                src.Circle(crcl.Center, (int)crcl.Radius, CvColor.Red, 2);
            }
            circl.Dispose();
            storage.Dispose();
            pictureBox1.Invalidate();
        }
        //描画処理
        private void pictureBox1_Paint(object sender, PaintEventArgs e)
        {
            if (flg)
            {
                Bitmap bmp = new Bitmap(src.Width, src.Height);
                bmp = src.ToBitmap();
                e.Graphics.DrawImage(bmp, 0, 0, bmp.Width, bmp.Height);
                bmp.Dispose();
            }
        }
    }
}
 処理結果 

元画像

円検出結果
Android版の結果と比較すると 同じ引数を使いましたが 誤検出がひとつ減っています。

 Windows7 Vs2008 OpenCv2.4 And OpenCvSharp
スポンサーリンク
Rectangle大広告
Rectangle大広告

シェアする

  • このエントリーをはてなブックマークに追加

フォローする

コメント

  1. MK より:

    OpenCvSharp.CvSeqでのエラー
    「OpenCv Sharp 実験記」は、OpenCvSharpでのプログラム開発において、非常に助かっております。
    その中の「円を検出する」についてなのですが、参考プログラムをビルドすると、
    「foreach ステートメントは、’OpenCvSharp.CvSeq’ が ‘GetEnumerator’ のパブリック定義を含んでいないため、型 ‘OpenCvSharp.CvSeq’ の変数に対して使用できません。」
    というエラーメッセージが出てしまいます。
    これは解決する方法をお教えいただけませんでしょうか?
    開発環境は
    Windous7+VisualStudio2008+OpenCV231
    です。
    宜しくお願いいたします。

  2. のぼった より:

    OpenCvSharp.CvSeqでのエラー
    試行錯誤しながら進めた 拙い実験記を参考にしていただき お恥ずかしい限りです。

    実験を行った際に 参考にしたページは https://opencvsharp.googlecode.com/svn-history/r33773/trunk/2.2/OpenCvSharp.Test/Samples/HoughCircles.cs
    です。ここでは Cv.HoughCirclesの戻り値を型指定付きのリストで受けているようです。
    完全に自分と同じ環境で ビルドエラーになったとのこと、確実な回答か否かは自信がありませんが、この方法を試されたらいかがでしょうか。

  3. 吉村 より:

    pictureBox内のみに表示
    初心者です。
    Cv.AdaptiveThreshold(img, binaryAdaptive, 255, AdaptiveThresholdType.GaussianC, ThresholdType.Binary, 9, 12);
    CvWindow.ShowImages(img, binaryAdaptive);
    で二値化された画像は表示されるのですが、
    form1内の
    pictureBoxIpl5.ImageIpl=img; には二値化された画像が表示できません。
    どのようにすればpictureBox内のみに表示できますでしょうか。
    よろしくご教示願います。