【OpenCvSharp】2019年環境でC#からOpenCVを利用する【Hello World】

  • 2022.03.15
  • C#
【OpenCvSharp】2019年環境でC#からOpenCVを利用する【Hello World】
【OpenCvSharp】2019年環境でC#からOpenCVを利用する【Hello World】

 

 
読了目安:732

Are you want to translate this page to English? Please click this link to translate via ‘©Google Translate'!

ganohr.net favicon

みなさんこんにちは、ガノー(Ganohr)です。

今回は『OpenCV』と『Visual Studio Community』(2017)を用いて、‘C#’で簡単に使えるフレームワークである『OpenCvSharp』(開発者:Schima氏、ブログリポジトリ)を導入し、‘Hello World’的な確認コードを実際に作成して試す手順を解説します。

OpenCvSharpは『NuGet』に対応しているので導入は簡単なのですが、公式サイトで公開されているテスト用のコードが最新版では動かなかったり、パッケージ導入などで調査が必要でしたので、本記事で解説します。

OpenCvSharp関連リンク集

 
更新履歴
2020/10/23 ウェブ上のサンプルコードへコメントを挿入
2020/08/06
 ・ダウンロードマネージャーを変更
 ・ダウンロードリストを再構築
2020/05/20
 ・ OpenCvSharpV2に「古い(非推奨)」を明示
 ・ V4に「推奨」を明示
 ・ V4の2つのサンプルに解説を追記
2020/05/15
 ・ シンタックスハイライトの改修
 ・ その他軽微な修正
2019/09/21 微修正
2019/07/03 カテゴリを調整
2019/07/01 リンク集を更新
2019/06/26 誤変換の修正、わかりにくい表現を修正
コントロールとして表示する方法の解説を追加
2019/06/25 サンプルコードをダウンロード可能に
2019/06/24 C#ライクな記述を追加公開
2019/06/23 公開
 

簡単な用語解説

OpenCVとはなにか

OpenCV’は、画像処理用のマルチプラットフォーム(※1)なフレームワーク(※2)です。

対応するプログラミング言語はメインはC言語、C++言語ですが、有志によりラッパーフレームワーク(※3)が多数開発されています。

そのため、数多くのプログラミング言語から使用可能です。

  • ※1 マルチプラットフォーム=複数のOSで使用可能という意味
  • ※2 フレームワーク=土台という意味。画像処理用の土台を提供している。
  • ※3 ラッパーフレームワーク=別の言語から使用できるようにしたフレームワーク。今回ならOpenCvSharpが該当する。
サムネイルHome - OpenCVOpenCV provides a real-time optimized Computer Vision library, tools, and hardware. It also supports model execution for Machine Learning (ML) and Art ... 外部サイトへアクセスopencv.org サムネイルOpenCV - Wikipedia ... 外部サイトへアクセスja.wikipedia.org

NuGetとはなにか

NuGet’は、.Net Frameworkに対応したパッケージマネージャー(※1)です。

NuGetは最近のVisual Studio(2012以降)には標準で搭載されており、インターネットに接続可能であれば簡単に使用できます。

 

NuGetを用いない場合、パッケージの導入には煩雑な作業(※2)が必要になります。

NuGetを用いれば、大抵の場合ワンクリックだけで導入できます。

今回使用するOpenCvSharpはこのNuGetに対応しているため、導入自体簡単です。

  • ※1 パッケージマネージャー=パッケージ(必要な機能がまとめられたもの)を管理するソフト
  • ※2 煩雑な導入作業:NuGetを用いない場合、例えばdllファイルのコピーや参照の追加などが必要です。
サムネイルNuGet - Wikipedia ... 外部サイトへアクセスja.wikipedia.org サムネイルNuGet とは何か。またどのような働きをするのかNuGet とは何で、どのような働きをするのかについて、総合的に紹介します ... 外部サイトへアクセスlearn.microsoft.com

OpenCvSharpとはなにか

OpenCvSharp’は、日本人開発者であるSchima氏(ブログ)による、OpenCVのC#用ラッパーフレームワークです。

OpenCVに習ったコーディングとともに、C#らしいコーディングが可能になったフレームワークです。

 

例えば、C言語やC++をターゲットにしたフレームワークは、往々にしてメモリ管理が煩雑な場合が多いのですが、

