Merge pull request #1408 from VenkateshVijaykumar:ridge_filter
commit
d3118ad003
7 changed files with 198 additions and 1 deletions
@ -0,0 +1,51 @@ |
||||
// This file is part of OpenCV project.
|
||||
// It is subject to the license terms in the LICENSE file found in the top-level directory
|
||||
// of this distribution and at http://opencv.org/license.html.
|
||||
|
||||
/*
|
||||
Ridge Detection Filter. |
||||
OpenCV port by : Kushal Vyas (@kushalvyas), Venkatesh Vijaykumar(@venkateshvijaykumar) |
||||
*/ |
||||
|
||||
#ifndef __OPENCV_XIMGPROC_RIDGEFILTER_HPP__ |
||||
#define __OPENCV_XIMGPROC_RIDGEFILTER_HPP__ |
||||
|
||||
#include <opencv2/core.hpp> |
||||
|
||||
namespace cv { namespace ximgproc { |
||||
|
||||
//! @addtogroup ximgproc_filters
|
||||
//! @{
|
||||
|
||||
/** @brief Applies Ridge Detection Filter to an input image.
|
||||
Implements Ridge detection similar to the one in [Mathematica](http://reference.wolfram.com/language/ref/RidgeFilter.html)
|
||||
using the eigen values from the Hessian Matrix of the input image using Sobel Derivatives. |
||||
Additional refinement can be done using Skeletonization and Binarization. |
||||
*/ |
||||
class CV_EXPORTS_W RidgeDetectionFilter : public Algorithm |
||||
{ |
||||
public: |
||||
/**
|
||||
@brief Create pointer to the Ridge detection filter. |
||||
@param ddepth Specifies output image depth. Defualt is CV_32FC1 |
||||
@param dx Order of derivative x, default is 1 |
||||
@param dy Order of derivative y, default is 1 |
||||
@param ksize Sobel kernel size , default is 3 |
||||
@param out_dtype Converted format for output, default is CV_8UC1 |
||||
@param scale Optional scale value for derivative values, default is 1 |
||||
@param delta Optional bias added to output, default is 0 |
||||
@param borderType Pixel extrapolation method, default is BORDER_DEFAULT |
||||
@see Sobel, threshold, getStructuringElement, morphologyEx.( for additional refinement) |
||||
*/ |
||||
CV_WRAP static Ptr<RidgeDetectionFilter> create(int ddepth = CV_32FC1, int dx=1, int dy=1, int ksize = 3, int out_dtype=CV_8UC1, double scale = 1, double delta = 0, int borderType = BORDER_DEFAULT); |
||||
/**
|
||||
@brief Apply Ridge detection filter on input image. |
||||
@param _img InputArray as supported by Sobel. img can be 1-Channel or 3-Channels. |
||||
@param out OutputAray of structure as RidgeDetectionFilter::ddepth. Output image with ridges. |
||||
*/ |
||||
CV_WRAP virtual void getRidgeFilteredImage(InputArray _img, OutputArray out) = 0; |
||||
}; |
||||
|
||||
//! @}
|
||||
}} // namespace
|
||||
#endif |
@ -0,0 +1,39 @@ |
||||
// This file is part of OpenCV project.
|
||||
// It is subject to the license terms in the LICENSE file found in the top-level directory
|
||||
// of this distribution and at http://opencv.org/license.html.
|
||||
#include "perf_precomp.hpp" |
||||
|
||||
namespace cvtest { |
||||
|
||||
using namespace perf; |
||||
using namespace testing; |
||||
using namespace cv; |
||||
using namespace cv::ximgproc; |
||||
|
||||
typedef tuple<MatDepth, int, Size> RDFParams; |
||||
typedef TestBaseWithParam<RDFParams> RidgeDetectionFilterPerfTest; |
||||
|
||||
PERF_TEST_P(RidgeDetectionFilterPerfTest, perf, Combine( |
||||
Values((MatDepth)CV_32F), |
||||
Values(3), |
||||
SZ_TYPICAL |
||||
)) |
||||
{ |
||||
RDFParams params = GetParam(); |
||||
int ddepth = get<0>(params); |
||||
int ksize = get<1>(params); |
||||
Size sz = get<2>(params); |
||||
|
||||
Mat src(sz, ddepth); |
||||
Mat out(sz, src.type()); |
||||
|
||||
declare.in(src).out(out); |
||||
|
||||
Ptr<RidgeDetectionFilter> rdf = RidgeDetectionFilter::create(ddepth,1, 1, ksize); |
||||
|
||||
TEST_CYCLE() rdf->getRidgeFilteredImage(src, out); |
||||
|
||||
SANITY_CHECK_NOTHING(); |
||||
} |
||||
|
||||
} // namespace
|
@ -0,0 +1,73 @@ |
||||
// This file is part of OpenCV project.
|
||||
// It is subject to the license terms in the LICENSE file found in the top-level directory
|
||||
// of this distribution and at http://opencv.org/license.html.
|
||||
|
||||
#include "precomp.hpp" |
||||
#include "opencv2/imgproc.hpp" |
||||
#include "opencv2/ximgproc/ridgefilter.hpp" |
||||
|
||||
namespace cv { namespace ximgproc { |
||||
|
||||
class RidgeDetectionFilterImpl : public RidgeDetectionFilter |
||||
{ |
||||
public: |
||||
int _ddepth, _dx, _dy, _ksize; |
||||
double _scale, _delta; |
||||
int _borderType; |
||||
int _out_dtype; |
||||
RidgeDetectionFilterImpl(int ddepth=CV_32FC1, int dx=1, int dy=1, int ksize = 3, int out_dtype=CV_8UC1, double scale = 1, double delta = 0, int borderType = BORDER_DEFAULT) |
||||
{ |
||||
CV_Assert((ksize == 1 || ksize == 3 || ksize == 5 || ksize == 7)); |
||||
CV_Assert((ddepth == CV_32FC1 || ddepth == CV_64FC1)); |
||||
_ddepth = ddepth; |
||||
_dx = dx; |
||||
_dy = dy; |
||||
_ksize = ksize; |
||||
_scale = scale; |
||||
_delta = delta; |
||||
_borderType = borderType; |
||||
_out_dtype = out_dtype; |
||||
} |
||||
virtual void getRidgeFilteredImage(InputArray _img, OutputArray out); |
||||
}; |
||||
|
||||
void RidgeDetectionFilterImpl::getRidgeFilteredImage(InputArray _img, OutputArray out) |
||||
{ |
||||
Mat img = _img.getMat(); |
||||
CV_Assert(img.channels() == 1 || img.channels() == 3); |
||||
|
||||
if(img.channels() == 3) |
||||
cvtColor(img, img, COLOR_BGR2GRAY); |
||||
|
||||
Mat sbx, sby; |
||||
Sobel(img, sbx, _ddepth, _dx, 0, _ksize, _scale, _delta, _borderType); |
||||
Sobel(img, sby, _ddepth, 0, _dy, _ksize, _scale, _delta, _borderType); |
||||
|
||||
Mat sbxx, sbyy, sbxy; |
||||
Sobel(sbx, sbxx, _ddepth, _dx, 0, _ksize, _scale, _delta, _borderType); |
||||
Sobel(sby, sbyy, _ddepth, 0, _dy, _ksize, _scale, _delta, _borderType); |
||||
Sobel(sbx, sbxy, _ddepth, 0, _dy, _ksize, _scale, _delta, _borderType); |
||||
|
||||
Mat sb2xx, sb2yy, sb2xy; |
||||
multiply(sbxx, sbxx, sb2xx); |
||||
multiply(sbyy, sbyy, sb2yy); |
||||
multiply(sbxy, sbxy, sb2xy); |
||||
|
||||
Mat sbxxyy; |
||||
multiply(sbxx, sbyy, sbxxyy); |
||||
|
||||
Mat rootex; |
||||
rootex = (sb2xx + (sb2xy + sb2xy + sb2xy + sb2xy) - (sbxxyy + sbxxyy) + sb2xy ); |
||||
Mat root; |
||||
sqrt(rootex, root); |
||||
Mat ridgexp; |
||||
ridgexp = ( (sbxx + sbyy) + root ); |
||||
ridgexp.convertTo(out, _out_dtype, 0.5); |
||||
} |
||||
|
||||
Ptr<RidgeDetectionFilter> RidgeDetectionFilter::create(int ddepth, int dx, int dy, int ksize, int out_dtype, double scale, double delta, int borderType) |
||||
{ |
||||
return makePtr<RidgeDetectionFilterImpl>(ddepth, dx, dy, ksize, out_dtype, scale, delta, borderType); |
||||
} |
||||
|
||||
}} // namespace
|
@ -0,0 +1,32 @@ |
||||
// This file is part of OpenCV project.
|
||||
// It is subject to the license terms in the LICENSE file found in the top-level directory
|
||||
// of this distribution and at http://opencv.org/license.html.
|
||||
|
||||
#include "test_precomp.hpp" |
||||
|
||||
namespace cvtest { |
||||
|
||||
using namespace cv; |
||||
using namespace cv::ximgproc; |
||||
|
||||
TEST(ximgproc_ridgedetectionfilter, ReferenceAccuracy) |
||||
{ |
||||
String openCVExtraDir = cvtest::TS::ptr()->get_data_path(); |
||||
String srcImgPath = "cv/ximgproc/sources/04.png"; |
||||
String refPath = "cv/ximgproc/results/ridge_filter_test_ref/04.png"; |
||||
Mat src = imread(openCVExtraDir + srcImgPath); |
||||
Mat ref = imread(openCVExtraDir + refPath, 0); |
||||
Mat n_ref; |
||||
ref.convertTo(n_ref, CV_8UC1); |
||||
Ptr<RidgeDetectionFilter> rdf = RidgeDetectionFilter::create(); |
||||
Mat out; |
||||
rdf->getRidgeFilteredImage(src, out); |
||||
Mat out_cmp; |
||||
out.convertTo(out_cmp, CV_8UC1); |
||||
Mat sb; |
||||
subtract(out_cmp, n_ref, sb); |
||||
int zeros = countNonZero(sb); |
||||
EXPECT_EQ(zeros, 0); |
||||
} |
||||
|
||||
} // namespace
|
Loading…
Reference in new issue