Commit 81c9b8a0 authored by vludv's avatar vludv

Experimental functionality (OpenCL versions and slow Weighted Median) was removed.

parent 3097f395
...@@ -119,24 +119,6 @@ CV_EXPORTS_W void amFilter(InputArray joint, InputArray src, OutputArray dst, do ...@@ -119,24 +119,6 @@ CV_EXPORTS_W void amFilter(InputArray joint, InputArray src, OutputArray dst, do
CV_EXPORTS_W CV_EXPORTS_W
void jointBilateralFilter(InputArray joint, InputArray src, OutputArray dst, int d, double sigmaColor, double sigmaSpace, int borderType = BORDER_DEFAULT); void jointBilateralFilter(InputArray joint, InputArray src, OutputArray dst, int d, double sigmaColor, double sigmaSpace, int borderType = BORDER_DEFAULT);
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
/*Interface for Weighted Median Filter*/
class CV_EXPORTS_W WeightedMedian : public Algorithm
{
public:
CV_WRAP virtual void filter(InputArray src, OutputArray dst, double rangeQuantizer = 1, int dDepth = -1) = 0;
};
/*Fabric function for Weighted Median Filter*/
CV_EXPORTS_W
Ptr<WeightedMedian> createWeightedMedianFilter(InputArray guide, double spatialSize, double colorSize, int filterType = DTF_NC);
/*One-line Weighted Median Filter call*/
CV_EXPORTS_W void weightedMedianFilter(InputArray guide, InputArray src, OutputArray dst, double spatialSize, double colorSize, int filterType = DTF_NC, double rangeQuantizer = 1);
} }
#endif #endif
#endif #endif
#include "precomp.hpp" #include "precomp.hpp"
#include "dtfilter_cpu.hpp" #include "dtfilter_cpu.hpp"
#include "dtfilter_ocl.hpp"
namespace cv namespace cv
{ {
static bool dtUseOpenCLVersion(InputArray guide, InputArray src, int mode, int numIters)
{
return
false && guide.isUMat() && ocl::useOpenCL() &&
(guide.cols() >= 256 && guide.rows() >= 256) &&
(guide.depth() == CV_32F || guide.depth() == CV_8U) &&
(src.depth() == CV_32F || src.depth() == CV_8U) &&
(numIters <= 3);
}
CV_EXPORTS_W CV_EXPORTS_W
Ptr<DTFilter> createDTFilter(InputArray guide, double sigmaSpatial, double sigmaColor, int mode, int numIters) Ptr<DTFilter> createDTFilter(InputArray guide, double sigmaSpatial, double sigmaColor, int mode, int numIters)
{ {
...@@ -24,25 +13,9 @@ Ptr<DTFilter> createDTFilter(InputArray guide, double sigmaSpatial, double sigma ...@@ -24,25 +13,9 @@ Ptr<DTFilter> createDTFilter(InputArray guide, double sigmaSpatial, double sigma
CV_EXPORTS_W CV_EXPORTS_W
void dtFilter(InputArray guide, InputArray src, OutputArray dst, double sigmaSpatial, double sigmaColor, int mode, int numIters) void dtFilter(InputArray guide, InputArray src, OutputArray dst, double sigmaSpatial, double sigmaColor, int mode, int numIters)
{ {
if (dtUseOpenCLVersion(guide, src, mode, numIters)) Ptr<DTFilterCPU> dtf = DTFilterCPU::create(guide, sigmaSpatial, sigmaColor, mode, numIters);
{ dtf->setSingleFilterCall(true);
Ptr<DTFilterOCL> dtf = DTFilterOCL::create(guide, sigmaSpatial, sigmaColor, mode, numIters); dtf->filter(src, dst);
dtf->setSingleFilterCall(true);
dtf->filter(src, dst);
}
else
{
Ptr<DTFilterCPU> dtf = DTFilterCPU::create(guide, sigmaSpatial, sigmaColor, mode, numIters);
dtf->setSingleFilterCall(true);
dtf->filter(src, dst);
}
}
CV_EXPORTS_W
Ptr<DTFilter> createDTFilterOCL(InputArray guide, double sigmaSpatial, double sigmaColor, int mode, int numIters)
{
Ptr<DTFilterOCL> dtf = DTFilterOCL::create(guide, sigmaSpatial, sigmaColor, mode, numIters);
return Ptr<DTFilter>(dtf);
} }
} }
\ No newline at end of file
#include "precomp.hpp"
#include <vector>
#include <iostream>
using std::vector;
#ifdef _MSC_VER
# pragma warning(disable: 4512)
#endif
namespace cv
{
template <typename T>
struct SymArray2D
{
vector<T> vec;
int sz;
SymArray2D()
{
sz = 0;
}
void create(int sz_)
{
CV_DbgAssert(sz_ > 0);
sz = sz_;
vec.resize(total());
}
inline T& operator()(int i, int j)
{
CV_DbgAssert(i >= 0 && i < sz && j >= 0 && j < sz);
if (i < j) std::swap(i, j);
return vec[i*(i+1)/2 + j];
}
inline T& operator()(int i)
{
return vec[i];
}
int total() const
{
return sz*(sz + 1)/2;
}
void release()
{
vec.clear();
sz = 0;
}
};
class GuidedFilterImplOCL : public GuidedFilter
{
Size sz;
int radius;
double eps;
SymArray2D<UMat> covGuide;
SymArray2D<UMat> covGuideInv;
int guideCnNum;
vector<UMat> guideCn;
vector<UMat> guideCnMean;
inline void meanFilter(UMat& src, UMat& dst);
public:
GuidedFilterImplOCL(InputArray guide, int radius, double eps);
void filter(InputArray src, OutputArray dst, int dDepth);
void computeCovGuide();
void computeCovGuideInv();
void computeCovSrcGuide(vector<UMat>& srcCn, vector<UMat>& srcCnMean, vector<vector<UMat> >& covSrcGuide);
void computeAlpha(vector<vector<UMat> >& covSrcGuide, vector<vector<UMat> >& alpha);
void computeBeta(vector<vector<UMat> >&alpha, vector<UMat>& srcCnMean, vector<UMat>& beta);
void applyTransform(vector<vector<UMat> >& alpha, vector<UMat>& beta);
};
void GuidedFilterImplOCL::meanFilter(UMat& src, UMat& dst)
{
boxFilter(src, dst, CV_32F, Size(2 * radius + 1, 2 * radius + 1), Point(-1, -1), true, BORDER_REFLECT);
}
GuidedFilterImplOCL::GuidedFilterImplOCL(InputArray guide, int radius_, double eps_)
{
CV_Assert(!guide.empty() && guide.channels() <= 3);
CV_Assert(radius_ >= 0 && eps_ >= 0);
radius = radius_;
eps = eps_;
guideCnNum = guide.channels();
guideCn.resize(guideCnNum);
guideCnMean.resize(guideCnNum);
if (guide.depth() == CV_32F)
{
split(guide, guideCn);
}
else
{
UMat buf;
guide.getUMat().convertTo(buf, CV_32F);
split(buf, guideCn);
}
for (int i = 0; i < guideCnNum; i++)
{
meanFilter(guideCn[i], guideCnMean[i]);
}
computeCovGuide();
computeCovGuideInv();
}
void GuidedFilterImplOCL::computeCovGuide()
{
covGuide.create(guideCnNum);
UMat buf;
for (int i = 0; i < guideCnNum; i++)
for (int j = 0; j <= i; j++)
{
multiply(guideCn[i], guideCn[j], covGuide(i, j));
meanFilter(covGuide(i, j), covGuide(i, j));
multiply(guideCnMean[i], guideCnMean[j], buf);
subtract(covGuide(i, j), buf, covGuide(i, j));
//add regulariztion term
if (i == j)
covGuide(i, j).convertTo(covGuide(i, j), covGuide(i, j).depth(), 1.0, eps);
}
}
void GuidedFilterImplOCL::computeCovGuideInv()
{
covGuideInv.create(guideCnNum);
if (guideCnNum == 3)
{
//for (int l = 0; l < 3; l++)
// covGuideInv(2, l) = covGuide(2, l);
UMat det, tmp1, tmp2;
for (int l = 0; l < 3; l++)
{
int l1 = (l + 1) % 3;
int l2 = (l + 2) % 3;
multiply(covGuide(1, l1), covGuide(2, l2), tmp1);
multiply(covGuide(1, l2), covGuide(2, l1), tmp2);
if (l == 0)
{
subtract(tmp1, tmp2, det);
}
else
{
add(det, tmp1, det);
subtract(det, tmp2, det);
}
}
for (int k = 0; k < 3; k++)
for (int l = 0; l <= k; l++)
{
int k1 = (k + 1) % 3, l1 = (l + 1) % 3;
int k2 = (k + 2) % 3, l2 = (l + 2) % 3;
multiply(covGuide(k1, l1), covGuide(k2, l2), tmp1);
multiply(covGuide(k1, l2), covGuide(k2, l1), tmp2);
subtract(tmp1, tmp2, covGuideInv(k, l));
divide(covGuideInv(k, l), det, covGuideInv(k, l));
}
}
else if (guideCnNum == 2)
{
covGuideInv(0, 0) = covGuide(1, 1);
covGuideInv(1, 1) = covGuide(0, 0);
covGuideInv(0, 1) = covGuide(0, 1);
UMat det, tmp;
multiply(covGuide(0, 0), covGuide(1, 1), det);
multiply(covGuide(0, 1), covGuide(1, 0), tmp);
subtract(det, tmp, det);
tmp.release();
divide(covGuideInv(0, 0), det, covGuideInv(0, 0));
divide(covGuideInv(1, 1), det, covGuideInv(1, 1));
divide(covGuideInv(0, 1), det, covGuideInv(0, 1), -1);
}
else
{
covGuideInv(0, 0) = covGuide(0, 0);
divide(1.0, covGuide(0, 0), covGuideInv(0, 0));
}
covGuide.release();
}
void GuidedFilterImplOCL::filter(InputArray src, OutputArray dst, int dDepth)
{
if (dDepth == -1) dDepth = src.depth();
int srcCnNum = src.channels();
vector<UMat> srcCn(srcCnNum);
vector<UMat> srcCnMean(srcCnNum);
if (src.depth() != CV_32F)
{
UMat tmp;
src.getUMat().convertTo(tmp, CV_32F);
split(tmp, srcCn);
}
else
{
split(src, srcCn);
}
for (int i = 0; i < srcCnNum; i++)
meanFilter(srcCn[i], srcCnMean[i]);
vector<vector<UMat> > covSrcGuide(srcCnNum);
computeCovSrcGuide(srcCn, srcCnMean, covSrcGuide);
vector<vector<UMat> > alpha(srcCnNum);
vector<UMat>& beta = srcCnMean;
computeAlpha(covSrcGuide, alpha);
computeBeta(alpha, srcCnMean, beta);
//if (true)
//{
// for (int i = 0; i < srcCnNum; i++)
// {
// Mat alphaViz;
// merge(alpha[i], alphaViz);
// imwrite("res/alpha" + format("%d", i) + ".png", alphaViz * 100);
// }
// Mat betaViz;
// merge(beta, betaViz);
// imwrite("res/beta.png", betaViz + Scalar::all(127));
//}
for (int i = 0; i < srcCnNum; i++)
for (int j = 0; j < guideCnNum; j++)
meanFilter(alpha[i][j], alpha[i][j]);
applyTransform(alpha, beta);
if (dDepth != CV_32F)
{
for (int i = 0; i < srcCnNum; i++)
beta[i].convertTo(beta[i], dDepth);
}
merge(beta, dst);
}
void GuidedFilterImplOCL::computeCovSrcGuide(vector<UMat>& srcCn, vector<UMat>& srcCnMean, vector<vector<UMat> >& covSrcGuide)
{
int srcCnNum = (int)srcCn.size();
covSrcGuide.resize(srcCnNum);
UMat buf;
for (int i = 0; i < srcCnNum; i++)
{
covSrcGuide[i].resize(guideCnNum);
for (int j = 0; j < guideCnNum; j++)
{
UMat& cov = covSrcGuide[i][j];
multiply(srcCn[i], guideCn[i], cov);
meanFilter(cov, cov);
multiply(srcCnMean[i], guideCnMean[j], buf);
subtract(cov, buf, cov);
}
}
}
void GuidedFilterImplOCL::computeAlpha(vector<vector<UMat> >& covSrcGuide, vector<vector<UMat> >& alpha)
{
int srcCnNum = (int)covSrcGuide.size();
alpha.resize(srcCnNum);
UMat buf;
for (int i = 0; i < srcCnNum; i++)
{
alpha[i].resize(guideCnNum);
for (int k = 0; k < guideCnNum; k++)
{
multiply(covGuideInv(k, 0), covSrcGuide[i][0], alpha[i][k]);
for (int l = 1; l < guideCnNum; l++)
{
multiply(covGuideInv(k, l), covSrcGuide[i][l], buf);
add(buf, alpha[i][k], alpha[i][k]);
}
}
}
}
void GuidedFilterImplOCL::computeBeta(vector<vector<UMat> >& alpha, vector<UMat>& srcCnMean, vector<UMat>& beta)
{
int srcCnNum = (int)srcCnMean.size();
CV_Assert(&beta == &srcCnMean);
UMat buf;
for (int i = 0; i < srcCnNum; i++)
{
multiply(alpha[i][0], guideCnMean[0], beta[i]);
for (int j = 1; j < guideCnNum; j++)
{
multiply(alpha[i][j], guideCnMean[j], buf);
subtract(beta[i], buf, beta[i]);
}
meanFilter(beta[i], beta[i]);
}
}
void GuidedFilterImplOCL::applyTransform(vector<vector<UMat> >& alpha, vector<UMat>& beta)
{
int srcCnNum = (int)beta.size();
UMat buf;
for (int i = 0; i < srcCnNum; i++)
{
for (int j = 0; j < guideCnNum; j++)
{
multiply(guideCn[j], alpha[i][j], buf);
add(beta[i], buf, beta[i]);
}
}
}
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
}
\ No newline at end of file
#include "precomp.hpp"
#include <vector>
using std::vector;
namespace cv
{
class WeightedMedianImpl : public WeightedMedian
{
public:
void filter(InputArray src, OutputArray dst, double rangeQuantizer, int dDepth);
WeightedMedianImpl(InputArray guide, double spatialSize, double colorSize, int convFilter);
protected:
Ptr<DTFilter> dtf;
Ptr<GuidedFilter> gf;
Size sz;
bool isDT;
class UpdateMedian_ParBody : public ParallelLoopBody
{
Mat &sum, &reached, &res;
float medianLevel;
int curLevelValue;
public:
UpdateMedian_ParBody(Mat& sum_, Mat& reached_, Mat& res_, int curLevelValue_, float medianLevel_ = 127.5f)
: sum(sum_), reached(reached_), res(res_), curLevelValue(curLevelValue_), medianLevel(medianLevel_) {}
void operator() (const Range& range) const;
};
class ComputeMedian_ParBody : public ParallelLoopBody
{
vector<Mat>& layersRes;
Mat &sum, &res;
int layersStart, layerSize;
public:
ComputeMedian_ParBody(vector<Mat>& layersRes_, Mat& sum_, Mat& res_, int layersStart_, int layerSize_)
:layersRes(layersRes_), sum(sum_), res(res_), layersStart(layersStart_), layerSize(layerSize_) {}
void operator() (const Range& range) const;
};
};
WeightedMedianImpl::WeightedMedianImpl(InputArray guide, double spatialSize, double colorSize, int filterType)
{
isDT = (filterType == DTF_NC || filterType == DTF_IC || filterType == DTF_RF);
if (isDT)
{
dtf = createDTFilter(guide, spatialSize, colorSize, filterType, 3);
}
else if (filterType == GUIDED_FILTER)
{
gf = createGuidedFilter(guide, cvRound(spatialSize), colorSize);
}
else
{
CV_Error(Error::StsBadFlag, "Unsupported type of edge aware filter (only guided filter and domain transform allowed)");
}
sz = guide.size();
}
void WeightedMedianImpl::filter(InputArray src, OutputArray dst, double rangeQuantizer, int dDepth)
{
CV_Assert(src.size() == sz && src.depth() == CV_8U);
int layerSize = cvRound(rangeQuantizer);
int srcCnNum = src.channels();
vector<Mat> srcCn(srcCnNum);
vector<Mat> resCn(srcCnNum);
if (srcCnNum == 1)
srcCn[0] = src.getMat();
else
split(src, srcCn);
Mat reached, sum;
vector<Mat> resLayers;
for (int cnId = 0; cnId < srcCnNum; cnId++)
{
double minVal, maxVal;
minMaxLoc(srcCn[cnId], &minVal, &maxVal);
int layerStart = (int)minVal;
int layerEnd = cvRound(maxVal);
int layersCount = (layerEnd - layerStart) / layerSize;
sum = Mat::zeros(sz, CV_32FC1);
if (isDT)
{
resCn[cnId] = Mat::zeros(sz, CV_8UC1);
reached = Mat::zeros(sz, CV_8UC1);
}
else
{
resLayers.resize(layersCount);
}
Mat layer, layerFiltered;
for (int layerId = 0; layerId < layersCount; layerId++)
{
int curLevelVal = layerStart + layerId*layerSize;
if (src.depth() == CV_8U && layerSize == 1)
{
layer = (srcCn[cnId] == layerStart + layerId);
}
else
{
layer = (srcCn[cnId] >= curLevelVal) & (srcCn[cnId] < curLevelVal + layerSize);
}
if (isDT)
{
dtf->filter(layer, layerFiltered, CV_32F);
add(layerFiltered, sum, sum);
UpdateMedian_ParBody updateMedian(sum, reached, resCn[cnId], curLevelVal);
parallel_for_(Range(0, sz.height), updateMedian);
}
else
{
gf->filter(layer, resLayers[layerId], CV_32F);
add(sum, resLayers[layerId], sum);
}
}
if (!isDT)
{
resCn[cnId].create(sz, CV_8UC1);
ComputeMedian_ParBody computeMedian(resLayers, sum, resCn[cnId], layerStart, layerSize);
parallel_for_(Range(0, sz.height), computeMedian);
}
}
if (dDepth == -1) dDepth = src.depth();
if (dDepth == CV_8U)
{
merge(resCn, dst);
}
else
{
Mat res;
merge(resCn, res);
res.convertTo(dst, dDepth);
}
}
void WeightedMedianImpl::UpdateMedian_ParBody::operator()(const Range& range) const
{
for (int i = range.start; i < range.end; i++)
{
float *sumLine = sum.ptr<float>(i);
uchar *resLine = res.ptr<uchar>(i);
uchar *reachedLine = reached.ptr<uchar>(i);
for (int j = 0; j < sum.cols; j++)
{
if (reachedLine[j])
{
continue;
}
else if (sumLine[j] >= medianLevel)
{
resLine[j] = (uchar) curLevelValue;
reachedLine[j] = 0xFF;
}
}
}
}
void WeightedMedianImpl::ComputeMedian_ParBody::operator()(const Range& range) const
{
for (int i = range.start; i < range.end; i++)
{
float *sumLine = sum.ptr<float>(i);
uchar *resLine = res.ptr<uchar>(i);
for (int j = 0; j < sum.cols; j++)
{
float curSum = 0.0f;
float medianSum = sumLine[j] / 2.0f;
int l = 0;
for (l = 0; l < (int)layersRes.size(); l++)
{
if (curSum >= medianSum)
break;
curSum += layersRes[l].at<float>(i, j);
}
resLine[j] = (uchar) (layersStart + l*layerSize);
}
}
}
CV_EXPORTS_W
Ptr<WeightedMedian> createWeightedMedianFilter(InputArray guide, double spatialSize, double colorSize, int filterType)
{
return Ptr<WeightedMedian>(new WeightedMedianImpl(guide, spatialSize, colorSize, filterType));
}
CV_EXPORTS_W void weightedMedianFilter(InputArray guide, InputArray src, OutputArray dst, double spatialSize, double colorSize, int filterType, double rangeQuantizer)
{
WeightedMedian *wm = new WeightedMedianImpl(guide, spatialSize, colorSize, filterType);
wm->filter(src, dst, rangeQuantizer);
delete wm;
}
}
\ No newline at end of file
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