2011/02/15

詳解OpenCVの練習問題(2)

今日も詳解OpenCVの練習問題を少し解いていきたいと思います。


問題1:
  byte型の3チャネルをもつ、100x100サイズの配列を作る。

問題2:
  cvCircleを使って、その中に円を描画する。


問題3:
  cvPtr2Dを使って、緑の四角形を描画する。

問題4:
  ポインタ計算を使って、(20,5)と(40,20)の間に緑の四角形を描画する。

ソースコードは別館の方に置いてあります。



問題1の解説:
OpenCVではcvCreateMat( int rows, int cols, int type ); を使うことで、行列を作ることができます。今回はbyte型の3チャネルなので、CV_8UC3を指定します。

CvMat* matArray=cvCreateMat(100,100,CV_8UC3);


で、3チャネル、byte型、100 x 100サイズの行列を作ることができます。
OpenCVのリファレンスによると、チャネルの型は下記のような書式で定義されているようです。
 CV_<ビット深度>{U|S|F}C<チャネル数>



問題2の解説:
cvCircleは、
void cvCircle(CvArr* img, CvPoint center, int radius, CvScalar color, int thickness=1, int lineType=8, int shift=0)
という関数になっていて、imgのcenterに半径radiusの円を描きます。線の色はcolor、線の幅はthickness、線の種類はlineTypeで指定できます。

今回は円を書くだけなので、
 cvCircle(matArray,cvPoint(50,50),20,CV_RGB(255,0,0),1,8,0);
で(50,50)の位置に円を書くことができます。


問題3の解説:
cvPtr2D関数は、指定した配列の行、列へのポインタを返してくれます。

uchar* cvPtr2D(const CvArr* arr, int idx0, int idx1, int* type=NULL);
typeはオプションで、NULLを入れなかった場合は配列の要素の型情報が出力されるようです。

今回は型情報は必要無いので、
  uchar *ptr;
  ptr=(uchar *)cvPtr2D(matArray,y,x,NULL);
  *ptr=255;

でy行x列の値を255に設定することができます。
ただし、OpenCVはBGRBGRBGR...というようにメモリ上にデータを格納しているので、緑のチャネルを指定する場合はptrに1を加える必要があります。


問題4の解説:
私もあまり分かってないポインタ演算。

CvMat構造体のヘッダを見ると、
  int type;
  int step;
  int* refcount;
 union
 {
     uchar* ptr;
     short*  s;
     int*      i;
     float*  fl;
    double* db; 
} data;
//以下省略


となっています。
このunionというのは共用体というもので、定義してあるもののうち、どれか1種類を格納できる、というものです。詳しくは共用体・union/構造体との違い@C/C++StudyRoom を参照ください。


今回の配列はbyte型のデータ配列なので、uchar* ptrにデータが入っているはずです。

というわけで、
  matArray->data.ptr[0]
でデータの先頭、つまり(0,0)の青チャネルにアクセスできます。

同じように、
matArray->(x+y*matArray->cols)*3+1]=255;
で(x,y)の緑チャネルの値を255に設定することができました。

ポインタ演算が一番高速だとは思うのですが、ポインタ計算がちょっと大変ですね。

ではまた。


0 件のコメント:

コメントを投稿