ビデオはテンプレート マッチングを提案していますが、これは速度が速いため、FFT (高速フーリエ変換) メソッドである可能性が高いと予想されます。これは EMGU で実装するのはかなり簡単ですが、完璧にするのは難しいです。
テンプレートマッチング
最初に、テンプレート マッチング メソッドを作成しました。フィードした画像内のオブジェクトに一致するメソッドを作成しました。FFT は、スペクトルを分割して結果の行列を追加する必要がある色の単一スペクトル画像でのみ機能します。
Point Location;
private bool Detect_object(Image<Gray, Byte> Area_Image, Image<Gray, Byte> image_object)
{
bool success = false;
//Work out padding array size
Point dftSize = new Point(Area_Image.Width + (image_object.Width * 2), Area_Image.Height + (image_object.Height * 2));
//Pad the Array with zeros
using (Image<Gray, Byte> pad_array = new Image<Gray, Byte>(dftSize.X, dftSize.Y))
{
//copy centre
pad_array.ROI = new Rectangle(image_object.Width, image_object.Height, Area_Image.Width, Area_Image.Height);
CvInvoke.cvCopy(Area_Image, pad_array, IntPtr.Zero);
pad_array.ROI = (new Rectangle(0, 0, dftSize.X, dftSize.Y));
//Match Template
using (Image<Gray, float> result_Matrix = pad_array.MatchTemplate(image_object, TM_TYPE.CV_TM_CCOEFF_NORMED))
{
Point[] MAX_Loc, Min_Loc;
double[] min, max;
//Limit ROI to look for Match
result_Matrix.ROI = new Rectangle(image_object.Width, image_object.Height, Area_Image.Width - image_object.Width, Area_Image.Height - image_object.Height);
result_Matrix.MinMax(out min, out max, out Min_Loc, out MAX_Loc);
Location = new Point((MAX_Loc[0].X), (MAX_Loc[0].Y));
success = true;
Results =result_Matrix.Convert<Gray,Double>();
}
}
return success;
}
ほとんどの人が忘れていることは、ゼロを使用するテンプレートのサイズに似たゼロで配列をパディングすることです。これは fft メソッドには影響しないためです。マトリックスをパディングしないと、エッジの周りのデータが適切に処理されず、一致するアイテムを見逃す可能性があります。
2 番目のポイントと、これがどれほど重要かを強調することはできません。現時点では、FFT メソッドはオブジェクトの左上隅に一致するものを返すということです。result_Matrix.MinMax は、オブジェクトが一致する可能性が最も高い場所を見つけます。実験しなければならないことがたくさんあるので、それ以上の問題があれば、ここまたは EMGU に質問してください。できる限りお手伝いします。このソリューションもコピーして貼り付けます。
ビデオの方法
時間に追われているので、ほとんどのコードはあなたに任せますが、実際には、ユーザーはペイントボックスのクリック イベントを使用して、画像内のオブジェクトのセット eX および eY 位置を見つけます。テンプレートは固定サイズなので 100x100
Image<Gray, Byte> template_img = Main_Image.Copy(new Rectangle(x, y, 100, 100);
次に、オブジェクトの周囲の元の画像に ROI を設定します。これは動きを説明します。この例では、テンプレートの周囲に 50 ピクセルのバッファー (ROI) が必要だとします。これは、次の初期 ROI に相当します。
Main_Image.ROI = new Rectangle(x - 50, y - 50, 200, 200);
画像の ROI を操作しているため、処理が遅くなるだけでなく、元の画像の表示が台無しになる可能性があるため、次のようなことを行う方がはるかに優れています。
using( Image<Gray, Byte> img_ROI = Main_Image.Copy(new Rectangle(x - 50, y - 50, 200, 200))
{
Detect_object(img_ROI, template_img)
}
using ステートメントを使用すると、終了時に余分な画像データが破棄され、リソースが解放されます。
トリックとして、ROI は Detect_object からの結果によって実際に制御されます。これが、Location をグローバル変数として保持する理由です。Location がテンプレートと正常に一致すると、using ステートメントは次のようになります。
using( Image<Gray, Byte> img_ROI = Main_Image.Copy(new Rectangle(Location.X - 50, Location.Y - 50, 200, 200))
{
...
}
ROI とテンプレートの四角形以外はこれでほぼ完了です。問題がある場合は画像にサイズと位置が描画されますが、コードはすぐに公開されるはずです。
乾杯、
クリス