From 563200fbf63525ad64952a481f896e4551154dc7 Mon Sep 17 00:00:00 2001 From: Nathan Jackson Date: Mon, 4 Aug 2014 16:11:21 -0400 Subject: [PATCH] CPU (non-OpenCL) CLAHE now supports CV_16UC1. --- modules/imgproc/src/clahe.cpp | 68 ++++++++++++++++++++--------------- 1 file changed, 40 insertions(+), 28 deletions(-) diff --git a/modules/imgproc/src/clahe.cpp b/modules/imgproc/src/clahe.cpp index f19f19243..6114c4e53 100644 --- a/modules/imgproc/src/clahe.cpp +++ b/modules/imgproc/src/clahe.cpp @@ -126,10 +126,11 @@ namespace clahe namespace { + template class CLAHE_CalcLut_Body : public cv::ParallelLoopBody { public: - CLAHE_CalcLut_Body(const cv::Mat& src, cv::Mat& lut, cv::Size tileSize, int tilesX, int clipLimit, float lutScale) : + CLAHE_CalcLut_Body(const cv::Mat& src, const cv::Mat& lut, const cv::Size& tileSize, const int& tilesX, const int& clipLimit, const float& lutScale) : src_(src), lut_(lut), tileSize_(tileSize), tilesX_(tilesX), clipLimit_(clipLimit), lutScale_(lutScale) { } @@ -146,12 +147,11 @@ namespace float lutScale_; }; - void CLAHE_CalcLut_Body::operator ()(const cv::Range& range) const + template + 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; + T* tileLut = lut_.ptr(range.start); + const size_t lut_step = lut_.step / sizeof(T); for (int k = range.start; k < range.end; ++k, tileLut += lut_step) { @@ -173,20 +173,20 @@ namespace int tileHist[histSize] = {0, }; int height = tileROI.height; - const size_t sstep = tile.step; - for (const uchar* ptr = tile.ptr(0); height--; ptr += sstep) + const size_t sstep = src_.step / sizeof(T); + for (const T* ptr = tile.ptr(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]++; + tileHist[t0 >> shift]++; tileHist[t1 >> shift]++; t0 = ptr[x+2]; t1 = ptr[x+3]; - tileHist[t0]++; tileHist[t1]++; + tileHist[t0 >> shift]++; tileHist[t1 >> shift]++; } for (; x < tileROI.width; ++x) - tileHist[ptr[x]]++; + tileHist[ptr[x] >> shift]++; } // clip histogram @@ -221,15 +221,16 @@ namespace for (int i = 0; i < histSize; ++i) { sum += tileHist[i]; - tileLut[i] = cv::saturate_cast(sum * lutScale_); + tileLut[i] = cv::saturate_cast(sum * lutScale_); } } } + template 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) : + CLAHE_Interpolation_Body(const cv::Mat& src, const cv::Mat& dst, const cv::Mat& lut, const cv::Size& tileSize, const int& tilesX, const int& tilesY) : src_(src), dst_(dst), lut_(lut), tileSize_(tileSize), tilesX_(tilesX), tilesY_(tilesY) { } @@ -246,14 +247,15 @@ namespace int tilesY_; }; - void CLAHE_Interpolation_Body::operator ()(const cv::Range& range) const + template + void CLAHE_Interpolation_Body::operator ()(const cv::Range& range) const { - const size_t lut_step = lut_.step; + const size_t lut_step = lut_.step / sizeof(T); for (int y = range.start; y < range.end; ++y) { - const uchar* srcRow = src_.ptr(y); - uchar* dstRow = dst_.ptr(y); + const T* srcRow = src_.ptr(y); + T* dstRow = dst_.ptr(y); const float tyf = (static_cast(y) / tileSize_.height) - 0.5f; @@ -265,8 +267,8 @@ namespace 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_); + const T* lutPlane1 = lut_.ptr(ty1 * tilesX_); + const T* lutPlane2 = lut_.ptr(ty2 * tilesX_); for (int x = 0; x < src_.cols; ++x) { @@ -292,7 +294,7 @@ namespace res += lutPlane2[ind1] * ((1.0f - xa) * (ya)); res += lutPlane2[ind2] * ((xa) * (ya)); - dstRow[x] = cv::saturate_cast(res); + dstRow[x] = cv::saturate_cast(res); } } } @@ -340,13 +342,13 @@ namespace void CLAHE_Impl::apply(cv::InputArray _src, cv::OutputArray _dst) { - CV_Assert( _src.type() == CV_8UC1 ); + CV_Assert( _src.type() == CV_8UC1 || _src.type() == CV_16UC1 ); #ifdef HAVE_OPENCL - bool useOpenCL = cv::ocl::useOpenCL() && _src.isUMat() && _src.dims()<=2; + bool useOpenCL = cv::ocl::useOpenCL() && _src.isUMat() && _src.dims()<=2 && _src.type() == CV_8UC1; #endif - const int histSize = 256; + int histSize = _src.type() == CV_8UC1 ? 256 : 4096; cv::Size tileSize; cv::_InputArray _srcForLut; @@ -394,13 +396,23 @@ namespace _dst.create( src.size(), src.type() ); cv::Mat dst = _dst.getMat(); cv::Mat srcForLut = _srcForLut.getMat(); - lut_.create(tilesX_ * tilesY_, histSize, CV_8UC1); + lut_.create(tilesX_ * tilesY_, histSize, _src.type()); - CLAHE_CalcLut_Body calcLutBody(srcForLut, lut_, tileSize, tilesX_, clipLimit, lutScale); - cv::parallel_for_(cv::Range(0, tilesX_ * tilesY_), calcLutBody); + cv::Ptr calcLutBody; + if (_src.type() == CV_8UC1) + calcLutBody = cv::makePtr >(srcForLut, lut_, tileSize, tilesX_, clipLimit, lutScale); + else if (_src.type() == CV_16UC1) + calcLutBody = cv::makePtr >(srcForLut, lut_, tileSize, tilesX_, clipLimit, lutScale); + CV_Assert(!calcLutBody.empty()); + 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); + cv::Ptr interpolationBody; + if (_src.type() == CV_8UC1) + interpolationBody = cv::makePtr >(src, dst, lut_, tileSize, tilesX_, tilesY_); + else if (_src.type() == CV_16UC1) + interpolationBody = cv::makePtr >(src, dst, lut_, tileSize, tilesX_, tilesY_); + CV_Assert(!interpolationBody.empty()); + cv::parallel_for_(cv::Range(0, src.rows), *interpolationBody); } void CLAHE_Impl::setClipLimit(double clipLimit)