GPU: updated upsample, downsample functions, added pyrDown, pyrUp, added support of 16S filtering; put spherical warper on GPU (from opencv_stitching)

This commit is contained in:
Alexey Spizhevoy
2011-06-30 14:39:48 +00:00
parent a44d6aacc8
commit 674b763395
19 changed files with 697 additions and 378 deletions

View File

@@ -47,14 +47,14 @@ using namespace cv;
static const float WEIGHT_EPS = 1e-5f;
Ptr<Blender> Blender::createDefault(int type)
Ptr<Blender> Blender::createDefault(int type, bool try_gpu)
{
if (type == NO)
return new Blender();
if (type == FEATHER)
return new FeatherBlender();
if (type == MULTI_BAND)
return new MultiBandBlender();
return new MultiBandBlender(try_gpu);
CV_Error(CV_StsBadArg, "unsupported blending method");
return NULL;
}
@@ -153,6 +153,13 @@ void FeatherBlender::blend(Mat &dst, Mat &dst_mask)
}
MultiBandBlender::MultiBandBlender(int try_gpu, int num_bands)
{
setNumBands(num_bands);
can_use_gpu_ = try_gpu && gpu::getCudaEnabledDeviceCount();
}
void MultiBandBlender::prepare(Rect dst_roi)
{
dst_roi_final_ = dst_roi;
@@ -222,14 +229,14 @@ void MultiBandBlender::feed(const Mat &img, const Mat &mask, Point tl)
int right = br_new.x - tl.x - img.cols;
// Create the source image Laplacian pyramid
vector<Mat> src_pyr_gauss(num_bands_ + 1);
copyMakeBorder(img, src_pyr_gauss[0], top, bottom, left, right,
Mat img_with_border;
copyMakeBorder(img, img_with_border, top, bottom, left, right,
BORDER_REFLECT);
for (int i = 0; i < num_bands_; ++i)
pyrDown(src_pyr_gauss[i], src_pyr_gauss[i + 1]);
vector<Mat> src_pyr_laplace;
createLaplacePyr(src_pyr_gauss, src_pyr_laplace);
src_pyr_gauss.clear();
if (can_use_gpu_)
createLaplacePyrGpu(img_with_border, num_bands_, src_pyr_laplace);
else
createLaplacePyr(img_with_border, num_bands_, src_pyr_laplace);
// Create the weight map Gaussian pyramid
Mat weight_map;
@@ -267,7 +274,7 @@ void MultiBandBlender::feed(const Mat &img, const Mat &mask, Point tl)
}
x_tl /= 2; y_tl /= 2;
x_br /= 2; y_br /= 2;
}
}
}
@@ -319,21 +326,43 @@ void createWeightMap(const Mat &mask, float sharpness, Mat &weight)
}
void createLaplacePyr(const vector<Mat> &pyr_gauss, vector<Mat> &pyr_laplace)
void createLaplacePyr(const Mat &img, int num_levels, vector<Mat> &pyr)
{
if (pyr_gauss.size() == 0)
return;
pyr_laplace.resize(pyr_gauss.size());
pyr.resize(num_levels + 1);
pyr[0] = img;
for (int i = 0; i < num_levels; ++i)
pyrDown(pyr[i], pyr[i + 1]);
Mat tmp;
for (size_t i = 0; i < pyr_laplace.size() - 1; ++i)
for (int i = 0; i < num_levels; ++i)
{
pyrUp(pyr_gauss[i + 1], tmp, pyr_gauss[i].size());
subtract(pyr_gauss[i], tmp, pyr_laplace[i]);
pyrUp(pyr[i + 1], tmp, pyr[i].size());
subtract(pyr[i], tmp, pyr[i]);
}
pyr_laplace[pyr_laplace.size() - 1] = pyr_gauss[pyr_laplace.size() - 1].clone();
}
void createLaplacePyrGpu(const Mat &img, int num_levels, vector<Mat> &pyr)
{
pyr.resize(num_levels + 1);
vector<gpu::GpuMat> gpu_pyr(num_levels + 1);
gpu_pyr[0] = img;
for (int i = 0; i < num_levels; ++i)
gpu::pyrDown(gpu_pyr[i], gpu_pyr[i + 1]);
gpu::GpuMat tmp;
for (int i = 0; i < num_levels; ++i)
{
gpu::pyrUp(gpu_pyr[i + 1], tmp);
gpu::subtract(gpu_pyr[i], tmp, gpu_pyr[i]);
pyr[i] = gpu_pyr[i];
}
pyr[num_levels] = gpu_pyr[num_levels];
}
void restoreImageFromLaplacePyr(vector<Mat> &pyr)
{
if (pyr.size() == 0)