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

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

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

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

Q&A

解決済

1回答

1897閲覧

OpenCVでブロブ検出と面積測定

oikawasouta

総合スコア6

C#

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

1グッド

0クリップ

投稿2023/01/04 11:11

編集2023/01/04 11:13

OpenCVを使用し画像処理を試しています。
二値化や白黒反転、膨張収縮などはできております。

一番最後のプロシージャにあるように、二値化画像の白い部分の面積をラベルに表示するということを行いたいです。

詳細
適当な画像を二値化するとに大小さまざまな白い輪郭が生まれるため、それらの輪郭を認識し1つずつの面積を測定。一番大きいものの面積を
ラベルに表示。

現在ラベルに1つずつの面積を表示することはできていますが、一番大きいものだけを表示することができていないため
どのように変更すれば希望の機能が満たせるでしょうか。ご教示ください。

該当のソースコード

//以下、OpenCvsharpの使用とMatの変換用として追加 using OpenCvSharp; using OpenCvSharp.Extensions; namespace OSS比較_OpenCV { public partial class Form1 : Form { Mat image; public Form1() { InitializeComponent(); } private void Form1_Load(object sender, EventArgs e) { pictureBox1.SizeMode = PictureBoxSizeMode.Zoom; } private void BtnLoad_Click(object sender, EventArgs e) { var ofd = new OpenFileDialog(); //ファイルフィルタ ofd.Filter = "Image File(*.bmp,*.jpg,*.png,*.tif)|*.bmp;*.jpg;*.png;*.tif|Bitmap(*.bmp)|*.bmp|Jpeg(*.jpg)|*.jpg|PNG(*.png)|*.png"; //ダイアログの表示 if (ofd.ShowDialog() == DialogResult.OK) { string path = ofd.FileName; image = Cv2.ImRead(path); pictureBox1.Image = BitmapConverter.ToBitmap(image); } } private void BtnBin_Click(object sender, EventArgs e) { //グレー化 var grayImage =image.CvtColor(ColorConversionCodes.BGR2GRAY); //二値化 var thresholdImege = grayImage.Threshold(128, 255, ThresholdTypes.Binary); pictureBox1.Image = BitmapConverter.ToBitmap(thresholdImege); } private void BtnBin_Auto_Click(object sender, EventArgs e) {   //グレー化 var grayImage = image.CvtColor(ColorConversionCodes.BGR2GRAY); //二値化(Otsu) var thresholdImege = grayImage.Threshold(0, 255, ThresholdTypes.Otsu); pictureBox1.Image = BitmapConverter.ToBitmap(thresholdImege); } private void BtnNega_Click(object sender, EventArgs e) { //グレー化 var grayImage = image.CvtColor(ColorConversionCodes.BGR2GRAY); //二値化 var thresholdImege = grayImage.Threshold(128, 255, ThresholdTypes.Binary); //Nega thresholdImege = 255 - thresholdImege; pictureBox1.Image = BitmapConverter.ToBitmap(thresholdImege); } private void BtnFilter_Click(object sender, EventArgs e) { //グレー化 var grayImage = image.CvtColor(ColorConversionCodes.BGR2GRAY); //二値化 var thresholdImege = grayImage.Threshold(128, 255, ThresholdTypes.Binary); //膨張収縮 var kernel = new Mat(new OpenCvSharp.Size(3, 3), MatType.CV_8UC1); var erodeMat = new Mat(); var dilateMat = new Mat(); //収縮処理 Cv2.Erode(thresholdImege, erodeMat, kernel); //膨張処理 Cv2.Dilate(erodeMat, dilateMat, kernel); pictureBox1.Image = BitmapConverter.ToBitmap(dilateMat); } private void BtnAreaBlob_Click(object sender, EventArgs e) { //グレー化 var grayImage = image.CvtColor(ColorConversionCodes.BGR2GRAY); //二値化 var thresholdImege = grayImage.Threshold(128, 255, ThresholdTypes.Binary); pictureBox1.Image = BitmapConverter.ToBitmap(thresholdImege); //ジャグ配列 OpenCvSharp.Point[][] contours; OpenCvSharp.HierarchyIndex[] hierarchyIndexes; //輪郭抽出 thresholdImege.FindContours(out contours, out hierarchyIndexes, RetrievalModes.External, ContourApproximationModes.ApproxSimple); string areas = null; var count = 1; foreach (var contour in contours) { //面積を算出 var area = Cv2.ContourArea(contour); if (count < contours.Count()) { areas = areas + area + " "; } else { areas = areas + area; } count++; } label5.Text = areas; } } }

補足情報(FW/ツールのバージョンなど)

バージョン
Microsoft Visual Studio Community 2022 Version 17.2.2
Windows フォームアプリをC# Framework 4.7.2で作成しています。

TN8001👍を押しています

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

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

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

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

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

TN8001

2023/01/11 14:40 編集

新しい質問をされていますが、こちらはどうなりましたか? 解決できたのなら「解決済」に、回答がよくわからないならコメントするなりしてください。 [ヘルプ|質問する時のヒント](https://teratail.com/help/question-tips#questionTips4)
oikawasouta

2023/01/11 14:43

大変失礼しました。現在対応中ですので後ほど返信いたします。
guest

回答1

0

ベストアンサー

OpenCVを使用し画像処理を試しています。
二値化や白黒反転、膨張収縮などはできております。

参考コードがあるときは質問に明示してください。
C#【OpenCvSharp】オブジェクトの輪郭を抽出し、面積を求める方法! | あおブログ

本人が書いた部分とそれ以外の部分がわからないと、レベル感がわからないです(何がわからないのかがわからない)
間違っていてもいいので、やってみたこともあるとなおいいです。


現在ラベルに1つずつの面積を表示することはできていますが、一番大きいものだけを表示することができていないためどのように変更すれば希望の機能が満たせるでしょうか。

現在は空白区切りですべての面積が出るわけですが、一番大きいものをひとつだけ表示したいということですね。
よくあるのはそれまでの最大値を覚えておいて、都度比較するような方法です。

cs

1double max = 0; // 暫定の最大値 2foreach (var contour in contours) 3{ 4 double area = Cv2.ContourArea(contour); 5 if (max < area) // もしこれまでの最大値より大きかったら... 6 { 7 max = area; // 最大値を更新 8 } 9} 10label5.Text = max.ToString();

1行でシンプルに書くこともできます。

cs

1label5.Text = contours.Max(x => Cv2.ContourArea(x)).ToString(); 2//double max = contours.Max(x => Cv2.ContourArea(x)); 3//label5.Text = max.ToString();

c# linq max - Google 検索

投稿2023/01/05 09:10

TN8001

総合スコア9862

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

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

oikawasouta

2023/02/15 13:58

TN8001様 回答ありがとうございます。参考にさせていただき、無事解決することができました。ありがとうございます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問