OpenCVSharp4で位相画像の作成

位相画像とは

位相限定相関法(Phase Only Correlation)などで使用される画像。フーリエ変換した画像の位相だけを取り出した画像のこと。

F[Xij]=GuvとするとPhaseImage(Xij)=F1[Guv|Guv|]定義より画像の明るさを何倍しても位相画像は変わらない。

方法

  1. 画像を読み込む
  2. 画像のサイズ調整
  3. 画像を複素平面に移す
  4. フーリエ変換(DFT)を行う
  5. 各画素の大きさ(実部と虚部の2乗平均)を取得
  6. 各画素を正規化(大きさで除算する)
  7. フーリエ変換を行う

※事前に
NuGetでOpenCVSharp4とOpenCVSharp4.runtime.winをインストールしておく

using System;  
using OpenCvSharp;  

namespace フーリエ画像 {  
    class Program {  
        static void Main(string[] args) {  
            //①画像をグレースケールで読み込み  
            Mat src = new Mat(@"D:\src.png");  
            Cv2.CvtColor(src, src, ColorConversionCodes.RGB2GRAY);  
            Cv2.ImShow("①src", src);  


            //②画像を最適なサイズに変形  
            Mat padded = new Mat();  
            int optimalRows = Cv2.GetOptimalDFTSize(src.Rows);  
            int optimalCols = Cv2.GetOptimalDFTSize(src.Cols);  
            Cv2.CopyMakeBorder(src, padded,  
                0, optimalRows - src.Rows,  
                0, optimalCols - src.Cols,  
                BorderTypes.Constant, Scalar.All(0));  

            //③0で拡張された別の平面に移す  
            Mat paddedF32 = new Mat();  
            padded.ConvertTo(paddedF32, MatType.CV_32F);  
            Mat[] planes = { paddedF32, Mat.Zeros(padded.Size(), MatType.CV_32F) };  
            Mat complex = new Mat();  
            Cv2.Merge(planes, complex);  


            //④dftを入力画像とフィットさせDFT(フーリエ変換)  
            Mat dft = new Mat();  
            Cv2.Dft(complex, dft);  


            //⑤各画素の大きさを計算する  
            Mat[] dftPlanes = Cv2.Split(dft);  
            Mat magnitude = new Mat();  
            Cv2.Magnitude(dftPlanes[0], dftPlanes[1], magnitude);  


            //⑥大きさで各要素を割って正規化  
            Mat phase = new Mat();  
            Cv2.Divide(dftPlanes[0], magnitude, dftPlanes[0]);  
            Cv2.Divide(dftPlanes[1], magnitude, dftPlanes[1]);  
            Cv2.Merge(dftPlanes, phase);  


            //⑦逆フーリエ   
            Mat inverseTransform = new Mat();  
            Cv2.Dft(phase, inverseTransform, DftFlags.Inverse | DftFlags.RealOutput);  


            //⑧逆フーリエ変換した結果を8bitに正規化して表示  
            Cv2.Normalize(inverseTransform, inverseTransform, 0, 255, NormTypes.MinMax);  
            inverseTransform.ConvertTo(inverseTransform, MatType.CV_8U);  

            Cv2.ImShow("Reconstructed by Inverse DFT", inverseTransform);  


            Cv2.WaitKey();  


        }  
    }  
}  

結果

入力画像

f:id:negizoku:20200920230803p:plain



出力画像

f:id:negizoku:20200920230820p:plain



参考

https://rest-term.com/archives/1375/
https://www.jstage.jst.go.jp/article/itej1997/54/10/54_10_1408/_pdf
http://www.aoki.ecei.tohoku.ac.jp/~ito/vol1_030.pdf

OpenCVSharp4のエッジ強調(一次微分、Prewitt、Sobel、Laplacian、canny etc...)

OpenCVSharp4の色々な輪郭抽出フィルタを試してみた
※2020/06/08追記 正規化の方法が間違っていました。

方法

  1. VisualStudioにNuGetでOpenCVSharp4とOpenCVSharp4.runtime.winをインストール
  2. 次のプログラムを実行
