変換行列を元に、画像を変形する

void warpPerspective(InputArray before, OutputArray after, InputArray matrix, Size dsize, int flags, int borderMode, const Scalar& borderValue);

  • beforeをMatrix(ホモグラフィ)に基づいて変換

引数

  • before:Mat型の画像。座標変換前の画像
  • after:Mat型の画像。座標変換後の画像
  • matrix:Mat型の変換行列(ホモグラフィ)
  • dsize:Size型の出力画像のサイズ
  • flag:int型で変換方法のフラグ。詳細は後述。省略した場合はINTER_LINEAR
  • borderMode:int型の、境界の対処方法。省略した場合はBORDER_CONSTANT
  • borderValue:Scalar型の値。WARP_FILL_OUTLIERSを指定した場合、この色で空いた部分を塗りつぶす

返り値

  • void型なのでなし

void warpAffine(InputArray before, OutputArray after, InputArray matrix, Size dsize, int flags, int borderMode, const Scalar& borderValue);

  • beforeをMatrix(アフィン行列)に基いて変換

引数

  • 基本的にwarpPerspectiveと同じ
  • before:Mat型の画像。座標変換前の画像
  • after:Mat型の画像。座標変換後の画像
  • matrix:Mat型の変換行列。2x3(2 rows , 3 columns)の変換行列
  • dsize:Size型の出力画像のサイズ
  • flag:int型で変換方法のフラグ。詳細は後述。省略した場合はINTER_LINEAR
  • borderMode:int型の、境界の対処方法。省略した場合はBORDER_CONSTANT
  • borderValue:Scalar型の値。WARP_FILL_OUTLIERSを指定した場合、この色で空いた部分を塗りつぶす

返り値

  • void型なのでなし

解説

  • flag、borderMode、borderValueの引数については下記の通り

引数flagについて

  • flagのデフォルト値はINTER_LINEAR。取れる値は以下の通り
    • INTER_NEAREST:最近傍補間(0)
    • INTER_LINEAR:線型補間(1)
    • INTER_CUBIC:バイキュービック補間(2)
    • INTER_LANCZOS4:Lanczos補間(4)
    • WARP_INVERSE_MAP:逆変換による補間(16)
    • INTER_AREAを指定すると、INTER_LINEARに置き換えられる。
  • flagsは基本的に補間方法を指定する
    • 補間方法による違いはサンプルコードの実行結果参照
  • WARP_INVERSE_MAPは、ホモグラフィ、もしくはアフィン変換を逆方向に行う場合に使う
  • WARP_FILL_OUTLIERSは、C時代の名残。指定されても、内部では参照されていないっぽい。
    • 代わりに、borderModeのBORDER_CONSTANTを使え、ということであろう。
    • ちなみに両関数ともCインタフェースはC++インタフェースのラッパー

引数borderModeについて

  • borderModeのデフォルト値はBORDER_CONSTANT。取れる値は以下の通り
    • BORDER_CONSTANT:指定した値(borderValue)で塗りつぶす(0)
    • BORDER_REPLICATE:縁の画素値を、繰り返し並べる(1)
    • BORDER_REFLECT:同じ画像を、反転させながら並べる(2)
    • BORDER_WRAP:同じ画像を繰り返し並べる(3)
    • BORDER_REFLECT_101:同じ画像を反転させながら並べる(4)
    • BORDER_TRANSPARENT:画像の外側には触れない(5)
  • 画像を変換させるので、もともとの画像の外側、縁をどう扱うか、がborderModeの意味するところ
  • 各borderModeで生成されうる画像についてはサンプルコードの実行結果を参照のこと
  • BORDER_REFLECTとBORDER_REFLECT_101は非常に似た挙動を示すが、微妙に違う
    • BORDER_REFLECTは、縁の画素が繰り返されるため、2度現れる
    • BORDER_REFLECT_101は、縁の画素は繰り返されない
    • サンプルコードで、この挙動の違いが見えるので、参照のこと
  • 以下2つの定義も存在するが、エイリアスである
    • BORDER_REFLECT101とBORDER_DEFAULT、BORDER_REFLECT_101のエイリアス
    • ちなみに省略した場合はBORDER_CONSTANTであり、BORDER_DEFAULTでは無いので注意
    • このenum定数群を使うのはwarpPerspectiveやwarpAffine以外にもたくさんあり、主にフィルタ処理する関数では、BORDER_DEFAULTが省略した場合のデフォルト値として利用される。

引数borderValueについて

  • borderValueのデフォルトは黒(Scalar())

