Commit b2cdb7fa authored by Alexey Spizhevoy's avatar Alexey Spizhevoy

implemented cv::gpu::merge and cv::gpu::split functions

parent 5a804717
......@@ -408,6 +408,30 @@ namespace cv
//! Supports INTER_NEAREST, INTER_LINEAR, INTER_CUBIC
CV_EXPORTS void rotate(const GpuMat& src, GpuMat& dst, Size dsize, double angle, double xShift = 0, double yShift = 0, int interpolation = INTER_LINEAR);
//! makes multi-channel array out of several single-channel arrays
CV_EXPORTS void merge(const GpuMat* src, size_t n, GpuMat& dst);
//! makes multi-channel array out of several single-channel arrays
CV_EXPORTS void merge(const vector<GpuMat>& src, GpuMat& dst);
//! makes multi-channel array out of several single-channel arrays (async version)
CV_EXPORTS void merge(const GpuMat* src, size_t n, GpuMat& dst, const Stream& stream);
//! makes multi-channel array out of several single-channel arrays (async version)
CV_EXPORTS void merge(const vector<GpuMat>& src, GpuMat& dst, const Stream& stream);
//! copies each plane of a multi-channel array to a dedicated array
CV_EXPORTS void split(const GpuMat& src, GpuMat* dst);
//! copies each plane of a multi-channel array to a dedicated array
CV_EXPORTS void split(const GpuMat& src, vector<GpuMat>& dst);
//! copies each plane of a multi-channel array to a dedicated array (async version)
CV_EXPORTS void split(const GpuMat& src, GpuMat* dst, const Stream& stream);
//! copies each plane of a multi-channel array to a dedicated array (async version)
CV_EXPORTS void split(const GpuMat& src, vector<GpuMat>& dst, const Stream& stream);
////////////////////////////// Image processing //////////////////////////////
// DST[x,y] = SRC[xmap[x,y],ymap[x,y]] with bilinear interpolation.
......
This diff is collapsed.
#include "precomp.hpp"
#include <vector>
using namespace std;
#if !defined (HAVE_CUDA)
void cv::gpu::merge(const GpuMat* /*src*/, size_t /*count*/, GpuMat& /*dst*/) { throw_nogpu(); }
void cv::gpu::merge(const vector<GpuMat>& /*src*/, GpuMat& /*dst*/) { throw_nogpu(); }
void cv::gpu::merge(const GpuMat* /*src*/, size_t /*count*/, GpuMat& /*dst*/, const Stream& /*stream*/) { throw_nogpu(); }
void cv::gpu::merge(const vector<GpuMat>& /*src*/, GpuMat& /*dst*/, const Stream& /*stream*/) { throw_nogpu(); }
void cv::gpu::split(const GpuMat& /*src*/, GpuMat* /*dst*/) { throw_nogpu(); }
void cv::gpu::split(const GpuMat& /*src*/, vector<GpuMat>& /*dst*/) { throw_nogpu(); }
void cv::gpu::split(const GpuMat& /*src*/, GpuMat* /*dst*/, const Stream& /*stream*/) { throw_nogpu(); }
void cv::gpu::split(const GpuMat& /*src*/, vector<GpuMat>& /*dst*/, const Stream& /*stream*/) { throw_nogpu(); }
#else /* !defined (HAVE_CUDA) */
namespace cv { namespace gpu { namespace split_merge
{
extern "C" void merge_caller(const DevMem2D* src, DevMem2D& dst,
int total_channels, int elem_size,
const cudaStream_t& stream);
extern "C" void split_caller(const DevMem2D& src, DevMem2D* dst,
int num_channels, int elem_size1,
const cudaStream_t& stream);
void merge(const GpuMat* src, size_t n, GpuMat& dst, const cudaStream_t& stream)
{
CV_Assert(src);
CV_Assert(n > 0);
int depth = src[0].depth();
Size size = src[0].size();
bool single_channel_only = true;
int total_channels = 0;
for (size_t i = 0; i < n; ++i)
{
CV_Assert(src[i].size() == size);
CV_Assert(src[i].depth() == depth);
single_channel_only = single_channel_only && src[i].channels() == 1;
total_channels += src[i].channels();
}
CV_Assert(single_channel_only);
CV_Assert(total_channels <= 4);
if (total_channels == 1)
src[0].copyTo(dst);
else
{
dst.create(size, CV_MAKETYPE(depth, total_channels));
DevMem2D src_as_devmem[4];
for(size_t i = 0; i < n; ++i)
src_as_devmem[i] = src[i];
split_merge::merge_caller(src_as_devmem, (DevMem2D)dst,
total_channels, CV_ELEM_SIZE(depth),
stream);
}
}
void split(const GpuMat& src, GpuMat* dst, const cudaStream_t& stream)
{
CV_Assert(dst);
int depth = src.depth();
int num_channels = src.channels();
Size size = src.size();
if (num_channels == 1)
{
src.copyTo(dst[0]);
return;
}
for (int i = 0; i < num_channels; ++i)
dst[i].create(src.size(), depth);
CV_Assert(num_channels <= 4);
DevMem2D dst_as_devmem[4];
for (int i = 0; i < num_channels; ++i)
dst_as_devmem[i] = dst[i];
split_merge::split_caller((DevMem2D)src, dst_as_devmem,
num_channels, src.elemSize1(),
stream);
}
}}}
void cv::gpu::merge(const GpuMat* src, size_t n, GpuMat& dst)
{
split_merge::merge(src, n, dst, 0);
}
void cv::gpu::merge(const vector<GpuMat>& src, GpuMat& dst)
{
split_merge::merge(&src[0], src.size(), dst, 0);
}
void cv::gpu::merge(const GpuMat* src, size_t n, GpuMat& dst, const Stream& stream)
{
split_merge::merge(src, n, dst, StreamAccessor::getStream(stream));
}
void cv::gpu::merge(const vector<GpuMat>& src, GpuMat& dst, const Stream& stream)
{
split_merge::merge(&src[0], src.size(), dst, StreamAccessor::getStream(stream));
}
void cv::gpu::split(const GpuMat& src, GpuMat* dst)
{
split_merge::split(src, dst, 0);
}
void cv::gpu::split(const GpuMat& src, vector<GpuMat>& dst)
{
dst.resize(src.channels());
if(src.channels() > 0)
split_merge::split(src, &dst[0], 0);
}
void cv::gpu::split(const GpuMat& src, GpuMat* dst, const Stream& stream)
{
split_merge::split(src, dst, StreamAccessor::getStream(stream));
}
void cv::gpu::split(const GpuMat& src, vector<GpuMat>& dst, const Stream& stream)
{
dst.resize(src.channels());
if(src.channels() > 0)
split_merge::split(src, &dst[0], StreamAccessor::getStream(stream));
}
#endif /* !defined (HAVE_CUDA) */
\ No newline at end of file
#include "gputest.hpp"
#include <opencv2/opencv.hpp>
#include <opencv2/gpu/gpu.hpp>
#include <iostream>
#include <string>
#include <vector>
using namespace std;
using namespace cv;
struct CV_MergeTest : public CvTest
{
CV_MergeTest() : CvTest("GPU-Merge", "merge") {}
void can_merge(size_t rows, size_t cols);
void can_merge_submatrixes(size_t rows, size_t cols);
void run(int);
} merge_test;
void CV_MergeTest::can_merge(size_t rows, size_t cols)
{
for (size_t num_channels = 1; num_channels <= 4; ++num_channels)
for (size_t depth = CV_8U; depth <= CV_64F; ++depth)
{
vector<Mat> src;
for (size_t i = 0; i < num_channels; ++i)
src.push_back(Mat(rows, cols, depth, Scalar::all(static_cast<double>(i))));
Mat dst(rows, cols, CV_MAKETYPE(depth, num_channels));
cv::merge(src, dst);
vector<gpu::GpuMat> dev_src;
for (size_t i = 0; i < num_channels; ++i)
dev_src.push_back(gpu::GpuMat(src[i]));
gpu::GpuMat dev_dst(rows, cols, CV_MAKETYPE(depth, num_channels));
cv::gpu::merge(dev_src, dev_dst);
Mat host_dst = dev_dst;
double err = norm(dst, host_dst, NORM_INF);
if (err > 1e-3)
{
//ts->printf(CvTS::CONSOLE, "\nNorm: %f\n", err);
//ts->printf(CvTS::CONSOLE, "Depth: %d\n", depth);
//ts->printf(CvTS::CONSOLE, "Rows: %d\n", rows);
//ts->printf(CvTS::CONSOLE, "Cols: %d\n", cols);
//ts->printf(CvTS::CONSOLE, "NumChannels: %d\n", num_channels);
ts->set_failed_test_info(CvTS::FAIL_INVALID_OUTPUT);
return;
}
}
}
void CV_MergeTest::can_merge_submatrixes(size_t rows, size_t cols)
{
for (size_t num_channels = 1; num_channels <= 4; ++num_channels)
for (size_t depth = CV_8U; depth <= CV_64F; ++depth)
{
vector<Mat> src;
for (size_t i = 0; i < num_channels; ++i)
{
Mat m(rows * 2, cols * 2, depth, Scalar::all(static_cast<double>(i)));
src.push_back(m(Range(rows / 2, rows / 2 + rows), Range(cols / 2, cols / 2 + cols)));
}
Mat dst(rows, cols, CV_MAKETYPE(depth, num_channels));
cv::merge(src, dst);
vector<gpu::GpuMat> dev_src;
for (size_t i = 0; i < num_channels; ++i)
dev_src.push_back(gpu::GpuMat(src[i]));
gpu::GpuMat dev_dst(rows, cols, CV_MAKETYPE(depth, num_channels));
cv::gpu::merge(dev_src, dev_dst);
Mat host_dst = dev_dst;
double err = norm(dst, host_dst, NORM_INF);
if (err > 1e-3)
{
//ts->printf(CvTS::CONSOLE, "\nNorm: %f\n", err);
//ts->printf(CvTS::CONSOLE, "Depth: %d\n", depth);
//ts->printf(CvTS::CONSOLE, "Rows: %d\n", rows);
//ts->printf(CvTS::CONSOLE, "Cols: %d\n", cols);
//ts->printf(CvTS::CONSOLE, "NumChannels: %d\n", num_channels);
ts->set_failed_test_info(CvTS::FAIL_INVALID_OUTPUT);
return;
}
}
}
void CV_MergeTest::run(int)
{
try
{
can_merge(1, 1);
can_merge(1, 7);
can_merge(53, 7);
can_merge_submatrixes(1, 1);
can_merge_submatrixes(1, 7);
can_merge_submatrixes(53, 7);
}
catch(const cv::Exception& e)
{
if (!check_and_treat_gpu_exception(e, ts))
throw;
}
}
struct CV_SplitTest : public CvTest
{
CV_SplitTest() : CvTest("GPU-Split", "split") {}
void can_split(size_t rows, size_t cols);
void can_split_submatrix(size_t rows, size_t cols);
void run(int);
} split_test;
void CV_SplitTest::can_split(size_t rows, size_t cols)
{
for (size_t num_channels = 1; num_channels <= 4; ++num_channels)
for (size_t depth = CV_8U; depth <= CV_64F; ++depth)
{
Mat src(rows, cols, CV_MAKETYPE(depth, num_channels), Scalar(1.0, 2.0, 3.0, 4.0));
vector<Mat> dst;
cv::split(src, dst);
gpu::GpuMat dev_src(src);
vector<gpu::GpuMat> dev_dst;
cv::gpu::split(dev_src, dev_dst);
if (dev_dst.size() != dst.size())
{
ts->printf(CvTS::CONSOLE, "Bad output sizes");
ts->set_failed_test_info(CvTS::FAIL_INVALID_OUTPUT);
}
for (size_t i = 0; i < num_channels; ++i)
{
Mat host_dst = dev_dst[i];
double err = norm(dst[i], host_dst, NORM_INF);
if (err > 1e-3)
{
//ts->printf(CvTS::CONSOLE, "\nNorm: %f\n", err);
//ts->printf(CvTS::CONSOLE, "Depth: %d\n", depth);
//ts->printf(CvTS::CONSOLE, "Rows: %d\n", rows);
//ts->printf(CvTS::CONSOLE, "Cols: %d\n", cols);
//ts->printf(CvTS::CONSOLE, "NumChannels: %d\n", num_channels);
ts->set_failed_test_info(CvTS::FAIL_INVALID_OUTPUT);
return;
}
}
}
}
void CV_SplitTest::can_split_submatrix(size_t rows, size_t cols)
{
for (size_t num_channels = 1; num_channels <= 4; ++num_channels)
for (size_t depth = CV_8U; depth <= CV_64F; ++depth)
{
Mat src_data(rows * 2, cols * 2, CV_MAKETYPE(depth, num_channels), Scalar(1.0, 2.0, 3.0, 4.0));
Mat src(src_data(Range(rows / 2, rows / 2 + rows), Range(cols / 2, cols / 2 + cols)));
vector<Mat> dst;
cv::split(src, dst);
gpu::GpuMat dev_src(src);
vector<gpu::GpuMat> dev_dst;
cv::gpu::split(dev_src, dev_dst);
if (dev_dst.size() != dst.size())
{
ts->printf(CvTS::CONSOLE, "Bad output sizes");
ts->set_failed_test_info(CvTS::FAIL_INVALID_OUTPUT);
}
for (size_t i = 0; i < num_channels; ++i)
{
Mat host_dst = dev_dst[i];
double err = norm(dst[i], host_dst, NORM_INF);
if (err > 1e-3)
{
//ts->printf(CvTS::CONSOLE, "\nNorm: %f\n", err);
//ts->printf(CvTS::CONSOLE, "Depth: %d\n", depth);
//ts->printf(CvTS::CONSOLE, "Rows: %d\n", rows);
//ts->printf(CvTS::CONSOLE, "Cols: %d\n", cols);
//ts->printf(CvTS::CONSOLE, "NumChannels: %d\n", num_channels);
ts->set_failed_test_info(CvTS::FAIL_INVALID_OUTPUT);
return;
}
}
}
}
void CV_SplitTest::run(int)
{
try
{
can_split(1, 1);
can_split(1, 7);
can_split(7, 53);
can_split_submatrix(1, 1);
can_split_submatrix(1, 7);
can_split_submatrix(7, 53);
}
catch(const cv::Exception& e)
{
if (!check_and_treat_gpu_exception(e, ts))
throw;
}
}
struct CV_SplitMergeTest : public CvTest
{
CV_SplitMergeTest() : CvTest("GPU-SplitMerge", "split merge") {}
void can_split_merge(size_t rows, size_t cols);
void run(int);
} split_merge_test;
void CV_SplitMergeTest::can_split_merge(size_t rows, size_t cols) {
for (size_t num_channels = 1; num_channels <= 4; ++num_channels)
for (size_t depth = CV_8U; depth <= CV_64F; ++depth)
{
Mat orig(rows, cols, CV_MAKETYPE(depth, num_channels), Scalar(1.0, 2.0, 3.0, 4.0));
gpu::GpuMat dev_orig(orig);
vector<gpu::GpuMat> dev_vec;
cv::gpu::split(dev_orig, dev_vec);
gpu::GpuMat dev_final(rows, cols, CV_MAKETYPE(depth, num_channels));
cv::gpu::merge(dev_vec, dev_final);
double err = cv::norm((Mat)dev_orig, (Mat)dev_final, NORM_INF);
if (err > 1e-3)
{
//ts->printf(CvTS::CONSOLE, "\nNorm: %f\n", err);
//ts->printf(CvTS::CONSOLE, "Depth: %d\n", depth);
//ts->printf(CvTS::CONSOLE, "Rows: %d\n", rows);
//ts->printf(CvTS::CONSOLE, "Cols: %d\n", cols);
//ts->printf(CvTS::CONSOLE, "NumChannels: %d\n", num_channels);
ts->set_failed_test_info(CvTS::FAIL_INVALID_OUTPUT);
return;
}
}
}
void CV_SplitMergeTest::run(int)
{
try
{
can_split_merge(1, 1);
can_split_merge(1, 7);
can_split_merge(7, 53);
}
catch(const cv::Exception& e)
{
if (!check_and_treat_gpu_exception(e, ts))
throw;
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment