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