自分だけのクイズを作成しよう - Quipha
スポンサーリンク

【C#】OpenCVSharpで画像処理!【Visual Studio 2022】

OpenCV

当サイトではアフィリエイト広告を利用しています。

スポンサーリンク

はじめに

WindowsアプリでOpenCVを利用した画像処理を行ってみましょう。
OpenCVはC++で利用できますが「難易度が高い!」という人でも、C#でOpenCVSharp使うと簡単で便利です。

今回使用する環境は以下です。

環境
  • Windows10
  • Visual Studio 2019 / 2022
  • C#.NET
  • OpenCVSharp

公式のOpenCvSharpの開発リポジトリは以下です。

GitHub - shimat/opencvsharp: OpenCV wrapper for .NET
OpenCV wrapper for .NET. Contribute to shimat/opencvsharp development by creating an account on GitHub.

他にも私のブログで、OpenCVSharpについて解説している記事がありますのでご覧ください。

ソースコードについて

今回使用するソースコードは、githubに公開しております。

GitHub - chigusa-web/OpenCVSharpSample: C#とOpenCVSharpで画像処理
C#とOpenCVSharpで画像処理. Contribute to chigusa-web/OpenCVSharpSample development by creating an account on GitHub.

Visual Studio 2022インストール

まずは、Visual Studio 2022をインストールします。
以下の記事にまとめましたので、参考ください。

2021/12/02追記:
以降の手順は、Visual Studio 2019を使用しておりますが、すべてのコードはVisual Studio 2022で動作確認できました。

C#プロジェクトの作成

Visual Studioを起動します。
新しいプロジェクトを作成します。

検索ボックスに、「C#」と入力し、Windowsフォームアプリケーションを作成します。

プロジェクト名や保存場所は任意で入力します。

プロジェクトが作成されました。

OpenCVSharpインストール

OpenCVとは、画像処理や解析などを行うことができるライブラリです。

OpenCvSharpは、OpenCVをC#で扱いやすいようにしたラッパーライブラリです。

OpenCVSharpを使用できるように準備します。
プロジェクト→NuGetパッケージの管理を開きます。

参照をクリックし、opencvsharp4」と入力します。
今回は、Windowsアプリを作成しますので、OpenCvSharp4.Windowsをインストールします。

ちなみに、OpenCvSharp3-AnyCPUOpenCvSharp-AnyCPUなどは、非推奨になったとのことで、こちらは使用しません。

OpenCvSharp4.Windowsを選択し、インストールを行います

2021/12/02追記:
最新のOpenCvSharp4のバージョンは、4.5.3.20210817でした。

OKボタンをクリックし進めます。

正常に終了しました。

基本

サンプル画像を用意しました。

本記事ではサンプル画像を利用していますが、各自ご用意ください。

寝落ちうとうとにゃんこ|フリー素材のぱくたそ
寝落ちうとうとにゃんこの写真はネコ・にゃんこ・寝落ちに関連する動物・生物のフリー素材です。高解像度(6000px×4000px)の素材を無料でダウンロードできます。

任意の場所に「img」フォルダを作りファイルを保存しました。

例:
D:\cs_source\img\neko.jpg

フォームにボタンを配置します。

usingディレクティブに以下を指定します。

using OpenCvSharp;

ボタンのクリックイベントを以下のようにしました。
最低限のサンプルコードです。

private void B_sample1_Click(object sender, EventArgs e)
{
    // 画像の読み込み
    using (Mat mat = new Mat(@"D:\cs_source\img\neko.jpg"))
    {
        // 画像をウィンドウに表示
        Cv2.ImShow("sample_show", mat);
    }
}

Matインスタンスは、開放する必要があります。(usingを使用しています)

画像パスは、保存したパスを指定しています。
ImShowを使用し、新しいウィンドウに画像を表示します。
第一引数はウィンドウ名を指定します。

それでは実行してみましょう。
フォームが表示されますので、ボタンをクリックします。

新しいウィンドウに画像が表示されました。

今回はこの基本操作をもとに、画像処理の実用例を以下にまとめました。

OpenCVの詳しいパラメータや仕様などは各自調べてください。

スポンサーリンク

グレースケールに変換

ボタンを追加します。

private void B_grayscale_Click(object sender, EventArgs e)
{
    // 画像の読み込み
    using (Mat mat = new Mat(@"D:\cs_source\img\neko.jpg"))
    using (Mat matGray = mat.CvtColor(ColorConversionCodes.BGR2GRAY))
    {
        // 画像をウィンドウに表示
        Cv2.ImShow("grayscale_show", matGray);
    }
}

実行してみると、グレースケールになりました。

画像ファイルの保存

加工した画像をファイルに保存する方法です。

// 画像の保存
Cv2.ImWrite(@"D:\cs_source\img\output.jpg", mat);

画像の切り抜き

画像を切り抜き、ファイルに保存する方法です。

// 画像の切り抜き
var mat2 = mat.Clone(new Rect(100, 100, 200, 150));
Cv2.ImWrite(@"D:\cs_source\img\output.jpg", mat2);

テンプレートマッチング

テンプレートマッチングを行います。
ある画像の中に、検索したい画像を探して赤枠をつけます。

ボタンを追加します。

探したいテンプレート画像も用意します。
猫ちゃんの顔にしました。

ソースコードは以下です。
テンプレートマッチングを行い、見つかった箇所に赤枠を表示しています。

