OpenCV Android開発実戦--学習ノート--Mat画素操作【第3章】

6463 ワード

3.1画素読み書き#概要-Matは画像コンテナとして、データ部分に画像の画素データを格納し、関連APIで画像の画素データを取得することができる-Matの種類とチャネル数に応じて、適切な大きさのメモリ空間を開く-そしてget()メソッドで各画素点の読み取りをループする-次にput()メソッドでMatに対応するデータ部分を修正すればよい-デフォルトでは、imread方式MatオブジェクトタイプをCV_にロード8UC3
#準備コード[基本データ取得]
  Mat src = Imgcodecs.imread(fileUri.getPath());
  if(src.empty()){
      return 0;
  }
  int channels = src.channels();
  int width = src.cols();
  int height = src.rows();

#1ピクセルポイントデータを一度に読み込む-CV_8 UC 3のMatタイプ、対応データタイプはbyte-初期化byte配列、配列長は画像チャネル数-コード[効率低メモリ需要最小]に依存する
  byte[] data = new byte[channels];
  int b = 0, g = 0, r = 0;
  for(int rows = 0; row < height; row++){
      for(int col = 0; col < width; col++){
          //  
          src.get(row,col,data);
          b = data[0]&0xff;
          g = data[1]&0xff;
          r = data[2]&0xff;

          //  -    
          b = 255 - b;
          g = 255 - g;
          r = 255 - r;

          //  
          data[0] = (byte)b;
          data[1] = (byte)g;
          data[2] = (byte)r;
          src.put(row,col,data);
      }
  }

#1行のピクセルデータを一度に読み込む-まず各行のピクセル配列の長さを定義する配列長=画像幅X各ピクセルのチャネル数の和-次にデータを繰り返し修正する-コード[速度が向上し、メモリ要件が増大]
  byte[] data = new byte[channels*width];
  int b = 0, g = 0, r = 0;
  int pv = 0;
  for(int row = 0; row < height; row++){
      //  
      src.get(row,0,data);

      //  
      for(int col= 0; col < data.length; col++){
          pv = data[col]&0xff;

          pv = 255 - pv;
          data[col] = (byte)pv;
      }

      //  
      src.put(row,0,data);
  }

#全画素を一度に読み込む-定義:配列長=画素幅X画像高さXチャネル数-コード[修正速度最速メモリ消費量最高]
  int pv = 0;
  byte[] data = new byte[channels*width*height];
  src.get(0,0,data);
  for(int i = 0; i < data.length, i++){
      pv = data[i]&0xff;
      pv = 255 - pv;
      data[i] = (byte)pv;
  }
  src.put(0,0,data);

3.2画像チャネルと平均分散計算#画像チャネルの分離、合成-取得チャネル数channels()-チャネル分離split()split(Matm,List mv)m:入力マルチチャネル画像mv:分離後の複数の単一チャネル画像、mv長さmチャネル数一致通路合并merge()merge(List mv,Mat dst)mv:複数のマージ対象の単一チャネル画像dst:マージ後のマルチチャネル画像-merge()split()メソッドは、CoreモジュールCoreモジュールから主にいくつかのMat操作とベースマトリクス書き込み機能-コード--Matオブジェクトの分離とマージを含む
  List mv = new ArrayList<>();
  Core.split(src,mv);

  for(Mat m : mv){
      int pv = 0;
      int channels = m.chanels();
      int width = m.cols();
      int height = m.rows();

      byte[] data = new byte[channels*width*height];

      m.get(0,0,data);

      for(int i = 0; i < data.length; i++){
          pv = data[i]&0fxx;
          pv = 255 - pv;
          data[i] = (byte)pv; 
      }

      m.put(0,0,data);
  }

  Core.merge(mv,src);


#平均値と標準分散計算・平均値計算-画素の和/画素個数・分散計算-各画素と平均値の差の分散と/画素個数の最終開根・実現方法-meantStdDev(Mattsrc,MatOfDouble mean,MatOfDouble stddev)src:Mat画像meanの入力:各チャネル平均値の計算、配列長とチャネル数が一致するstddev:各チャネル標準分散を計算し、配列長とチャネル数が一致する-meantStdDev(Matt src,MatOfDouble mean,MatOfDouble stddev,Mat mask)src:Mat画像meanの入力:各チャネル平均を計算し、配列長とチャネル数が一致するstddev:各チャネル標準分散を計算し、配列長とチャネル数が一致するmask:maskの同じ位置に対応する画素値がゼロに等しくない場合にのみ、srcの同じ位置の画素点が平均値と分散・適用の計算に関与する--平均値に基づいて画像を二値化-標準分散が小さいほど、図像の各画素の差が小さいことを示す.この場合の2値画像は無効な画像または空白の画像-効果:抽出またはフィルタ品質の低いスキャンまたは印刷画像・コード--平均値と分散を計算する
    //    
    Mat src = Imgcodecs.imread(fileUri.getPath());
    if(src.empty){
        return 0;
    }

    //     
    Mat gray = new Mat();
    Imgproc.cvtColor(src, gray, Imgproc.COLOR_BGR2GRAY);
    
    //      
    MatOfDouble means = new MatOfDouble();
    MatOfDouble stddevs = new MatOfDouble();
    Core.meanStdDev(gray, means, stddevs);
    
    //      
    double[] mean = means.toArray();
    double[] stddev = stddevs.toArray();
    Log.i(TAG,"gray image means : " + mean[0]);
    Log.i(TAG,"gray image stddev : " + stddev[0]);
    
    //      
    imt width = gray.cols();
    int height = gray.rows();
    byte[] data = new byte[width*height];
    gray.get(0,0,data);
    int pv = 0;
    
    //       
    int t = (int) mean[0];
    for(int i = 0; i < data.length, i++){
        pv = data[i]&0xff;

        if(pv > t){
            data[i] = (byte)255;
        }else{
            data[i] = (byte)0;
        }
    }
    gray.put(0,0,data);

