Added translation parameter into stitching module warpers. For now only PlaneWarper and PlaneWarperGpu warpers support it.

This commit is contained in:
Alexey Spizhevoy
2011-09-21 10:53:23 +00:00
parent 0aaaad1ea8
commit 4a5abc7552
5 changed files with 110 additions and 24 deletions

View File

@@ -237,7 +237,7 @@ Stitcher::Status Stitcher::stitch(InputArray imgs_, OutputArray pano_)
K(0,0) *= seam_work_aspect; K(0,2) *= seam_work_aspect;
K(1,1) *= seam_work_aspect; K(1,2) *= seam_work_aspect;
corners[i] = warper->warp(seam_est_imgs[i], K, cameras[i].R, images_warped[i]);
corners[i] = warper->warp(seam_est_imgs[i], K, cameras[i].R, images_warped[i], INTER_LINEAR, BORDER_REFLECT);
sizes[i] = images_warped[i].size();
warper->warp(masks[i], K, cameras[i].R, masks_warped[i], INTER_NEAREST, BORDER_CONSTANT);
@@ -321,7 +321,7 @@ Stitcher::Status Stitcher::stitch(InputArray imgs_, OutputArray pano_)
cameras[img_idx].K().convertTo(K, CV_32F);
// Warp the current image
warper->warp(img, K, cameras[img_idx].R, img_warped);
warper->warp(img, K, cameras[img_idx].R, img_warped, INTER_LINEAR, BORDER_REFLECT);
// Warp the current image mask
mask.create(img_size, CV_8U);

View File

@@ -47,10 +47,11 @@ using namespace std;
namespace cv {
namespace detail {
void ProjectorBase::setCameraParams(const Mat &K, const Mat &R)
void ProjectorBase::setCameraParams(const Mat &K, const Mat &R, const Mat &T)
{
CV_Assert(K.size() == Size(3, 3) && K.type() == CV_32F);
CV_Assert(R.size() == Size(3, 3) && R.type() == CV_32F);
CV_Assert((T.size() == Size(1, 3) || T.size() == Size(3, 1)) && T.type() == CV_32F);
Mat_<float> K_(K);
k[0] = K_(0,0); k[1] = K_(0,1); k[2] = K_(0,2);
@@ -71,6 +72,51 @@ void ProjectorBase::setCameraParams(const Mat &K, const Mat &R)
k_rinv[0] = K_Rinv(0,0); k_rinv[1] = K_Rinv(0,1); k_rinv[2] = K_Rinv(0,2);
k_rinv[3] = K_Rinv(1,0); k_rinv[4] = K_Rinv(1,1); k_rinv[5] = K_Rinv(1,2);
k_rinv[6] = K_Rinv(2,0); k_rinv[7] = K_Rinv(2,1); k_rinv[8] = K_Rinv(2,2);
Mat_<float> T_(T.reshape(0, 3));
t[0] = T_(0,0); t[1] = T_(1,0); t[2] = T_(2,0);
}
Point PlaneWarper::warp(const Mat &src, const Mat &K, const Mat &R, const Mat &T, Mat &dst,
int interp_mode, int border_mode)
{
src_size_ = src.size();
projector_.setCameraParams(K, R, T);
Point dst_tl, dst_br;
detectResultRoi(dst_tl, dst_br);
Mat xmap(dst_br.y - dst_tl.y + 1, dst_br.x - dst_tl.x + 1, CV_32F);
Mat ymap(dst_br.y - dst_tl.y + 1, dst_br.x - dst_tl.x + 1, CV_32F);
float x, y;
for (int v = dst_tl.y; v <= dst_br.y; ++v)
{
for (int u = dst_tl.x; u <= dst_br.x; ++u)
{
projector_.mapBackward(static_cast<float>(u), static_cast<float>(v), x, y);
xmap.at<float>(v - dst_tl.y, u - dst_tl.x) = x;
ymap.at<float>(v - dst_tl.y, u - dst_tl.x) = y;
}
}
dst.create(dst_br.y - dst_tl.y + 1, dst_br.x - dst_tl.x + 1, src.type());
remap(src, dst, xmap, ymap, interp_mode, border_mode);
return dst_tl;
}
Rect PlaneWarper::warpRoi(const Size &sz, const Mat &K, const Mat &R, const Mat &T)
{
src_size_ = sz;
projector_.setCameraParams(K, R, T);
Point dst_tl, dst_br;
detectResultRoi(dst_tl, dst_br);
return Rect(dst_tl, Point(dst_br.x + 1, dst_br.y + 1));
}
@@ -105,11 +151,20 @@ void PlaneWarper::detectResultRoi(Point &dst_tl, Point &dst_br)
dst_br.y = static_cast<int>(br_vf);
}
#ifndef ANDROID
Point PlaneWarperGpu::warp(const Mat &src, const Mat &K, const Mat &R, Mat &dst, int interp_mode, int border_mode)
Point PlaneWarperGpu::warp(const Mat &src, const Mat &K, const Mat &R, Mat &dst,
int interp_mode, int border_mode)
{
return warp(src, K, R, Mat::zeros(3, 1, CV_32F), dst, interp_mode, border_mode);
}
Point PlaneWarperGpu::warp(const Mat &src, const Mat &K, const Mat &R, const Mat &T, Mat &dst,
int interp_mode, int border_mode)
{
src_size_ = src.size();
projector_.setCameraParams(K, R);
projector_.setCameraParams(K, R, T);
Point dst_tl, dst_br;
detectResultRoi(dst_tl, dst_br);
@@ -145,8 +200,6 @@ void SphericalWarper::detectResultRoi(Point &dst_tl, Point &dst_br)
float z = projector_.rinv[7];
if (y > 0.f)
{
//x = projector_.focal * x / z + src_size_.width * 0.5f;
//y = projector_.focal * y / z + src_size_.height * 0.5f;
float x_ = (projector_.k[0] * x + projector_.k[1] * y) / z + projector_.k[2];
float y_ = projector_.k[4] * y / z + projector_.k[5];
if (x_ > 0.f && x_ < src_size_.width && y_ > 0.f && y_ < src_size_.height)
@@ -161,8 +214,6 @@ void SphericalWarper::detectResultRoi(Point &dst_tl, Point &dst_br)
z = projector_.rinv[7];
if (y > 0.f)
{
//x = projector_.focal * x / z + src_size_.width * 0.5f;
//y = projector_.focal * y / z + src_size_.height * 0.5f;
float x_ = (projector_.k[0] * x + projector_.k[1] * y) / z + projector_.k[2];
float y_ = projector_.k[4] * y / z + projector_.k[5];
if (x_ > 0.f && x_ < src_size_.width && y_ > 0.f && y_ < src_size_.height)
@@ -178,6 +229,7 @@ void SphericalWarper::detectResultRoi(Point &dst_tl, Point &dst_br)
dst_br.y = static_cast<int>(br_vf);
}
#ifndef ANDROID
Point SphericalWarperGpu::warp(const Mat &src, const Mat &K, const Mat &R, Mat &dst,
int interp_mode, int border_mode)