C#/VB.NETで画像処理⑭<背景差分>
こんにちは、SKです。
C#/VB.NETで画像処理シリーズの第14弾。
今回は、画像処理の分野で良く使われる背景差分を行う方法を紹介します。
背景画像と現在画像を重ね合わせ、画像の中で変化のあった領域を抽出できます。
動体検知に使われたりします。
ボタン押下時に背景画像を登録し、背景差分をリアルタイムで行った結果の二値化画像を表示してみます。
OpenCVSharpとは?
(前回)テンプレートマッチング
動画手順
①背景画像登録ボタンを配置する
フォーム上にボタンを配置します。
前回同様、メインのProcess関数内でカメラ画像を常に変数picImageに格納しつつ、このボタンのクリックイベントで背景画像の変数backImageに格納します。
private Mat picImage; private Mat backImage; private void Process(Mat img) { //カメラ画像格納 if(picImage == null) { picImage = img.Clone(); } else { img.CopyTo(picImage); } } private void button1_Click(object sender, EventArgs e) { //背景画像格納 backImage = picImage.Clone(); }
②背景差分を行う
AbsDiff関数を使用し、背景画像とカメラ画像の差分画像を作成します。
出力画像もBGRの3チャンネルですが、結果が分かりやすいように二値化して表示します。
AbsDiff関数
Cv2.Absdiff Method
・第1引数:入力画像1
・第2引数:入力画像2
・第3引数:出力画像
//背景差分 if(backImage != null) { using(Mat dst = new Mat()) { Cv2.Absdiff(img, backImage, dst); using(Mat gray = dst.CvtColor(ColorConversionCodes.BGR2GRAY)) { Cv2.Threshold(gray, gray, 120, 255, ThresholdTypes.Binary); Cv2.ImShow("diff", gray); Cv2.WaitKey(1); } } }
実行します。
背景画像を登録すると、最初は真っ黒
カップを入れるとこんな感じ
最後に、コード全文を載せておきます。
C#
using System; 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 Mat picImage; private Mat backImage; private void Process(Mat img) { //カメラ画像格納 if(picImage == null) { picImage = img.Clone(); } else { img.CopyTo(picImage); } //背景差分 if(backImage != null) { using(Mat dst = new Mat()) { Cv2.Absdiff(img, backImage, dst); using(Mat gray = dst.CvtColor(ColorConversionCodes.BGR2GRAY)) { Cv2.Threshold(gray, gray, 120, 255, ThresholdTypes.Binary); Cv2.ImShow("diff", gray); Cv2.WaitKey(1); } } } } private void button1_Click(object sender, EventArgs e) { //背景画像格納 backImage = picImage.Clone(); } } }
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 picImage As Mat Private backImage As Mat Private Sub Process(ByVal img As Mat) 'カメラ画像格納 If picImage Is Nothing Then picImage = img.Clone Else img.CopyTo(picImage) End If '背景差分 If backImage IsNot Nothing Then Using dst As New Mat Cv2.Absdiff(img, backImage, dst) Using gray As Mat = dst.CvtColor(ColorConversionCodes.BGR2GRAY) Cv2.Threshold(gray, gray, 120, 255, ThresholdTypes.Binary) Cv2.ImShow("diff", gray) Cv2.WaitKey(1) End Using End Using End If End Sub '背景画像格納 Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click backImage = picImage.Clone End Sub End Class