OpenCvSharpであればIDisposableが適宜に実装されているため、using { }ステートメントによる自動解放の恩恵を受けられます。

また、OpenCVの内部画素表現を、.Net FrameworkのBitmap型へ変換するための実装が含まれるなど、実用性に配慮されている点も特徴といえます。

 

その他、NuGetパッケージも2019年4月時点でも更新がかかっているなど、他のOpenCV系ラッパーフレームワークと比べて開発が続いている点も特筆すべきでしょう。

ただし、OpenCvSharpはOpenCVのAPIに準じた実装のために、OpenCvSharp Ver 2.4.xと、それ以外のバージョンで大幅に実装が異なっている点は留意せねばなりません。

これはOpenCV自体の変遷なのでどうしようもないのですが、公式サイトでのサンプルコードを実行する際にも留意が必要です。

サムネイルOpenCvSharp カテゴリーの記事一覧 - schima.hatenablog.com schima.hatenablog.com ... 外部サイトへアクセスschima.hatenablog.com

NuGetを用いたOpenCvSharpの導入とサンプルコード / Hello World

OpenCvSharpを導入するには、NuGetを用いれば簡単です。

ただし、NuGet上に現在公開されているOpenCvSharpには複数のバージョンや複数のプラットフォームに向けた実装が公開されているため、留意が必要です。

今回は「『Windows 10』の64bit環境で動作させる」ことを前提として導入していきます。

 

また、OpenCvSharpのバージョンは大まかに分けて

  • OpenCvSharp 2.4.x
  • OpenCvSharp 3
  • OpenCvSharp 4

と3つのバージョンがあります。

今回はAPI仕様が2.4.x系とそれ以外に分かれる点と、現行最新で更新が続いている4系での導入を解説し、それぞれのサンプルコード(‘Hello World’)を解説します。

各種サンプルコードのダウンロード

当記事では、解説しているコードを全てダウンロードできます。

ダウンロードの際は、以下の条件に同意してください。

  • このサンプルやファイルをWEBサイト等に公開することを禁止します
  • このサンプルをベースに改造・開発を行った場合、ソースコードを不特定多数に公開することを禁止します
  • このサンプルをベースに改造・開発を行い、ビルドした結果については一切の制限事項はありません

 

なお、この制限の意図は「最近横行している、他人のWEBコンテンツを不正に流用して金儲けをおこなおうとするスプログやまとめサイトへの転載を排除するため」です。

良識的な利用においては、一切の制限を課す予定はありません。

ご理解の上、ダウンロードをお願いします。

 

ダウンロード

  • HelloOpenCVSharpV4_2.zip
    C#で一からOpenCV Ver4を用いた開発を行うことが想定されたサンプルです。
    ダウンロード情報 File size: 347 KB Downloads: 1044 File type: zip
  • HelloOpenCVSharpV4_1.zip
    多言語にてOpenCV Ver4を用いているプログラムをC#へ移植することが想定されたサンプルです。
    ダウンロード情報 File size: 201 KB Downloads: 258 File type: zip
  • HelloOpenCVSharpV2.zip
    多言語にてOpenCV Ver2(相当古い)を用いているプログラムをC#へ移植することが想定されたサンプルです。非推奨です。
    ダウンロード情報 File size: 277 KB Downloads: 148 File type: zip
ダウンロード情報の「Copy:File-Hash」について…

各ファイルの「Copy:File-Hash」にマウスカーソルを重ねると、今からダウンロードするファイルの、 「ファイルが公開された際のハッシュ値」を、SHA256で計算して表示します。

そのままタップしたり、マウスでクリックすると、そのハッシュ値をコピーできます。改ざんされたファイルをダウンロードしていないかチェックしたい場合にご活用下さい。

例えばファイルのダウンロード後に、7-zipなどのツールでダウンロードしたファイルの「CRC-SHA256ハッシュ値を計算し、 コピーした結果と同値であるかチェックする」ことにより、ファイル改ざんの有無を検証できます。このとき、大文字か小文字かの違いは、問題ありません。

なお、「もしもハッシュ値が異なっていた場合、お手数をおかけいたしますが、 作者のTwitter(Ganohr) までご報告ください」ますよう、お願いいたします。