using System;  
using OpenCvSharp;  

namespace 輪郭抽出 {  
    class Program {  
        static void Main(string[] args) {  
            Mat src = new Mat(@"D:\picture.png");  
            Cv2.CvtColor(src, src, ColorConversionCodes.BGR2GRAY);  

            Mat bibun = new Mat(),  
                prewitt = new Mat(),   
                sobel = new Mat(),   
                laplacian = new Mat(),   
                emboss = new Mat(),   
                canny = new Mat(),  
                roberts = new Mat();  


            //一次微分フィルタ  
            Mat bibunX = new Mat();  
            Mat bibunKernelX = new Mat(3, 3, MatType.CV_32FC1,  
                new float[,] {  
                    {  0, 0, 0 },  
                    { -1, 0, 1 },  
                    {  0, 0, 0 }  
                });  

            Mat bibunY = new Mat();  
            Mat bibunKernelY = new Mat(3, 3, MatType.CV_32FC1,  
                new float[,] {  
                    { 0, -1, 0 },  
                    { 0,  0, 0 },  
                    { 0,  1, 0 }  
                });  


            Cv2.Filter2D(src, bibunX, MatType.CV_32FC1, bibunKernelX);  
            Cv2.Filter2D(src, bibunY, MatType.CV_32FC1, bibunKernelY);  
            Cv2.Sqrt(bibunX.Pow(2) + bibunY.Pow(2), bibun);  



            //Prewitt法  
            Mat prewittX = new Mat();  
            Mat prewittKernelX = new Mat(3, 3, MatType.CV_32FC1,  
                new float[,] {  
                    { -1, 0, 1 },  
                    { -1, 0, 1 },  
                    { -1, 0, 1 }  
                });  

            Mat prewittY = new Mat();  
            Mat prewittKernelY = new Mat(3, 3, MatType.CV_32FC1,  
                new float[,] {  
                    { -1, -1, -1 },  
                    {  0,  0,  0 },  
                    {  1,  1,  1 }  
                });  

            Cv2.Filter2D(src, prewittX, MatType.CV_32FC1, prewittKernelX);  
            Cv2.Filter2D(src, prewittY, MatType.CV_32FC1, prewittKernelY);  
            Cv2.Sqrt(prewittX.Pow(2) + prewittY.Pow(2), prewitt);  


            //Sobel法  
            Mat sobelX = new Mat();  
            Cv2.Sobel(src, sobelX, MatType.CV_32FC1, 1, 0);  
            Mat sobelY = new Mat();  
            Cv2.Sobel(src, sobelY, MatType.CV_32FC1, 0, 1);  
            Cv2.Sqrt(sobelX.Pow(2) + sobelY.Pow(2), sobel);  


            //Laplacian法  
            int ksize = 3;  
            Cv2.Laplacian(src, laplacian, MatType.CV_32FC1, ksize);  


            //Emboss法  
            Mat embossKernel = new Mat(3, 3, MatType.CV_32FC1,  
                new float[,] {  
                    {-2, -1, 0},  
                    {-1,  1, 1},  
                    { 0,  1, 2}  
                });  
            Cv2.Filter2D(src, emboss, MatType.CV_32FC1, embossKernel);  


            //canny法  
            double minThresh = 100;  
            double maxThresh = 200;  
            Cv2.Canny(src, canny, minThresh, maxThresh);  


            //表示  
            Cv2.ImShow("入力画像", src);  
            Cv2.ImShow("一次微分", bibun);  
            Cv2.ImShow("Prewitt", prewitt);  
            Cv2.ImShow("Sobel", sobel);  
            Cv2.ImShow("Laplacian", laplacian);  
            Cv2.ImShow("Emboss", emboss);  
            Cv2.ImShow("Canny", canny);  

            Cv2.WaitKey();  

        }  
    }  
}  

OpenCVSharp4のカラーマップ機能を使った

カラーバーにするには

Cv2.ApplyColorMap(src, dst, ColorConversionCodes)  

を使う

//サンプルコード  
using System;  
using OpenCvSharp;  