private void B_template1_Click(object sender, EventArgs e)
{
    // 検索対象の画像とテンプレート画像
    using (Mat mat = new Mat(@"D:\cs_source\img\neko.jpg"))
    using (Mat temp = new Mat(@"D:\cs_source\img\template1.jpg"))
    using (Mat result = new Mat())
    {

        // テンプレートマッチ
        Cv2.MatchTemplate(mat, temp, result, TemplateMatchModes.CCoeffNormed);

        // 類似度が最大/最小となる画素の位置を調べる
        OpenCvSharp.Point minloc, maxloc;
        double minval, maxval;
        Cv2.MinMaxLoc(result, out minval, out maxval, out minloc, out maxloc);

        // しきい値で判断
        var threshold = 0.9;
        if (maxval >= threshold)
        {

            // 最も見つかった場所に赤枠を表示
            Rect rect = new Rect(maxloc.X, maxloc.Y, temp.Width, temp.Height);
            Cv2.Rectangle(mat, rect, new OpenCvSharp.Scalar(0, 0, 255), 2);

            // ウィンドウに画像を表示
            Cv2.ImShow("template1_show", mat);

        } else
        {
            // 見つからない
            MessageBox.Show("見つかりませんでした");
        }

    }

}

見つかった箇所に赤枠が表示されます。

テンプレートマッチング 複数検索

先程の例ですと、1つのテンプレートを検索し最も近い場所に赤枠を表示しました。
複数の画像もマッチングし検索することができます

試しに猫ちゃんの顔をコピーした画像を用意しました。
これで2箇所検索されるはずです。

ソースコードは以下です。

private void B_template2_Click(object sender, EventArgs e)
{

    // 検索対象の画像とテンプレート画像
    using (Mat mat = new Mat(@"D:\cs_source\img\neko2.jpg"))
    using (Mat temp = new Mat(@"D:\cs_source\img\template1.jpg"))
    using (Mat result = new Mat())
    {

        // テンプレートマッチ
        Cv2.MatchTemplate(mat, temp, result, TemplateMatchModes.CCoeffNormed);

        // しきい値の範囲に絞る
        Cv2.Threshold(result, result, 0.8, 1.0, ThresholdTypes.Tozero);

        while (true)
        {
            // 類似度が最大/最小となる画素の位置を調べる
            OpenCvSharp.Point minloc, maxloc;
            double minval, maxval;
            Cv2.MinMaxLoc(result, out minval, out maxval, out minloc, out maxloc);

            var threshold = 0.8;
            if (maxval >= threshold)
            {

                // 見つかった場所に赤枠を表示
                Rect rect = new Rect(maxloc.X, maxloc.Y, temp.Width, temp.Height);
                Cv2.Rectangle(mat, rect, new OpenCvSharp.Scalar(0, 0, 255), 2);

                // 見つかった箇所は塗りつぶす
                Rect outRect;
                Cv2.FloodFill(result, maxloc, new OpenCvSharp.Scalar(0), out outRect, new OpenCvSharp.Scalar(0.1),
                            new OpenCvSharp.Scalar(1.0), FloodFillFlags.Link4);

            } else { 
                break;
            }
        }

        // ウィンドウに画像を表示
        Cv2.ImShow("template2_show", mat);
    }

}

実行してみると2箇所赤枠が表示され、見つかりました。

顔抽出

写真の中の顔を認識してみたいと思います。
サンプル画像を用意しました。(各自ご用意ください)

私たちにお任せください!デキるビジネスパーソン風の男女|フリー素材のぱくたそ
私たちにお任せください!デキるビジネスパーソン風の男女の写真はオールアバウト・デキるビジネスパーソンに関連する人物のフリー素材です。高解像度(5760px×3840px)の素材を無料でダウンロードできます。

ボタンを追加します。

ソースコードは以下です。

private void B_face_Click(object sender, EventArgs e)
{

    //顔の矩形を抽出
    using (Mat mat = new Mat(@"D:\cs_source\img\face.jpg"))
    {
        // 分類機の用意
        using (CascadeClassifier cascade = new CascadeClassifier(@"D:\cs_source\haarcascade_frontalface_default.xml"))
        {
            foreach (Rect rectFace in cascade.DetectMultiScale(mat))
            {
                // 見つかった場所に赤枠を表示
                Rect rect = new Rect(rectFace.X, rectFace.Y, rectFace.Width, rectFace.Height);
                Cv2.Rectangle(mat, rect, new OpenCvSharp.Scalar(0, 0, 255), 2);
            }
        }

        // ウィンドウに画像を表示
        Cv2.ImShow("face_show", mat);
    }

}

haarcascade_frontalface_default.xmlは以下のgithubからダウンロードしました。
任意の場所に配置してパスを指定します。

https://github.com/opencv/opencv/blob/master/data/haarcascades/haarcascade_frontalface_default.xml

顔を認識することができました。

画像の中の顔や体などの物体検出については、以下の記事で更に詳しく解説しています。

さいごに

基本的な操作例から、実用的な実装例をまとめました。
OpenCVは非常に強力なライブラリですので、沢山の画像処理を行うことができます
色々と試してみてください😊

他にも私のブログで、OpenCVSharpについて解説している記事がありますのでご覧ください。

\オススメ/

コメント

タイトルとURLをコピーしました