現在地 >> メニュー >> サンプルコード::OpenCV >>OpenCV::シーケンス >> OpenCV::シーケンス2 >> OpenCV::シーケンス3


問題


以下の三点で構成される三角形に、
外接するような矩形(くけい)を描画せよ。

(150,200)
(50,100)
(250,100)

その他条件:
 シーケンスを利用し、
  [CvBox2D型のデータを取得] → [矩形の頂点データ取得]
 としてデータを取ること。

 3点の頂点位置も描画する。



答え



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

using namespace std;

/*** 頂点データ ***/
#define NUM 3

int point_data[NUM][2]=
{
{150,200},
{50,100},
{20,100}
};


/** プロトタイプ宣言 **/
void DATA_SEQ_DATA(CvSeq *points, int data[][2]);
void GET_BOX_DATA(CvSeq *points, CvPoint *p);




int main( int argc, char **argv)
{

static CvSize window_size={300,300};
IplImage *imgA = cvCreateImage(window_size,IPL_DEPTH_8U,3);
cvSet (imgA, cvScalarAll (255), 0);


/* シーケンスの初期設定 */
CvMemStorage *storage1 = cvCreateMemStorage (0);
CvSeq *seq = cvCreateSeq (CV_SEQ_ELTYPE_POINT, sizeof (CvSeq), sizeof (CvPoint), storage1);


DATA_SEQ_DATA(seq, point_data); //シーケンスにデータをセット


CvPoint p[4];
GET_BOX_DATA(seq,p); //シーケンスからboxの頂点を取得(第2引数に格納)



/** 描画部分 **/
int k;
for(k = 0;k < NUM;k++)
{
cvCircle(imgA,*(CvPoint *)cvGetSeqElem( seq, k ),4,cvScalar(0,0,255),CV_FILLED);
}

for(k = 0;k < 4;k++)
{
cvLine(imgA,p[k],p[(k+1) % 4] ,CV_RGB (0, 0, 255));
}



cvNamedWindow("window",CV_WINDOW_AUTOSIZE);
cvShowImage("window",imgA);

cvWaitKey(0);

cvReleaseMemStorage( &storage1 );
cvReleaseImage(& imgA);
cvDestroyWindow("window");

return 0;
}



/***************[ここから、各種関数]****************/

/* シーケンスにデータをセット */
void DATA_SEQ_DATA(CvSeq *seq, int data[][2])
{

CvPoint tmp;
for(int k = 0; k < NUM;k++)
{
tmp.x = data[k][0];
tmp.y = data[k][1];
cvSeqPush (seq, &tmp);
}

}


/* シーケンスからboxの頂点を取得 */
void GET_BOX_DATA(CvSeq *seq, CvPoint *p)
{
CvBox2D box;
box = cvMinAreaRect2 (seq, NULL); //四角取得

CvPoint2D32f box_point[4];
cvBoxPoints (box, box_point); //四角から頂点を取得

for(int k = 0 ; k < 4;k++)
{
p[k] = cvPointFrom32f(box_point[k]); //int型で取得しなおす
}

}

メモ


3点以上だと、もっとも外にあるもので囲む。

傾いてない矩形の場合は、cvBoundingRect()

rotating calipers法
http://cgm.cs.mcgill.ca/~godfried/research/caliper...


傾いてない矩形の場合→cvBoundingRect()を使用した場合


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

using namespace std;

/*** 頂点データ ***/
#define NUM 3

int point_data[NUM][2]=
{
{150,200},
{50,100},
{20,150}
};


/** プロトタイプ宣言 **/
void DATA_SEQ_DATA(CvSeq *points, int data[][2]);





int main( int argc, char **argv)
{

static CvSize window_size={300,300};
IplImage *imgA = cvCreateImage(window_size,IPL_DEPTH_8U,3);
cvSet (imgA, cvScalarAll (255), 0);


/* シーケンスの初期設定 */
CvMemStorage *storage1 = cvCreateMemStorage (0);
CvSeq *seq = cvCreateSeq (CV_SEQ_ELTYPE_POINT, sizeof (CvSeq), sizeof (CvPoint), storage1);


DATA_SEQ_DATA(seq, point_data); //シーケンスにデータをセット


CvRect p;
p = cvBoundingRect(seq); //矩形のデータを取得


/** 描画部分 **/
int k;
for(k = 0;k < NUM;k++)
{
cvCircle(imgA,*(CvPoint *)cvGetSeqElem( seq, k ),4,cvScalar(0,0,255),CV_FILLED);
}

cvRectangle( imgA, cvPoint(p.x,p.y), cvPoint(p.x + p.width, p.y + p.height), CV_RGB(0,0,255));


cvNamedWindow("window",CV_WINDOW_AUTOSIZE);
cvShowImage("window",imgA);

cvWaitKey(0);

cvReleaseMemStorage( &storage1 );
cvReleaseImage(& imgA);
cvDestroyWindow("window");

return 0;
}



/***************[ここから、各種関数]****************/

/* シーケンスにデータをセット */
void DATA_SEQ_DATA(CvSeq *seq, int data[][2])
{

CvPoint tmp;
for(int k = 0; k < NUM;k++)
{
tmp.x = data[k][0];
tmp.y = data[k][1];
cvSeqPush (seq, &tmp);
}

}

目次

― その他 ―

Wiki内検索

計測中...(07.10.8〜)

Save The World






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


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

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