mirror of
https://github.com/opencv/opencv.git
synced 2026-07-30 15:53:03 +04:00
Merge remote-tracking branch 'origin/2.4'
Pull requests: #943 from jet47:cuda-5.5-support #944 from jet47:cmake-2.8.11-cuda-fix #912 from SpecLad:contributing #934 from SpecLad:parallel-for #931 from jet47:gpu-test-fixes #932 from bitwangyaoyao:2.4_fixBFM #918 from bitwangyaoyao:2.4_samples #924 from pengx17:2.4_arithm_fix #925 from pengx17:2.4_canny_tmp_fix #927 from bitwangyaoyao:2.4_perf #930 from pengx17:2.4_haar_ext #928 from apavlenko:bugfix_3027 #920 from asmorkalov:android_move #910 from pengx17:2.4_oclgfft #913 from janm399:2.4 #916 from bitwangyaoyao:2.4_fixPyrLK #919 from abidrahmank:2.4 #923 from pengx17:2.4_macfix Conflicts: modules/calib3d/src/stereobm.cpp modules/features2d/src/detectors.cpp modules/gpu/src/error.cpp modules/gpu/src/precomp.hpp modules/imgproc/src/distransform.cpp modules/imgproc/src/morph.cpp modules/ocl/include/opencv2/ocl/ocl.hpp modules/ocl/perf/perf_color.cpp modules/ocl/perf/perf_imgproc.cpp modules/ocl/perf/perf_match_template.cpp modules/ocl/perf/precomp.cpp modules/ocl/perf/precomp.hpp modules/ocl/src/arithm.cpp modules/ocl/src/canny.cpp modules/ocl/src/filtering.cpp modules/ocl/src/haar.cpp modules/ocl/src/hog.cpp modules/ocl/src/imgproc.cpp modules/ocl/src/opencl/haarobjectdetect.cl modules/ocl/src/pyrlk.cpp modules/video/src/bgfg_gaussmix2.cpp modules/video/src/lkpyramid.cpp platforms/linux/scripts/cmake_arm_gnueabi_hardfp.sh platforms/linux/scripts/cmake_arm_gnueabi_softfp.sh platforms/scripts/ABI_compat_generator.py samples/ocl/facedetect.cpp
This commit is contained in:
@@ -0,0 +1,334 @@
|
||||
/*M///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
||||
//
|
||||
// By downloading, copying, installing or using the software you agree to this license.
|
||||
// If you do not agree to this license, do not download, install,
|
||||
// copy or use the software.
|
||||
//
|
||||
//
|
||||
// License Agreement
|
||||
// For Open Source Computer Vision Library
|
||||
//
|
||||
// Copyright (C) 2013, NVIDIA Corporation, all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
// are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * Redistribution's of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistribution's in binary form must reproduce the above copyright notice,
|
||||
// this list of conditions and the following disclaimer in the documentation
|
||||
// and/or other materials provided with the distribution.
|
||||
//
|
||||
// * The name of the copyright holders may not be used to endorse or promote products
|
||||
// derived from this software without specific prior written permission.
|
||||
//
|
||||
// This software is provided by the copyright holders and contributors "as is" and
|
||||
// any express or implied warranties, including, but not limited to, the implied
|
||||
// warranties of merchantability and fitness for a particular purpose are disclaimed.
|
||||
// In no event shall the copyright holders or contributors be liable for any direct,
|
||||
// indirect, incidental, special, exemplary, or consequential damages
|
||||
// (including, but not limited to, procurement of substitute goods or services;
|
||||
// loss of use, data, or profits; or business interruption) however caused
|
||||
// and on any theory of liability, whether in contract, strict liability,
|
||||
// or tort (including negligence or otherwise) arising in any way out of
|
||||
// the use of this software, even if advised of the possibility of such damage.
|
||||
//
|
||||
//M*/
|
||||
|
||||
#include "precomp.hpp"
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// CLAHE
|
||||
|
||||
namespace
|
||||
{
|
||||
class CLAHE_CalcLut_Body : public cv::ParallelLoopBody
|
||||
{
|
||||
public:
|
||||
CLAHE_CalcLut_Body(const cv::Mat& src, cv::Mat& lut, cv::Size tileSize, int tilesX, int tilesY, int clipLimit, float lutScale) :
|
||||
src_(src), lut_(lut), tileSize_(tileSize), tilesX_(tilesX), tilesY_(tilesY), clipLimit_(clipLimit), lutScale_(lutScale)
|
||||
{
|
||||
}
|
||||
|
||||
void operator ()(const cv::Range& range) const;
|
||||
|
||||
private:
|
||||
cv::Mat src_;
|
||||
mutable cv::Mat lut_;
|
||||
|
||||
cv::Size tileSize_;
|
||||
int tilesX_;
|
||||
int tilesY_;
|
||||
int clipLimit_;
|
||||
float lutScale_;
|
||||
};
|
||||
|
||||
void CLAHE_CalcLut_Body::operator ()(const cv::Range& range) const
|
||||
{
|
||||
const int histSize = 256;
|
||||
|
||||
uchar* tileLut = lut_.ptr(range.start);
|
||||
const size_t lut_step = lut_.step;
|
||||
|
||||
for (int k = range.start; k < range.end; ++k, tileLut += lut_step)
|
||||
{
|
||||
const int ty = k / tilesX_;
|
||||
const int tx = k % tilesX_;
|
||||
|
||||
// retrieve tile submatrix
|
||||
|
||||
cv::Rect tileROI;
|
||||
tileROI.x = tx * tileSize_.width;
|
||||
tileROI.y = ty * tileSize_.height;
|
||||
tileROI.width = tileSize_.width;
|
||||
tileROI.height = tileSize_.height;
|
||||
|
||||
const cv::Mat tile = src_(tileROI);
|
||||
|
||||
// calc histogram
|
||||
|
||||
int tileHist[histSize] = {0, };
|
||||
|
||||
int height = tileROI.height;
|
||||
const size_t sstep = tile.step;
|
||||
for (const uchar* ptr = tile.ptr<uchar>(0); height--; ptr += sstep)
|
||||
{
|
||||
int x = 0;
|
||||
for (; x <= tileROI.width - 4; x += 4)
|
||||
{
|
||||
int t0 = ptr[x], t1 = ptr[x+1];
|
||||
tileHist[t0]++; tileHist[t1]++;
|
||||
t0 = ptr[x+2]; t1 = ptr[x+3];
|
||||
tileHist[t0]++; tileHist[t1]++;
|
||||
}
|
||||
|
||||
for (; x < tileROI.width; ++x)
|
||||
tileHist[ptr[x]]++;
|
||||
}
|
||||
|
||||
// clip histogram
|
||||
|
||||
if (clipLimit_ > 0)
|
||||
{
|
||||
// how many pixels were clipped
|
||||
int clipped = 0;
|
||||
for (int i = 0; i < histSize; ++i)
|
||||
{
|
||||
if (tileHist[i] > clipLimit_)
|
||||
{
|
||||
clipped += tileHist[i] - clipLimit_;
|
||||
tileHist[i] = clipLimit_;
|
||||
}
|
||||
}
|
||||
|
||||
// redistribute clipped pixels
|
||||
int redistBatch = clipped / histSize;
|
||||
int residual = clipped - redistBatch * histSize;
|
||||
|
||||
for (int i = 0; i < histSize; ++i)
|
||||
tileHist[i] += redistBatch;
|
||||
|
||||
for (int i = 0; i < residual; ++i)
|
||||
tileHist[i]++;
|
||||
}
|
||||
|
||||
// calc Lut
|
||||
|
||||
int sum = 0;
|
||||
for (int i = 0; i < histSize; ++i)
|
||||
{
|
||||
sum += tileHist[i];
|
||||
tileLut[i] = cv::saturate_cast<uchar>(sum * lutScale_);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class CLAHE_Interpolation_Body : public cv::ParallelLoopBody
|
||||
{
|
||||
public:
|
||||
CLAHE_Interpolation_Body(const cv::Mat& src, cv::Mat& dst, const cv::Mat& lut, cv::Size tileSize, int tilesX, int tilesY) :
|
||||
src_(src), dst_(dst), lut_(lut), tileSize_(tileSize), tilesX_(tilesX), tilesY_(tilesY)
|
||||
{
|
||||
}
|
||||
|
||||
void operator ()(const cv::Range& range) const;
|
||||
|
||||
private:
|
||||
cv::Mat src_;
|
||||
mutable cv::Mat dst_;
|
||||
cv::Mat lut_;
|
||||
|
||||
cv::Size tileSize_;
|
||||
int tilesX_;
|
||||
int tilesY_;
|
||||
};
|
||||
|
||||
void CLAHE_Interpolation_Body::operator ()(const cv::Range& range) const
|
||||
{
|
||||
const size_t lut_step = lut_.step;
|
||||
|
||||
for (int y = range.start; y < range.end; ++y)
|
||||
{
|
||||
const uchar* srcRow = src_.ptr<uchar>(y);
|
||||
uchar* dstRow = dst_.ptr<uchar>(y);
|
||||
|
||||
const float tyf = (static_cast<float>(y) / tileSize_.height) - 0.5f;
|
||||
|
||||
int ty1 = cvFloor(tyf);
|
||||
int ty2 = ty1 + 1;
|
||||
|
||||
const float ya = tyf - ty1;
|
||||
|
||||
ty1 = std::max(ty1, 0);
|
||||
ty2 = std::min(ty2, tilesY_ - 1);
|
||||
|
||||
const uchar* lutPlane1 = lut_.ptr(ty1 * tilesX_);
|
||||
const uchar* lutPlane2 = lut_.ptr(ty2 * tilesX_);
|
||||
|
||||
for (int x = 0; x < src_.cols; ++x)
|
||||
{
|
||||
const float txf = (static_cast<float>(x) / tileSize_.width) - 0.5f;
|
||||
|
||||
int tx1 = cvFloor(txf);
|
||||
int tx2 = tx1 + 1;
|
||||
|
||||
const float xa = txf - tx1;
|
||||
|
||||
tx1 = std::max(tx1, 0);
|
||||
tx2 = std::min(tx2, tilesX_ - 1);
|
||||
|
||||
const int srcVal = srcRow[x];
|
||||
|
||||
const size_t ind1 = tx1 * lut_step + srcVal;
|
||||
const size_t ind2 = tx2 * lut_step + srcVal;
|
||||
|
||||
float res = 0;
|
||||
|
||||
res += lutPlane1[ind1] * ((1.0f - xa) * (1.0f - ya));
|
||||
res += lutPlane1[ind2] * ((xa) * (1.0f - ya));
|
||||
res += lutPlane2[ind1] * ((1.0f - xa) * (ya));
|
||||
res += lutPlane2[ind2] * ((xa) * (ya));
|
||||
|
||||
dstRow[x] = cv::saturate_cast<uchar>(res);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class CLAHE_Impl : public cv::CLAHE
|
||||
{
|
||||
public:
|
||||
CLAHE_Impl(double clipLimit = 40.0, int tilesX = 8, int tilesY = 8);
|
||||
|
||||
cv::AlgorithmInfo* info() const;
|
||||
|
||||
void apply(cv::InputArray src, cv::OutputArray dst);
|
||||
|
||||
void setClipLimit(double clipLimit);
|
||||
double getClipLimit() const;
|
||||
|
||||
void setTilesGridSize(cv::Size tileGridSize);
|
||||
cv::Size getTilesGridSize() const;
|
||||
|
||||
void collectGarbage();
|
||||
|
||||
private:
|
||||
double clipLimit_;
|
||||
int tilesX_;
|
||||
int tilesY_;
|
||||
|
||||
cv::Mat srcExt_;
|
||||
cv::Mat lut_;
|
||||
};
|
||||
|
||||
CLAHE_Impl::CLAHE_Impl(double clipLimit, int tilesX, int tilesY) :
|
||||
clipLimit_(clipLimit), tilesX_(tilesX), tilesY_(tilesY)
|
||||
{
|
||||
}
|
||||
|
||||
CV_INIT_ALGORITHM(CLAHE_Impl, "CLAHE",
|
||||
obj.info()->addParam(obj, "clipLimit", obj.clipLimit_);
|
||||
obj.info()->addParam(obj, "tilesX", obj.tilesX_);
|
||||
obj.info()->addParam(obj, "tilesY", obj.tilesY_))
|
||||
|
||||
void CLAHE_Impl::apply(cv::InputArray _src, cv::OutputArray _dst)
|
||||
{
|
||||
cv::Mat src = _src.getMat();
|
||||
|
||||
CV_Assert( src.type() == CV_8UC1 );
|
||||
|
||||
_dst.create( src.size(), src.type() );
|
||||
cv::Mat dst = _dst.getMat();
|
||||
|
||||
const int histSize = 256;
|
||||
|
||||
lut_.create(tilesX_ * tilesY_, histSize, CV_8UC1);
|
||||
|
||||
cv::Size tileSize;
|
||||
cv::Mat srcForLut;
|
||||
|
||||
if (src.cols % tilesX_ == 0 && src.rows % tilesY_ == 0)
|
||||
{
|
||||
tileSize = cv::Size(src.cols / tilesX_, src.rows / tilesY_);
|
||||
srcForLut = src;
|
||||
}
|
||||
else
|
||||
{
|
||||
cv::copyMakeBorder(src, srcExt_, 0, tilesY_ - (src.rows % tilesY_), 0, tilesX_ - (src.cols % tilesX_), cv::BORDER_REFLECT_101);
|
||||
|
||||
tileSize = cv::Size(srcExt_.cols / tilesX_, srcExt_.rows / tilesY_);
|
||||
srcForLut = srcExt_;
|
||||
}
|
||||
|
||||
const int tileSizeTotal = tileSize.area();
|
||||
const float lutScale = static_cast<float>(histSize - 1) / tileSizeTotal;
|
||||
|
||||
int clipLimit = 0;
|
||||
if (clipLimit_ > 0.0)
|
||||
{
|
||||
clipLimit = static_cast<int>(clipLimit_ * tileSizeTotal / histSize);
|
||||
clipLimit = std::max(clipLimit, 1);
|
||||
}
|
||||
|
||||
CLAHE_CalcLut_Body calcLutBody(srcForLut, lut_, tileSize, tilesX_, tilesY_, clipLimit, lutScale);
|
||||
cv::parallel_for_(cv::Range(0, tilesX_ * tilesY_), calcLutBody);
|
||||
|
||||
CLAHE_Interpolation_Body interpolationBody(src, dst, lut_, tileSize, tilesX_, tilesY_);
|
||||
cv::parallel_for_(cv::Range(0, src.rows), interpolationBody);
|
||||
}
|
||||
|
||||
void CLAHE_Impl::setClipLimit(double clipLimit)
|
||||
{
|
||||
clipLimit_ = clipLimit;
|
||||
}
|
||||
|
||||
double CLAHE_Impl::getClipLimit() const
|
||||
{
|
||||
return clipLimit_;
|
||||
}
|
||||
|
||||
void CLAHE_Impl::setTilesGridSize(cv::Size tileGridSize)
|
||||
{
|
||||
tilesX_ = tileGridSize.width;
|
||||
tilesY_ = tileGridSize.height;
|
||||
}
|
||||
|
||||
cv::Size CLAHE_Impl::getTilesGridSize() const
|
||||
{
|
||||
return cv::Size(tilesX_, tilesY_);
|
||||
}
|
||||
|
||||
void CLAHE_Impl::collectGarbage()
|
||||
{
|
||||
srcExt_.release();
|
||||
lut_.release();
|
||||
}
|
||||
}
|
||||
|
||||
cv::Ptr<cv::CLAHE> cv::createCLAHE(double clipLimit, cv::Size tileGridSize)
|
||||
{
|
||||
return new CLAHE_Impl(clipLimit, tileGridSize.width, tileGridSize.height);
|
||||
}
|
||||
@@ -1815,7 +1815,7 @@ const int ITUR_BT_601_CGV = -385875;
|
||||
const int ITUR_BT_601_CBV = -74448;
|
||||
|
||||
template<int bIdx, int uIdx>
|
||||
struct YUV420sp2RGB888Invoker
|
||||
struct YUV420sp2RGB888Invoker : ParallelLoopBody
|
||||
{
|
||||
Mat* dst;
|
||||
const uchar* my1, *muv;
|
||||
@@ -1824,10 +1824,10 @@ struct YUV420sp2RGB888Invoker
|
||||
YUV420sp2RGB888Invoker(Mat* _dst, int _stride, const uchar* _y1, const uchar* _uv)
|
||||
: dst(_dst), my1(_y1), muv(_uv), width(_dst->cols), stride(_stride) {}
|
||||
|
||||
void operator()(const BlockedRange& range) const
|
||||
void operator()(const Range& range) const
|
||||
{
|
||||
int rangeBegin = range.begin() * 2;
|
||||
int rangeEnd = range.end() * 2;
|
||||
int rangeBegin = range.start * 2;
|
||||
int rangeEnd = range.end * 2;
|
||||
|
||||
//R = 1.164(Y - 16) + 1.596(V - 128)
|
||||
//G = 1.164(Y - 16) - 0.813(V - 128) - 0.391(U - 128)
|
||||
@@ -1884,7 +1884,7 @@ struct YUV420sp2RGB888Invoker
|
||||
};
|
||||
|
||||
template<int bIdx, int uIdx>
|
||||
struct YUV420sp2RGBA8888Invoker
|
||||
struct YUV420sp2RGBA8888Invoker : ParallelLoopBody
|
||||
{
|
||||
Mat* dst;
|
||||
const uchar* my1, *muv;
|
||||
@@ -1893,10 +1893,10 @@ struct YUV420sp2RGBA8888Invoker
|
||||
YUV420sp2RGBA8888Invoker(Mat* _dst, int _stride, const uchar* _y1, const uchar* _uv)
|
||||
: dst(_dst), my1(_y1), muv(_uv), width(_dst->cols), stride(_stride) {}
|
||||
|
||||
void operator()(const BlockedRange& range) const
|
||||
void operator()(const Range& range) const
|
||||
{
|
||||
int rangeBegin = range.begin() * 2;
|
||||
int rangeEnd = range.end() * 2;
|
||||
int rangeBegin = range.start * 2;
|
||||
int rangeEnd = range.end * 2;
|
||||
|
||||
//R = 1.164(Y - 16) + 1.596(V - 128)
|
||||
//G = 1.164(Y - 16) - 0.813(V - 128) - 0.391(U - 128)
|
||||
@@ -1957,7 +1957,7 @@ struct YUV420sp2RGBA8888Invoker
|
||||
};
|
||||
|
||||
template<int bIdx>
|
||||
struct YUV420p2RGB888Invoker
|
||||
struct YUV420p2RGB888Invoker : ParallelLoopBody
|
||||
{
|
||||
Mat* dst;
|
||||
const uchar* my1, *mu, *mv;
|
||||
@@ -1967,19 +1967,19 @@ struct YUV420p2RGB888Invoker
|
||||
YUV420p2RGB888Invoker(Mat* _dst, int _stride, const uchar* _y1, const uchar* _u, const uchar* _v, int _ustepIdx, int _vstepIdx)
|
||||
: dst(_dst), my1(_y1), mu(_u), mv(_v), width(_dst->cols), stride(_stride), ustepIdx(_ustepIdx), vstepIdx(_vstepIdx) {}
|
||||
|
||||
void operator()(const BlockedRange& range) const
|
||||
void operator()(const Range& range) const
|
||||
{
|
||||
const int rangeBegin = range.begin() * 2;
|
||||
const int rangeEnd = range.end() * 2;
|
||||
const int rangeBegin = range.start * 2;
|
||||
const int rangeEnd = range.end * 2;
|
||||
|
||||
size_t uvsteps[2] = {width/2, stride - width/2};
|
||||
int usIdx = ustepIdx, vsIdx = vstepIdx;
|
||||
|
||||
const uchar* y1 = my1 + rangeBegin * stride;
|
||||
const uchar* u1 = mu + (range.begin() / 2) * stride;
|
||||
const uchar* v1 = mv + (range.begin() / 2) * stride;
|
||||
const uchar* u1 = mu + (range.start / 2) * stride;
|
||||
const uchar* v1 = mv + (range.start / 2) * stride;
|
||||
|
||||
if(range.begin() % 2 == 1)
|
||||
if(range.start % 2 == 1)
|
||||
{
|
||||
u1 += uvsteps[(usIdx++) & 1];
|
||||
v1 += uvsteps[(vsIdx++) & 1];
|
||||
@@ -2025,7 +2025,7 @@ struct YUV420p2RGB888Invoker
|
||||
};
|
||||
|
||||
template<int bIdx>
|
||||
struct YUV420p2RGBA8888Invoker
|
||||
struct YUV420p2RGBA8888Invoker : ParallelLoopBody
|
||||
{
|
||||
Mat* dst;
|
||||
const uchar* my1, *mu, *mv;
|
||||
@@ -2035,19 +2035,19 @@ struct YUV420p2RGBA8888Invoker
|
||||
YUV420p2RGBA8888Invoker(Mat* _dst, int _stride, const uchar* _y1, const uchar* _u, const uchar* _v, int _ustepIdx, int _vstepIdx)
|
||||
: dst(_dst), my1(_y1), mu(_u), mv(_v), width(_dst->cols), stride(_stride), ustepIdx(_ustepIdx), vstepIdx(_vstepIdx) {}
|
||||
|
||||
void operator()(const BlockedRange& range) const
|
||||
void operator()(const Range& range) const
|
||||
{
|
||||
int rangeBegin = range.begin() * 2;
|
||||
int rangeEnd = range.end() * 2;
|
||||
int rangeBegin = range.start * 2;
|
||||
int rangeEnd = range.end * 2;
|
||||
|
||||
size_t uvsteps[2] = {width/2, stride - width/2};
|
||||
int usIdx = ustepIdx, vsIdx = vstepIdx;
|
||||
|
||||
const uchar* y1 = my1 + rangeBegin * stride;
|
||||
const uchar* u1 = mu + (range.begin() / 2) * stride;
|
||||
const uchar* v1 = mv + (range.begin() / 2) * stride;
|
||||
const uchar* u1 = mu + (range.start / 2) * stride;
|
||||
const uchar* v1 = mv + (range.start / 2) * stride;
|
||||
|
||||
if(range.begin() % 2 == 1)
|
||||
if(range.start % 2 == 1)
|
||||
{
|
||||
u1 += uvsteps[(usIdx++) & 1];
|
||||
v1 += uvsteps[(vsIdx++) & 1];
|
||||
@@ -2102,48 +2102,40 @@ template<int bIdx, int uIdx>
|
||||
inline void cvtYUV420sp2RGB(Mat& _dst, int _stride, const uchar* _y1, const uchar* _uv)
|
||||
{
|
||||
YUV420sp2RGB888Invoker<bIdx, uIdx> converter(&_dst, _stride, _y1, _uv);
|
||||
#ifdef HAVE_TBB
|
||||
if (_dst.total() >= MIN_SIZE_FOR_PARALLEL_YUV420_CONVERSION)
|
||||
parallel_for(BlockedRange(0, _dst.rows/2), converter);
|
||||
parallel_for_(Range(0, _dst.rows/2), converter);
|
||||
else
|
||||
#endif
|
||||
converter(BlockedRange(0, _dst.rows/2));
|
||||
converter(Range(0, _dst.rows/2));
|
||||
}
|
||||
|
||||
template<int bIdx, int uIdx>
|
||||
inline void cvtYUV420sp2RGBA(Mat& _dst, int _stride, const uchar* _y1, const uchar* _uv)
|
||||
{
|
||||
YUV420sp2RGBA8888Invoker<bIdx, uIdx> converter(&_dst, _stride, _y1, _uv);
|
||||
#ifdef HAVE_TBB
|
||||
if (_dst.total() >= MIN_SIZE_FOR_PARALLEL_YUV420_CONVERSION)
|
||||
parallel_for(BlockedRange(0, _dst.rows/2), converter);
|
||||
parallel_for_(Range(0, _dst.rows/2), converter);
|
||||
else
|
||||
#endif
|
||||
converter(BlockedRange(0, _dst.rows/2));
|
||||
converter(Range(0, _dst.rows/2));
|
||||
}
|
||||
|
||||
template<int bIdx>
|
||||
inline void cvtYUV420p2RGB(Mat& _dst, int _stride, const uchar* _y1, const uchar* _u, const uchar* _v, int ustepIdx, int vstepIdx)
|
||||
{
|
||||
YUV420p2RGB888Invoker<bIdx> converter(&_dst, _stride, _y1, _u, _v, ustepIdx, vstepIdx);
|
||||
#ifdef HAVE_TBB
|
||||
if (_dst.total() >= MIN_SIZE_FOR_PARALLEL_YUV420_CONVERSION)
|
||||
parallel_for(BlockedRange(0, _dst.rows/2), converter);
|
||||
parallel_for_(Range(0, _dst.rows/2), converter);
|
||||
else
|
||||
#endif
|
||||
converter(BlockedRange(0, _dst.rows/2));
|
||||
converter(Range(0, _dst.rows/2));
|
||||
}
|
||||
|
||||
template<int bIdx>
|
||||
inline void cvtYUV420p2RGBA(Mat& _dst, int _stride, const uchar* _y1, const uchar* _u, const uchar* _v, int ustepIdx, int vstepIdx)
|
||||
{
|
||||
YUV420p2RGBA8888Invoker<bIdx> converter(&_dst, _stride, _y1, _u, _v, ustepIdx, vstepIdx);
|
||||
#ifdef HAVE_TBB
|
||||
if (_dst.total() >= MIN_SIZE_FOR_PARALLEL_YUV420_CONVERSION)
|
||||
parallel_for(BlockedRange(0, _dst.rows/2), converter);
|
||||
parallel_for_(Range(0, _dst.rows/2), converter);
|
||||
else
|
||||
#endif
|
||||
converter(BlockedRange(0, _dst.rows/2));
|
||||
converter(Range(0, _dst.rows/2));
|
||||
}
|
||||
|
||||
///////////////////////////////////// RGB -> YUV420p /////////////////////////////////////
|
||||
@@ -2227,7 +2219,7 @@ static void cvtRGBtoYUV420p(const Mat& src, Mat& dst)
|
||||
///////////////////////////////////// YUV422 -> RGB /////////////////////////////////////
|
||||
|
||||
template<int bIdx, int uIdx, int yIdx>
|
||||
struct YUV422toRGB888Invoker
|
||||
struct YUV422toRGB888Invoker : ParallelLoopBody
|
||||
{
|
||||
Mat* dst;
|
||||
const uchar* src;
|
||||
@@ -2236,10 +2228,10 @@ struct YUV422toRGB888Invoker
|
||||
YUV422toRGB888Invoker(Mat* _dst, int _stride, const uchar* _yuv)
|
||||
: dst(_dst), src(_yuv), width(_dst->cols), stride(_stride) {}
|
||||
|
||||
void operator()(const BlockedRange& range) const
|
||||
void operator()(const Range& range) const
|
||||
{
|
||||
int rangeBegin = range.begin();
|
||||
int rangeEnd = range.end();
|
||||
int rangeBegin = range.start;
|
||||
int rangeEnd = range.end;
|
||||
|
||||
const int uidx = 1 - yIdx + uIdx * 2;
|
||||
const int vidx = (2 + uidx) % 4;
|
||||
@@ -2273,7 +2265,7 @@ struct YUV422toRGB888Invoker
|
||||
};
|
||||
|
||||
template<int bIdx, int uIdx, int yIdx>
|
||||
struct YUV422toRGBA8888Invoker
|
||||
struct YUV422toRGBA8888Invoker : ParallelLoopBody
|
||||
{
|
||||
Mat* dst;
|
||||
const uchar* src;
|
||||
@@ -2282,10 +2274,10 @@ struct YUV422toRGBA8888Invoker
|
||||
YUV422toRGBA8888Invoker(Mat* _dst, int _stride, const uchar* _yuv)
|
||||
: dst(_dst), src(_yuv), width(_dst->cols), stride(_stride) {}
|
||||
|
||||
void operator()(const BlockedRange& range) const
|
||||
void operator()(const Range& range) const
|
||||
{
|
||||
int rangeBegin = range.begin();
|
||||
int rangeEnd = range.end();
|
||||
int rangeBegin = range.start;
|
||||
int rangeEnd = range.end;
|
||||
|
||||
const int uidx = 1 - yIdx + uIdx * 2;
|
||||
const int vidx = (2 + uidx) % 4;
|
||||
@@ -2326,24 +2318,20 @@ template<int bIdx, int uIdx, int yIdx>
|
||||
inline void cvtYUV422toRGB(Mat& _dst, int _stride, const uchar* _yuv)
|
||||
{
|
||||
YUV422toRGB888Invoker<bIdx, uIdx, yIdx> converter(&_dst, _stride, _yuv);
|
||||
#ifdef HAVE_TBB
|
||||
if (_dst.total() >= MIN_SIZE_FOR_PARALLEL_YUV422_CONVERSION)
|
||||
parallel_for(BlockedRange(0, _dst.rows), converter);
|
||||
parallel_for_(Range(0, _dst.rows), converter);
|
||||
else
|
||||
#endif
|
||||
converter(BlockedRange(0, _dst.rows));
|
||||
converter(Range(0, _dst.rows));
|
||||
}
|
||||
|
||||
template<int bIdx, int uIdx, int yIdx>
|
||||
inline void cvtYUV422toRGBA(Mat& _dst, int _stride, const uchar* _yuv)
|
||||
{
|
||||
YUV422toRGBA8888Invoker<bIdx, uIdx, yIdx> converter(&_dst, _stride, _yuv);
|
||||
#ifdef HAVE_TBB
|
||||
if (_dst.total() >= MIN_SIZE_FOR_PARALLEL_YUV422_CONVERSION)
|
||||
parallel_for(BlockedRange(0, _dst.rows), converter);
|
||||
parallel_for_(Range(0, _dst.rows), converter);
|
||||
else
|
||||
#endif
|
||||
converter(BlockedRange(0, _dst.rows));
|
||||
converter(Range(0, _dst.rows));
|
||||
}
|
||||
|
||||
/////////////////////////// RGBA <-> mRGBA (alpha premultiplied) //////////////
|
||||
|
||||
@@ -442,7 +442,7 @@ static void getDistanceTransformMask( int maskType, float *metrics )
|
||||
}
|
||||
}
|
||||
|
||||
struct DTColumnInvoker
|
||||
struct DTColumnInvoker : ParallelLoopBody
|
||||
{
|
||||
DTColumnInvoker( const Mat* _src, Mat* _dst, const int* _sat_tab, const float* _sqr_tab)
|
||||
{
|
||||
@@ -452,9 +452,9 @@ struct DTColumnInvoker
|
||||
sqr_tab = _sqr_tab;
|
||||
}
|
||||
|
||||
void operator()( const BlockedRange& range ) const
|
||||
void operator()( const Range& range ) const
|
||||
{
|
||||
int i, i1 = range.begin(), i2 = range.end();
|
||||
int i, i1 = range.start, i2 = range.end;
|
||||
int m = src->rows;
|
||||
size_t sstep = src->step, dstep = dst->step/sizeof(float);
|
||||
AutoBuffer<int> _d(m);
|
||||
@@ -489,7 +489,7 @@ struct DTColumnInvoker
|
||||
};
|
||||
|
||||
|
||||
struct DTRowInvoker
|
||||
struct DTRowInvoker : ParallelLoopBody
|
||||
{
|
||||
DTRowInvoker( Mat* _dst, const float* _sqr_tab, const float* _inv_tab )
|
||||
{
|
||||
@@ -498,10 +498,10 @@ struct DTRowInvoker
|
||||
inv_tab = _inv_tab;
|
||||
}
|
||||
|
||||
void operator()( const BlockedRange& range ) const
|
||||
void operator()( const Range& range ) const
|
||||
{
|
||||
const float inf = 1e15f;
|
||||
int i, i1 = range.begin(), i2 = range.end();
|
||||
int i, i1 = range.start, i2 = range.end;
|
||||
int n = dst->cols;
|
||||
AutoBuffer<uchar> _buf((n+2)*2*sizeof(float) + (n+2)*sizeof(int));
|
||||
float* f = (float*)(uchar*)_buf;
|
||||
@@ -578,7 +578,7 @@ trueDistTrans( const Mat& src, Mat& dst )
|
||||
for( ; i <= m*3; i++ )
|
||||
sat_tab[i] = i - shift;
|
||||
|
||||
cv::parallel_for(cv::BlockedRange(0, n), cv::DTColumnInvoker(&src, &dst, sat_tab, sqr_tab));
|
||||
cv::parallel_for_(cv::Range(0, n), cv::DTColumnInvoker(&src, &dst, sat_tab, sqr_tab));
|
||||
|
||||
// stage 2: compute modified distance transform for each row
|
||||
float* inv_tab = sqr_tab + n;
|
||||
@@ -590,7 +590,7 @@ trueDistTrans( const Mat& src, Mat& dst )
|
||||
sqr_tab[i] = (float)(i*i);
|
||||
}
|
||||
|
||||
cv::parallel_for(cv::BlockedRange(0, m), cv::DTRowInvoker(&dst, sqr_tab, inv_tab));
|
||||
cv::parallel_for_(cv::Range(0, m), cv::DTRowInvoker(&dst, sqr_tab, inv_tab));
|
||||
}
|
||||
|
||||
|
||||
@@ -664,7 +664,7 @@ distanceATS_L1_8u( const Mat& src, Mat& dst )
|
||||
// do right edge
|
||||
a = lut[dbase[width-1+dststep]];
|
||||
dbase[width-1] = (uchar)(MIN(a, dbase[width-1]));
|
||||
|
||||
|
||||
for( x = width - 2; x >= 0; x-- )
|
||||
{
|
||||
int b = dbase[x+dststep];
|
||||
|
||||
@@ -2985,29 +2985,23 @@ cvCalcProbDensity( const CvHistogram* hist, const CvHistogram* hist_mask,
|
||||
}
|
||||
}
|
||||
|
||||
class EqualizeHistCalcHist_Invoker
|
||||
class EqualizeHistCalcHist_Invoker : public cv::ParallelLoopBody
|
||||
{
|
||||
public:
|
||||
enum {HIST_SZ = 256};
|
||||
|
||||
#ifdef HAVE_TBB
|
||||
typedef tbb::mutex* MutextPtr;
|
||||
#else
|
||||
typedef void* MutextPtr;
|
||||
#endif
|
||||
|
||||
EqualizeHistCalcHist_Invoker(cv::Mat& src, int* histogram, MutextPtr histogramLock)
|
||||
EqualizeHistCalcHist_Invoker(cv::Mat& src, int* histogram, cv::Mutex* histogramLock)
|
||||
: src_(src), globalHistogram_(histogram), histogramLock_(histogramLock)
|
||||
{ }
|
||||
|
||||
void operator()( const cv::BlockedRange& rowRange ) const
|
||||
void operator()( const cv::Range& rowRange ) const
|
||||
{
|
||||
int localHistogram[HIST_SZ] = {0, };
|
||||
|
||||
const size_t sstep = src_.step;
|
||||
|
||||
int width = src_.cols;
|
||||
int height = rowRange.end() - rowRange.begin();
|
||||
int height = rowRange.end - rowRange.start;
|
||||
|
||||
if (src_.isContinuous())
|
||||
{
|
||||
@@ -3015,7 +3009,7 @@ public:
|
||||
height = 1;
|
||||
}
|
||||
|
||||
for (const uchar* ptr = src_.ptr<uchar>(rowRange.begin()); height--; ptr += sstep)
|
||||
for (const uchar* ptr = src_.ptr<uchar>(rowRange.start); height--; ptr += sstep)
|
||||
{
|
||||
int x = 0;
|
||||
for (; x <= width - 4; x += 4)
|
||||
@@ -3030,9 +3024,7 @@ public:
|
||||
localHistogram[ptr[x]]++;
|
||||
}
|
||||
|
||||
#ifdef HAVE_TBB
|
||||
tbb::mutex::scoped_lock lock(*histogramLock_);
|
||||
#endif
|
||||
cv::AutoLock lock(*histogramLock_);
|
||||
|
||||
for( int i = 0; i < HIST_SZ; i++ )
|
||||
globalHistogram_[i] += localHistogram[i];
|
||||
@@ -3040,12 +3032,7 @@ public:
|
||||
|
||||
static bool isWorthParallel( const cv::Mat& src )
|
||||
{
|
||||
#ifdef HAVE_TBB
|
||||
return ( src.total() >= 640*480 );
|
||||
#else
|
||||
(void)src;
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
private:
|
||||
@@ -3053,10 +3040,10 @@ private:
|
||||
|
||||
cv::Mat& src_;
|
||||
int* globalHistogram_;
|
||||
MutextPtr histogramLock_;
|
||||
cv::Mutex* histogramLock_;
|
||||
};
|
||||
|
||||
class EqualizeHistLut_Invoker
|
||||
class EqualizeHistLut_Invoker : public cv::ParallelLoopBody
|
||||
{
|
||||
public:
|
||||
EqualizeHistLut_Invoker( cv::Mat& src, cv::Mat& dst, int* lut )
|
||||
@@ -3065,13 +3052,13 @@ public:
|
||||
lut_(lut)
|
||||
{ }
|
||||
|
||||
void operator()( const cv::BlockedRange& rowRange ) const
|
||||
void operator()( const cv::Range& rowRange ) const
|
||||
{
|
||||
const size_t sstep = src_.step;
|
||||
const size_t dstep = dst_.step;
|
||||
|
||||
int width = src_.cols;
|
||||
int height = rowRange.end() - rowRange.begin();
|
||||
int height = rowRange.end - rowRange.start;
|
||||
int* lut = lut_;
|
||||
|
||||
if (src_.isContinuous() && dst_.isContinuous())
|
||||
@@ -3080,8 +3067,8 @@ public:
|
||||
height = 1;
|
||||
}
|
||||
|
||||
const uchar* sptr = src_.ptr<uchar>(rowRange.begin());
|
||||
uchar* dptr = dst_.ptr<uchar>(rowRange.begin());
|
||||
const uchar* sptr = src_.ptr<uchar>(rowRange.start);
|
||||
uchar* dptr = dst_.ptr<uchar>(rowRange.start);
|
||||
|
||||
for (; height--; sptr += sstep, dptr += dstep)
|
||||
{
|
||||
@@ -3110,12 +3097,7 @@ public:
|
||||
|
||||
static bool isWorthParallel( const cv::Mat& src )
|
||||
{
|
||||
#ifdef HAVE_TBB
|
||||
return ( src.total() >= 640*480 );
|
||||
#else
|
||||
(void)src;
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
private:
|
||||
@@ -3142,23 +3124,18 @@ void cv::equalizeHist( InputArray _src, OutputArray _dst )
|
||||
if(src.empty())
|
||||
return;
|
||||
|
||||
#ifdef HAVE_TBB
|
||||
tbb::mutex histogramLockInstance;
|
||||
EqualizeHistCalcHist_Invoker::MutextPtr histogramLock = &histogramLockInstance;
|
||||
#else
|
||||
EqualizeHistCalcHist_Invoker::MutextPtr histogramLock = 0;
|
||||
#endif
|
||||
Mutex histogramLockInstance;
|
||||
|
||||
const int hist_sz = EqualizeHistCalcHist_Invoker::HIST_SZ;
|
||||
int hist[hist_sz] = {0,};
|
||||
int lut[hist_sz];
|
||||
|
||||
EqualizeHistCalcHist_Invoker calcBody(src, hist, histogramLock);
|
||||
EqualizeHistCalcHist_Invoker calcBody(src, hist, &histogramLockInstance);
|
||||
EqualizeHistLut_Invoker lutBody(src, dst, lut);
|
||||
cv::BlockedRange heightRange(0, src.rows);
|
||||
cv::Range heightRange(0, src.rows);
|
||||
|
||||
if(EqualizeHistCalcHist_Invoker::isWorthParallel(src))
|
||||
parallel_for(heightRange, calcBody);
|
||||
parallel_for_(heightRange, calcBody);
|
||||
else
|
||||
calcBody(heightRange);
|
||||
|
||||
@@ -3182,303 +3159,11 @@ void cv::equalizeHist( InputArray _src, OutputArray _dst )
|
||||
}
|
||||
|
||||
if(EqualizeHistLut_Invoker::isWorthParallel(src))
|
||||
parallel_for(heightRange, lutBody);
|
||||
parallel_for_(heightRange, lutBody);
|
||||
else
|
||||
lutBody(heightRange);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// CLAHE
|
||||
|
||||
namespace
|
||||
{
|
||||
class CLAHE_CalcLut_Body : public cv::ParallelLoopBody
|
||||
{
|
||||
public:
|
||||
CLAHE_CalcLut_Body(const cv::Mat& src, cv::Mat& lut, cv::Size tileSize, int tilesX, int tilesY, int clipLimit, float lutScale) :
|
||||
src_(src), lut_(lut), tileSize_(tileSize), tilesX_(tilesX), tilesY_(tilesY), clipLimit_(clipLimit), lutScale_(lutScale)
|
||||
{
|
||||
}
|
||||
|
||||
void operator ()(const cv::Range& range) const;
|
||||
|
||||
private:
|
||||
cv::Mat src_;
|
||||
mutable cv::Mat lut_;
|
||||
|
||||
cv::Size tileSize_;
|
||||
int tilesX_;
|
||||
int tilesY_;
|
||||
int clipLimit_;
|
||||
float lutScale_;
|
||||
};
|
||||
|
||||
void CLAHE_CalcLut_Body::operator ()(const cv::Range& range) const
|
||||
{
|
||||
const int histSize = 256;
|
||||
|
||||
uchar* tileLut = lut_.ptr(range.start);
|
||||
const size_t lut_step = lut_.step;
|
||||
|
||||
for (int k = range.start; k < range.end; ++k, tileLut += lut_step)
|
||||
{
|
||||
const int ty = k / tilesX_;
|
||||
const int tx = k % tilesX_;
|
||||
|
||||
// retrieve tile submatrix
|
||||
|
||||
cv::Rect tileROI;
|
||||
tileROI.x = tx * tileSize_.width;
|
||||
tileROI.y = ty * tileSize_.height;
|
||||
tileROI.width = tileSize_.width;
|
||||
tileROI.height = tileSize_.height;
|
||||
|
||||
const cv::Mat tile = src_(tileROI);
|
||||
|
||||
// calc histogram
|
||||
|
||||
int tileHist[histSize] = {0, };
|
||||
|
||||
int height = tileROI.height;
|
||||
const size_t sstep = tile.step;
|
||||
for (const uchar* ptr = tile.ptr<uchar>(0); height--; ptr += sstep)
|
||||
{
|
||||
int x = 0;
|
||||
for (; x <= tileROI.width - 4; x += 4)
|
||||
{
|
||||
int t0 = ptr[x], t1 = ptr[x+1];
|
||||
tileHist[t0]++; tileHist[t1]++;
|
||||
t0 = ptr[x+2]; t1 = ptr[x+3];
|
||||
tileHist[t0]++; tileHist[t1]++;
|
||||
}
|
||||
|
||||
for (; x < tileROI.width; ++x)
|
||||
tileHist[ptr[x]]++;
|
||||
}
|
||||
|
||||
// clip histogram
|
||||
|
||||
if (clipLimit_ > 0)
|
||||
{
|
||||
// how many pixels were clipped
|
||||
int clipped = 0;
|
||||
for (int i = 0; i < histSize; ++i)
|
||||
{
|
||||
if (tileHist[i] > clipLimit_)
|
||||
{
|
||||
clipped += tileHist[i] - clipLimit_;
|
||||
tileHist[i] = clipLimit_;
|
||||
}
|
||||
}
|
||||
|
||||
// redistribute clipped pixels
|
||||
int redistBatch = clipped / histSize;
|
||||
int residual = clipped - redistBatch * histSize;
|
||||
|
||||
for (int i = 0; i < histSize; ++i)
|
||||
tileHist[i] += redistBatch;
|
||||
|
||||
for (int i = 0; i < residual; ++i)
|
||||
tileHist[i]++;
|
||||
}
|
||||
|
||||
// calc Lut
|
||||
|
||||
int sum = 0;
|
||||
for (int i = 0; i < histSize; ++i)
|
||||
{
|
||||
sum += tileHist[i];
|
||||
tileLut[i] = cv::saturate_cast<uchar>(sum * lutScale_);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class CLAHE_Interpolation_Body : public cv::ParallelLoopBody
|
||||
{
|
||||
public:
|
||||
CLAHE_Interpolation_Body(const cv::Mat& src, cv::Mat& dst, const cv::Mat& lut, cv::Size tileSize, int tilesX, int tilesY) :
|
||||
src_(src), dst_(dst), lut_(lut), tileSize_(tileSize), tilesX_(tilesX), tilesY_(tilesY)
|
||||
{
|
||||
}
|
||||
|
||||
void operator ()(const cv::Range& range) const;
|
||||
|
||||
private:
|
||||
cv::Mat src_;
|
||||
mutable cv::Mat dst_;
|
||||
cv::Mat lut_;
|
||||
|
||||
cv::Size tileSize_;
|
||||
int tilesX_;
|
||||
int tilesY_;
|
||||
};
|
||||
|
||||
void CLAHE_Interpolation_Body::operator ()(const cv::Range& range) const
|
||||
{
|
||||
const size_t lut_step = lut_.step;
|
||||
|
||||
for (int y = range.start; y < range.end; ++y)
|
||||
{
|
||||
const uchar* srcRow = src_.ptr<uchar>(y);
|
||||
uchar* dstRow = dst_.ptr<uchar>(y);
|
||||
|
||||
const float tyf = (static_cast<float>(y) / tileSize_.height) - 0.5f;
|
||||
|
||||
int ty1 = cvFloor(tyf);
|
||||
int ty2 = ty1 + 1;
|
||||
|
||||
const float ya = tyf - ty1;
|
||||
|
||||
ty1 = std::max(ty1, 0);
|
||||
ty2 = std::min(ty2, tilesY_ - 1);
|
||||
|
||||
const uchar* lutPlane1 = lut_.ptr(ty1 * tilesX_);
|
||||
const uchar* lutPlane2 = lut_.ptr(ty2 * tilesX_);
|
||||
|
||||
for (int x = 0; x < src_.cols; ++x)
|
||||
{
|
||||
const float txf = (static_cast<float>(x) / tileSize_.width) - 0.5f;
|
||||
|
||||
int tx1 = cvFloor(txf);
|
||||
int tx2 = tx1 + 1;
|
||||
|
||||
const float xa = txf - tx1;
|
||||
|
||||
tx1 = std::max(tx1, 0);
|
||||
tx2 = std::min(tx2, tilesX_ - 1);
|
||||
|
||||
const int srcVal = srcRow[x];
|
||||
|
||||
const size_t ind1 = tx1 * lut_step + srcVal;
|
||||
const size_t ind2 = tx2 * lut_step + srcVal;
|
||||
|
||||
float res = 0;
|
||||
|
||||
res += lutPlane1[ind1] * ((1.0f - xa) * (1.0f - ya));
|
||||
res += lutPlane1[ind2] * ((xa) * (1.0f - ya));
|
||||
res += lutPlane2[ind1] * ((1.0f - xa) * (ya));
|
||||
res += lutPlane2[ind2] * ((xa) * (ya));
|
||||
|
||||
dstRow[x] = cv::saturate_cast<uchar>(res);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class CLAHE_Impl : public cv::CLAHE
|
||||
{
|
||||
public:
|
||||
CLAHE_Impl(double clipLimit = 40.0, int tilesX = 8, int tilesY = 8);
|
||||
|
||||
cv::AlgorithmInfo* info() const;
|
||||
|
||||
void apply(cv::InputArray src, cv::OutputArray dst);
|
||||
|
||||
void setClipLimit(double clipLimit);
|
||||
double getClipLimit() const;
|
||||
|
||||
void setTilesGridSize(cv::Size tileGridSize);
|
||||
cv::Size getTilesGridSize() const;
|
||||
|
||||
void collectGarbage();
|
||||
|
||||
private:
|
||||
double clipLimit_;
|
||||
int tilesX_;
|
||||
int tilesY_;
|
||||
|
||||
cv::Mat srcExt_;
|
||||
cv::Mat lut_;
|
||||
};
|
||||
|
||||
CLAHE_Impl::CLAHE_Impl(double clipLimit, int tilesX, int tilesY) :
|
||||
clipLimit_(clipLimit), tilesX_(tilesX), tilesY_(tilesY)
|
||||
{
|
||||
}
|
||||
|
||||
CV_INIT_ALGORITHM(CLAHE_Impl, "CLAHE",
|
||||
obj.info()->addParam(obj, "clipLimit", obj.clipLimit_);
|
||||
obj.info()->addParam(obj, "tilesX", obj.tilesX_);
|
||||
obj.info()->addParam(obj, "tilesY", obj.tilesY_))
|
||||
|
||||
void CLAHE_Impl::apply(cv::InputArray _src, cv::OutputArray _dst)
|
||||
{
|
||||
cv::Mat src = _src.getMat();
|
||||
|
||||
CV_Assert( src.type() == CV_8UC1 );
|
||||
|
||||
_dst.create( src.size(), src.type() );
|
||||
cv::Mat dst = _dst.getMat();
|
||||
|
||||
const int histSize = 256;
|
||||
|
||||
lut_.create(tilesX_ * tilesY_, histSize, CV_8UC1);
|
||||
|
||||
cv::Size tileSize;
|
||||
cv::Mat srcForLut;
|
||||
|
||||
if (src.cols % tilesX_ == 0 && src.rows % tilesY_ == 0)
|
||||
{
|
||||
tileSize = cv::Size(src.cols / tilesX_, src.rows / tilesY_);
|
||||
srcForLut = src;
|
||||
}
|
||||
else
|
||||
{
|
||||
cv::copyMakeBorder(src, srcExt_, 0, tilesY_ - (src.rows % tilesY_), 0, tilesX_ - (src.cols % tilesX_), cv::BORDER_REFLECT_101);
|
||||
|
||||
tileSize = cv::Size(srcExt_.cols / tilesX_, srcExt_.rows / tilesY_);
|
||||
srcForLut = srcExt_;
|
||||
}
|
||||
|
||||
const int tileSizeTotal = tileSize.area();
|
||||
const float lutScale = static_cast<float>(histSize - 1) / tileSizeTotal;
|
||||
|
||||
int clipLimit = 0;
|
||||
if (clipLimit_ > 0.0)
|
||||
{
|
||||
clipLimit = static_cast<int>(clipLimit_ * tileSizeTotal / histSize);
|
||||
clipLimit = std::max(clipLimit, 1);
|
||||
}
|
||||
|
||||
CLAHE_CalcLut_Body calcLutBody(srcForLut, lut_, tileSize, tilesX_, tilesY_, clipLimit, lutScale);
|
||||
cv::parallel_for_(cv::Range(0, tilesX_ * tilesY_), calcLutBody);
|
||||
|
||||
CLAHE_Interpolation_Body interpolationBody(src, dst, lut_, tileSize, tilesX_, tilesY_);
|
||||
cv::parallel_for_(cv::Range(0, src.rows), interpolationBody);
|
||||
}
|
||||
|
||||
void CLAHE_Impl::setClipLimit(double clipLimit)
|
||||
{
|
||||
clipLimit_ = clipLimit;
|
||||
}
|
||||
|
||||
double CLAHE_Impl::getClipLimit() const
|
||||
{
|
||||
return clipLimit_;
|
||||
}
|
||||
|
||||
void CLAHE_Impl::setTilesGridSize(cv::Size tileGridSize)
|
||||
{
|
||||
tilesX_ = tileGridSize.width;
|
||||
tilesY_ = tileGridSize.height;
|
||||
}
|
||||
|
||||
cv::Size CLAHE_Impl::getTilesGridSize() const
|
||||
{
|
||||
return cv::Size(tilesX_, tilesY_);
|
||||
}
|
||||
|
||||
void CLAHE_Impl::collectGarbage()
|
||||
{
|
||||
srcExt_.release();
|
||||
lut_.release();
|
||||
}
|
||||
}
|
||||
|
||||
cv::Ptr<cv::CLAHE> cv::createCLAHE(double clipLimit, cv::Size tileGridSize)
|
||||
{
|
||||
return new CLAHE_Impl(clipLimit, tileGridSize.width, tileGridSize.height);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
/* Implementation of RTTI and Generic Functions for CvHistogram */
|
||||
|
||||
@@ -1081,7 +1081,7 @@ cv::Mat cv::getStructuringElement(int shape, Size ksize, Point anchor)
|
||||
namespace cv
|
||||
{
|
||||
|
||||
class MorphologyRunner
|
||||
class MorphologyRunner : public ParallelLoopBody
|
||||
{
|
||||
public:
|
||||
MorphologyRunner(Mat _src, Mat _dst, int _nStripes, int _iterations,
|
||||
@@ -1102,14 +1102,14 @@ public:
|
||||
columnBorderType = _columnBorderType;
|
||||
}
|
||||
|
||||
void operator () ( const BlockedRange& range ) const
|
||||
void operator () ( const Range& range ) const
|
||||
{
|
||||
int row0 = std::min(cvRound(range.begin() * src.rows / nStripes), src.rows);
|
||||
int row1 = std::min(cvRound(range.end() * src.rows / nStripes), src.rows);
|
||||
int row0 = std::min(cvRound(range.start * src.rows / nStripes), src.rows);
|
||||
int row1 = std::min(cvRound(range.end * src.rows / nStripes), src.rows);
|
||||
|
||||
/*if(0)
|
||||
printf("Size = (%d, %d), range[%d,%d), row0 = %d, row1 = %d\n",
|
||||
src.rows, src.cols, range.begin(), range.end(), row0, row1);*/
|
||||
src.rows, src.cols, range.start, range.end, row0, row1);*/
|
||||
|
||||
Mat srcStripe = src.rowRange(row0, row1);
|
||||
Mat dstStripe = dst.rowRange(row0, row1);
|
||||
@@ -1173,15 +1173,15 @@ static void morphOp( int op, InputArray _src, OutputArray _dst,
|
||||
}
|
||||
|
||||
int nStripes = 1;
|
||||
#if defined HAVE_TBB && defined HAVE_TEGRA_OPTIMIZATION
|
||||
#if defined HAVE_TEGRA_OPTIMIZATION
|
||||
if (src.data != dst.data && iterations == 1 && //NOTE: threads are not used for inplace processing
|
||||
(borderType & BORDER_ISOLATED) == 0 && //TODO: check border types
|
||||
src.rows >= 64 ) //NOTE: just heuristics
|
||||
nStripes = 4;
|
||||
#endif
|
||||
|
||||
parallel_for(BlockedRange(0, nStripes),
|
||||
MorphologyRunner(src, dst, nStripes, iterations, op, kernel, anchor, borderType, borderType, borderValue));
|
||||
parallel_for_(Range(0, nStripes),
|
||||
MorphologyRunner(src, dst, nStripes, iterations, op, kernel, anchor, borderType, borderType, borderValue));
|
||||
|
||||
//Ptr<FilterEngine> f = createMorphologyFilter(op, src.type(),
|
||||
// kernel, anchor, borderType, borderType, borderValue );
|
||||
|
||||
Reference in New Issue
Block a user