OpenCVの関数の意味がわからずに困っています。

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
keho

OpenCVの関数の意味がわからずに困っています。

#1

投稿記事 by keho » 12年前

WEBカメラからの画像の特定色の面積を算出するプログラムを作りたく、サイトで見つけた特定色のマスキングプログラムを参考にして勉強をしておりますが、参考書にも検索をかけても載っていないプログラムがあり困っています。
無知で申し訳ありませんが

CV_INIT_PIXEL_POS(pos_src, (unsigned char*) tmp->imageData, tmp->widthStep,cvGetSize(tmp), x, y, tmp->origin);

p_src = CV_MOVE_TO(pos_src, x, y, 3);

の二つの関数の意味を教えていただきたいです。
CV_INIT_PIXEL_POSdはpos_srcに座標情報を与えているなかな、と推測はしていますがpos_srcやp_srcにどのような値が入っていてどのように扱ってよいのかがわかりません。

以下がサイトで見つけたソースコードとなります。
よろしくお願いいたします。

コード:

///////////////////////////////////////////////////////////////////////////////////////////
#include <cv.h>
#include <highgui.h>


void GetMaskHSV(IplImage* src, IplImage* mask,int erosions, int dilations)
{
	int x = 0, y = 0;
	uchar H, S, V;
	uchar minH, minS, minV, maxH, maxS, maxV;

	CvPixelPosition8u pos_src, pos_dst;
	uchar* p_src;
	uchar* p_dst;
	IplImage* tmp;


	tmp = cvCreateImage(cvGetSize(src), IPL_DEPTH_8U, 3);

	//HSVに変換
	cvCvtColor(src, tmp, CV_RGB2HSV);

	CV_INIT_PIXEL_POS(pos_src, (unsigned char*) tmp->imageData,
					   tmp->widthStep,cvGetSize(tmp), x, y, tmp->origin);

	CV_INIT_PIXEL_POS(pos_dst, (unsigned char*) mask->imageData,
					   mask->widthStep, cvGetSize(mask), x, y, mask->origin);

	minH = 100;	maxH = 115;
	minS = 80;	maxS = 255;
	minV = 120;	maxV = 255;
	for(y = 0; y < tmp->height; y++) {
		for(x = 0; x < tmp->width; x++) {
			p_src = CV_MOVE_TO(pos_src, x, y, 3);
			p_dst = CV_MOVE_TO(pos_dst, x, y, 3);

			H = p_src[0];	//0から180
			S = p_src[1];
			V = p_src[2];

			if( minH <= H && H <= maxH &&
				minS <= S && S <= maxS &&
				minV <= V && V <= maxV
			) {
				p_dst[0] = 255;
				p_dst[1] = 255;
				p_dst[2] = 255;
			} else {
				p_dst[0] = 0;
				p_dst[1] = 0;
				p_dst[2] = 0;
			}
		}
	}

	if(erosions > 0)  cvErode(mask, mask, 0, erosions);
	if(dilations > 0) cvDilate(mask, mask, 0, dilations);

	cvReleaseImage(&tmp);
}


int main(int argc, char **argv)
{
	int c;
	CvCapture* capture = 0;
	IplImage* frame = 0;
	IplImage* mask = 0;
	IplImage* dst = 0;

	if(argc == 1 || (argc == 2 && strlen (argv[1]) == 1 && isdigit(argv[1][0])))
		capture = cvCreateCameraCapture(argc == 2 ? argv[1][0] - '0' : 0);

	frame = cvQueryFrame(capture);
	mask = cvCreateImage(cvSize(frame->width, frame->height), IPL_DEPTH_8U, 3);
	dst = cvCreateImage(cvSize(frame->width, frame->height), IPL_DEPTH_8U, 3);

	cvNamedWindow("src", CV_WINDOW_AUTOSIZE);
	cvNamedWindow("dst", CV_WINDOW_AUTOSIZE);

	while(1) {
		frame = cvQueryFrame(capture);
		GetMaskHSV(frame, mask, 1, 1);
		cvAnd(frame, mask, dst);

		cvShowImage("src", frame);
		cvShowImage("dst", dst);
		c = cvWaitKey(10);
		if(c == 'q') break;
	}

	cvDestroyWindow("src");
	cvDestroyWindow("dst");

	cvReleaseImage(&frame);
	cvReleaseImage(&dst);
	cvReleaseImage(&mask);
	cvReleaseCapture(&capture);

	return(0);
}

アバター
usao
記事: 1892
登録日時: 13年前
連絡を取る:

Re: OpenCVの関数の意味がわからずに困っています。

#2

投稿記事 by usao » 12年前

OpenCV2.3.1 のソースを検索したところ,CV_INIT_PIXEL_POSなどは legacy.hpp に書かれているようですよ.

#IplImageの画素データへのアクセス用ヘルパみたいな雰囲気のものなのかな

keho

Re: OpenCVの関数の意味がわからずに困っています。

#3

投稿記事 by keho » 12年前

usaoさん
返信ありがとうございます。
legacy.hpp内でCV_INIT_PIXEL_POSを検索かけてみましたが見つかりませんでした。
opencv2.4.8を使用しているのですが・・・。
なぜp_src[0],p_src[1],p_src[2]にHSVの値が入るのかということと、pos_srcにどの様な値が入っているのかが理解できません。
配列化しているのですかね?