3.3演算操作と画像の明るさとコントラストの調整#演算操作API-OpenCVのCoreモジュールはMatオブジェクトの加減乗除演算操作をサポートする-これらの操作は2つのMatオブジェクトの間でもよいし、MattオブジェクトとScalarが直接行うこともできる-一般的な方法add(Mat src 1,Mat src 2,Mat dst)subtract(Mat src 1,Mat src 2,Mat dst)multiply(Mat src 1,Mat src 2,Mat dst)divide(Mat src 1,Mat src 2,Mat dst)src 1:入力された最初のMat画像オブジェクトsrc 2:入力された2番目のMat画像オブジェクトdst:演算操作で出力されたMat画像オブジェクトsrc 2のタイプは、Scalarタイプであってもよい.この場合、画素点がScalarの各ベクトルで指定された演算を完了する-src 1 src 2サイズタイプと一致しなければならないことを示す.デフォルトの出力画像タイプは入力画像タイプと一致しています
#画像の明るさとコントラストを調整する-画像の明るさとコントラストは、画像の2つの基本的な属性であるRGB色画像である:輝度が高いほど、画素点の対応するRGB値が大きくなり、255に近づくほど、逆に低くなる.-画像コントラストは、画像の色と輝度との差感知を記述するために使用される限り.コントラストが大きいほど、画像の各画素と周囲との差が大きくなり、画像全体の細部が顕著になる-乗算法拡大/縮小画像画素間の差加減法による画像輝度調整-コード実装
    //    
    Mat src = Imgcodecs.imread(fileUri.getPath());
    if(src.empty){
        return 0;
    }

    /*
    *    
    *b       [        ]
    */
    Mat dst1 = new Mat();
    Core.add(src, new Scalar(b,b,b), dst1);

    /*
    *      
    *c       [     0~3.0] [  1       ]
    */
    Mat dst2 = new Mat();
    Core.multiply(dst1, new Scalar(c,c,c), dst2);

    //   Bitmap,  
    Bitmap bm = Bitmap.creatBitmap(src,cols(),crs.rows(),Bitmap.Config.ARGB_8888);
    Mat result = new Mat();
    Imgproc.cvtColor(dst2, result, Imgproc.COLOR_RGB2RGBA);
    Utils.matToBitmap(result, bm);


3.4重みに基づく画像重畳#実現関数・addWeighted(Mat src 1,double alpha,Mat src 2,double beta,double gama,Matdst)-src 1:入力された1番目のMat画像alpha:混合時に1番目のMatオブジェクトが占める重みの大きさsrc 2:入力された2番目のMat画像beta:混合時に2番目のMat画像が占める重みの大きさgamma:混合後に輝度補正(アップまたはダウン)dstを行うか否かを示す:重み重畳後のMatオブジェクトを出力する-よくある場合、ウェイト調整には条件を満たす必要があります:alpha+beta=1.0-メソッド式:dst=src 1*alpha+src 2*beta+gamma
3.5 Matのその他各種画素操作#概要-OpenCVは画像算数操作に加え、画像論理操作、二乗、LOG取り、正規化等の操作#画像論理操作-bitwise_をサポートするnot(Mat src,Mat dst)取反操作-bitwise_and(Mat src 1,Mat src 2,Mat dst)は、両画像を混合した出力画像に対して、操作により画像輝度を低下させる効果がある-bitwise_or(Mat src 1,Mat src 2,Mat dst)または両画像混合後の出力画像に対する操作による画像輝度強化効果-bitwise_xor(Mat src 1,Mat src 2,Mat dst)異種または操作による入力画像の重ね合わせに対する逆効果#正規化と線形絶対値縮小変換-convertScale Abs(Mat src,Mat dst)-normalize(Mat src,Mat dst,double alpha,double beta,int norm_type,Mat mask)alpha:指定範囲に正規化された低値beta:指定範囲に正規化された高値type:dst画像タイプ、デフォルト-1、表示タイプは入力画像srcと同じmask:マスクレイヤデフォルトnew Mat()