namespace カラーマップ {  
    class Program {  
        static void Main(string[] args) {  
            Mat mat = new Mat(@"D:\icon.jpg");  
            mat.CvtColor(ColorConversionCodes.RGB2GRAY);  

            Cv2.ApplyColorMap(mat, mat, ColormapTypes.Rainbow);  
            Cv2.ImShow("mat", mat);  
            Cv2.WaitKey();  
        }  
    }  
}  

カラースケールの種類

ColorConversionCodes スケール 説明 サンプル
色マップなし

f:id:negizoku:20200920230033j:plain

ふつうのグレースケール f:id:negizoku:20200920230047j:plain
Bone f:id:negizoku:20200920230101j:plain 普通のグレースケールより見やすい

f:id:negizoku:20200920230114p:plain

Autumn

f:id:negizoku:20200920230127j:plain

熱画像っぽい。hotより狭い

f:id:negizoku:20200920230138p:plain

Hot

f:id:negizoku:20200920230153j:plain

熱画像っぽい。Autumnより広い

f:id:negizoku:20200920230210p:plain

Cividis

f:id:negizoku:20200920230222j:plain

均等な配色で、色盲の人にも同じに見えるらしい

f:id:negizoku:20200920230233p:plain

Viridis

f:id:negizoku:20200920230247j:plain

大小の比較がしやすい。色盲にも対応。

 

f:id:negizoku:20200920230338p:plain



Jet

 

f:id:negizoku:20200920230353j:plain



たぶん一番使うやつ サンプルなし
Hsv

f:id:negizoku:20200920230408j:plain

Jetより配色がスムースだが、並びが逆 サンプルなし
TwilightShifted

f:id:negizoku:20200920230423j:plain

くすんだ配色がエモい

f:id:negizoku:20200920230435p:plain

Pink

f:id:negizoku:20200920230447j:plain

Pinkという名のセピア調

f:id:negizoku:20200920230510p:plain

参考

https://journals.plos.org/plosone/article?id=10.1371/journal.pone.0199239
https://docs.opencv.org/3.2.0/d3/d50/group__imgproc__colormap.html#ga9a805d8262bcbe273f16be9ea2055a65

OpenCVSharp4でmatの要素(画素)にアクセス

はじめに

OpenCVSharp4でmatの要素にアクセスする方法をまとめた

値の取得

値の取得方法として
①Atメソッドを使う方法
②getメソッドを使う方法
③インデクサーを使う方法
がある。

using System;  
using OpenCvSharp;  

namespace Matの要素にアクセス {  
    class Program {  
        static void Main(string[] args) {  
            double[,] magicSquare = new double[,] {  
                {2,9,4 },  
                {7,5,3 },  
                {6,1,8 }  
            };  

            Mat mat = new Mat(3, 3, MatType.CV_64FC1, magicSquare);  
            mat.ConvertTo(mat, MatType.CV_32FC1);  
            Console.WriteLine(Cv2.Format(mat));  

            //①Atを使う方法  
            for(int j = 0; j < mat.Rows;j++)   
                for(int i = 0; i < mat.Cols; i++) {  
                    double x = mat.At<float>(j, i);  
                    Console.WriteLine(x);  
                }  
            Console.WriteLine("");  

            //②getを使う方法  
            for(int j = 0; j < mat.Rows; j++)   
                for(int i = 0; i < mat.Cols; i++) {  
                    double x = mat.Get<float>(j, i);  
                    Console.WriteLine(x);  
                }  
            Console.WriteLine("");  

            //③インデクサーを使う方法  
            var indexer = mat.GetGenericIndexer<float>();  
            for(int j = 0; j < mat.Rows; j++)  
                for(int i = 0; i < mat.Cols; i++) {  
                    Console.WriteLine(indexer[j, i]);  
                }  
            Console.WriteLine("");  

        }  
    }  
}  

各メソッド内の<>はmatのMatTypeに合わせて書き換える必要がある

MatType <>の中身
CV_8UC1 char
CV_32FC1 float
CV_64FC1 double
CV_8UC3 Vec3b
CV_32FC3 Vec3f
CV_64FC3 Vec3

