読者です 読者をやめる 読者になる 読者になる

SourceChord

C#とXAML好きなプログラマの備忘録。最近はWPF系の話題が中心です。

OpenCVで色々な画像生成

今回もOpenCvSharpネタ。

今度はちょっと脱線気味。
OpenCVピクセル操作や図形描画機能を使って、いろんな画像を生成してみます。

ノイズ画像の生成

ピクセルのRGB値を乱数で設定すると、このようなノイズ画像が作成できます。

        static void Main(string[] args)
        {
            var r = new Random();
            var img = new Mat(240, 320, MatType.CV_8UC3, new Scalar(0, 0, 0));

            var mat3 = new MatOfByte3(img);
            var indexer = mat3.GetIndexer();
            for (var y = 0; y < img.Height; y++)
            {
                for (var x = 0; x < img.Width; x++)
                {
                    var px = indexer[y, x];
                    // RGB値すべて同じ値で、乱数値を設定
                    var val = (byte)(r.Next() * 255);
                    px[0] = val;
                    px[1] = val;
                    px[2] = val;
                    indexer[y, x] = px;
                }
            }

            Cv2.ImShow("image", img);
            Cv2.WaitKey();
        }

ピクセルのRGB値を同じ値にすると、こんな風にモノクロなノイズになり、
f:id:minami_SC:20160825074421p:plain RGB各々を別々なランダム値にすると、色のついたノイズ画像になります。

                    var px = indexer[y, x];
                    // RGB値それぞれ、別々の乱数値を設定
                    px[0] = (byte)(r.Next() * 255);
                    px[1] = (byte)(r.Next() * 255);
                    px[2] = (byte)(r.Next() * 255);
                    indexer[y, x] = px;

f:id:minami_SC:20160825074517p:plain

グラデーション画像の生成

今度は、各ピクセル値をループ変数で徐々に変化させ、グラデーション画像を描画してみます。

        static void Main(string[] args)
        {
            var img = new Mat(240, 320, MatType.CV_8UC3, new Scalar(0, 0, 0));

            var mat3 = new MatOfByte3(img);
            var indexer = mat3.GetIndexer();
            for (var y = 0; y < img.Height; y++)
            {
                for (var x = 0; x < img.Width; x++)
                {
                    var px = indexer[y, x];
                    var r = (float)x / img.Width;
                    var b = (float)y / img.Height;
                    px[0] = (byte)(r * 255);
                    px[1] = (byte)0;
                    px[2] = (byte)(y * 255);
                    indexer[y, x] = px;
                }
            }

            Cv2.ImShow("image", img);
            Cv2.WaitKey();
        }

f:id:minami_SC:20160825074532p:plain

ラインアート

もう、ここまでくると、完全にOpenCVでやるべき内容じゃないですね・・・w

        static void Main(string[] args)
        {
            var img = new Mat(240, 320, MatType.CV_8UC3, new Scalar(0, 0, 0));

            var mat3 = new MatOfByte3(img);
            var indexer = mat3.GetIndexer();

            var lineNum = 20; // 描画する線の数
            for (var i = 0; i < lineNum; i++)
            {
                var val = (float)i / lineNum;
                var x = val * img.Width;
                var y = val * img.Height;

                Cv2.Line(img, new Point(0, y), new Point(x, img.Height), new Scalar(0, val*255, 255-(val*255)));
            }

            Cv2.ImShow("image", img);
            Cv2.WaitKey();
        }

f:id:minami_SC:20160825074547p:plain

こんな風に、OpenCVの図形描画関数を使って、ラインアートを書いたりすることもできます。

ただし、OpenCVの図形描画関数は、α値を用いた透過処理をサポートしていません。
Scalarを引数で受けていて、Scalar型はα値も含んだ値を定義することができますが、α値は無視されて単純にRGBの色で上書きされます。

なので、αブレンドを用いて、キレイなグラフィック描画をする、などには向かないのです。
こういう用途は、OpenGLDirectXなど、ちゃんとしたグラフィック描画のためのライブラリ/フレームワークを使う方がよいですね。

まぁ、こんな風に使うこともできる、、、ってことで。