C#/VB.NETで画像処理⑨<画像のラベリング処理>
こんにちは、SKです。
C#/VB.NETで画像処理シリーズの第9弾。
カメラ画像のラベリング処理を実装します。
ラベリングとは、二値化画像の白領域の連結領域を抽出する処理のことです。前回の輪郭抽出処理と似ていますが、ラベリングは各領域の面積が簡単に取り出せたり、使い勝手が良い関数です。
OpenCVSharpの作者さんも好きだと公言しているのがこのラベリング。下記の記事は本当に参考になります。
★OpenCVSharpのラベリングについて
OpenCVSharpとは?
(前回)画像の輪郭抽出
動画手順
①ラベリングボタンを配置する
フォーム上にボタンを配置します。
このボタンの押下イベントで、ラベリングフラグのTrue/Falseを切り替えます。フラグがTrueの時に、Process関数内で画像の二値化→ラベリング処理を行い、各ラベリング領域に矩形を描画してPictureBoxに表示します。
表示テキストは"Labeling"。
ラベリングフラグのbool変数isLabelingを追加します。
②画像を二値化する
まずは前回同様、画像を二値化し、Mat変数grayに格納します。
Usingで定義することを忘れずに。
(参考)Usingについて
C# Tips −usingを使え、使えったら使え(^^)−
③ラベリング処理
ラベリングには、OpenCVSharpのConnectedComponentsEx関数を使用します。これは、OpenCVのConnectedComponents関数をより使いやすくShimat先生が改良した独自の関数です。
ConnectedComponentsEx関数
OpenCvSharpをつかう その24 (OpenCV 3.0のラベリング) - schima.hatenablog.com
引数には二値化画像を渡すのみ。そして戻り値のラベリングデータBlobsをForループで回し1つずつアクセスできます。超簡単!
Cv2.Rectangle関数で各領域の矩形を描画します。
private void Process(Mat img) { if (isLabeling) { using (Mat gray = new Mat(img.Size(), MatType.CV_8UC1)) { Cv2.CvtColor(img, gray, ColorConversionCodes.BGR2GRAY); Cv2.Threshold(gray, gray, 0, 255, ThresholdTypes.Otsu); ConnectedComponents cc = Cv2.ConnectedComponentsEx(gray); foreach (var blob in cc.Blobs.Skip(1)) { img.Rectangle(blob.Rect, Scalar.Lime, 2); } } } }
実行します。
起動時
Contours押下時
最後に、コード全文を載せておきます。
C#
using System; using System.Linq; using System.Threading.Tasks; using System.Windows.Forms; using OpenCvSharp; using OpenCvSharp.Extensions; namespace WindowsFormsApp1 { public partial class Form1 : Form { public Form1() { InitializeComponent(); } private void Form1_Load(object sender, EventArgs e) { Task.Run(() => { using (VideoCapture v = new VideoCapture(0)) using (Mat img = new Mat()) { while (true) { v.Read(img); Process(img); pictureBox1.Image = BitmapConverter.ToBitmap(img); } } }); } private bool isLabeling = false; private void Process(Mat img) { if (isLabeling) { using (Mat gray = new Mat(img.Size(), MatType.CV_8UC1)) { Cv2.CvtColor(img, gray, ColorConversionCodes.BGR2GRAY); Cv2.Threshold(gray, gray, 0, 255, ThresholdTypes.Otsu); ConnectedComponents cc = Cv2.ConnectedComponentsEx(gray); foreach (var blob in cc.Blobs.Skip(1)) { img.Rectangle(blob.Rect, Scalar.Lime, 2); } } } } private void button1_Click(object sender, EventArgs e) { isLabeling = !isLabeling; } } }
Imports OpenCvSharp Imports OpenCvSharp.Extensions Public Class Form1 Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load Task.Run(Sub() Using v As New VideoCapture(0) Using img As New Mat Do v.Read(img) Process(img) PictureBox1.Image = img.ToBitmap Loop End Using End Using End Sub) End Sub Private isLabeling As Boolean = False Private Sub Process(ByVal img As Mat) If isLabeling Then Using gray As New Mat(img.Size, MatType.CV_8UC1) Cv2.CvtColor(img, gray, ColorConversionCodes.BGR2GRAY) Cv2.Threshold(gray, gray, 0, 255, ThresholdTypes.Otsu) Dim cc As ConnectedComponents = Cv2.ConnectedComponentsEx(gray) For Each blob As ConnectedComponents.Blob In cc.Blobs.Skip(1) img.Rectangle(blob.Rect, Scalar.Lime, 2) Next End Using End If End Sub Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click isLabeling = Not isLabeling End Sub End Class