4.OpenCVで画像処理アプリを作ろう(画像グレー化)

こんにちは、ゆたんぽです。

引き続き画像処理アプリを作成していきます。

前回までに画像選択を行いましたので、今回は選択した画像で実際に画像処理をしていこうと思います。

やっとOpenCVの出番です。


準備

今までの準備ですぐに画像処理できると思ったのですが甘かったです、、、

前回までの記事でImageの選択まで行いましたが、選択したBitmapImage型とOpenCVで使用する画像のMat型の変換が必要でした。

いろいろ試してできるようになったので説明していきます。

OpenCVSharp4.WpfExtensionsのインストール

まず、Bitmap型とMat型の変換を行ってくれる、 OpenCVSharp4.WpfExtensions をインストールしていきます。

例のごとく、Nugetを使用して「opencv wpf」と検索して、インストールを進めてください。

これだけで型変換できるぞと進めていたのですができませんでした、、

上記をインストールした状態で型変換を進めていたのですが、「OpenCvSharp4.WpfExtensions.dllがみつからない」と怒られてエラーで止まってしまいました。

そのため、以下のインストールも行ってください。

OpenCvSharp4.runtime.winのインストール

これは、WindowsでOpenCVを使用するために必要なツールらしいのです。なくても使用できていたのですが、、

とりあえず、画像型の変換では使用するみたいなのでインストールします。

こちらもNuGetを使用して、「opencvsharp runtime」など検索してインストールしていきます。

以上でNuGetでのインストールは終了です。

今まで、OpenCV関連で3つのツールをNuGetでインストールしてきましたので確認お願いします。

拡張メソッドの準備

上記の準備でBitmap型⇔Mat型の変換はできるようになったのですが、Bitmap型⇔BitmapImage型への変換はできないので、拡張メソッドを作成していきます。

拡張メソッドとは

既存の型やクラスに、元の型の変更や継承、インスタンス化をすることなく使用できるメソッドのこと。

●●.methodなどの形でメソッドを呼び出せる。

MyExtensionsというフォルダを新たに作成してその中に拡張メソッドを入れていきます。

拡張メソッドは「MyExtensionClass」という名前で以下のように作成しました。

using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Input;
using System.Windows.Media.Imaging;

namespace OpenCV_Prism.MyExtension
{
    static class MyExtensionClass
    {
        public static BitmapImage ToBitmapImage(this Bitmap bitmap)
        {
            using (var memory = new MemoryStream())
            {
                bitmap.Save(memory, ImageFormat.Png);
                memory.Position = 0;

                var bitmapImage = new BitmapImage();
                bitmapImage.BeginInit();
                bitmapImage.StreamSource = memory;
                bitmapImage.CacheOption = BitmapCacheOption.OnLoad;
                bitmapImage.EndInit();
                bitmapImage.Freeze();

                return bitmapImage;
            }
        }
    }
}

詳細の説明は省きますが上記のように拡張メソッドを作成することで、Bitmap型の変数に.ToBitmapImageを呼び出せるようになり、戻り値をBitmapImage型にすることができます。


画像処理の実装

以上で準備が整見ました。長かったです。笑

実際に実装していきます。

その前に 前回 作成した抽象メソッド「ImageProcess.cs」を一部変更してます。
申し訳ありませんが確認をお願いします。
1つ画像変数を追加しています。(2021.10.28)

ImageProcessExe の実装

上記が確認出来たら、前回作成したImageProcessExemyRunの中身を編集していきましょう。

using OpenCV_Prism.Abstract;
using OpenCV_Prism.MyExtension;
using OpenCvSharp;
using OpenCvSharp.Extensions;
using OpenCvSharp.WpfExtensions;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Windows.Media.Imaging;

namespace OpenCV_Prism.Models
{
    class ImageProcessExe : ImageProcess
    {
        public override void myRun()
        {
            //BitmaoImage⇒Matへ変換
            using (var src = _originImage.ToMat())
            using (var dst = new Mat())
            {
                //グレー画像へ変換
                Cv2.CvtColor(src, dst, ColorConversionCodes.RGB2GRAY);

                //Mat⇒Bitmap⇒Bitmapへ変換
                Image = BitmapConverter.ToBitmap(dst).ToBitmapImage();
            }
        }
    }
}

以下で説明していきます。

var src = _originImage.ToMat()では、_originImage(BitmapImage型)をMat型へ変換しています。

ToMatはusing OpenCvSharp.WpfExtensionsで使用することができます。

また、usingをつけると中で定義したオブジェクトを処理後にDisposeしてくれます。

usingの中に入れるだけなので便利ですね。

using (var dst = new Mat())では、新しいMat型の変数を定義しています。これも処理後にはDisposeしたいので、usingで囲みます。画像などはHeapメモリ上にたまってしまうのですぐに消したいのでこの処理をしています。

Cv2.CvtColor(src, dst, ColorConversionCodes.RGB2GRAY)でグレー画像に変換しています。

詳細は次の章で説明します。

Image = BitmapConverter.ToBitmap(dst).ToBitmapImage();

ここでは、 BitmapConverter.ToBitmap(dst)で先ほどグレーにしたMat型の画像をBitmap型に変換しています。これは、using OpenCvSharp.Extensionsで使えます。

そして、先ほど定義した拡張メソッドToBitmapImageでBitmapImage型へ変換して、Imageへ格納しています。ImageはView側とデータバインディングしていますので画面の表示が変わり、グレー画像が表示されます。

Cv2.CvtColor説明

Cv2.CvtColor は画像の色空間を変換するメソッドです。

CvtColor
public static void CvtColor(
InputArray src,
OutputArray dst,
ColorConversionCodes code,
 int dstCn = 0
);

以下の表に説明を載せます。

引数説明
InputArray src 入力画像(行列)です。
8,16ビット符号なし、あるいは単精度浮動小数点です。Matを入れます。
OutputArray dst 入力画像(行列)です。 形式はsrcと同じです。
ColorConversionCodes code 「(srcの色空間)2(dstの色空間)」で ColorConversionCodes を指定します。今回は、 RGB2GRAY でカラー画像⇒グレー画像を指定しています。
int dstCn = 0 入力画像のチャンネル数を指定できます。0にしておくとsrcとcodeから自動的にチャンネル数が決まります。今回は、指定していないので0が入り自動で決まっています。

それでは、デバッグを開始してみてください。

上記のように選択したカラー画像がグレー画像に変換出来たら成功です。


まとめ&次回予告

今回は、選択したBitmapImageをグレー画像に変換して表示することができました。

いろいろ試して成功しましたが、他にいいやり方があるかもしれません。

よろしければコメントに書いていただけると幸いです。

次回は、閾値処理を行って、パラメータを指定できるようにしたいと思います。

5.OpenCVで画像処理アプリを作ろう(Threshold)

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です