- 追加された行はこの色です。
- 削除された行はこの色です。
cvWarpPerspectiveで画像を変換
変換行列を元に、画像を変形する
#contents
*void cvFindHomography( const CvMat* src_points, const CvMat* dst_points, CvMat* homography ); [#k45858bc]
*void warpPerspective(InputArray before, OutputArray after, InputArray matrix, Size dsize, int flags, int borderMode, const Scalar& borderValue); [#s6c1bcab]
-beforeをMatrix(ホモグラフィ)に基づいて変換
src_pointsをdst_pointsに変換するホモグラフィhomographyを計算する.
**引数 [#y819908b]
-before:Mat型の画像。座標変換前の画像
-after:Mat型の画像。座標変換後の画像
-matrix:Mat型の変換行列(ホモグラフィ)
-dsize:Size型の出力画像のサイズ
-flag:int型で変換方法のフラグ。詳細は後述。省略した場合はINTER_LINEAR
-borderMode:int型の、境界の対処方法。省略した場合はBORDER_CONSTANT
-borderValue:Scalar型の値。WARP_FILL_OUTLIERSを指定した場合、この色で空いた部分を塗りつぶす
**引数 [#p38c0b97]
-src_points:CvMat*型の変換前の座標
-dst_points:CvMat*型の変換後の座標
-homography:CvMat*型のhomography
**返り値 [#u32972d5]
**返り値 [#a16c0fa4]
-void型なのでなし
*void cvWarpPerspective(const IplImage* before, IplImage* after, const CvMat* homography, int flag, CvScalar fillval); [#qa77189e]
*void warpAffine(InputArray before, OutputArray after, InputArray matrix, Size dsize, int flags, int borderMode, const Scalar& borderValue); [#g439206c]
-beforeをMatrix(アフィン行列)に基いて変換
beforeをhomographyに基づいて変換
**引数 [#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を指定した場合、この色で空いた部分を塗りつぶす
**引数 [#gdcd4c3e]
-before:IplImage*型の画像.CvMat*型も可.座標変換前の画像
-after:IplImage*型の画像.CvMat*型も可.座標変換後の画像
-homography:CvMat*型のホモグラフィ
-flag:int型で変換方法のフラグ.下記の組み合わせ
--CV_INTER_LINEAR:共1次内挿
--CV_INTER_CUBIC:共3次内挿
--CV_WARP_INVERSE_MAP:逆内挿
--CV_WARP_FILL_OUTLIERS:指定色で外部を塗りつぶす
-fillval:cvScalar型の値.CV_WARP_FILL_OUTLIERSを指定した場合,この色で空いた部分を塗りつぶす.
**返り値 [#p4138794]
**返り値 [#b2663204]
-void型なのでなし
*解説 [#cd085ec9]
-src_pointsとdst_pointsには2次元座標を格納する.
--src_pointsは&mimetex(\(\array{2,cc$X_1&Y_1\\ \vdots&\vdots\\X_N&Y_N\));, dst_pointsは&mimetex(\(\array{2,cc$x_1&y_1\\ \vdots&\vdots\\x_N&y_N\));
--座標は縦横逆にしてもOK
--斉次座標でもOK
-homographyは線形連立方程式を解いて再投影誤差が小さくなるようなhomographyを求める.
-cvWarpPerspectiveはhomographyに基づき,透視変換を行う
--変換前の座標を&mimetex( \(x, y, 1\)^\top );,変換後の座標を&mimetex(\(x\prime, y\prime, 1\)^\top);とすると,次式に様な変換を行う.
--&mimetex( s\(\array{3,c$x\prime\\y\prime\\1}\) = \(\array{3,ccc$h_{11}&h_{12}&h_{13}\\h_{21}&h_{22}&h_{23}\\h_{31}&h_{32}&h_{33}}\)\(\array{3,c$x\\y\\1}\) = \mathbb{h}\(\array{3,c$x\\y\\1}\));
--フラグにCV_WARP_INVERSE_MAPを利用した場合,次式の様に逆変換を行う.
--&mimetex( s\(\array{3,c$x\\y\\1}\) = \(\array{3,ccc$h_{11}&h_{12}&h_{13}\\h_{21}&h_{22}&h_{23}\\h_{31}&h_{32}&h_{33}}\)\(\array{3,c$x\prime\\y\prime\\1}\)= \mathbb{H}\(\array{3,c$x\prime\\y\prime\\1}\));
-flagのデフォルト値はCV_INTER_LINEAR+CV_WARP_FILL_OUTLIERS
--CV_INTER_LINEARかCV_INTER_CUBICで内挿法を指定する
--CV_INTER_NNとCV_INTER_AREAを指定しても無視される
--CV_WARP_FILL_OUTLIERS,CV_WARP_INVERSE_MAPは加算で指定する.
-fillvalのデフォルトは黒(cvScalarAll(0))
*解説 [#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>
// ホモグラフィによる変換
// 変数宣言
IplImage *image, *converted;
CvMat *homography;
homography = cvCreateMat(3, 3, CV_32F); // 領域確保
cvFindHomography(src_points, dst_points, homography); // ホモグラフィ計算
image = cvLoadImage("input.bmp", CV_LOAD_IMAGE_UNCHANGED); // 画像のロード
converted = cvCreateImage(cvGetSize(image), image->depth, image->nChannels);
// 画像の領域確保
cvWarpPerspective(image, converted, homography,CV_INTER_LINEAR+CV_WARP_FILL_OUTLIERS, cvScalarAll(255));
// ホモグラフィに基づき変換
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;
*実体ファイル [#ffff384b]
-cv/include/cv.h
-cv/src/cvcalibration.cpp (cvFindHomography)
-cv/src/cvimgwarp.cpp (cvWarpPerspective)
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;
ジャンル[[:OpenCV]]
// 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]]準拠