2016年1月1日金曜日

OpenCVのcv::Matについてメモ(画素の扱いとか)

OpenCVのcv::Matについてメモ

勉強し始めた時、あれMatのチャンネルって何?
あれ?どうやって各画素値いじるの?
あれ全部真っ白なっちゃった!?orzってなったのでそのメモ


#include <iostream>
#include <opencv2\opencv.hpp>


#define height 100
#define width 100

 void main(){

  double* data = new double[height*width](); //0で初期化
  //省略したけど、dataになにかいろんな数値入れておく
  /*
  .... dataに数値入れる処理
  for :
  data[i] = a とかで数値入れる
  */

  //dataをMatにぶち込む
  //32F、64Fにすれば255以上の数値も扱える
  Mat input(height, width, CV_64FC1, data);


  Mat img(input.rows, input.cols, CV_8UC3); //inputと同じ行数と列数を用意


  //ここでMatの各要素にアクセスする
  for (int y = 0; y < input.rows; ++y) {
   for (int x = 0; x < input.cols; ++x) {

    //ピクセルにアクセスするためのインデックス
    //G,B,Rの順 チャンネル数は3つ必要→Matは1次元だから3倍する
    int index = ((y * input.cols) + x) * 3;

    //とりあえず画素に何か数値入れる
    //doubleの数値を扱えるのは .atだけらしい
    int rgb = input.at<double>(y, x) + (x * y) % 255; //255諧調に

    //.dataでは扱える数値の最大が255
    //B,G,Rと連続しているのでindex, index+1, index+2でアクセス可能
    img.data[index] = rgb;
    img.data[index + 1] = rgb;
    img.data[index + 2] = rgb;
    //これで1ピクセルの色を扱える

   }
  }


  delete[] data; //明示的に解放

 }

こんな感じでやる。

#define height 100
#define width 100
は定数。const int とかでもいいと思うけどとりあえず、ここではあまり重要じゃない。

double* data = new double[height*width]();
cv::Mat input(height, width, CV_64FC1, data);
height*widthの1次元配列を確保。()をつけると0で初期化できるらしい。
heigh*widthつまり100x100の行列。
CV_64FC1はdouble型の1チャンネルの行列。
CV_8UC1とか
CV_8UC3とかいろいろある。C1とかC2がチャンネル数。
RGBの画像を扱いたかったら、CV_8UC3ってやる。R、G、Bそれぞれ1チャンネルずつ使うから。
でも、想像するのは1次元配列なのでデータのアクセスではじめはややこしいと思った。

3x3の画像    数値をいじるときの想像
■■□  →  ■■□■□■□■■
■□■     [0][1] .....                [8]  
□■■   

3x3のRGB画像だったら
BGR BGR BGR   →   BGR BGR BGR BGR BGR BGR BGR BGR BGR
BGR BGR BGR        [0][1][2]     .......                       [24][25][26]
BGR BGR BGR 


input.at<double>(y, x)
255以上の数値を扱うときは.atを使う。
あとCV_32FとかCV_64FとかでMatを作る

img.data[index]         //B
img.data[index + 1]    //G
img.data[index + 2]    //R
B,G,Rと1ピクセルを1次元配列の要素3つで扱うので
3チャンネルでMatを作っておく。
.dataでアクセスして、+1, +2で3つ分。



以上。



0 件のコメント:

コメントを投稿