※ ダウンロードしたコードにはコメントが付与されておりません。
※ なお、ダウンロードしたコードで分からない点がありましたら、当記事にコメントを頂ければフォローアップいたします。

OpenCvSharp Ver2.4(古い / 非推奨)

(2020/05/20 追記)このバージョンは非常に古く、通常は次節にて解説している「Ver4系」をご使用くださいVer2系からVer4系への変更は現実的ではありません。(追記以上)

 

ここでは、以下の手順を行います。

  • Visual Studioで新規プロジェクトとして「HelloOpenCvSharpV2」を作成する
  • NuGetでOpenCvSharp ver 2.4系のパッケージを導入する
  • Hello Worldを作成し実行する

実際のサンプルコードもダウンロードできます。

(実際に動作させて確認するには、Visual Studioでのビルドが必要です)

新規プロジェクトの作成

新規プロジェクトから、

Windows フォームアプリケーション」を選択し、「HelloOpenCvSharpV2」という名前でプロジェクトを作成します。

 

自動生成される「Form1.cs」は不要なので、削除します。

また、それに伴い、コード内の不必要な定義も削除します。

 

 

OpenCvSharpの導入手順解説画像-新規プロジェクトの作成1/2
「ファイル(F)」⇒「新規作成(N)」⇒「プロジェクト(P)」の順番で選択して、新規プロジェクトを作成する
OpenCvSharpの導入手順解説画像-2/2
言語は「Visual C#」を、「Windowsフォームアプリケーション」を選択し、「名前(N)」には「HelloOpenCVSharpV2」と指定し、「OK」ボタンを押す。
OpenCvSharpの導入手順解説画像-不要なフォームを削除する1/3
今回のサンプルコードにはユーザーフォーム(Form1.cs)は不要なので、「ソリューションエクスプローラー」で「Form1.cs」を選択後、「Delete」キーを押し⇒「OK」を押して削除する。
OpenCvSharpの導入手順解説画像-不要なフォームを削除する2/3
「Form1.cs」を削除すると「Program.cs」でエラーが出る。
OpenCvSharpの導入手順解説画像-不要なフォームを削除する3/3
グレーアウトしている「using」定義を削除し、「Main関数の内容」(ブラケット…{}で囲まれた範囲)を削除する。

NuGetでOpenCvSharpのパッケージを導入する

NuGetでパッケージを導入します。

様々なパッケージがありますが、インストールするのは「OpenCvSharp-AnyCPU v2.4.xxxx」のみです。

それ以外は必要ありません。

 

まず、「プロジェクト(P)」⇒「NuGetパッケージの管理」を選択します。

続けて、「参照」タブを選択し、「opencvsharp」と入力してパッケージを探します。

「OpenCvSharp-AnyCPU」をクリックすると「インストール」というボタンが出てくるので、それを押せばインストールされます。

 

 

OpenCvSharpの導入手順解説画像-NuGetでOpenCvSharpを導入する1/3
「プロジェクト(P)」⇒「NuGetパッケージの管理(N)」を選択する。
OpenCvSharpの導入手順解説画像-NuGetでOpenCvSharpを導入する2/3
「参照」タブに切り替え、「opencvsharp」で検索し、「OpenCvSharp-AnyCPU v2.4.xxxx」を選択後、現れる「インストール」ボタンを押す。
OpenCvSharpの導入手順解説画像-NuGetでOpenCvSharpを導入する3/3
インストールに成功すれば、ソリューションエクスプローラーの「参照」を開くと、「OpenCvSharp」が追加されていることが確認できる。

Hello Worldの作成

後は、以下に示すサンプルのHello World(ハローワールド)のコードを、実際に入力します。


using System;
using OpenCvSharp;

