変換行列を元に、画像を変形する
#contents
*void warpPerspective(InputArray before, OutputArray after, InputArray matrix, Size dsize, int flags, int borderMode, const Scalar& borderValue); [#s6c1bcab]
-beforeをMatrix(ホモグラフィ)に基づいて変換
**引数 [#y819908b]
-before:Mat型の画像。座標変換前の画像
-after:Mat型の画像。座標変換後の画像
-matrix:Mat型の変換行列(ホモグラフィ)
-dsize:Size型の出力画像のサイズ
-flag:int型で変換方法のフラグ。詳細は後述。省略した場合はINTER_LINEAR
-borderMode:int型の、境界の対処方法。省略した場合はBORDER_CONSTANT
-borderValue:Scalar型の値。WARP_FILL_OUTLIERSを指定した場合、この色で空いた部分を塗りつぶす
**返り値 [#a16c0fa4]
-void型なのでなし
*void warpAffine(InputArray before, OutputArray after, InputArray matrix, Size dsize, int flags, int borderMode, const Scalar& borderValue); [#g439206c]
-beforeをMatrix(アフィン行列)に基いて変換
**引数 [#b02d976e]
-基本的に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を指定した場合、この色で空いた部分を塗りつぶす
**返り値 [#b2663204]
-void型なのでなし
*解説 [#caf29950]
-flag、borderMode、borderValueの引数については下記の通り
**引数flagについて [#gb8eeeee]
-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について [#t2d621ad]
-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について [#vc9bc3b6]
-borderValueのデフォルトは黒(Scalar())
**変換方法について [#ka29d2bb]
-ホモグラフィを用いて変換する場合はwarpPerspectiveを、アフィン行列を用いて変換する場合はwarpAffineを使用する
-warpPerspectiveは以下の数式に基づいて変換を行う
--&mimetex(\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));
--書き換えると、ヘッダ/ドキュメントにある様な、下記の式になる
--&mimetex(\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は以下の数式に基づいて変換を行う
--&mimetex(\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));
--書き換えると、ヘッダ/ドキュメントにある様な、下記の式になる
--&mimetex(\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));
*サンプルコード [#pde0c698]
#geshi(c++){{
#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;
}
}}
**実行結果 [#tff79c15]
-TBW
#ref(result0000AffineConstant.png)
#ref(result0001AffineReplicate.png)
#ref(result0002PerspectiveConstant.png)
#ref(result0003PerspectiveReplicate.png)
#ref(result0004PerspectiveWrap.png)
#ref(result0005PerspectiveReflect.png)
#ref(result0006PerspectiveReflect101.png)
#ref(result0007PerspectiveTransparent.png)
#ref(result0008InterpolationNearest.png)
#ref(result0009InterpolationLinear.png)
#ref(result0010InterpolationCubic.png)
#ref(result0011InterpolationLanczos4.png)
#ref(result0012InterpolationArea.png)
#ref(result0013BorderReflect.png)
#ref(result0014BorderReflect101.png)
*実体ファイル [#me219ce5]
**OpenCV 2.4系列 [#b7c56afd]
-warpPerspective、warpAffine
--modules/imgproc/include/opencv2/imgproc/iimgproc.hpp
--modules/imgproc/src/imgwarp.cpp
**OpenCV 3.0系列 [#fe0ecd83]
-warpPerspective、warpAffine
--modules/imgproc/include/opencv2/imgproc/iimgproc.hpp
--modules/imgproc/src/imgwarp.cpp
ジャンル[[:OpenCV]][[:OpenCV 2.4]][[:OpenCV 3.0]][[:OpenCV 3.1]]準拠