CV_INIT_PIXEL_POS(pos_src, (unsigned char*) tmp->imageData,tmp->widthStep,cvGetSize(tmp), x, y, tmp->origin);
で、ある座標x,yにおけるH,S,Vの値を取得しpos_srcに格納、
p_src = CV_MOVE_TO(pos_src, x, y, 3);
           H = p_src[0]; //0から180
S = p_src[1];
V = p_src[2];
でp_srcを3次元の配列化してそれぞれにH,S,Vの値を格納する。
とざっくり解釈したのですが大丈夫ですか?
以下はマスキングの部分だけ抜き出したものです。
何度も申し訳ありませんがよろしくお願いしますm(__)m

コード:

void GetMaskHSV(IplImage* src, IplImage* mask,int erosions, int dilations)
{
	int x = 0, y = 0;
	uchar H, S, V;
	uchar minH, minS, minV, maxH, maxS, maxV;

	CvPixelPosition8u pos_src, pos_dst;
	uchar* p_src;
	uchar* p_dst;
	IplImage* tmp;


	tmp = cvCreateImage(cvGetSize(src), IPL_DEPTH_8U, 3);

	//HSVに変換
	cvCvtColor(src, tmp, CV_RGB2HSV);

	CV_INIT_PIXEL_POS(pos_src, (unsigned char*) tmp->imageData,
					   tmp->widthStep,cvGetSize(tmp), x, y, tmp->origin);

	CV_INIT_PIXEL_POS(pos_dst, (unsigned char*) mask->imageData,
					   mask->widthStep, cvGetSize(mask), x, y, mask->origin);

	minH = 100;	maxH = 115;
	minS = 80;	maxS = 255;
	minV = 120;	maxV = 255;
	for(y = 0; y < tmp->height; y++) {
		for(x = 0; x < tmp->width; x++) {
			p_src = CV_MOVE_TO(pos_src, x, y, 3);
			p_dst = CV_MOVE_TO(pos_dst, x, y, 3);

			H = p_src[0];	//0から180
			S = p_src[1];
			V = p_src[2];

			if( minH <= H && H <= maxH &&
				minS <= S && S <= maxS &&
				minV <= V && V <= maxV
			) {
				p_dst[0] = 255;
				p_dst[1] = 255;
				p_dst[2] = 255;
			} else {
				p_dst[0] = 0;
				p_dst[1] = 0;
				p_dst[2] = 0;
			}
		}
	}

	if(erosions > 0)  cvErode(mask, mask, 0, erosions);
	if(dilations > 0) cvDilate(mask, mask, 0, dilations);

	cvReleaseImage(&tmp);
}


アバター
usao
記事: 1892
登録日時: 13年前
連絡を取る:

Re: OpenCVの関数の意味がわからずに困っています。

#4

投稿記事 by usao » 12年前

私はマクロの存在をちらっと確認しただけで,中身までしっかり読んだわけじゃないので,
解釈が合ってるかどうかを正確には答えられませんが,

CV_INIT_PIXEL_POS は,構造体(この例だとCvPixelPosition8u)に各値をひたすら格納している
(要するに,画素データの位置を特定するのに十分な情報を獲得している)ようでしたので,
その後,
CV_MOVE_TO では,任意の座標の画素データへのポインタを得られる,ということでしょう.きっと.


>legacy.hpp内でCV_INIT_PIXEL_POSを検索かけてみましたが見つかりませんでした。

とのことですが,コンパイルは通っているんでしょうか?
元気に動いているのなら,どこかに CV_INIT_PIXEL_POS とかが書かれているハズなので,
includeしているヘッダを辿っていけば見つかるはずですから,解読してみてください.
オフトピック
あるいは,そのようなマクロの正体をあばくことに時間と労力をかけることが主たる関心事ではない,という話だったりするのならば
IplImageの画素データへの(自前での)アクセス方法
(imageDataの先に,どういう並びで画素データが詰まっているのか)を調べるのも良いかもしれません.
OpenCVのリファレンスマニュアルを見れば書いてあるかと思います.
また,動作速度をあまり気にしなくてよいならば cvGet2D とか cvSet2D とかで一応読み書きはできます.

[ちょっと投げやりすぎた気もするので追記]

コード:

IplImage *pImg = cvCreateImage( ... );  //画素値を見たい画像
//y=5のラインの先頭位置はこう
int y = 5;
unsigned char *pLine = pImg->imageData  +  y * pImg->widthStep;
//なので,(x=10,y=5)の画素データ位置を得たいならば,xの分だけオフセットすればいい.
//例えば,pImgが8bit3chであれば
int x = 10;
unsigned char *pPixel = pLine  +  x * 3;
//pImgがBGRフォーマットなのであれば,(x=10,y=5)の位置の色は
unsigned char B = pPixel[0];
unsigned char G = pPixel[1];
unsigned char R = pPixel[2];
といった感じです.
それらのマクロでも,最終的にこういった計算をしていると思います.

アバター
usao
記事: 1892
登録日時: 13年前
連絡を取る:

Re: OpenCVの関数の意味がわからずに困っています。

#5

投稿記事 by usao » 12年前

申し訳ありません.これ↓は誤報でした!
>OpenCV2.3.1 のソースを検索したところ,CV_INIT_PIXEL_POSなどは legacy.hpp に書かれているようですよ.

正しくは,
compat.hpp
です.
(フォルダ名とファイル名とを取り違えてしまっていました…)

CV_MOVE_TO の他にも
CV_MOVE_LEFT だとか CV_MOVE_UP だとかいうのがいろいろあるようです.

閉鎖

“C言語何でも質問掲示板” へ戻る