特定の画像に適用された変換行列は、同じ画像のスケーリングされたバージョンで再利用できますか?
説明するには:「cv::findHomography」を使用して、最初に両方の画像間の対応を収集することにより、正投影参照画像と歪み補正された写真の間の 3x3 ホモグラフィ行列「Href」を計算することに成功しています。
Href = findHomography(mpts_2,
mpts_1,
cv::RANSAC,
Settings::getHomography_ransacReprojThr(),
outlier_mask);
写真入力とオルソフォト参照のサンプルについては、以下を参照してください。これは、エジプトのテーベにあるラムセス 2 世によって建てられた神殿のすべての壁のエジプト学的リファレンスを作成する考古学的コンピューティング プロジェクトです。
上記のマトリックスを使用すると、「cv::warpPerspective」を使用して、オルソモザイク参照オブジェクトの姿勢を正しく模倣する補間画像を作成できます。下の右側の画像を参照してください。
以下のコードで正しい結果が得られると思いますが (コード セクション A を参照)、同じ 'Href' マトリックスを、上記の同じ入力画像 'src' のより大きなバージョンに適用したいと思います。
これは可能ですか?
プロキシ イメージの以前の変換からの結果を拡大縮小して、それを最大解像度の写真に適用しようとすると、下の左側に示すように歪みが発生し、右側の正しい結果とは対照的です。
要約すると、小さいプロキシ イメージを変換することはできますが、イメージのより大きなフル解像度バージョンで同じマトリックスを使用できるかどうかはわかりません。
コード セクション A
これは正投影参照画像に従ってプロキシ画像を変換する作業コードです。ここにあるコードのほとんどは、出力画像のサイズ変更とオフセットに関連しています。「cv::warpPerspective」呼び出しはブロックの最後にあります。
// http://en.wikipedia.org/wiki/Transformation_matrix
cv::namedWindow(REMAP_WINDOW, CV_WINDOW_AUTOSIZE); // create homography display window
bool redraw = true;
// load image associated with current image
src = cv::imread("input.jpg", 1);
dst.create(src.size(), src.type()); // create destination and the maps
// Identify source image corners
std::vector<cv::Point2f> obj_corners(4);
obj_corners[0] = cvPoint(0,0);
obj_corners[1] = cvPoint(src.cols, 0);
obj_corners[2] = cvPoint(src.cols, src.rows);
obj_corners[3] = cvPoint(0, src.rows);
std::vector<cv::Point2f> scene_corners(4);
cv::perspectiveTransform(obj_corners, scene_corners, Href); // Transform source image corners by Href to find transformed bounds
int minCols = 0, maxCols = 0, minRows = 0, maxRows = 0;
for(int i=0; i < scene_corners.size(); i++)
{
//cout << "scene_corners.at(i).y: " << scene_corners.at(i).y << "scene_corners.at(i).x: " << scene_corners.at(i).x << endl;
if(maxRows < scene_corners.at(i).y)
maxRows = scene_corners.at(i).y;
if(minRows > scene_corners.at(i).y)
minRows = scene_corners.at(i).y;
if(maxCols < scene_corners.at(i).x)
maxCols = scene_corners.at(i).x;
if(minCols > scene_corners.at(i).x)
minCols = scene_corners.at(i).x;
}
int imageWidth = (maxCols-minCols)+30;
int imageHeight = (maxRows-minRows)+30;
double w = (double)imageWidth, h = (double)imageHeight;
int f = 500;
int x = -minCols; // This is an approximation only!
int y = -minRows; // This is an approximation only!
// Projection 2D -> 3D matrix
cv::Mat A1 = (cv::Mat_<double>(4,3) <<
1, 0, -w/2,
0, 1, -h/2,
0, 0, 0,
0, 0, 1);
// Camera Intrinsics matrix 3D -> 2D
cv::Mat A2 = (cv::Mat_<double>(3,4) <<
f, 0, w/2, 0,
0, f, h/2, 0,
0, 0, 1, 0);
// Translation matrix on the X and Y axis
cv::Mat T = (cv::Mat_<double>(4, 4) <<
1, 0, 0, x,
0, 1, 0, y,
0, 0, 1, 500,
0, 0, 0, 1);
// Apply matrix transformation
cv::Mat transfo = A2 * (T * A1);
// Apply image interpolation
cv::warpPerspective(src, dst, Href * transfo, cv::Size(imageWidth, imageHeight), CV_INTER_CUBIC);
imshow(REMAP_WINDOW, dst);
コード セクション B
この 2 番目のセクションは、'Href' マトリックスを拡大縮小された画像 (つまり、小さいプロキシではなく、フル解像度の写真) に適用する試みを示しています。
src = cv::imread("C:\\Users\\insight\\Documents\\Visual Studio 2010\\Projects\\find-object\\bin\\Release\\genies\\Img4913_pt.jpg", 1);
dst.create(src.size(), src.type()); // create destination and the maps
// Scale existing min/max cols/rows to fit larger image
int imageWidth = ((maxCols-minCols)*(src.cols/image.cols))+30; // Arbitrary border of 30 pixels
int imageHeight = ((maxRows-minRows)*(src.rows/image.rows))+30;
double w = (double)imageWidth, h = (double)imageHeight;
cout << "original image width: " << src.cols << ", original image height: " << src.rows << endl;
cout << "transformed image width: " << imageWidth << ", transformed image height: " << imageHeight << endl;
int f = 500;
int x = (minCols*(src.cols/image.cols))*2; // This is an approximation only!
int y = (minRows*(src.rows/image.rows))*2; // This is an approximation only!
vector<cv::Point2f> corners;
corners.push_back(cv::Point2f(0, 0));
corners.push_back(cv::Point2f(image.cols, 0));
corners.push_back(cv::Point2f(image.cols, image.rows));
corners.push_back(cv::Point2f(0, image.rows));
// Corners of the destination image
vector<cv::Point2f> output_corner;
output_corner.push_back(cv::Point2f(0, 0));
output_corner.push_back(cv::Point2f(dst.cols, 0));
output_corner.push_back(cv::Point2f(dst.cols, dst.rows));
output_corner.push_back(cv::Point2f(0, dst.rows));
// Get transformation matrix
cv::Mat Hscale = getPerspectiveTransform(corners, output_corner);
int j = 0;
x = -14500;
y = -9500;
int z = 4000;
int xfactor = 0;
int yfactor = 0;
int width = dst.cols;
int height = dst.rows;
// Projection 2D -> 3D matrix
cv::Mat A1 = (cv::Mat_<double>(4,3) <<
1, 0, -w/2,
0, 1, -h/2,
0, 0, 0,
0, 0, 1);
// Camera Intrinsics matrix 3D -> 2D
cv::Mat A2 = (cv::Mat_<double>(3,4) <<
f, 0, w/2, 0,
0, f, h/2, 0,
0, 0, 1, 0);
// Translation matrix on the X and Y axis
cv::Mat T = (cv::Mat_<double>(4, 4) <<
1, 0, 0, x,
0, 1, 0, y,
0, 0, 1, z,
0, 0, 0, 1);
// Apply matrix transformation
cv::Mat transfo = A2 * (T * A1);
warpPerspective(src, dst, Href * Hscale * transfo, cv::Size(imageWidth, imageHeight), CV_INTER_CUBIC, cv::BORDER_CONSTANT, 0);
cv::imwrite("C:\\Users\\Kevin\\Documents\\Find-Object\\image.png", dst);