MatTypeがわからないときは下のような関数でゴリ押し
(もっとマシな調べ方募集中)

static void WriteMatType(Mat src) {  
var type = src.Type();  

    if(      type == MatType.CV_16SC1) Console.WriteLine("CV_16SC1");  
    else if(type == MatType.CV_16SC2)  Console.WriteLine("CV_16SC2");  
    else if(type == MatType.CV_16UC3)  Console.WriteLine("CV_16SC3");  
    else if(type == MatType.CV_16SC4)  Console.WriteLine("CV_16SC4");  
    else if(type == MatType.CV_32FC1)  Console.WriteLine("CV_32FC1");  
    else if(type == MatType.CV_32FC2)  Console.WriteLine("CV_32FC2");  
    else if(type == MatType.CV_32FC3)  Console.WriteLine("CV_32FC3");  
    else if(type == MatType.CV_32FC4)  Console.WriteLine("CV_32FC4");  
    else if(type == MatType.CV_64FC1)  Console.WriteLine("CV_64FC1");  
    else if(type == MatType.CV_64FC2)  Console.WriteLine("CV_64FC2");  
    else if(type == MatType.CV_64FC3)  Console.WriteLine("CV_64FC3");  
    else if(type == MatType.CV_64FC4)  Console.WriteLine("CV_64FC4");  
    else if(type == MatType.CV_8SC1)   Console.WriteLine("CV_8SC1" );  
    else if(type == MatType.CV_8SC2)   Console.WriteLine("CV_8SC2" );  
    else if(type == MatType.CV_8SC3)   Console.WriteLine("CV_8SC3" );  
    else if(type == MatType.CV_8SC4)   Console.WriteLine("CV_8SC4" );  
    else if(type == MatType.CV_8UC1)   Console.WriteLine("CV_8UC1" );  
    else if(type == MatType.CV_8UC2)   Console.WriteLine("CV_8UC2" );  
    else if(type == MatType.CV_8UC3)   Console.WriteLine("CV_8UC3" );  
    else if(type == MatType.CV_8UC4)   Console.WriteLine("CV_8UC4" );  
}  

値の書き換え

値の書き換えは
①Setメソッドを使う方法
②インデクサーを使う方法
がある

//①Setメソッドを使う方法  
for(int j = 0; j < mat.Rows; j++)   
    for(int i = 0; i < mat.Cols; i++) {  
        mat.Set(j, i, x);//xは書き込む値  
    }  
//②インデクサーを使う方法  
var indexer = mat.GetGenericIndexer<float>();  
for(int j = 0; j < mat.Rows; j++)   
    for(int i = 0; i < mat.Cols; i++) {  
        indexer = x;//xは書き込む値  
    }  

参考

https://tech-blog.s-yoshiki.com/2018/11/787/
http://kassymemo.blogspot.com/2011/09/opencv2cvmat.html
http://sourcechord.hatenablog.com/entry/2016/08/15/235654

OpenCVSharp4でフーリエ画像の作成

サンプルプログラムをほとんどそのまま流用して、プログラムの順序を観察した。
ちなみにOpenCVでのフーリエ変換FFTでなくDFTである。

方法

  1. VisualStudioにNuGetでOpenCVSHarp4とOpenCVSHarp4.runtime.winをインストール
  2. 下記のプログラムを実行
using System;  
using OpenCvSharp;  