namespace HelloOpenCVSharpV2
{
    static class Program
    {
        /// <summary>
        /// アプリケーションのメイン エントリ ポイントです。
        /// </summary>
        [STAThread]
        static void Main()
        {
            // 生成する画像と画面の大きさを定義
            var w = 1024;
            var h = 768;
            // 画像を記憶する変数を定義(IplImageが使えるのはVer2まで)
            IplImage img = Cv.CreateImage(new CvSize(w, h), BitDepth.U8, 3);

            // 画像内の全ピクセル分繰り返す
            for (int y = 0; y < img.Height; y++)
            {
                for (int x = 0; x < img.Width; x++)
                {
                    // Cv.Set2Dで画像の任意の位置(y, x)へ、特定の色を設定する
                    // 色はCvScalarで指定する。この関数は引数として「r,g,b」(0-255)を受け取る。
                    // なお255以上は255と読み替えられる(Ver2まで)。
                    Cv.Set2D(img, y, x, new CvScalar(x, y, x + y));
                }
            }

            // ウィンドウのタイトル及び画像の上に書き出す文字列を定義する
            var hello = "Hello OpenCVSharp";
            // 画像の上の、「文字列を書き出す位置」を指定する
            var pos = new CvPoint(50, 100);
            // 画像の上に、「文字列を書き出すときのフォント」を指定する
            var font = new CvFont(FontFace.HersheyPlain, 4.0f, 4.0f);
            // 画像の上に、「文字列を書き出すときの色」を指定する
            var color = new CvScalar(255, 255, 255);

            // 変数「hello」で指定されたタイトルを持つフォームを作る
            Cv.NamedWindow(hello);
            // 画像の任意の位置へ、文字列をフォントと色を指定して書き込む
            Cv.PutText(img, hello, pos, font, color);
            // 作成した画像をフォームへ配置する
            Cv.ShowImage(hello, img);

            // フォームで何らかのキー入力がなされるまで待機する
            Cv.WaitKey();

            // 作成したウィンドウを破棄する
            Cv.DestroyWindow(hello);
            // 作成した画像を破棄する
            Cv.ReleaseImage(img);
        }
    }
}

実行結果

実行すると以下のようなグラフィカルな画面が表示されます。

OpenCvSharpの導入手順解説画像-HelloWorldの実行
サンプルのHelloWorldを実行すると、グラフィカルな画面が表示される。

OpenCvSharp 4(参考/推奨)

(2020/05/20 追記)特段の理由がない限り、このバージョンを使用してください。なお、このサンプルは既存のOpenCVを用いた別言語からの移植を想定しています。C#で新たにOpenCVを用いたアプリケーションを作成したいと考えている方は、次節にて解説している「C#らしいコーディング例」を参考にしてください。(追記以上)

続けて、OpenCvSharp4を導入して同じ動作をするように記述します。

導入するパッケージが「OpenCvSharp4.Windows」である以外、導入手順は同じです。

新規プロジェクトの作成

OpenCvSharp v4の導入手順解説画像-新規プロジェクトの作成1/3
まず新規プロジェクトを作る
OpenCvSharp v4の導入手順解説画像-新規プロジェクトの作成2/3
「HelloOpenCVSharpV4_1」としてWindowsフォームアプリケーションを作成する。
OpenCvSharp v4の導入手順解説画像-新規プロジェクトの作成3/3
不要なフォームを削除する。

NuGetでOpenCvSharp4.Windowsのパッケージを導入する

OpenCvSharp v4の導入手順解説画像-導入
NuGetを用いて「OpenCvSharp4.Windows」をインストールする。

Hello Worldの作成

OpenCvSharp v4の導入手順解説画像-HelloWorldコードを記述する
OpenCvSharp v2のコードと同じ形でv4も記述可能。ただし、様々な点で差異がある。
using System;
using OpenCvSharp;

