勉強し始めた時、あれ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 とかでもいいと思うけどとりあえず、ここではあまり重要じゃない。
#define width 100
double* data = new double[height*width]();
cv::Mat input(height, width, CV_64FC1, data);
height*widthの1次元配列を確保。()をつけると0で初期化できるらしい。cv::Mat input(height, width, CV_64FC1, data);
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つで扱うのでimg.data[index + 1] //G
img.data[index + 2] //R
3チャンネルでMatを作っておく。
.dataでアクセスして、+1, +2で3つ分。
以上。
![]() |

![]() |

0 件のコメント:
コメントを投稿