namespace フーリエ画像 {  
    class Program {  
        static void Main(string[] args) {  
            //①画像をグレースケールで読み込み  
            Mat src = new Mat(@"D:\src.png");  
            Cv2.CvtColor(src, src, ColorConversionCodes.RGB2GRAY);  
            Cv2.ImShow("①src", src);  


            //②画像を最適なサイズに変形  
            Mat padded = new Mat();  
            int optimalRows = Cv2.GetOptimalDFTSize(src.Rows);  
            int optimalCols = Cv2.GetOptimalDFTSize(src.Cols);  
            Cv2.CopyMakeBorder(src, padded,   
                0, optimalRows - src.Rows,   
                0, optimalCols - src.Cols,  
                BorderTypes.Constant, Scalar.All(0));  

            Cv2.ImShow("②padded", padded);  

            //③0で拡張された別の平面に移す  
            Mat paddedF32 = new Mat();  
            padded.ConvertTo(paddedF32, MatType.CV_32F);  
            Mat[] planes = { paddedF32, Mat.Zeros(padded.Size(), MatType.CV_32F) };  
            Mat complex = new Mat();  
            Cv2.Merge(planes, complex);  


            //④dftを入力画像とフィットさせDFT(フーリエ変換)  
            Mat dft = new Mat();  
            Cv2.Dft(complex, dft);  

            Mat[] dftPlanes =  Cv2.Split(dft);  

            double minVal, maxVal;  

            Mat dft0 = new Mat(), dft1 = new Mat();  
            Cv2.Normalize(dftPlanes[0], dft0, 0, 255, NormTypes.MinMax);  
            Cv2.Normalize(dftPlanes[1], dft1, 0, 255, NormTypes.MinMax);  
            dft0.ConvertTo(dft0, MatType.CV_8UC1);  
            dft1.ConvertTo(dft1, MatType.CV_8UC1);  

            Cv2.MinMaxLoc(dft0, out minVal, out maxVal);  
            Console.WriteLine(maxVal);  
            Cv2.ImShow("④-1", dft0);  
            Cv2.ImShow("④-2", dft1);  


            //⑤各画素の大きさを計算する  
            Mat magnitude = new Mat();  
            Cv2.Magnitude(dftPlanes[0], dftPlanes[1], magnitude);  



            //Cv2.MinMaxLoc(magnitude, out minVal, out maxVal);  
            Mat magntuideImg = new Mat();  
            Cv2.Normalize(magnitude, magntuideImg, 0, 255, NormTypes.MinMax);  
            Cv2.ImShow("⑤", magntuideImg);  

            //⑥対数スケールに変更  
            magnitude += Scalar.All(1);  
            Cv2.Log(magnitude, magnitude);  

            Cv2.MinMaxLoc(magnitude, out minVal, out maxVal);  
            Mat magnitudeLogImg = magnitude / maxVal * 255;  
            magnitudeLogImg.ConvertTo(magnitudeLogImg, MatType.CV_8UC1);  
            Cv2.MinMaxLoc(magnitudeLogImg, out minVal, out maxVal);  
            Cv2.ImShow("⑥", magnitudeLogImg);  

            //⑦奇数の行及び列を持つ場合、偶数にクロップする  
            Mat spectrum = magnitude[new Rect(0, 0, magnitude.Cols & -2, magnitude.Rows & -2)];  


            //⑧原点が画像の中心になるように4象限を入れ替え  
            int cx = spectrum.Cols / 2;//各象限の行数と列数を計算  
            int cy = spectrum.Rows / 2;  

            Mat q0 = new Mat(spectrum, new Rect( 0,  0, cx, cy));//各象限に対応するMatを作成  
            Mat q1 = new Mat(spectrum, new Rect(cx,  0, cx, cy));  
            Mat q2 = new Mat(spectrum, new Rect( 0, cy, cx, cy));  
            Mat q3 = new Mat(spectrum, new Rect(cx, cy, cx, cy));  

            Mat tmp = new Mat();  
            q0.CopyTo(tmp);//第1象限と第3象限の入れ替え  
            q3.CopyTo(q0);  
            tmp.CopyTo(q3);  

            q1.CopyTo(tmp);//第2象限と第3象限の入れ替え  
            q2.CopyTo(q1);  
            tmp.CopyTo(q2);  


            Cv2.Normalize(spectrum, spectrum, 0, 255, NormTypes.MinMax);//0~255に正規化  
            spectrum.ConvertTo(spectrum, MatType.CV_8U);  

            Cv2.ImShow("⑧", spectrum);  

            //逆フーリエも表示する   
            Mat inverseTransform = new Mat();  
            Cv2.Dft(dft, inverseTransform, DftFlags.Inverse | DftFlags.RealOutput);  
            Cv2.Normalize(inverseTransform, inverseTransform, 0, 255, NormTypes.MinMax);  
            inverseTransform.ConvertTo(inverseTransform, MatType.CV_8U);  

            Cv2.ImShow("Reconstructed by Inverse DFT", inverseTransform);  
            //  

            Cv2.WaitKey();  


        }  
    }  
}  

