2009年8月10日星期一

利用OpenCV进行图像连接

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

/* プロトタイプ宣言 */
IplImage *combine_image (int num, IplImage ** tmp);

/* メイン関数 */
int
main (int argc, char **argv)
{
  int i, img_num;
  IplImage **img;
  IplImage *combined_img;

  // (1)コマンド引数で指定された画像を全て読み込む
  if (argc < 2) {
    return 1;
  }
  else {
    img_num = argc - 1;
    img = (IplImage **) cvAlloc (sizeof (IplImage *) * img_num);
    for (i = 0; i < img_num; i++) {
      img[i] = cvLoadImage (argv[i + 1], CV_LOAD_IMAGE_COLOR);
      if (img[i] == 0)
        return -1;
    }
  }

  // (2)画像を連結する
  combined_img = combine_image (img_num, img);

  cvNamedWindow ("Image", CV_WINDOW_AUTOSIZE);
  cvShowImage ("Image", combined_img);
  cvWaitKey (0);

  cvDestroyWindow ("Image");
  cvReleaseImage (&combined_img);
  for (i = 0; i < img_num; i++) {
    cvReleaseImage (&img[i]);
  }
  cvFree (&img);

  return 0;
}

/* 画像を連結する関数 */
IplImage *
combine_image (int num, IplImage ** tmp)
{
  int i;
  int width = 0, height = 0;
  IplImage *cimg;
  CvRect roi = cvRect (0, 0, 0, 0);

  // (3)与えられた各画像から,連結後の幅と高さを求める
  for (i = 0; i < num; i++) {
    width += tmp[i]->width;
    height = height < tmp[i]->height ? tmp[i]->height : height;
  }
  cimg = cvCreateImage (cvSize (width, height), IPL_DEPTH_8U, 3);
  cvZero (cimg);

  // (4)ROIを利用して各画像をコピーする
  for (i = 0; i < num; i++) {
    roi.width = tmp[i]->width;
    roi.height = tmp[i]->height;
    cvSetImageROI (cimg, roi);
    cvCopy (tmp[i], cimg);
    roi.x += roi.width;
  }
  cvResetImageROI (cimg);

  return cimg;
}

// (1)コマンド引数で指定された画像を全て読み込む
コマンド引数で指定された画像を全て,カラー画像として読み込む.そのなかに1つでも読み込めない画像がある場合には終了する.

// (2)画像を連結する
あらかめ定義した関数combined_img()を呼び出して,画像を横方向に連結する.この例では単純に画像の上辺を揃えて横方向に連結を行うだけであるが,画像を折り返して連結したり,さらにいわゆる「矩形パッキング問題」をの解を求めることで無駄な領域が小さくなるように連結することもできる.また,このサンプルでは連結する関数combined_image()に画像のポインタの配列を渡しているが,可変引数を利用(stdarg.h)して,combine_image()を次のように定義する方法もある.

IplImage*
combine_image(int num, ...)
{
  va_list list;
  int i;
  int width = 0, height = 0;
  IplImage *tmp[num];
  IplImage *cimg;
  CvRect roi = cvRect(0, 0, 0, 0);
        
  va_start(list, num);
  for(i=0; iwidth;
    height = height < tmp[i]->height ? tmp[i]->height : height;
  }
  va_end(list);
  cimg = cvCreateImage(cvSize(width, height), IPL_DEPTH_8U, 3);
  cvZero(cimg);

  for(i=0; iwidth;
    roi.height = tmp[i]->height;
    cvSetImageROI(cimg, roi);
    cvCopy(tmp[i], cimg);
    roi.x += roi.width;
  }
  cvResetImageROI(cimg);
  
  return cimg;
}

没有评论:

发表评论

欢迎访问、交流!对本博客有何建议,请
来信告知!
本博内容来源于网络,如有不当或侵犯权益,请来信告知,将及时撤除!
如引用博客内容、论文,请注明原作者!

Google一下本博客