変換方法について

  • ホモグラフィを用いて変換する場合はwarpPerspectiveを、アフィン行列を用いて変換する場合はwarpAffineを使用する
  • warpPerspectiveは以下の数式に基づいて変換を行う
    • \left(\begin{array}{c} x^{\prime} \\ y^{\prime} \\ 1 \end{array}\right) = s\left(\begin{array}{ccc} M_{11} & M_{12} &  M_{13} \\ M _{21} &  M _{22} &  M _{23} \\ M _{31} &  M _{32} &  1 \end{array}\right)\left(\begin{array}{c} x \\ y \\ 1 \end{array}\right)
    • 書き換えると、ヘッダ/ドキュメントにある様な、下記の式になる
    • \left(\begin{array}{c} x^{\prime} \\ y^{\prime} \end{array}\right) =  \left(\begin{array}{c} \frac{M_{11} x + M_{12} y + M_{13}}{M_{31} x + M_{32} y + 1} \\ \frac{M_{21} x + M_{22} y + M_{23}}{M_{31} x + M_{32} y + 1} \end{array} \right)
  • warpAffineは以下の数式に基づいて変換を行う
    • \left(\begin{array}{c} x^{\prime} \\ y^{\prime} \end{array}\right) = \left(\begin{array}{ccc} M _{11} & M _{12} &  M _{13} \\ M _{21} &  M _{22} &  M _{23} \end{array}\right)\left(\begin{array}{c} x \\ y \end{array}\right)
    • 書き換えると、ヘッダ/ドキュメントにある様な、下記の式になる
    • \left(\begin{array}{c} x^{\prime} \\ y^{\prime} \end{array}\right) = \left(\begin{array}{c} M _{11} x +  M _{12} y +  M _{13} \\ M _{21} x +  M _{22} y +  M _{23}\end{array}\right)

サンプルコード

#include <opencv2/calib3d/calib3d.hpp>
#include <opencv2/imgcodecs/imgcodecs.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/highgui/highgui.hpp>

const char filename[]      = "/path/to/opencv/samples/data/lena.jpg";
const char windowName[]    = "output";
const float srcPoints[]   = {  0.0,  0.0,1.0,  512.0,  0.0,1.0,  512.0,512.0,1.0,    0.0,512.0,1.0};
const float dstPoints[]   = {218.0,110.0,1.0,  451.0,202.0,1.0,  328.0,395.0,1.0,  112.0,313.0,1.0};
const float dstPoints2[]  = {502.0,-10.0,1.0,  522.0,-10.0,1.0,  522.0, 10.0,1.0,  502.0, 10.0,1.0};
const unsigned int cPoints = 4;

void warpAffineAndShow(cv::Mat& before, cv::Mat& after, cv::Mat& matrix, cv::Size& dstSize, int flag, int borderMode = cv::BORDER_CONSTANT, int fillval = 0)
{
	using namespace cv;

	// warp the image
	warpAffine(before, after, matrix, dstSize, flag, borderMode, fillval);
	imshow(windowName, after);
	waitKey(0);
}

void warpAndShow(cv::Mat& before, cv::Mat& after, cv::Mat& matrix, cv::Size& dstSize, int flag, int borderMode = cv::BORDER_CONSTANT, int fillval = 0)
{
	using namespace cv;

	// warp the image
	warpPerspective(before, after, matrix, dstSize, flag, borderMode, fillval);
	imshow(windowName, after);
	waitKey(0);
}

