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
CV_EXPORTS_W
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
#include "precomp.hpp"
#include "dtfilter_cpu.hpp"
#include "dtfilter_ocl.hpp"
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
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
CV_EXPORTS_W
void dtFilter(InputArray guide, InputArray src, OutputArray dst, double sigmaSpatial, double sigmaColor, int mode, int numIters)
{
if (dtUseOpenCLVersion(guide, src, mode, numIters))
{
Ptr<DTFilterOCL> dtf = DTFilterOCL::create(guide, sigmaSpatial, sigmaColor, mode, numIters);
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