namespace OpenCvSharpTest
{
    static class Program
    {
        /// <summary>
        /// アプリケーションのメイン エントリ ポイントです。
        /// </summary>
        [STAThread]
        static void Main()
        {
            // 生成する画像と画面の大きさを定義
            var w = 1024;
            var h = 768;
            // 画像を記憶する変数を定義(Ver3以降はMat型を使用)
            // ※ MatType.CV_8UC3は「8ビット・アンサインド・3色」という意味
            var img = new Mat(new Size(w, h), MatType.CV_8UC3);

            // 画像内の全ピクセル分繰り返す
            for (int y = 0; y < img.Height; y++)
            {
                for (int x = 0; x < img.Width; x++)
                {
                    // img.Setで画像の任意の位置(y, x)へ、特定の色を設定する
                    // 色は自作関数のMyScalarで指定する
                    // この関数はCv.Scalar/Cv2.Scalarのバージョン差異を吸収する
                    img.Set(y, x, MyScalar(x, y, x + y));
                }
            }

            // ウィンドウのタイトル及び画像の上に書き出す文字列を定義する
            var hello = "Hello OpenCVSharp V4";
            // 画像の上の、「文字列を書き出す位置」を指定する
            var pos = new Point(50, 100);
            // 画像の上に、「文字列を書き出すときのフォント」を指定する
            var font = HersheyFonts.HersheyPlain;
            // 画像の上に、「文字列を書き出すときの色」を指定する
            var color = new Scalar(255, 255, 255);

            // 変数「hello」で指定されたタイトルを持つフォームを作る
            Cv2.NamedWindow(hello);
            // ウィンドウの大きさを変更する
            Cv2.ResizeWindow(hello, w, h);
            // 画像の任意の位置へ、文字列をフォントと色を指定して書き込む
            Cv2.PutText(img, hello, pos, font, 4.0f, color);
            // 作成した画像をフォームへ配置する
            Cv2.ImShow(hello, img);

            // フォームで何らかのキー入力がなされるまで待機する
            Cv2.WaitKey();

            // 作成したウィンドウを破棄する
            Cv2.DestroyWindow(hello);
            // 作成した画像を破棄する
            img.Dispose();
        }

        // CvScalarのバージョン差異を吸収するための関数を定義
        static int MyScalar(int b, int g, int r)
        {
            return
                (r > 255 ? 255 : r) * 256 * 256 +
                (g > 255 ? 255 : g) * 256 +
                (b > 255 ? 255 : b);
        }
    }
}

実行結果

OpenCvSharp v4の導入手順解説画像-V2と同じ動作が可能
OpenCvSharp4でも同じ動作が可能。

OpenCvSharp2と、OpenCvSharp3&OpenCvSharp4の違い

OpenCvSharpはバージョン2系か、それ以上のバージョンかによって、記述が異なります。

 

わかりにくいのですが、2系の場合はCvクラスを用い、3以上のバージョンではCv2を用います。

また、IplImageクラスが使えるのは『OpenCvSharp ver 2.4』までであり、それ以降はMatクラスを用います。

多くのクラス名・フィールド名からも冗長なCvの名称が消えているため、それに合わせて変更が必要です。

 

さらに、ScalarCvScalar)も動作がバージョンで異なるため、考慮せねばなりません。

 

OpenCvSharp v4でScalarを用いた動作例
Scalarの動作がV2とV4で異なる。「img.Set(y, x, new Scalar(x, y, x + y).ToVec3b());」の場合の例。
OpenCvSharp v4でScalarを用いた動作例2
V2のようにScalarを「.ToVec3b()」せずに呼び出すと、色が出ない。

OpenCvSharp 4でのC#ライクなコーディング(推奨)

(2020/05/20 追記)特段の理由がない限り、C#で一からコーディングする際は、この内容をベースに開発を行ってください。(追記以上)

Cv2を用いた記述はC言語やC++言語での記述を踏襲できることは強みです。

しかし、私はC#ならC#っぽい記述がしたいのと、そもそもオリジナルのアプリケーションに機能拡張を目的としてOpenCVが使用したいのです。

そのためにWindowsコントロールとして表示したり、Bitmapオブジェクトとして表示できるようにしましょう。

  • C#ライクなコーディングがしたい
  • Windowsコントロールとして表示したい
  • Bitmapオブジェクトとして表示したい

コード

OpenCvSharp v4の導入手順解説画像-
Bitmap型のオブジェクトへコンバートすることも可能。
using System;
using System.Windows.Forms;
using OpenCvSharp;
using OpenCvSharp.Extensions;

