現在地 >> メニュー >> サンプルコード::OpenCV >> OpenCV::基本編08 >> OpenCV::データへの直接アクセス
関連間接アクセス


直接アクセス


配列やポインタなどで直接アクセスする場合、
  • 効率的である
  • 範囲外にアクセスした時の処理がない
といった特徴がある。

直接アクセスのおもな方法として以下の方法がある。

[方法1]


リファレンスのFAQに書いてある方法。

この方法は、縦方向(y)はアドレスで移動し、横方向(x)は配列でのアクセスを行っている。


(A).シングルチャネルのbyte(unsigned char)の場合



IplImage* img = cvCreateImage(cvSize(640,480),IPL_DEPTH_8U,1);
 ... ...
reinterpret_cast<unsigned char *>(imgA->imageData + y*imgA->widthStep)[x]=255; //(x,y)の位置を255にする



(B).マルチチャネルのbyte(unsigned char)の場合


オペレータ[]内の記述が少し異なる。


IplImage* img=cvCreateImage(cvSize(640,480),IPL_DEPTH_8U,3);
... ...
reinterpret_cast<unsigned char *>(imgA->imageData + y*imgA->widthStep)[x*imgA->nChannels]=0;  //B
reinterpret_cast<unsigned char *>(imgA->imageData + y*imgA->widthStep)[x*imgA->nChannels+1]=0; //G 
reinterpret_cast<unsigned char *>(imgA->imageData + y*imgA->widthStep)[x*imgA->nChannels+2]=0; //R



例えば、ループをまわして、ある1部分を書き換える場合は、

	for(int y = 50; y < 100 ; ++y)
	{
		for(int x = 100; x < 150; ++x)
		{
			reinterpret_cast<unsigned char *>(imgA->imageData + y*imgA->widthStep)[x*imgA->nChannels]=0;  //B
			reinterpret_cast<unsigned char *>(imgA->imageData + y*imgA->widthStep)[x*imgA->nChannels+1]=255; //G 
			reinterpret_cast<unsigned char *>(imgA->imageData + y*imgA->widthStep)[x*imgA->nChannels+2]=0; //R
		}
	}

といった感じで書くことができる。

※データがfloat型の時などは?

キャストを部分を変えるだけでよい。
reinterpret_cast<float *>(imgA->imageData + y*imgA->widthStep)[x*imgA->nChannels]=0;  //B




[方法2]


オペレータ[]の中に記述する。

(A).シングルチャネルで1バイトアライメント(char)の場合



IplImage* img  = cvCreateImage(cvSize(640,480),IPL_DEPTH_8U,1);
... ...
img->imageData[y*img->widthStep + x] = 0;


(B).マルチチャネルで1バイトアライメント



IplImage* img  = cvCreateImage(cvSize(640,480),IPL_DEPTH_8U,3);
... ...
img->imageData[y*img->widthStep + x*img->nChannels] = 100;
img->imageData[y*img->widthStep + x*img->nChannels + 1] = 100;
img->imageData[y*img->widthStep + x*img->nChannels + 2] = 100;


※注意点
imageDataの型が「char型」であって、「unsigned char」でない事に気をつける必要がある。


(C).float(4バイトアライメント)の時は?


widthStepをバイトサイズで割る必要がある。


IplImage* img  = cvCreateImage(cvSize(640,480),IPL_DEPTH_32F,3);
... ...
int step  = img->widthStep/sizeof(float);  //バイトサイズで割る
float * data   = (float *)img->imageData; //floatのポインタとしてわたす

data[y*step+x*img->nChannels] = 150;
data[y*step+x*img->nChannels+1] = 150;
data[y*step+x*img->nChannels+2] = 150;




[方法3]:CV_IMAGE_ELEMマクロ


OpenCVには「CV_IMAGE_ELEMマクロ」が用意されているので、
これを使った方が見やすいかもしれない。

[例]

	for(int y = 50; y < 100 ; ++y)
	{
		for(int x = 100; x < 150; ++x)
		{
			CV_IMAGE_ELEM(imgA,unsigned char,y,x*imgA->nChannels)= 0;
			CV_IMAGE_ELEM(imgA,unsigned char,y,x*imgA->nChannels+1)= 255;
			CV_IMAGE_ELEM(imgA,unsigned char,y,x*imgA->nChannels+2)= 0;
		}
	}


サンプルコード >> 直接アクセス::まとめコード

目次

― その他 ―

Wiki内検索

計測中...(07.10.8〜)

Save The World






▲よろしければ広告のクリックもお願いします


▲ランキングに参加しました

管理人/副管理人のみ編集できます