複数の矩形を包含する矩形
C
#include <cv.h>
#include <highgui.h>
#define RECT_NUM (8) /** number of inner rectangles **/
int
main (int argc, char **argv)
{
IplImage *img = 0;
CvRNG rng = cvRNG(cvGetTickCount());
CvRect inner[RECT_NUM], outer;
int i;
CvMat *rnum = cvCreateMat(RECT_NUM*2, 1, CV_32SC2);
// (1)allocate and initialize an image
img = cvCreateImage(cvSize(640, 480), IPL_DEPTH_8U, 3);
cvRectangle(img, cvPoint(0,0), cvPoint(640,480), CV_RGB(100,100,100), CV_FILLED, 8, 0);
// (2)generate rundom coordinates within a center space
cvRandArr(&rng, rnum, CV_RAND_UNI, cvScalar(img->width/8, img->height/8, 0, 0), cvScalar(img->width*7./8, img->height*7./8,0,0));
// (3)draw rectangles based on generated coordinates
for(i=0; i<RECT_NUM; i++) {
int x1 = rnum->data.i[i*4+0];
int y1 = rnum->data.i[i*4+1];
int x2 = rnum->data.i[i*4+2];
int y2 = rnum->data.i[i*4+3];
CvPoint tl = cvPoint(MIN(x1, x2), MIN(y1,y2));
CvPoint br = cvPoint(MAX(x1, x2), MAX(y1,y2));
cvRectangle(img, tl, br, CV_RGB(255,200,200), 2, 8, 0);
inner[i] = cvRect(tl.x, tl.y, br.x-tl.x, br.y-tl.y);
}
// (4)find a minimum rectangle including all rectangles
outer = inner[0];
for(i=1; i<RECT_NUM; i++)
outer = cvMaxRect(&outer, &inner[i]);
cvRectangle(img, cvPoint(outer.x, outer.y),
cvPoint(outer.x+outer.width, outer.y+outer.height), CV_RGB(255,0,0), 3, 8, 0);
// (5)show the iamge, and quit when any key pressed
cvNamedWindow ("BoundingRect", CV_WINDOW_AUTOSIZE);
cvShowImage ("BoundingRect", img);
cvWaitKey (0);
cvDestroyWindow("BoundingRect");
cvReleaseImage(&img);
return 0;
}
// (1)画像領域を確保し,それを初期化します.
サイズ 640×480 の画像領域を確保し,それを cvRectangle でグレー(100,100,100)に塗りつぶします.
// (2)画像中心領域に収まるランダムな座標を生成します.
cvRandArr を用いて,上下左右に 1/8 の余白を持つ中心領域に収まるような座標を生成します.
// (3)生成された座標を用いて,矩形を描画します.
生成された乱数座標を矩形の対角座標とすることでランダムな矩形を生成し,それを描画します. cvRectangle は,左上,右下の座標を必要とするので, MIN, MAX マクロを用いて適切な座標を利用します.
// (4)すべての矩形を包含する最小の矩形を求めます.
関数 cvMaxRect を用いて,生成された矩形を包含する最小の矩形を求めます. cvRectangle により,その矩形を赤色で描画します.
// (5)画像を表示します.
すべての矩形が描画された画像を表示し,何かキーが押されるまで待ちます.
C++
#include <cv.h>
#include <highgui.h>
using namespace cv;
int
main (int argc, char **argv)
{
// (1)allocate and initialize an image
Mat img(Size(640, 480), CV_8UC3, Scalar(100, 100, 100));
// (2)generate rundom coordinates within a center space
const int rect_num = 8; /** number of inner rectangles **/
Mat rnum(Size(rect_num*2,1), CV_32SC2);
RNG(getTickCount()).fill(rnum, RNG::UNIFORM, Scalar(img.cols/8, img.rows/8), Scalar(img.cols*7./8, img.rows*7./8));
// (3)draw rectangles based on generated random coordinates
vector<Rect> inner;
MatIterator_<Vec2i> itp = rnum.begin<Vec2i>();
for(; itp!=rnum.end<Vec2i>(); itp+=2) {
Point a((*itp)[0], (*itp)[1]), b((*(itp+1))[0], (*(itp+1))[1]);
rectangle(img, a, b, Scalar(200,200,255), 2);
inner.push_back(Rect(a, b));
}
// (4)find a minimum rectangle including all rectangles
vector<Rect>::iterator itr = inner.begin();
Rect outer = *itr;
for(++itr; itr!=inner.end(); ++itr)
outer |= *itr;
rectangle(img, outer.tl(), outer.br(), Scalar(0,0,255), 3);
// (5)show the iamge, and quit when any key pressed
namedWindow("img", CV_WINDOW_AUTOSIZE);
imshow("img", img);
waitKey(0);
return 0;
}
// (1)画像領域を確保し,それを初期化します.
サイズ 640×480 のグレー(100,100,100)で塗りつぶされた画像領域を確保します.
// (2)画像中心領域に収まるランダムな座標を生成します.
指定範囲内(上述のCの例と同様)に一様分布する疑似乱数で,行列を埋めます.
ここでは,低レベルな関数 RNG を利用して行列を埋めていますが, randu を利用しても同様のことが可能です.ただし,randu
は,常に同じシードを利用するデフォルト乱数生成器を利用するため,常に同じ順列の乱数が生成されます.実行の度に異なる乱数を使用したい場合には,例えばここで用いているように getTickCount を利用して乱数を生成します.このサンプルでは,上下左右に 1/8
の余白を持つ中心領域に収まるような座標が生成されます.
// (3)生成された座標を用いて,矩形を描画します.
生成された乱数座標を矩形の対角座標とすることでランダムな矩形を生成し,それを描画します. cvRectangleとは異なり, rectangle はパラメータとして入力された座標が左上,右下の順ではなくとも適切な矩形を描画するので,座標をそのまま利用します.
// (4)すべての矩形を包含する最小の矩形を求めます.
Rect クラスのオーバーライドされた |= 演算子を用いて,すべての矩形を含む矩形(すべての矩形の論理和)を求めます.関数 rectangle により,その矩形を赤色で描画します.
// (5)画像を表示します.
すべての矩形が描画された画像を表示し,何かキーが押されるまで待ちます.