int main(int argc, char **argv)
{
	using namespace cv;
	Mat lena = imread(filename, IMREAD_GRAYSCALE);

	// prepare the corresponding points
	Mat src        = Mat(cPoints, 3, CV_32FC1, (void*)srcPoints);
	Mat dst        = Mat(cPoints, 3, CV_32FC1, (void*)dstPoints);

	// find the homography
	Mat homography = findHomography(src, dst);

	// prepare the result image
	Mat warpImage;
	Size dstSize = lena.size();

	// make a window
	namedWindow(windowName);

	// warp the image using homography
	warpPerspective(lena, warpImage, homography, dstSize);
	// show the result
	imshow(windowName, warpImage);
	// wait
	waitKey(0);

	// cut out 3 points from corresponding points
	// Affine matrix only acceps 3 x 2 matrix
	Mat src1   = src.colRange(0,2).rowRange(0,3).clone();
	Mat dst1   = dst.colRange(0,2).rowRange(0,3).clone();
	// get affine matrix
	Mat affine = getAffineTransform(src1, dst1);

	// warp the image using affine matrix
	warpAffineAndShow(lena, warpImage, affine, dstSize, INTER_LINEAR); 
	warpAffineAndShow(lena, warpImage, affine, dstSize, INTER_LINEAR, BORDER_REPLICATE); 

	// try various border types
	warpAndShow(lena,    warpImage, homography, dstSize, INTER_LINEAR);
	warpAndShow(lena,    warpImage, homography, dstSize, INTER_LINEAR, BORDER_REPLICATE);
	warpAndShow(lena,    warpImage, homography, dstSize, INTER_LINEAR, BORDER_WRAP);
	warpAndShow(lena,    warpImage, homography, dstSize, INTER_LINEAR, BORDER_REFLECT);
	warpAndShow(lena,    warpImage, homography, dstSize, INTER_LINEAR, BORDER_REFLECT_101);
	warpAndShow(lena.clone(), lena, homography, dstSize, INTER_LINEAR, BORDER_TRANSPARENT);

	// find the homography
	dst = Mat(cPoints, 3, CV_32FC1, (void*)dstPoints2);
	homography = findHomography(src, dst);

	// try various interpolation method
	warpAndShow(lena, warpImage, homography, dstSize, INTER_NEAREST +WARP_INVERSE_MAP);
	warpAndShow(lena, warpImage, homography, dstSize, INTER_LINEAR  +WARP_INVERSE_MAP);
	warpAndShow(lena, warpImage, homography, dstSize, INTER_CUBIC   +WARP_INVERSE_MAP);
	warpAndShow(lena, warpImage, homography, dstSize, INTER_LANCZOS4+WARP_INVERSE_MAP);
	warpAndShow(lena, warpImage, homography, dstSize, INTER_AREA    +WARP_INVERSE_MAP);

	// check difference of BORDER_REFLECT and BORDER_REFLECT_101
	warpAndShow(lena, warpImage, homography, dstSize, INTER_NEAREST+WARP_INVERSE_MAP, BORDER_REFLECT);
	warpAndShow(lena, warpImage, homography, dstSize, INTER_NEAREST+WARP_INVERSE_MAP, BORDER_REFLECT_101);

	destroyAllWindows();

	return 0;
}

実行結果

  • TBW
    result0000AffineConstant.png
    result0001AffineReplicate.png
    result0002PerspectiveConstant.png
    result0003PerspectiveReplicate.png
    result0004PerspectiveWrap.png
    result0005PerspectiveReflect.png
    result0006PerspectiveReflect101.png
    result0007PerspectiveTransparent.png
    result0008InterpolationNearest.png
    result0009InterpolationLinear.png
    result0010InterpolationCubic.png
    result0011InterpolationLanczos4.png
    result0012InterpolationArea.png
    result0013BorderReflect.png
    result0014BorderReflect101.png

実体ファイル

OpenCV 2.4系列

  • warpPerspective、warpAffine
    • modules/imgproc/include/opencv2/imgproc/iimgproc.hpp
    • modules/imgproc/src/imgwarp.cpp

OpenCV 3.0系列

  • warpPerspective、warpAffine
    • modules/imgproc/include/opencv2/imgproc/iimgproc.hpp
    • modules/imgproc/src/imgwarp.cpp

ジャンル:OpenCV:OpenCV 2.4:OpenCV 3.0:OpenCV 3.1準拠


添付ファイル: fileresult0014BorderReflect101.png 377件 [詳細] fileresult0013BorderReflect.png 349件 [詳細] fileresult0012InterpolationArea.png 338件 [詳細] fileresult0011InterpolationLanczos4.png 342件 [詳細] fileresult0010InterpolationCubic.png 339件 [詳細] fileresult0009InterpolationLinear.png 346件 [詳細] fileresult0008InterpolationNearest.png 354件 [詳細] fileresult0007PerspectiveTransparent.png 346件 [詳細] fileresult0006PerspectiveReflect101.png 343件 [詳細] fileresult0005PerspectiveReflect.png 347件 [詳細] fileresult0004PerspectiveWrap.png 345件 [詳細] fileresult0003PerspectiveReplicate.png 339件 [詳細] fileresult0002PerspectiveConstant.png 353件 [詳細] fileresult0001AffineReplicate.png 358件 [詳細] fileresult0000AffineConstant.png 359件 [詳細]

トップ   編集 凍結 差分 バックアップ 添付 複製 名前変更 リロード   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS
Last-modified: 2016-01-15 (金) 10:50:33 (679d)