namespace HelloOpenCVSharpV4_2
{
    static class Program
    {
        /// <summary>
        /// アプリケーションのメイン エントリ ポイントです。
        /// </summary>
        [STAThread]
        static void Main()
        {
            // 生成する画像と画面の大きさを定義
            var w = 1024;
            var h = 768;
            // 画像を記憶する変数を定義(Ver3以降はMat型を使用)し、自動解放させる
            // ※ MatType.CV_8UC3は「8ビット・アンサインド・3色」という意味
            using (var img = new Mat(new Size(w, h), MatType.CV_8UC3))
            {
                // 画像内の全ピクセル分繰り返す
                for (int y = 0; y < img.Height; y++)
                {
                    for (int x = 0; x < img.Width; x++)
                    {
                        // img.Setで画像の任意の位置(y, x)へ、特定の色を設定する
                        // 色は自作関数のMyScalarで指定する
                        // この関数はCv.Scalar/Cv2.Scalarのバージョン差異を吸収する
                        img.Set(y, x, MyScalar(x, y, x + y));
                    }
                }

                // ウィンドウのタイトル及び画像の上に書き出す文字列を定義する
                var hello = "Hello OpenCVSharp V4";
                // 画像の上の、「文字列を書き出す位置」を指定する
                var pos = new Point(50, 100);
                // 画像の上に、「文字列を書き出すときのフォント」を指定する
                var font = HersheyFonts.HersheyPlain;
                // 画像の上に、「文字列を書き出すときの色」を指定する
                var color = new Scalar(255, 255, 255);

                // 画像の任意の位置へ、文字列をフォントと色を指定して書き込む

                img.PutText(hello, pos, font, 4.0f, color);

                // フォームを作成する
                // ※ 別にRADで作成してもよい
                using (var form = new Form())
                {
                    // 変数「hello」で指定されたタイトルをフォームへ設定する
                    form.Text = hello;
                    // ウィンドウの大きさを変更する
                    form.Size = new System.Drawing.Size(w, h);
                    // 作成した画像をフォームへ配置する
                    form.BackgroundImage = BitmapConverter.ToBitmap(img);
                    // 作成した画像をフォームに(伸縮許可指定で)フィットさせる
                    form.BackgroundImageLayout = ImageLayout.Stretch;

                    // 作成したフォームをアプリケーションとして作動させる(終了まで待機される)
                    Application.Run(form);
                }
            }
        }

        // CvScalarのバージョン差異を吸収するための関数を定義
        static int MyScalar(int b, int g, int r)
        {
            return System.Drawing.Color.FromArgb(
                r > 255 ? 255 : r,
                g > 255 ? 255 : g,
                b > 255 ? 255 : b).ToArgb();
        }
    }
}

解説

  • System.Drawing.SizeOpenCvSharp.Sizeで名称がバッティングしているため、明示的に指定しなければなりません。
  • Cv.CvFontには倍率が含まれるものの、OpenCvSharp.Fontには倍率が含まれません。
  • Matのインスタンスを、BitmapConverter.ToBitmap(img);によってBitmapのインスタンスへコンバートできます。
  • MyScalarSystem.Drawing.Color.FromArgb(…).ToArgb()を使って記述できます。

フォームコントロール

Bitmap型ではなく、直接コントロールとしてフォーム上に配置することも可能です。

OpenCvSharp v4の導入手順解説画像-
OpenCvSharpなら、処理結果の内部画素表現を、直接フォーム上に配置して表示することも可能。
  • using OpenCvSharp.Userinterface;で参照を追加しておく
  • using(var pbox = new PictureBoxIpl()){ ~ }でインスタンス作成と解放を可能に
  • PictureBoxIpl.ImageIplImageIpl型ではなく、Mat型のインスタンスを受け取り、表示する

最後に

OpenCvSharpはどのパッケージを導入すればよいのか初見だとわかりにくい点と、

そもそもバージョンによって色々な違いがあるためインターネット上にある情報が色々と古いという欠点があります。

しかし、一度情報を整理すれば最新のAPIも比較的容易に使えるように感じました。

 

今後OpenCVを使っていく上で、活用していく予定です。

この場を借りて、開発者のSchima氏にお礼を申し上げます。ありがとうございました!

 

今回の内容が参考になれば幸いです。

以上、ガノー(Ganohr)でした!

WordPressの不具合対応/カスタマイズ¥15,000~

PC歴25年超、SE歴10年超、WordPress運営歴7年超、WordPressエンジニア歴5年超のスキルとノウハウを提供します

当サイト管理人の「ガノー」(Ganohr)は、日本最大手且つ東証一部上場企業が運営するクラウドソーシングサイト『Lancers』にて、認定ランサーとして活動しています。


※ 認定ランサーとはLancersにより様々な能力 ( 高い仕事遂行率・高い顧客満足度・多くの実績、など ) を評価したプロフェッショナルを認定する制度です。

 

C#カテゴリの最新記事