今回は、前回の記事で基礎を行いました。
基礎の内容では、垂直方向の検出は出来ましたが、水平方向の検出は出来ませんでした。
そこで、今回は『どこの引数を変更すれば、検出するエッジの方向を変更できるか?』を紹介したいと思います。
エッジの検出方向を指定できれば、前回検出できなかった水平方向も検出できるようになります。
下記は、前回の記事です。前回の記事で作成したサンプルを修正していきます。
【C#】HALCON de 画像処理(エッジ検出) 基礎 | 育児パパの人生備忘録 (t19488sns.com)
使用する関数
エッジ検出に必要な3つの関数です。
■HOperatorSet.GenMeasureRectangle2 (HTuple,HTuple,HTuple,HTuple,HTuple,HTuple,HTuple,HTuple,out HTuple) ⇒ エッジ検出に必要な長方形のエリアを抽出する ■HOperatorSet.MeasurePos (HObject,HTuple,HTuple,HTuple,HTuple,HTuple,out HTuple, out HTuple,out HTuple,out HTuple) ⇒ エッジ検出を実行する。 ■HOperatorSet.CloseMeasure(HTuple) ⇒ エッジ検出を行ったオブジェクトを開放します。
今回、修正を加える関数は、HOperatorSet.GenMeasureRectangle2()になります。
復習がてら、この関数の引数の内容です。
■HOperatorSet.GenMeasureRectangle2()
引数1:長方形の中心座標Y (行/Row)
引数2:長方形の中心座標X (列/Column)
引数3:水平に対する長方形の縦軸の角度 (ラジアン)
引数4:長方形の半分の幅
引数5:長方形の半分の高さ
引数6:処理する画像の幅
引数7:処理する画像の高さ
引数8:使用する補間手法(nearest_neighbor/bicubic/bilinear)
引数9:[出力]測定するオブジェクトのハンドル
今回注目したいのは、引数3の内容です。
前回は[0.0]で実施したのですが、ここの内容を紹介します。
要は、Phiの数値でエッジ検出する方向を決めています!
前回のサンプルだとこんなイメージです。
では、早速前回のサンプルを修正していきます。
サンプルを作っていく
画像は前回と同じものを使います。
操作画面
コンボボックスを追加し、検出方向を指定できるようにしました。
コンボボックスのアイテム(選択肢)として、下記4つを登録しました。
定義
定義は、下記を追加します。
コンボボックスのアイテム(SelectedIndex)に合わせて、列挙体を定義します。
enum eDirection
{
LR, //左⇒右
TB, //上⇒下
RL, //右⇒左
BT, //下⇒上
}
続いて、この列挙体に応じて数値を変更できるように、Dictionary型を定義します。
定義の段階で、初期値も登録します。
readonly Dictionary<eDirection, double> Phi = new Dictionary<eDirection, double> {
{ eDirection.LR, 0.0 },
{ eDirection.TB,-Math.PI/2 },
{ eDirection.RL, Math.PI },
{ eDirection.BT,Math.PI/2 }
};
処理
気になる処理ですが、[赤太字で修正場所/青の太字で追加場所]を紹介します。
private void BtnEdge_Click(object sender, EventArgs e)
{
if (DispOrgImg == null) return; //画像読込されてないなら処理しない
//Zoom方式で表示
HTuple hwnd = hWindowControl1.HalconWindow;
HOperatorSet.ClearWindow(hwnd);
DispZoom(hwnd, DispOrgImg);
//検出エリアの中心座標
double halfW = (double)(nudW.Value / 2);
double halfH = (double)(nudH.Value / 2);
double centerX = (double)nudX.Value + halfW;
double centerY = (double)nudY.Value + halfH;
//検出方向に応じて変更する引数の変数
eDirection select = (eDirection)cmbDirection.SelectedIndex;
double phi = Phi[select];
if (select == eDirection.TB || select == eDirection.BT)
{
(halfW, halfH) = (halfH, halfW);
}
//検出エリアの表示
HOperatorSet.SetDraw(hwnd, "margin");
HOperatorSet.SetColor(hwnd, "yellow");
HOperatorSet.SetLineWidth(hwnd, 1);
HOperatorSet.DispRectangle2(hwnd, centerY, centerX, phi, halfW, halfH);
//画像サイズ取得
HOperatorSet.GetImageSize(DispOrgImg, out HTuple w, out HTuple h);
//測定オブジェクトのハンドルを取得
HOperatorSet.GenMeasureRectangle2(
centerY, centerX, phi, halfW, halfH, w, h, "nearest_neighbor",
out HTuple handle);
//エッジ検出実行
HOperatorSet.MeasurePos(
DispOrgImg, handle, 1.0, 30, "all", "all",
out HTuple row, out HTuple col, out HTuple ampl, out HTuple dist);
//エッジ検出終了
HOperatorSet.CloseMeasure(handle);
//結果表示
dgvResult.Rows.Clear();
int cnt = row.Length;
if (cnt <= 0) return;
dgvResult.Rows.Add(cnt);
for(int indx = 0;indx < cnt;indx++)
{
dgvResult.Rows[indx].Cells[0].Value = col[indx].D.ToString("F2");
dgvResult.Rows[indx].Cells[1].Value = row[indx].D.ToString("F2");
dgvResult.Rows[indx].Cells[2].Value = ampl[indx].D.ToString("F2");
//クロス線を描画
HOperatorSet.SetColor(hwnd, "red");
HOperatorSet.SetLineWidth(hwnd, 3);
HOperatorSet.DispCross(hwnd, row[indx], col[indx], 10, 0.0);
if (indx + 1 < cnt)
{
dgvResult.Rows[indx].Cells[3].Value = dist[indx].D.ToString("F2");
}
}
//描画の設定を戻す
HOperatorSet.SetColor(hwnd, "white");
HOperatorSet.SetLineWidth(hwnd, 1);
}
ココで注意したいのが、HOperatorSet.DispRectangle2()とHOperatorSet.GenMeasureRectangle2()では、回転後の幅と高さを指定しないといけない事です。
その為、追加したコードを見ていただければわかりますが、水平方向の検出の時(90°と270°の時)は、幅と高さを反転させています。
今は便利ですね。変数の入れ替えは、タプルを利用する事が出来るようになっています。
※VisualStudioのバージョンやC#のバージョンによっては出来ません。
(halfW, halfH) = (halfH, halfW)
実行結果
コンボボックスを変更する事で、水平方向や垂直方向を検出する事が出来ました。
また、[左⇒右]と[右⇒左]を比較すると、検出結果の順番が逆になっている事が分かります。
補足
フォームロード処理
ここでは、追加したコンボボックスの初期値を指定します。
そうする事で、選択された状態でソフトを起動させることが出来ます。
private void FrmEdge_Load(object sender, EventArgs e)
{
cmbDirection.SelectedIndex = 0;
}
コントロールの活性制御
コントロール(コンボボックス)を追加したので、それの分を追加します。
private void ControlEnable(bool sw)
{
btnReadImg.Enabled = sw;
btnEdgeInspectArea.Enabled = sw;
grpParam.Enabled = sw;
btnEdge.Enabled = sw;
dgvResult.Enabled = sw;
cmbDirection.Enabled = sw;
}
業務でプログラミング(C#/VB/Python)を作っている。
挫折を何回も繰り返し、幾度の壁を乗り越えてきた。
乗り越えてきた事を忘れないように記録に残す。
同じ思いをしている人への情報提供になれたらと思う。
基本は初心者に向けたプログラムの情報を提供する。
コメント