Commit 5720eaf3 authored by Vladislav Vinogradov's avatar Vladislav Vinogradov

refactored Morphology Filters

parent 12ae11e2
......@@ -228,11 +228,10 @@ private:
cv::gpu::GpuMat countBuf_;
cv::gpu::GpuMat buf_;
cv::gpu::GpuMat filterBuf_;
cv::gpu::GpuMat filterBrd_;
cv::Ptr<cv::gpu::FilterEngine_GPU> dilateFilter_;
cv::Ptr<cv::gpu::FilterEngine_GPU> erodeFilter_;
cv::Ptr<cv::gpu::Filter> dilateFilter_;
cv::Ptr<cv::gpu::Filter> erodeFilter_;
CvMemStorage* storage_;
};
......@@ -305,8 +304,8 @@ void cv::gpu::FGDStatModel::Impl::create(const cv::gpu::GpuMat& firstFrame, cons
cv::Mat kernel = cv::getStructuringElement(cv::MORPH_RECT, cv::Size(1 + params_.perform_morphing * 2, 1 + params_.perform_morphing * 2));
cv::Point anchor(params_.perform_morphing, params_.perform_morphing);
dilateFilter_ = cv::gpu::createMorphologyFilter_GPU(cv::MORPH_DILATE, CV_8UC1, kernel, filterBuf_, anchor);
erodeFilter_ = cv::gpu::createMorphologyFilter_GPU(cv::MORPH_ERODE, CV_8UC1, kernel, filterBuf_, anchor);
dilateFilter_ = cv::gpu::createMorphologyFilter(cv::MORPH_DILATE, CV_8UC1, kernel, anchor);
erodeFilter_ = cv::gpu::createMorphologyFilter(cv::MORPH_ERODE, CV_8UC1, kernel, anchor);
}
}
......@@ -326,7 +325,6 @@ void cv::gpu::FGDStatModel::Impl::release()
countBuf_.release();
buf_.release();
filterBuf_.release();
filterBrd_.release();
}
......@@ -488,14 +486,14 @@ namespace
namespace
{
void morphology(const cv::gpu::GpuMat& src, cv::gpu::GpuMat& dst, cv::gpu::GpuMat& filterBrd, int brd, cv::Ptr<cv::gpu::FilterEngine_GPU>& filter, cv::Scalar brdVal)
void morphology(const cv::gpu::GpuMat& src, cv::gpu::GpuMat& dst, cv::gpu::GpuMat& filterBrd, int brd, cv::Ptr<cv::gpu::Filter>& filter, cv::Scalar brdVal)
{
cv::gpu::copyMakeBorder(src, filterBrd, brd, brd, brd, brd, cv::BORDER_CONSTANT, brdVal);
filter->apply(filterBrd(cv::Rect(brd, brd, src.cols, src.rows)), dst, cv::Rect(0, 0, src.cols, src.rows));
filter->apply(filterBrd(cv::Rect(brd, brd, src.cols, src.rows)), dst);
}
void smoothForeground(cv::gpu::GpuMat& foreground, cv::gpu::GpuMat& filterBrd, cv::gpu::GpuMat& buf,
cv::Ptr<cv::gpu::FilterEngine_GPU>& erodeFilter, cv::Ptr<cv::gpu::FilterEngine_GPU>& dilateFilter,
cv::Ptr<cv::gpu::Filter>& erodeFilter, cv::Ptr<cv::gpu::Filter>& dilateFilter,
const cv::gpu::FGDStatModel::Params& params)
{
const int brd = params.perform_morphing;
......
......@@ -48,6 +48,7 @@
#endif
#include "opencv2/core/gpu.hpp"
#include "opencv2/imgproc.hpp"
#if defined __GNUC__
#define __OPENCV_GPUFILTERS_DEPR_BEFORE__
......@@ -203,8 +204,42 @@ inline void GaussianBlur(InputArray src, OutputArray dst, Size ksize, double sig
f->apply(src, dst, stream);
}
////////////////////////////////////////////////////////////////////////////////////////////////////
// Morphology Filter
//! returns 2D morphological filter
//! supports CV_8UC1 and CV_8UC4 types
CV_EXPORTS Ptr<Filter> createMorphologyFilter(int op, int srcType, InputArray kernel, Point anchor = Point(-1, -1), int iterations = 1);
__OPENCV_GPUFILTERS_DEPR_BEFORE__ void erode(InputArray src, OutputArray dst, InputArray kernel,
Point anchor = Point(-1, -1), int iterations = 1,
Stream& stream = Stream::Null()) __OPENCV_GPUFILTERS_DEPR_AFTER__;
inline void erode(InputArray src, OutputArray dst, InputArray kernel, Point anchor, int iterations, Stream& stream)
{
Ptr<gpu::Filter> f = gpu::createMorphologyFilter(MORPH_ERODE, src.type(), kernel, anchor, iterations);
f->apply(src, dst, stream);
}
__OPENCV_GPUFILTERS_DEPR_BEFORE__ void dilate(InputArray src, OutputArray dst, InputArray kernel,
Point anchor = Point(-1, -1), int iterations = 1,
Stream& stream = Stream::Null()) __OPENCV_GPUFILTERS_DEPR_AFTER__;
inline void dilate(InputArray src, OutputArray dst, InputArray kernel, Point anchor, int iterations, Stream& stream)
{
Ptr<gpu::Filter> f = gpu::createMorphologyFilter(MORPH_DILATE, src.type(), kernel, anchor, iterations);
f->apply(src, dst, stream);
}
__OPENCV_GPUFILTERS_DEPR_BEFORE__ void morphologyEx(InputArray src, OutputArray dst, int op,
InputArray kernel, Point anchor = Point(-1, -1), int iterations = 1,
Stream& stream = Stream::Null()) __OPENCV_GPUFILTERS_DEPR_AFTER__;
inline void morphologyEx(InputArray src, OutputArray dst, int op, InputArray kernel, Point anchor, int iterations, Stream& stream)
{
Ptr<gpu::Filter> f = gpu::createMorphologyFilter(op, src.type(), kernel, anchor, iterations);
f->apply(src, dst, stream);
}
......@@ -285,18 +320,7 @@ CV_EXPORTS Ptr<BaseColumnFilter_GPU> getColumnSumFilter_GPU(int sumType, int dst
//! returns 2D morphological filter
//! only MORPH_ERODE and MORPH_DILATE are supported
//! supports CV_8UC1 and CV_8UC4 types
//! kernel must have CV_8UC1 type, one rows and cols == ksize.width * ksize.height
CV_EXPORTS Ptr<BaseFilter_GPU> getMorphologyFilter_GPU(int op, int type, const Mat& kernel, const Size& ksize,
Point anchor=Point(-1,-1));
//! returns morphological filter engine. Only MORPH_ERODE and MORPH_DILATE are supported.
CV_EXPORTS Ptr<FilterEngine_GPU> createMorphologyFilter_GPU(int op, int type, const Mat& kernel,
const Point& anchor = Point(-1,-1), int iterations = 1);
CV_EXPORTS Ptr<FilterEngine_GPU> createMorphologyFilter_GPU(int op, int type, const Mat& kernel, GpuMat& buf,
const Point& anchor = Point(-1,-1), int iterations = 1);
......@@ -310,22 +334,7 @@ CV_EXPORTS Ptr<BaseFilter_GPU> getMinFilter_GPU(int srcType, int dstType, const
//! erodes the image (applies the local minimum operator)
CV_EXPORTS void erode(const GpuMat& src, GpuMat& dst, const Mat& kernel, Point anchor = Point(-1, -1), int iterations = 1);
CV_EXPORTS void erode(const GpuMat& src, GpuMat& dst, const Mat& kernel, GpuMat& buf,
Point anchor = Point(-1, -1), int iterations = 1,
Stream& stream = Stream::Null());
//! dilates the image (applies the local maximum operator)
CV_EXPORTS void dilate(const GpuMat& src, GpuMat& dst, const Mat& kernel, Point anchor = Point(-1, -1), int iterations = 1);
CV_EXPORTS void dilate(const GpuMat& src, GpuMat& dst, const Mat& kernel, GpuMat& buf,
Point anchor = Point(-1, -1), int iterations = 1,
Stream& stream = Stream::Null());
//! applies an advanced morphological operation to the image
CV_EXPORTS void morphologyEx(const GpuMat& src, GpuMat& dst, int op, const Mat& kernel, Point anchor = Point(-1, -1), int iterations = 1);
CV_EXPORTS void morphologyEx(const GpuMat& src, GpuMat& dst, int op, const Mat& kernel, GpuMat& buf1, GpuMat& buf2,
Point anchor = Point(-1, -1), int iterations = 1, Stream& stream = Stream::Null());
......
......@@ -263,13 +263,6 @@ PERF_TEST_P(Sz_Type_KernelSz, GaussianBlur, Combine(GPU_TYPICAL_MAT_SIZES, Value
}
}
//////////////////////////////////////////////////////////////////////
// Erode
......@@ -289,9 +282,10 @@ PERF_TEST_P(Sz_Type, Erode, Combine(GPU_TYPICAL_MAT_SIZES, Values(CV_8UC1, CV_8U
{
const cv::gpu::GpuMat d_src(src);
cv::gpu::GpuMat dst;
cv::gpu::GpuMat d_buf;
TEST_CYCLE() cv::gpu::erode(d_src, dst, ker, d_buf);
cv::Ptr<cv::gpu::Filter> erode = cv::gpu::createMorphologyFilter(cv::MORPH_ERODE, src.type(), ker);
TEST_CYCLE() erode->apply(d_src, dst);
GPU_SANITY_CHECK(dst);
}
......@@ -324,9 +318,10 @@ PERF_TEST_P(Sz_Type, Dilate, Combine(GPU_TYPICAL_MAT_SIZES, Values(CV_8UC1, CV_8
{
const cv::gpu::GpuMat d_src(src);
cv::gpu::GpuMat dst;
cv::gpu::GpuMat d_buf;
TEST_CYCLE() cv::gpu::dilate(d_src, dst, ker, d_buf);
cv::Ptr<cv::gpu::Filter> dilate = cv::gpu::createMorphologyFilter(cv::MORPH_DILATE, src.type(), ker);
TEST_CYCLE() dilate->apply(d_src, dst);
GPU_SANITY_CHECK(dst);
}
......@@ -364,10 +359,10 @@ PERF_TEST_P(Sz_Type_Op, MorphologyEx, Combine(GPU_TYPICAL_MAT_SIZES, Values(CV_8
{
const cv::gpu::GpuMat d_src(src);
cv::gpu::GpuMat dst;
cv::gpu::GpuMat d_buf1;
cv::gpu::GpuMat d_buf2;
TEST_CYCLE() cv::gpu::morphologyEx(d_src, dst, morphOp, ker, d_buf1, d_buf2);
cv::Ptr<cv::gpu::Filter> morph = cv::gpu::createMorphologyFilter(morphOp, src.type(), ker);
TEST_CYCLE() morph->apply(d_src, dst);
GPU_SANITY_CHECK(dst);
}
......
This diff is collapsed.
......@@ -489,15 +489,6 @@ INSTANTIATE_TEST_CASE_P(GPU_Filters, GaussianBlur, testing::Combine(
BorderType(cv::BORDER_REFLECT)),
WHOLE_SUBMAT));
/////////////////////////////////////////////////////////////////////////////////////////////////
// Erode
......@@ -528,8 +519,10 @@ GPU_TEST_P(Erode, Accuracy)
cv::Mat src = randomMat(size, type);
cv::Mat kernel = cv::Mat::ones(3, 3, CV_8U);
cv::Ptr<cv::gpu::Filter> erode = cv::gpu::createMorphologyFilter(cv::MORPH_ERODE, src.type(), kernel, anchor, iterations);
cv::gpu::GpuMat dst = createMat(size, type, useRoi);
cv::gpu::erode(loadMat(src, useRoi), dst, kernel, anchor, iterations);
erode->apply(loadMat(src, useRoi), dst);
cv::Mat dst_gold;
cv::erode(src, dst_gold, kernel, anchor, iterations);
......@@ -577,8 +570,10 @@ GPU_TEST_P(Dilate, Accuracy)
cv::Mat src = randomMat(size, type);
cv::Mat kernel = cv::Mat::ones(3, 3, CV_8U);
cv::Ptr<cv::gpu::Filter> dilate = cv::gpu::createMorphologyFilter(cv::MORPH_DILATE, src.type(), kernel, anchor, iterations);
cv::gpu::GpuMat dst = createMat(size, type, useRoi);
cv::gpu::dilate(loadMat(src, useRoi), dst, kernel, anchor, iterations);
dilate->apply(loadMat(src, useRoi), dst);
cv::Mat dst_gold;
cv::dilate(src, dst_gold, kernel, anchor, iterations);
......@@ -630,8 +625,10 @@ GPU_TEST_P(MorphEx, Accuracy)
cv::Mat src = randomMat(size, type);
cv::Mat kernel = cv::Mat::ones(3, 3, CV_8U);
cv::Ptr<cv::gpu::Filter> morph = cv::gpu::createMorphologyFilter(morphOp, src.type(), kernel, anchor, iterations);
cv::gpu::GpuMat dst = createMat(size, type, useRoi);
cv::gpu::morphologyEx(loadMat(src, useRoi), dst, morphOp, kernel, anchor, iterations);
morph->apply(loadMat(src, useRoi), dst);
cv::Mat dst_gold;
cv::morphologyEx(src, dst_gold, morphOp, kernel, anchor, iterations);
......
#include <iostream>
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/gpu/gpu.hpp"
#include <stdlib.h>
#include <stdio.h>
#include "opencv2/imgproc.hpp"
#include "opencv2/highgui.hpp"
#include "opencv2/gpufilters.hpp"
#include "opencv2/gpuimgproc.hpp"
using namespace std;
using namespace cv;
using namespace cv::gpu;
static void help()
class App
{
public:
App(int argc, const char* argv[]);
printf("\nShow off image morphology: erosion, dialation, open and close\n"
"Call:\n morphology2 [image]\n"
"This program also shows use of rect, elipse and cross kernels\n\n");
printf( "Hot keys: \n"
"\tESC - quit the program\n"
"\tr - use rectangle structuring element\n"
"\te - use elliptic structuring element\n"
"\tc - use cross-shaped structuring element\n"
"\tSPACE - loop through all the options\n" );
}
int run();
GpuMat src, dst;
private:
void help();
int element_shape = MORPH_RECT;
void OpenClose();
void ErodeDilate();
//the address of variable which receives trackbar position update
int max_iters = 10;
int open_close_pos = 0;
int erode_dilate_pos = 0;
static void OpenCloseCallback(int, void*);
static void ErodeDilateCallback(int, void*);
// callback function for open/close trackbar
static void OpenClose(int, void*)
{
int n = open_close_pos - max_iters;
int an = n > 0 ? n : -n;
Mat element = getStructuringElement(element_shape, Size(an*2+1, an*2+1), Point(an, an) );
if( n < 0 )
cv::gpu::morphologyEx(src, dst, MORPH_OPEN, element);
else
cv::gpu::morphologyEx(src, dst, MORPH_CLOSE, element);
imshow("Open/Close",(Mat)dst);
}
gpu::GpuMat src, dst;
// callback function for erode/dilate trackbar
static void ErodeDilate(int, void*)
{
int n = erode_dilate_pos - max_iters;
int an = n > 0 ? n : -n;
Mat element = getStructuringElement(element_shape, Size(an*2+1, an*2+1), Point(an, an) );
if( n < 0 )
cv::gpu::erode(src, dst, element);
else
cv::gpu::dilate(src, dst, element);
imshow("Erode/Dilate",(Mat)dst);
}
int element_shape;
int max_iters;
int open_close_pos;
int erode_dilate_pos;
};
int main( int argc, char** argv )
App::App(int argc, const char* argv[])
{
char* filename = argc == 2 ? argv[1] : (char*)"baboon.jpg";
if (string(argv[1]) == "--help")
{
help();
return -1;
}
element_shape = MORPH_RECT;
open_close_pos = erode_dilate_pos = max_iters = 10;
src.upload(imread(filename, 1));
if (src.empty())
if (argc == 2 && String(argv[1]) == "--help")
{
help();
return -1;
exit(0);
}
cv::gpu::printShortCudaDeviceInfo(cv::gpu::getDevice());
help();
String filename = argc == 2 ? argv[1] : "baboon.jpg";
Mat img = imread(filename);
if (img.empty())
{
cerr << "Can't open image " << filename.c_str() << endl;
exit(-1);
}
src.upload(img);
if (src.channels() == 3)
{
// gpu support only 4th channel images
GpuMat src4ch;
cv::gpu::cvtColor(src, src4ch, COLOR_BGR2BGRA);
gpu::GpuMat src4ch;
gpu::cvtColor(src, src4ch, COLOR_BGR2BGRA);
src = src4ch;
}
//create windows for output images
namedWindow("Open/Close",1);
namedWindow("Erode/Dilate",1);
help();
open_close_pos = erode_dilate_pos = max_iters;
createTrackbar("iterations", "Open/Close",&open_close_pos,max_iters*2+1,OpenClose);
createTrackbar("iterations", "Erode/Dilate",&erode_dilate_pos,max_iters*2+1,ErodeDilate);
gpu::printShortCudaDeviceInfo(gpu::getDevice());
}
int App::run()
{
// create windows for output images
namedWindow("Open/Close");
namedWindow("Erode/Dilate");
createTrackbar("iterations", "Open/Close", &open_close_pos, max_iters * 2 + 1, OpenCloseCallback, this);
createTrackbar("iterations", "Erode/Dilate", &erode_dilate_pos, max_iters * 2 + 1, ErodeDilateCallback, this);
for(;;)
{
int c;
OpenClose();
ErodeDilate();
OpenClose(open_close_pos, 0);
ErodeDilate(erode_dilate_pos, 0);
c = waitKey();
char c = (char) waitKey();
if( (char)c == 27 )
switch (c)
{
case 27:
return 0;
break;
if( (char)c == 'e' )
case 'e':
element_shape = MORPH_ELLIPSE;
else if( (char)c == 'r' )
break;
case 'r':
element_shape = MORPH_RECT;
else if( (char)c == 'c' )
break;
case 'c':
element_shape = MORPH_CROSS;
else if( (char)c == ' ' )
break;
case ' ':
element_shape = (element_shape + 1) % 3;
break;
}
}
}
void App::help()
{
cout << "Show off image morphology: erosion, dialation, open and close \n";
cout << "Call: \n";
cout << " gpu-example-morphology [image] \n";
cout << "This program also shows use of rect, elipse and cross kernels \n" << endl;
cout << "Hot keys: \n";
cout << "\tESC - quit the program \n";
cout << "\tr - use rectangle structuring element \n";
cout << "\te - use elliptic structuring element \n";
cout << "\tc - use cross-shaped structuring element \n";
cout << "\tSPACE - loop through all the options \n" << endl;
}
void App::OpenClose()
{
int n = open_close_pos - max_iters;
int an = n > 0 ? n : -n;
Mat element = getStructuringElement(element_shape, Size(an*2+1, an*2+1), Point(an, an));
if (n < 0)
{
Ptr<gpu::Filter> openFilter = gpu::createMorphologyFilter(MORPH_OPEN, src.type(), element);
openFilter->apply(src, dst);
}
else
{
Ptr<gpu::Filter> closeFilter = gpu::createMorphologyFilter(MORPH_CLOSE, src.type(), element);
closeFilter->apply(src, dst);
}
Mat h_dst(dst);
imshow("Open/Close", h_dst);
}
void App::ErodeDilate()
{
int n = erode_dilate_pos - max_iters;
int an = n > 0 ? n : -n;
Mat element = getStructuringElement(element_shape, Size(an*2+1, an*2+1), Point(an, an));
if (n < 0)
{
Ptr<gpu::Filter> erodeFilter = gpu::createMorphologyFilter(MORPH_ERODE, src.type(), element);
erodeFilter->apply(src, dst);
}
else
{
Ptr<gpu::Filter> dilateFilter = gpu::createMorphologyFilter(MORPH_DILATE, src.type(), element);
dilateFilter->apply(src, dst);
}
return 0;
Mat h_dst(dst);
imshow("Erode/Dilate", h_dst);
}
void App::OpenCloseCallback(int, void* data)
{
App* thiz = (App*) data;
thiz->OpenClose();
}
void App::ErodeDilateCallback(int, void* data)
{
App* thiz = (App*) data;
thiz->ErodeDilate();
}
int main(int argc, const char* argv[])
{
App app(argc, argv);
return app.run();
}
......@@ -746,10 +746,12 @@ TEST(erode)
d_src.upload(src);
gpu::erode(d_src, d_dst, ker, d_buf);
Ptr<gpu::Filter> erode = gpu::createMorphologyFilter(MORPH_ERODE, d_src.type(), ker);
erode->apply(d_src, d_dst);
GPU_ON;
gpu::erode(d_src, d_dst, ker, d_buf);
erode->apply(d_src, d_dst);
GPU_OFF;
}
}
......
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