OpenCVSharp4の二値化を試す(単純二値化、大津の二値化、適応的二値化)

方法

  1. VisualStudioにNuGetでOpenCVSharp4とOpenCVSharp4.runtime.winをインストールする
  2. 次のプログラムを実行する
using System;  
using OpenCvSharp;  

namespace 二値化 {  
    class Program {  
        static void Main(string[] args) {  
            //入力画像を読み込みグレースケール化する  
            Mat src = new Mat(@"D:\picture.png");  
            Cv2.CvtColor(src, src, ColorConversionCodes.RGB2GRAY);  

            //出力用のMat  
            Mat binary = new Mat(), binearyInv = new Mat(), otsu = new Mat() , adaptiveMean = new Mat(), adaptiveGaussian = new Mat();  

            //最大値の定義  
            double maxVal =255;  


            //単純二値化は、閾値を決めておく必要がある。  
            double thresh = 127;   
            Cv2.Threshold(src, binary    , thresh, maxVal, ThresholdTypes.Binary);  
            Cv2.Threshold(src, binearyInv, thresh, maxVal, ThresholdTypes.BinaryInv);  
            Cv2.Threshold(src, otsu      ,      0, maxVal, ThresholdTypes.Otsu);  


            //適応的二値化は、ブロックサイズと重み付けから差し引く定数を決めておく必要がある  
            int blocksize = 7, c = 3;  
            Cv2.AdaptiveThreshold(src, adaptiveMean    , maxVal, AdaptiveThresholdTypes.MeanC    , ThresholdTypes.Binary, blocksize, c);  
            Cv2.AdaptiveThreshold(src, adaptiveGaussian, maxVal, AdaptiveThresholdTypes.GaussianC, ThresholdTypes.Binary, blocksize, c);  


            //画像の表示  
            Cv2.ImShow("src"              , src);  
            Cv2.ImShow("bineary"          , binary);  
            Cv2.ImShow("bineary inv"      , binearyInv);  
            Cv2.ImShow("otsu"             , otsu);  
            Cv2.ImShow("adaptive mean"    , adaptiveMean);  
            Cv2.ImShow("adaptive gaussian", adaptiveGaussian);  

            Cv2.WaitKey();  
        }  
    }  
}  

参考

https://docs.opencv.org/4.0.0/d7/d1b/group__imgproc__misc.html#gaa9e58d2860d4afa658ef70a9b1115576

http://labs.eecs.tottori-u.ac.jp/sd/Member/oyamada/OpenCV/html/py_tutorials/py_imgproc/py_thresholding/py_thresholding.html

OpenCVSharp4のMat行列の基本演算

自分へのメモも兼ねて基本演算をメモしておく

プログラム

using System;  
using OpenCvSharp;  

