Miyabiarts.net

一年に一度の更新頻度

2枚の画像のモザイキング

前に紹介した「OpenCVを用いた特徴点対応付け」を応用することで複数の画像をモザイキングすることができます。
今回は、OpenCVを用いて下に示す2枚の画像をモザイキングして、1枚の大きな画像を作ります。
今回の例では、2枚の画像が大体半分程度重なり合ってないと上手くいかないです。
あと、画像合成の関係上、1枚目の画像に対して2枚目の画像が左側になるように撮影しないと正しい結果が得られませんので気をつけてください。

モザイキングする画像

画像間の対応付け

SURFで検出した特徴点間の対応を全て表示しています。

モザイキング結果

コード

#include <opencv/opencv2.h>

int main()
{
  // モザイキングする画像
  std::string fn1 = "image0.png";
  std::string fn2 = "image1.png";

  // 画像読み込み(グレースケールで読み込み)
  cv::Mat_< unsigned char > image1 = cv::imread( fn1, 0 );
  cv::Mat_< unsigned char > image2 = cv::imread( fn2, 0 );

  // 特徴点の検出
  cv::SurfFeatureDetector detector;
  std::vector< cv::KeyPoint > keys1, keys2;
  detector.detect( image1, keys1 );
  detector.detect( image2, keys2 );

  // 特徴量の記述
  cv::SurfDescriptorExtractor extractor;
  cv::Mat_ desp1, desp2;
  extractor.compute( image1, keys1, desp1 );
  extractor.compute( image2, keys2, desp2 );

  // 特徴点の対応付け
  std::vector< cv::DMatch > matches;
  cv::FlannBasedMatcher matcher;
  matcher.match( desp1, desp2, matches );

  // 対応点をstd::vectorに格納
  std::vector< cv::Vec2f > points1( matches.size() );
  std::vector< cv::Vec2f > points2( matches.size() );

  for( size_t i = 0 ; i < matches.size() ; ++i )
  {
    points1[ i ][ 0 ] = keys1[ matches[ i ].queryIdx ].pt.x;
    points1[ i ][ 1 ] = keys1[ matches[ i ].queryIdx ].pt.y;

    points2[ i ][ 0 ] = keys2[ matches[ i ].trainIdx ].pt.x;
    points2[ i ][ 1 ] = keys2[ matches[ i ].trainIdx ].pt.y;
  }

  // 画像間の平面射影変換行列を取得
  cv::Mat_< float > homography = cv::findHomography( points1, points2, CV_RANSAC );

  // 画像の読み込み(RGB画像で読み込み直し)
  cv::Mat_< cv::Vec3b > rgb_image1 = cv::imread( fn1, 1 );
  cv::Mat_< cv::Vec3b > rgb_image2 = cv::imread( fn2, 1 );

  // 画像1を画像2の空間に投影
  // 出力画像の大きさは適当に決定
  cv::Mat_< cv::Vec3b > result;
  cv::warpPerspective( rgb_image1, result, homography, cv::Size( static_cast( rgb_image1.cols * 1.5 ), rgb_image1.rows ) );

  // 画像2を結果画像にコピー
  // 合成方法は上書き
  for( int y = 0 ; y < rgb_image2.rows ; ++y )
  {
    for( int x = 0 ; x < rgb_image2.cols ; ++x )
    {
      result( y, x ) = rgb_image2( y, x );
    }
  }

  // モザイキング結果を表示
  cv::imshow( "Mosaicing", result );
  cv::waitKey();

  return 0;
}
広告

2枚の画像のモザイキング」への1件のフィードバック

  1. MOHD NORZALI HAJI MOHD 2011年12月3日 04:43

    there was an error in the for loop below at x and y:

    for( size_t i = 0 ; i —— ビルド開始: プロジェクト: surf mosaicing, 構成: Debug Win32 ——
    1>2011/12/03 13:40:02 にビルドを開始しました。
    1>InitializeBuildStatus:
    1> “Debug\surf mosaicing.unsuccessfulbuild” のタッチ タスクを実行しています。
    1>ClCompile:
    1> main.cpp
    1>c:\users\mohd\documents\visual studio 2010\projects\opencv2.3.1\surf mosaicing\surf mosaicing\main.cpp(40): error C2039: ‘x’ : ‘cv::Vec’ のメンバーではありません。
    1> with
    1> [
    1> _Tp=float,
    1> cn=2
    1> ]
    1>c:\users\mohd\documents\visual studio 2010\projects\opencv2.3.1\surf mosaicing\surf mosaicing\main.cpp(41): error C2039: ‘y’ : ‘cv::Vec’ のメンバーではありません。
    1> with
    1> [
    1> _Tp=float,
    1> cn=2
    1> ]
    1>c:\users\mohd\documents\visual studio 2010\projects\opencv2.3.1\surf mosaicing\surf mosaicing\main.cpp(43): error C2039: ‘x’ : ‘cv::Vec’ のメンバーではありません。
    1> with
    1> [
    1> _Tp=float,
    1> cn=2
    1> ]
    1>c:\users\mohd\documents\visual studio 2010\projects\opencv2.3.1\surf mosaicing\surf mosaicing\main.cpp(44): error C2039: ‘y’ : ‘cv::Vec’ のメンバーではありません。
    1> with
    1> [
    1> _Tp=float,
    1> cn=2
    1> ]
    1>
    1>ビルドに失敗しました。
    1>
    1>経過時間 00:00:01.33
    ========== ビルド: 0 正常終了、1 失敗、0 更新不要、0 スキップ ==========

%d人のブロガーが「いいね」をつけました。