質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

OpenCV

OpenCV(オープンソースコンピュータービジョン)は、1999年にインテルが開発・公開したオープンソースのコンピュータビジョン向けのクロスプラットフォームライブラリです。

Q&A

解決済

1回答

2758閲覧

OpenCvでハフ変換による直線抽出がうまくいかない

yrema

総合スコア286

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

OpenCV

OpenCV(オープンソースコンピュータービジョン)は、1999年にインテルが開発・公開したオープンソースのコンピュータビジョン向けのクロスプラットフォームライブラリです。

0グッド

0クリップ

投稿2019/03/19 06:47

タイトルの通りですが、
下記カレンダー画像の枠線をハフ変換による抽出をしたいです。

▼元画像
イメージ説明
▼ハフ変換による直線抽出した画像
イメージ説明

▼コード 

c#

1 private void Form1_Load(object sender, EventArgs e) 2 { 3 cvTest(); 4 } 5 6 private void cvTest() 7 { 8 string fileName = INPUT_DIR + "calendar.png"; 9 Mat mat = new Mat(fileName); 10 // 切り出し 11 Mat dst = cutOut(mat); 12 } 13 14 private Mat cutOut(Mat src) 15 { 16 Mat dst = new Mat(); 17 18 // グレースケール 19 Cv2.CvtColor(src, dst, ColorConversionCodes.BGRA2GRAY); 20 Cv2.ImWrite(OUTPUT_DIR + "grayScale_" + getNowString() + ".png", dst); 21 22 // コントラストを上げる 23 changeContrust(dst, dst, 50f); // 0~100 24 Cv2.ImWrite(OUTPUT_DIR + "contrustUP_" + getNowString() + ".png", dst); 25 26 // 二値化 27 Cv2.Threshold(dst, dst, 30, 255, ThresholdTypes.Binary); 28 Cv2.ImWrite(OUTPUT_DIR + "binary_" + getNowString() + ".png", dst); 29 30 // エッジ検出 31 Cv2.Canny(dst, dst, 50, 200); // TODO パラメータ調査 32 Cv2.ImWrite(OUTPUT_DIR + "canny_" + getNowString() + ".png", dst); 33 34 // 標準ハフ変換 35 double paramRho = 10d; 36 double paramTheta = Math.PI / 180 * 10; 37 int threshold = 0; 38 Mat dstHoughLines = src.Clone(); 39 LineSegmentPolar[] lines = Cv2.HoughLines(dst, paramRho, paramTheta, threshold); 40 Debug.WriteLine("lines.Count:" + lines.Count().ToString()); 41 foreach (LineSegmentPolar lsp in lines) { 42 float rho = lsp.Rho; 43 float theta = lsp.Theta; 44 double a = Math.Cos(theta); 45 double b = Math.Sin(theta); 46 double x0 = a * rho; 47 double y0 = b * rho; 48 int x1 = (int)Math.Round(x0 + 1000 * (-b)); 49 int y1 = (int)Math.Round(y0 + 1000 * (a)); 50 int x2 = (int)Math.Round(x0 - 1000 * (-b)); 51 int y2 = (int)Math.Round(y0 - 1000 * (a)); 52 OpenCvSharp.Point pt1 = new OpenCvSharp.Point(x1, y1); 53 OpenCvSharp.Point pt2 = new OpenCvSharp.Point(x2, y2); 54 Cv2.Line(dstHoughLines, pt1, pt2, new Scalar(255, 0, 0), 1, LineTypes.AntiAlias); 55 } 56 Cv2.ImWrite(OUTPUT_DIR + "houghlines_" + getNowString() + ".png", dstHoughLines); 57 58 //using (new Window("dst image", dst)) 59 //{ 60 // Cv2.WaitKey(); 61 //} 62 return dst; 63 } 64 65 /// <summary> 66 /// コントラスト変更 67 /// </summary> 68 /// <param name="src"></param> 69 /// <param name="dst"></param> 70 /// <param name="contrust"></param> 71 void changeContrust(Mat src, Mat dst, float contrust) 72 { 73 byte[] lut = new byte[256]; 74 for (int i = 0; i < lut.Length; i++) 75 { 76 lut[i] = (byte)(255 / (1.0f + Math.Exp(-contrust * (i - 128) / 255))); 77 } 78 Cv2.LUT(src, lut, dst); 79 } 80 81 /// <summary> 82 /// 現在日時文字列を返す 83 /// </summary> 84 /// <returns></returns> 85 private string getNowString() 86 { 87 DateTime dt = System.DateTime.Now; 88 string ret = dt.ToString("yyyyMMdd_HHmmss"); 89 return ret; 90 }

◆環境
OpenCv 4.0.0
VisualStudio2017

paramRhoやparamThetaを色々変えましたが、
イメージ説明
イメージ説明
といった具合に枠線を抽出するにはほど遠いようです。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

yrema

2019/03/19 07:29

同じパラメータでうまくいきました。ありがとうございます。 さらに質問で申し訳ないですが、このようにパラメーターを調整して人間が目で見てOKと判断するまで調整を続けないといけないのなら、自動認識という意味からほど遠くなってしまいます。何か良い方法ないでしょうか。
tiitoi

2019/03/19 07:40

回答にも書きましたが、質問者さんが想定される「自動認識」の程度を追記してください
guest

回答1

0

ベストアンサー

このようにパラメーターを調整して人間が目で見てOKと判断するまで調整を続けないといけないのなら、自動認識という意味からほど遠くなってしまいます。何か良い方法ないでしょうか。

ハフ変換のような画像処理を利用するケースというのは、撮影環境などが固定化されていて、撮影対象が同じものを検出するというケースです。

例えば、工場のラインに画像処理システムを導入するといった場合、検出対象は変わりませんし、照明などで明るさも固定して、検出するたびに同じ条件の画像が取得できます。

自動認識というのが、どの程度の自動化を指しているのかわかりませんが、どんないかなる状況でも検出できる仕組みというのは難しいと思います。
ある程度、仮定なり条件なりが必要です。

具体的なユースケースをお持ちの場合は質問に追記してくだささい。

投稿2019/03/19 07:39

tiitoi

総合スコア21956

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

yrema

2019/03/19 07:56 編集

>例えば、工場のラインに画像処理システムを導入するといった場合、検出対象は変わりませんし、照明などで明るさも固定して、検出するたびに同じ条件の画像が取得できます。 なるほど、確かにおっしゃる通りですね。想定しているのは「機械の設計図のようなものから特定の枠に囲まれた部分の抽出」で、その設計図のようなもののパターンは決まっておらず未知数です。(具体的な画像を上げられなくてすみません) 結局あきらめるしかないんですかね・・・。
tiitoi

2019/03/19 08:04

白い紙に黒い線が引かれているのであれば、輪郭抽出 (OpenCV の findContours())等でいける気もします。画像がないのでこれ以上の具体的なアドバイスはできないですが、、
pepperleaf

2019/03/19 11:07

上記のサンプルならば、色でフィルタすれば、良い気もしますが、、、 外形だけならば、方法はありそうな気がします。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問