namespace matの演算を試してみる {  
    class Program {  
        static void Main(string[] args) {  

            //計算用のmat1とmat2を定義  
            Mat mat1 = new Mat(3, 3, MatType.CV_64FC1,  
                new double[,] {  
                    {1,2,3 },  
                    {4,5,6 },  
                    {7,8,9 }  
                }  
                );  

            Mat mat2 = new Mat(3, 3, MatType.CV_64FC1,  
                new double[,] {  
                    {2,9,4 },  
                    {7,5,3 },  
                    {6,1,8 }  
                 }  
                );  

            double num = 3;  

            //行列と行列の演算  
            Mat matA = mat1 + mat2;    //行列の和  
            Mat matB = mat1 - mat2;    //行列の差  
            Mat matC = mat1 * mat2;    //行列の積  
            Mat matD = mat1.Mul(mat2); //要素の積  
            Mat matL = new mat();  
            cv2.Divide(mat1, mat2, matL);//要素の除算  


            //行列とスカラーの演算  
            Mat matE = mat1 + num;//要素の和(順序はどちらでもよい)  
            Mat matF = mat1 - num;//要素の差  
            Mat matG = mat1 * num;//スカラー倍(順序はどちらでもよい)  
            Mat matH = mat1 / num;//スカラーで割る  
            Mat matI = num / mat1;//要素を逆数にしてスカラー倍  

            //行列の単項演算  
            double a = Cv2.Determinant(mat2); //行列式  
            double b = Cv2.Norm(mat2);       //L-2ノルム  
            Mat matJ = mat2.T();              //転置  
            Mat matK = mat2.Inv();            //逆行列(SVD)  



            Console.WriteLine("mat1 + mat2=");    Console.WriteLine(Cv2.Format(matA)); Console.WriteLine();  
            Console.WriteLine("mat1 - mat2=");    Console.WriteLine(Cv2.Format(matB)); Console.WriteLine();  
            Console.WriteLine("mat1 * mat2=");    Console.WriteLine(Cv2.Format(matC)); Console.WriteLine();  
            Console.WriteLine("mat1.Mul(mat2)="); Console.WriteLine(Cv2.Format(matD)); Console.WriteLine();  

            Console.WriteLine("mat1 + num=");   Console.WriteLine(Cv2.Format(matE)); Console.WriteLine();  
            Console.WriteLine("mat1 - num=");     Console.WriteLine(Cv2.Format(matF)); Console.WriteLine();  
            Console.WriteLine("mat1 * num=");     Console.WriteLine(Cv2.Format(matG)); Console.WriteLine();  
            Console.WriteLine("mat1 / num=");     Console.WriteLine(Cv2.Format(matH)); Console.WriteLine();  
            Console.WriteLine("num / mat1=");     Console.WriteLine(Cv2.Format(matI)); Console.WriteLine();  

            Console.WriteLine("Cv2.Determinant(mat2)="); Console.WriteLine(a);                Console.WriteLine();  
            Console.WriteLine("Cv2.Norm(mat2)");         Console.WriteLine(b);                Console.WriteLine();  
            Console.WriteLine("mat2.T=");                Console.WriteLine(Cv2.Format(matJ)); Console.WriteLine();  
            Console.WriteLine("mat2.Inv()=");            Console.WriteLine(Cv2.Format(matK)); Console.WriteLine();  


            Cv2.WaitKey();  
        }  
    }  
}  

結果

mat1 + mat2=  
[3, 11, 7;  
 11, 10, 9;  
 13, 9, 17]  

mat1 - mat2=  
[-1, -7, -1;  
 -3, 0, 3;  
 1, 7, 1]  

mat1 * mat2=  
[34, 22, 34;  
 79, 67, 79;  
 124, 112, 124]  

mat1.Mul(mat2)=  
[2, 18, 12;  
 28, 25, 18;  
 42, 8, 72]  

mat1 + num=  
[4, 5, 6;  
 7, 8, 9;  
 10, 11, 12]  

mat1 - num=  
[-2, -1, 0;  
 1, 2, 3;  
 4, 5, 6]  

mat1 * num=  
[3, 6, 9;  
 12, 15, 18;  
 21, 24, 27]  

mat1 / num=  
[0.3333333333333333, 0.6666666666666666, 1;  
 1.333333333333333, 1.666666666666667, 2;  
 2.333333333333333, 2.666666666666667, 3]  

num / mat1=  
[3, 1.5, 1;  
 0.75, 0.6, 0.5;  
 0.4285714285714285, 0.375, 0.3333333333333333]  

Cv2.Determinant(mat2)=  
-360  

Cv2.Norm(mat2)  
16.881943016134134  

mat2.T=  
[2, 7, 6;  
 9, 5, 1;  
 4, 3, 8]  

mat2.Inv()=  
[-0.1027777777777778, 0.1888888888888889, -0.01944444444444444;  
 0.1055555555555556, 0.02222222222222222, -0.06111111111111112;  
 0.0638888888888889, -0.1444444444444445, 0.1472222222222222]  
Console

#参考
http://opencv.jp/cookbook/opencv_mat.html