// 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. // // Author: Longbu Wang // Jinheng Zhang // Chenqi Shan #ifndef __OPENCV_CCM_UTILS_HPP__ #define __OPENCV_CCM_UTILS_HPP__ #include #include namespace cv { namespace ccm { /** @brief gamma correction. \f[ C_l=C_n^{\gamma},\qquad C_n\ge0\\ C_l=-(-C_n)^{\gamma},\qquad C_n<0\\\\ \f] @param src the input array,type of Mat. @param gamma a constant for gamma correction greater than zero. @param dst the output array, type of Mat. */ CV_EXPORTS_W void gammaCorrection(InputArray src, OutputArray dst, double gamma); /** @brief maskCopyTo a function to delete unsatisfied elementwise. @param src the input array, type of Mat. @param mask operation mask that used to choose satisfided elementwise. */ Mat maskCopyTo(const Mat& src, const Mat& mask); /** @brief multiple the function used to compute an array with n channels mulipied by ccm. @param xyz the input array, type of Mat. @param ccm the ccm matrix to make color correction. */ Mat multiple(const Mat& xyz, const Mat& ccm); /** @brief multiple the function used to get the mask of saturated colors, colors between low and up will be choosed. @param src the input array, type of Mat. @param low the threshold to choose saturated colors @param up the threshold to choose saturated colors */ Mat saturate(Mat& src, double low, double up); /** @brief function for elementWise operation @param src the input array, type of Mat @param lambda a for operation */ template Mat elementWise(const Mat& src, F&& lambda, Mat dst=Mat()) { if (dst.empty() || !dst.isContinuous() || dst.total() != src.total() || dst.type() != src.type()) dst = Mat(src.rows, src.cols, src.type()); const int channel = src.channels(); if (src.isContinuous()) { const int num_elements = (int)src.total()*channel; const double *psrc = (double*)src.data; double *pdst = (double*)dst.data; const int batch = getNumThreads() > 1 ? 128 : num_elements; const int N = (num_elements / batch) + ((num_elements % batch) > 0); parallel_for_(Range(0, N),[&](const Range& range) { const int start = range.start * batch; const int end = std::min(range.end*batch, num_elements); for (int i = start; i < end; i++) { pdst[i] = lambda(psrc[i]); } }); return dst; } switch (channel) { case 1: { MatIterator_ it, end; for (it = dst.begin(), end = dst.end(); it != end; ++it) { (*it) = lambda((*it)); } break; } case 3: { MatIterator_ it, end; for (it = dst.begin(), end = dst.end(); it != end; ++it) { for (int j = 0; j < 3; j++) { (*it)[j] = lambda((*it)[j]); } } break; } default: CV_Error(Error::StsBadArg, "Wrong channel!" ); break; } return dst; } /** @brief function for channel operation @param src the input array, type of Mat @param lambda the function for operation */ template Mat channelWise(const Mat& src, F&& lambda) { Mat dst = src.clone(); MatIterator_ it, end; for (it = dst.begin(), end = dst.end(); it != end; ++it) { *it = lambda(*it); } return dst; } /** @brief function for distance operation. @param src the input array, type of Mat. @param ref another input array, type of Mat. @param lambda the computing method for distance . */ template Mat distanceWise(Mat& src, Mat& ref, F&& lambda) { Mat dst = Mat(src.size(), CV_64FC1); MatIterator_ it_src = src.begin(), end_src = src.end(), it_ref = ref.begin(); MatIterator_ it_dst = dst.begin(); for (; it_src != end_src; ++it_src, ++it_ref, ++it_dst) { *it_dst = lambda(*it_src, *it_ref); } return dst; } Mat multiple(const Mat& xyz, const Mat& ccm); } } // namespace cv::ccm #endif