diff --git a/modules/mcc/CMakeLists.txt b/modules/mcc/CMakeLists.txt deleted file mode 100644 index 181cd3d64e4..00000000000 --- a/modules/mcc/CMakeLists.txt +++ /dev/null @@ -1,9 +0,0 @@ -set(the_description "Color Correction Module") -ocv_define_module(mcc - opencv_core - opencv_imgproc - opencv_3d - opencv_dnn - WRAP - python -) diff --git a/modules/mcc/include/opencv2/ccm.hpp b/modules/mcc/include/opencv2/ccm.hpp deleted file mode 100644 index b44ac657af0..00000000000 --- a/modules/mcc/include/opencv2/ccm.hpp +++ /dev/null @@ -1,520 +0,0 @@ -// 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. -// -// -// License Agreement -// For Open Source Computer Vision Library -// -// Copyright(C) 2020, Huawei Technologies Co.,Ltd. All rights reserved. -// Third party copyrights are property of their respective owners. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// -// Author: Longbu Wang -// Jinheng Zhang -// Chenqi Shan - -#ifndef __OPENCV_CCM_HPP__ -#define __OPENCV_CCM_HPP__ - -#include -#include - -namespace cv -{ -namespace ccm -{ - -/** @defgroup ccm Color Correction module -@{ - -Introduction ------------- - -The purpose of color correction is to adjust the color response of input -and output devices to a known state. The device being calibrated is sometimes -called the calibration source; the color space used as the standard is sometimes -called the calibration target. Color calibration has been used in many industries, -such as television production, games, photography, engineering, chemistry, -medicine, etc. Due to the manufacturing process of the input and output equipment, -the channel response has nonlinear distortion. In order to correct the picture output -of the equipment, it is nessary to calibrate the captured color and the actual color. - -*/ - - - -/** @brief Enum of the possible types of ccm. -*/ -enum CCM_TYPE -{ - CCM_3x3, ///< The CCM with the shape \f$3\times3\f$ performs linear transformation on color values. - CCM_4x3, ///< The CCM with the shape \f$4\times3\f$ performs affine transformation. -}; - -/** @brief Enum of the possible types of initial method. -*/ -enum INITIAL_METHOD_TYPE -{ - INITIAL_METHOD_WHITE_BALANCE, ///< The white balance method. The initial value is:\n - /// \f$ - /// M_{CCM}= - /// \begin{bmatrix} - /// k_R & 0 & 0\\ - /// 0 & k_G & 0\\ - /// 0 & 0 & k_B\\ - /// \end{bmatrix} - /// \f$\n - /// where\n - /// \f$ - /// k_R=mean(R_{li}')/mean(R_{li})\\ - /// k_R=mean(G_{li}')/mean(G_{li})\\ - /// k_R=mean(B_{li}')/mean(B_{li}) - /// \f$ - INITIAL_METHOD_LEAST_SQUARE, ///0\\ -C_{sl}=0, \qquad C_s=0 -\f] - -Because \f$exp(ln(0))\to\infty \f$, the channel whose component is 0 is directly mapped to 0 in the formula above. - -For fitting channels respectively, we have: -\f[ -r=polyfit(ln(R_s),ln(R_{dl}))\\ -g=polyfit(ln(G_s),ln(G_{dl}))\\ -b=polyfit(ln(B_s),ln(B_{dl}))\\ -\f] -Note that the parameter of \f$ln(*) \f$ cannot be 0. -Therefore, we need to delete the channels whose values are 0 from \f$R_s \f$ and \f$R_{dl} \f$, \f$G_s\f$ and \f$G_{dl}\f$, \f$B_s\f$ and \f$B_{dl}\f$. - -Therefore: - -\f[ -ln(R_{sl})=r(ln(R_s)), \qquad R_s>0\\ -R_{sl}=0, \qquad R_s=0\\ -ln(G_{sl})=g(ln(G_s)),\qquad G_s>0\\ -G_{sl}=0, \qquad G_s=0\\ -ln(B_{sl})=b(ln(B_s)),\qquad B_s>0\\ -B_{sl}=0, \qquad B_s=0\\ -\f] - -For grayscale polynomials, there are also: -\f[ -f=polyfit(ln(G_{sl}),ln(G_{dl})) -\f] -and: -\f[ -ln(C_{sl})=f(ln(C_s)), \qquad C_s>0\\ -C_sl=0, \qquad C_s=0 -\f] -*/ -enum LINEAR_TYPE -{ - - LINEARIZATION_IDENTITY, /// p; -}; - -//! @} ccm -} // namespace ccm -} // namespace cv - -#endif \ No newline at end of file diff --git a/modules/mcc/perf/perf_ccm.cpp b/modules/mcc/perf/perf_ccm.cpp deleted file mode 100644 index 0d523e3478c..00000000000 --- a/modules/mcc/perf/perf_ccm.cpp +++ /dev/null @@ -1,41 +0,0 @@ -// 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. - -#include "perf_precomp.hpp" -#include "opencv2/ccm.hpp" - -namespace opencv_test -{ -namespace -{ - -using namespace std; -using namespace cv::ccm; - -PERF_TEST(CV_mcc_perf, infer) { - // read gold chartsRGB - string path = cvtest::findDataFile("cv/mcc/mcc_ccm_test.yml"); - FileStorage fs(path, FileStorage::READ); - Mat chartsRGB; - FileNode node = fs["chartsRGB"]; - node >> chartsRGB; - fs.release(); - - // compute CCM - ColorCorrectionModel model(chartsRGB.col(1).clone().reshape(3, chartsRGB.rows/3) / 255., COLORCHECKER_Macbeth); - model.run(); - - Mat img(1000, 4000, CV_8UC3); - randu(img, 0, 255); - img.convertTo(img, CV_64F, 1. / 255.); - - TEST_CYCLE() { - model.infer(img); - } - - SANITY_CHECK_NOTHING(); -} - -} // namespace -} // namespace opencv_test diff --git a/modules/mcc/perf/perf_main.cpp b/modules/mcc/perf/perf_main.cpp deleted file mode 100644 index a5b36b66913..00000000000 --- a/modules/mcc/perf/perf_main.cpp +++ /dev/null @@ -1,3 +0,0 @@ -#include "perf_precomp.hpp" - -CV_PERF_TEST_MAIN(ccm) diff --git a/modules/mcc/perf/perf_precomp.hpp b/modules/mcc/perf/perf_precomp.hpp deleted file mode 100644 index e494ddca5e6..00000000000 --- a/modules/mcc/perf/perf_precomp.hpp +++ /dev/null @@ -1,13 +0,0 @@ -#ifndef __OPENCV_PERF_PRECOMP_HPP__ -#define __OPENCV_PERF_PRECOMP_HPP__ - -#include "opencv2/ts.hpp" -#include "opencv2/ccm.hpp" - -namespace opencv_test -{ -using namespace cv::ccm; -using namespace perf; -} - -#endif diff --git a/modules/mcc/samples/color_correction_model.cpp b/modules/mcc/samples/color_correction_model.cpp deleted file mode 100644 index 02dd62e73a8..00000000000 --- a/modules/mcc/samples/color_correction_model.cpp +++ /dev/null @@ -1,158 +0,0 @@ -//! [tutorial] -#include - -#include -#include -#include -#include - -using namespace std; -using namespace cv; -using namespace ccm; - -const char *about = "Basic chart detection"; -const char *keys = - "{ help h | | show this message }" - "{ f | 1 | Path of the file to process (-v) }"; - -int main(int argc, char *argv[]) -{ - - - // ---------------------------------------------------------- - // Scroll down a bit (~40 lines) to find actual relevant code - // ---------------------------------------------------------- - //! [get_messages_of_image] - CommandLineParser parser(argc, argv, keys); - parser.about(about); - if (argc==1 || parser.has("help")) - { - parser.printMessage(); - return 0; - } - - string filepath = parser.get("f"); - - if (!parser.check()) - { - parser.printErrors(); - return 0; - } - - Mat image = imread(filepath, IMREAD_COLOR); - if (!image.data) - { - cout << "Invalid Image!" << endl; - return 1; - } - //! [get_messages_of_image] - - Mat src(24, 1, CV_64FC3); - - // Hardcoded values. Image used: opencv_extra/testdata/cv/mcc/mcc_ccm_test.jpg - double values[24][3] = { - {0.380463, 0.31696, 0.210053}, - {0.649781, 0.520561, 0.452553}, - {0.323114, 0.37593, 0.50123}, - {0.314785, 0.396522, 0.258116}, - {0.452971, 0.418602, 0.578767}, - {0.34908, 0.608649, 0.652283}, - {0.691127, 0.517818, 0.144984}, - {0.208668, 0.224391, 0.485851}, - {0.657849, 0.378126, 0.304115}, - {0.285762, 0.229671, 0.31913}, - {0.513422, 0.685031, 0.337381}, - {0.786459, 0.676133, 0.246303}, - {0.11751, 0.135079, 0.383441}, - {0.190745, 0.470513, 0.296844}, - {0.587832, 0.299132, 0.196117}, - {0.783908, 0.746261, 0.294357}, - {0.615481, 0.359983, 0.471403}, - {0.107095, 0.370516, 0.573142}, - {0.708598, 0.718936, 0.740915}, - {0.593812, 0.612474, 0.63222}, - {0.489774, 0.510077, 0.521757}, - {0.380591, 0.398499, 0.393662}, - {0.27461, 0.293267, 0.275244}, - {0.180753, 0.194968, 0.145006} - }; - - // Assign values to src - for (int i = 0; i < 24; i++) { - src.at(i, 0) = cv::Vec3d(values[i][0], values[i][1], values[i][2]); - } - - //compte color correction matrix - //! [get_ccm_Matrix] - ColorCorrectionModel model1(src, COLORCHECKER_Macbeth); - model1.run(); - Mat ccm = model1.getCCM(); - std::cout<<"ccm "<(18, 1) << - // Vec3d(100, 0.00520000001, -0.0104), - // Vec3d(73.0833969, -0.819999993, -2.02099991), - // Vec3d(62.493, 0.425999999, -2.23099995), - // Vec3d(50.4640007, 0.446999997, -2.32399988), - // Vec3d(37.7970009, 0.0359999985, -1.29700005), - // Vec3d(0, 0, 0), - // Vec3d(51.5880013, 73.5179977, 51.5690002), - // Vec3d(93.6989975, -15.7340002, 91.9420013), - // Vec3d(69.4079971, -46.5940018, 50.4869995), - // Vec3d(66.61000060000001, -13.6789999, -43.1720009), - // Vec3d(11.7110004, 16.9799995, -37.1759987), - // Vec3d(51.973999, 81.9440002, -8.40699959), - // Vec3d(40.5489998, 50.4399986, 24.8490009), - // Vec3d(60.8160019, 26.0690002, 49.4420013), - // Vec3d(52.2529984, -19.9500008, -23.9960003), - // Vec3d(51.2859993, 48.4700012, -15.0579996), - // Vec3d(68.70700069999999, 12.2959995, 16.2129993), - // Vec3d(63.6839981, 10.2930002, 16.7639999)); - - // ColorCorrectionModel model8(src,ref,COLOR_SPACE_Lab_D50_2); - // model8.run(); - //! [reference_color_values] - - //! [make_color_correction] - Mat img_; - cvtColor(image, img_, COLOR_BGR2RGB); - img_.convertTo(img_, CV_64F); - const int inp_size = 255; - const int out_size = 255; - img_ = img_ / inp_size; - Mat calibratedImage= model1.infer(img_); - Mat out_ = calibratedImage * out_size; - //! [make_color_correction] - - //! [Save_calibrated_image] - // Save the calibrated image to {FILE_NAME}.calibrated.{FILE_EXT} - out_.convertTo(out_, CV_8UC3); - Mat img_out = min(max(out_, 0), out_size); - Mat out_img; - cvtColor(img_out, out_img, COLOR_RGB2BGR); - string filename = filepath.substr(filepath.find_last_of('/')+1); - size_t dotIndex = filename.find_last_of('.'); - string baseName = filename.substr(0, dotIndex); - string ext = filename.substr(dotIndex+1, filename.length()-dotIndex); - string calibratedFilePath = baseName + ".calibrated." + ext; - imwrite(calibratedFilePath, out_img); - //! [Save_calibrated_image] - - return 0; -} -//! [tutorial] \ No newline at end of file diff --git a/modules/mcc/src/ccm.cpp b/modules/mcc/src/ccm.cpp deleted file mode 100644 index 27c3728a661..00000000000 --- a/modules/mcc/src/ccm.cpp +++ /dev/null @@ -1,437 +0,0 @@ -// 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. -// -// -// License Agreement -// For Open Source Computer Vision Library -// -// Copyright(C) 2020, Huawei Technologies Co.,Ltd. All rights reserved. -// Third party copyrights are property of their respective owners. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// -// Author: Longbu Wang -// Jinheng Zhang -// Chenqi Shan - -#include "opencv2/ccm.hpp" -#include "linearize.hpp" -namespace cv { -namespace ccm { -class ColorCorrectionModel::Impl -{ -public: - Mat src; - std::shared_ptr dst = std::make_shared(); - Mat dist; - RGBBase_& cs; - Mat mask; - - // RGBl of detected data and the reference - Mat src_rgbl; - Mat dst_rgbl; - - // ccm type and shape - CCM_TYPE ccm_type; - int shape; - - // linear method and distance - std::shared_ptr linear = std::make_shared(); - DISTANCE_TYPE distance; - LINEAR_TYPE linear_type; - - Mat weights; - Mat weights_list; - Mat ccm; - Mat ccm0; - double gamma; - int deg; - std::vector saturated_threshold; - INITIAL_METHOD_TYPE initial_method_type; - double weights_coeff; - int masked_len; - double loss; - int max_count; - double epsilon; - Impl(); - - /** @brief Make no change for CCM_3x3. - convert cv::Mat A to [A, 1] in CCM_4x3. - @param inp the input array, type of cv::Mat. - @return the output array, type of cv::Mat - */ - Mat prepare(const Mat& inp); - - /** @brief Calculate weights and mask. - @param weights_list the input array, type of cv::Mat. - @param weights_coeff type of double. - @param saturate_mask the input array, type of cv::Mat. - */ - void calWeightsMasks(const Mat& weights_list, double weights_coeff, Mat saturate_mask); - - /** @brief Fitting nonlinear - optimization initial value by white balance. - @return the output array, type of Mat - */ - void initialWhiteBalance(void); - - /** @brief Fitting nonlinear-optimization initial value by least square. - @param fit if fit is True, return optimalization for rgbl distance function. - */ - void initialLeastSquare(bool fit = false); - - double calc_loss_(Color color); - double calc_loss(const Mat ccm_); - - /** @brief Fitting ccm if distance function is associated with CIE Lab color space. - see details in https://github.com/opencv/opencv/blob/master/modules/core/include/opencv2/core/optim.hpp - Set terminal criteria for solver is possible. - */ - void fitting(void); - - void getColor(Mat& img_, bool islinear = false); - void getColor(CONST_COLOR constcolor); - void getColor(Mat colors_, COLOR_SPACE cs_, Mat colored_); - void getColor(Mat colors_, COLOR_SPACE ref_cs_); - - /** @brief Loss function base on cv::MinProblemSolver::Function. - see details in https://github.com/opencv/opencv/blob/master/modules/core/include/opencv2/core/optim.hpp - */ - class LossFunction : public MinProblemSolver::Function - { - public: - ColorCorrectionModel::Impl* ccm_loss; - LossFunction(ColorCorrectionModel::Impl* ccm) - : ccm_loss(ccm) {}; - - /** @brief Reset dims to ccm->shape. - */ - int getDims() const CV_OVERRIDE - { - return ccm_loss->shape; - } - - /** @brief Reset calculation. - */ - double calc(const double* x) const CV_OVERRIDE - { - Mat ccm_(ccm_loss->shape, 1, CV_64F); - for (int i = 0; i < ccm_loss->shape; i++) - { - ccm_.at(i, 0) = x[i]; - } - ccm_ = ccm_.reshape(0, ccm_loss->shape / 3); - return ccm_loss->calc_loss(ccm_); - } - }; -}; - -ColorCorrectionModel::Impl::Impl() - : cs(*GetCS::getInstance().get_rgb(COLOR_SPACE_sRGB)) - , ccm_type(CCM_3x3) - , distance(DISTANCE_CIE2000) - , linear_type(LINEARIZATION_GAMMA) - , weights(Mat()) - , gamma(2.2) - , deg(3) - , saturated_threshold({ 0, 0.98 }) - , initial_method_type(INITIAL_METHOD_LEAST_SQUARE) - , weights_coeff(0) - , max_count(5000) - , epsilon(1.e-4) -{} - -Mat ColorCorrectionModel::Impl::prepare(const Mat& inp) -{ - switch (ccm_type) - { - case cv::ccm::CCM_3x3: - shape = 9; - return inp; - case cv::ccm::CCM_4x3: - { - shape = 12; - Mat arr1 = Mat::ones(inp.size(), CV_64F); - Mat arr_out(inp.size(), CV_64FC4); - Mat arr_channels[3]; - split(inp, arr_channels); - merge(std::vector { arr_channels[0], arr_channels[1], arr_channels[2], arr1 }, arr_out); - return arr_out; - } - default: - CV_Error(Error::StsBadArg, "Wrong ccm_type!"); - break; - } -} - -void ColorCorrectionModel::Impl::calWeightsMasks(const Mat& weights_list_, double weights_coeff_, Mat saturate_mask) -{ - // weights - if (!weights_list_.empty()) - { - weights = weights_list_; - } - else if (weights_coeff_ != 0) - { - pow(dst->toLuminant(cs.io), weights_coeff_, weights); - } - - // masks - Mat weight_mask = Mat::ones(src.rows, 1, CV_8U); - if (!weights.empty()) - { - weight_mask = weights > 0; - } - this->mask = (weight_mask) & (saturate_mask); - - // weights' mask - if (!weights.empty()) - { - Mat weights_masked = maskCopyTo(this->weights, this->mask); - weights = weights_masked / mean(weights_masked)[0]; - } - masked_len = (int)sum(mask)[0]; -} - -void ColorCorrectionModel::Impl::initialWhiteBalance(void) -{ - Mat schannels[4]; - split(src_rgbl, schannels); - Mat dchannels[4]; - split(dst_rgbl, dchannels); - std::vector initial_vec = { sum(dchannels[0])[0] / sum(schannels[0])[0], 0, 0, 0, - sum(dchannels[1])[0] / sum(schannels[1])[0], 0, 0, 0, - sum(dchannels[2])[0] / sum(schannels[2])[0], 0, 0, 0 }; - std::vector initial_vec_(initial_vec.begin(), initial_vec.begin() + shape); - Mat initial_white_balance = Mat(initial_vec_, true).reshape(0, shape / 3); - ccm0 = initial_white_balance; -} - -void ColorCorrectionModel::Impl::initialLeastSquare(bool fit) -{ - Mat A, B, w; - if (weights.empty()) - { - A = src_rgbl; - B = dst_rgbl; - } - else - { - pow(weights, 0.5, w); - Mat w_; - merge(std::vector { w, w, w }, w_); - A = w_.mul(src_rgbl); - B = w_.mul(dst_rgbl); - } - solve(A.reshape(1, A.rows), B.reshape(1, B.rows), ccm0, DECOMP_SVD); - - // if fit is True, return optimalization for rgbl distance function. - if (fit) - { - ccm = ccm0; - Mat residual = A.reshape(1, A.rows) * ccm.reshape(0, shape / 3) - B.reshape(1, B.rows); - Scalar s = residual.dot(residual); - double sum = s[0]; - loss = sqrt(sum / masked_len); - } -} - -double ColorCorrectionModel::Impl::calc_loss_(Color color) -{ - Mat distlist = color.diff(*dst, distance); - Color lab = color.to(COLOR_SPACE_Lab_D50_2); - Mat dist_; - pow(distlist, 2, dist_); - if (!weights.empty()) - { - dist_ = weights.mul(dist_); - } - Scalar ss = sum(dist_); - return ss[0]; -} - -double ColorCorrectionModel::Impl::calc_loss(const Mat ccm_) -{ - Mat converted = src_rgbl.reshape(1, 0) * ccm_; - Color color(converted.reshape(3, 0), *(cs.l)); - return calc_loss_(color); -} - -void ColorCorrectionModel::Impl::fitting(void) -{ - cv::Ptr solver = cv::DownhillSolver::create(); - cv::Ptr ptr_F(new LossFunction(this)); - solver->setFunction(ptr_F); - Mat reshapeccm = ccm0.clone().reshape(0, 1); - Mat step = Mat::ones(reshapeccm.size(), CV_64F); - solver->setInitStep(step); - TermCriteria termcrit = TermCriteria(TermCriteria::MAX_ITER + TermCriteria::EPS, max_count, epsilon); - solver->setTermCriteria(termcrit); - double res = solver->minimize(reshapeccm); - ccm = reshapeccm.reshape(0, shape / 3); - loss = pow((res / masked_len), 0.5); -} - -Mat ColorCorrectionModel::infer(const Mat& img, bool islinear) -{ - if (!p->ccm.data) - { - CV_Error(Error::StsBadArg, "No CCM values!" ); - } - Mat img_lin = (p->linear)->linearize(img); - Mat ccm = p->ccm.reshape(0, p->shape / 3); - Mat img_ccm = multiple(p->prepare(img_lin), ccm); - if (islinear == true) - { - return img_ccm; - } - return p->cs.fromLFunc(img_ccm, img_lin); -} - -void ColorCorrectionModel::Impl::getColor(CONST_COLOR constcolor) -{ - dst = (GetColor::getColor(constcolor)); -} -void ColorCorrectionModel::Impl::getColor(Mat colors_, COLOR_SPACE ref_cs_) -{ - dst.reset(new Color(colors_, *GetCS::getInstance().get_cs(ref_cs_))); -} -void ColorCorrectionModel::Impl::getColor(Mat colors_, COLOR_SPACE cs_, Mat colored_) -{ - dst.reset(new Color(colors_, *GetCS::getInstance().get_cs(cs_), colored_)); -} -ColorCorrectionModel::ColorCorrectionModel(const Mat& src_, CONST_COLOR constcolor) - : p(std::make_shared()) -{ - p->src = src_; - p->getColor(constcolor); -} -ColorCorrectionModel::ColorCorrectionModel(const Mat& src_, Mat colors_, COLOR_SPACE ref_cs_) - : p(std::make_shared()) -{ - p->src = src_; - p->getColor(colors_, ref_cs_); -} -ColorCorrectionModel::ColorCorrectionModel(const Mat& src_, Mat colors_, COLOR_SPACE cs_, Mat colored_) - : p(std::make_shared()) -{ - p->src = src_; - p->getColor(colors_, cs_, colored_); -} - -void ColorCorrectionModel::setColorSpace(COLOR_SPACE cs_) -{ - p->cs = *GetCS::getInstance().get_rgb(cs_); -} -void ColorCorrectionModel::setCCM_TYPE(CCM_TYPE ccm_type_) -{ - p->ccm_type = ccm_type_; -} -void ColorCorrectionModel::setDistance(DISTANCE_TYPE distance_) -{ - p->distance = distance_; -} -void ColorCorrectionModel::setLinear(LINEAR_TYPE linear_type) -{ - p->linear_type = linear_type; -} -void ColorCorrectionModel::setLinearGamma(const double& gamma) -{ - p->gamma = gamma; -} -void ColorCorrectionModel::setLinearDegree(const int& deg) -{ - p->deg = deg; -} -void ColorCorrectionModel::setSaturatedThreshold(const double& lower, const double& upper) -{ //std::vector saturated_threshold - p->saturated_threshold = { lower, upper }; -} -void ColorCorrectionModel::setWeightsList(const Mat& weights_list) -{ - p->weights_list = weights_list; -} -void ColorCorrectionModel::setWeightCoeff(const double& weights_coeff) -{ - p->weights_coeff = weights_coeff; -} -void ColorCorrectionModel::setInitialMethod(INITIAL_METHOD_TYPE initial_method_type) -{ - p->initial_method_type = initial_method_type; -} -void ColorCorrectionModel::setMaxCount(const int& max_count_) -{ - p->max_count = max_count_; -} -void ColorCorrectionModel::setEpsilon(const double& epsilon_) -{ - p->epsilon = epsilon_; -} -void ColorCorrectionModel::run() -{ - - Mat saturate_mask = saturate(p->src, p->saturated_threshold[0], p->saturated_threshold[1]); - p->linear = getLinear(p->gamma, p->deg, p->src, *(p->dst), saturate_mask, (p->cs), p->linear_type); - p->calWeightsMasks(p->weights_list, p->weights_coeff, saturate_mask); - p->src_rgbl = p->linear->linearize(maskCopyTo(p->src, p->mask)); - p->dst->colors = maskCopyTo(p->dst->colors, p->mask); - p->dst_rgbl = p->dst->to(*(p->cs.l)).colors; - - // make no change for CCM_3x3, make change for CCM_4x3. - p->src_rgbl = p->prepare(p->src_rgbl); - - // distance function may affect the loss function and the fitting function - switch (p->distance) - { - case cv::ccm::DISTANCE_RGBL: - p->initialLeastSquare(true); - break; - default: - switch (p->initial_method_type) - { - case cv::ccm::INITIAL_METHOD_WHITE_BALANCE: - p->initialWhiteBalance(); - break; - case cv::ccm::INITIAL_METHOD_LEAST_SQUARE: - p->initialLeastSquare(); - break; - default: - CV_Error(Error::StsBadArg, "Wrong initial_methoddistance_type!" ); - break; - } - break; - } - p->fitting(); -} -Mat ColorCorrectionModel::getCCM() const -{ - return p->ccm; -} -double ColorCorrectionModel::getLoss() const -{ - return p->loss; -} -Mat ColorCorrectionModel::get_src_rgbl() const{ - return p->src_rgbl; -} -Mat ColorCorrectionModel::get_dst_rgbl() const{ - return p->dst_rgbl; -} -Mat ColorCorrectionModel::getMask() const{ - return p->mask; -} -Mat ColorCorrectionModel::getWeights() const{ - return p->weights; -} -} -} // namespace cv::ccm diff --git a/modules/mcc/src/color.cpp b/modules/mcc/src/color.cpp deleted file mode 100644 index ce00ac47e70..00000000000 --- a/modules/mcc/src/color.cpp +++ /dev/null @@ -1,398 +0,0 @@ -// 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. -// -// -// License Agreement -// For Open Source Computer Vision Library -// -// Copyright(C) 2020, Huawei Technologies Co.,Ltd. All rights reserved. -// Third party copyrights are property of their respective owners. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// -// Author: Longbu Wang -// Jinheng Zhang -// Chenqi Shan - -#include "color.hpp" - -namespace cv { -namespace ccm { -Color::Color() - : colors(Mat()) - , cs(*std::make_shared()) -{} -Color::Color(Mat colors_, enum COLOR_SPACE cs_) - : colors(colors_) - , cs(*GetCS::getInstance().get_cs(cs_)) -{} - -Color::Color(Mat colors_, const ColorSpace& cs_, Mat colored_) - : colors(colors_) - , cs(cs_) - , colored(colored_) -{ - grays = ~colored; -} -Color::Color(Mat colors_, enum COLOR_SPACE cs_, Mat colored_) - : colors(colors_) - , cs(*GetCS::getInstance().get_cs(cs_)) - , colored(colored_) -{ - grays = ~colored; -} - -Color::Color(Mat colors_, const ColorSpace& cs_) - : colors(colors_) - , cs(cs_) -{} - -Color Color::to(const ColorSpace& other, CAM method, bool save) -{ - if (history.count(other) == 1) - { - return *history[other]; - } - if (cs.relate(other)) - { - return Color(cs.relation(other).run(colors), other); - } - Operations ops; - ops.add(cs.to).add(XYZ(cs.io).cam(other.io, method)).add(other.from); - std::shared_ptr color(new Color(ops.run(colors), other)); - if (save) - { - history[other] = color; - } - return *color; -} -Color Color::to(COLOR_SPACE other, CAM method, bool save) -{ - return to(*GetCS::getInstance().get_cs(other), method, save); -} - -Mat Color::channel(Mat m, int i) -{ - Mat dchannels[3]; - split(m, dchannels); - return dchannels[i]; -} - -Mat Color::toGray(IO io, CAM method, bool save) -{ - XYZ xyz = *XYZ::get(io); - return channel(this->to(xyz, method, save).colors, 1); -} - -Mat Color::toLuminant(IO io, CAM method, bool save) -{ - Lab lab = *Lab::get(io); - return channel(this->to(lab, method, save).colors, 0); -} - -Mat Color::diff(Color& other, DISTANCE_TYPE method) -{ - return diff(other, cs.io, method); -} - -Mat Color::diff(Color& other, IO io, DISTANCE_TYPE method) -{ - Lab lab = *Lab::get(io); - switch (method) - { - case cv::ccm::DISTANCE_CIE76: - case cv::ccm::DISTANCE_CIE94_GRAPHIC_ARTS: - case cv::ccm::DISTANCE_CIE94_TEXTILES: - case cv::ccm::DISTANCE_CIE2000: - case cv::ccm::DISTANCE_CMC_1TO1: - case cv::ccm::DISTANCE_CMC_2TO1: - return distance(to(lab).colors, other.to(lab).colors, method); - case cv::ccm::DISTANCE_RGB: - return distance(to(*cs.nl).colors, other.to(*cs.nl).colors, method); - case cv::ccm::DISTANCE_RGBL: - return distance(to(*cs.l).colors, other.to(*cs.l).colors, method); - default: - CV_Error(Error::StsBadArg, "Wrong method!" ); - break; - } -} - -void Color::getGray(double JDN) -{ - if (!grays.empty()) - { - return; - } - Mat lab = to(COLOR_SPACE_Lab_D65_2).colors; - Mat gray(colors.size(), colors.type()); - int fromto[] = { 0, 0, -1, 1, -1, 2 }; - mixChannels(&lab, 1, &gray, 1, fromto, 3); - Mat d = distance(lab, gray, DISTANCE_CIE2000); - this->grays = d < JDN; - this->colored = ~grays; -} - -Color Color::operator[](Mat mask) -{ - return Color(maskCopyTo(colors, mask), cs); -} - -Mat GetColor::getColorChecker(const double* checker, int row) -{ - Mat res(row, 1, CV_64FC3); - for (int i = 0; i < row; ++i) - { - res.at(i, 0) = Vec3d(checker[3 * i], checker[3 * i + 1], checker[3 * i + 2]); - } - return res; -} - -Mat GetColor::getColorCheckerMASK(const uchar* checker, int row) -{ - Mat res(row, 1, CV_8U); - for (int i = 0; i < row; ++i) - { - res.at(i, 0) = checker[i]; - } - return res; -} - -std::shared_ptr GetColor::getColor(CONST_COLOR const_color) -{ - - /** @brief Data is from https://www.imatest.com/wp-content/uploads/2011/11/Lab-data-Iluminate-D65-D50-spectro.xls - see Miscellaneous.md for details. -*/ - static const double ColorChecker2005_LAB_D50_2[24][3] = { { 37.986, 13.555, 14.059 }, - { 65.711, 18.13, 17.81 }, - { 49.927, -4.88, -21.925 }, - { 43.139, -13.095, 21.905 }, - { 55.112, 8.844, -25.399 }, - { 70.719, -33.397, -0.199 }, - { 62.661, 36.067, 57.096 }, - { 40.02, 10.41, -45.964 }, - { 51.124, 48.239, 16.248 }, - { 30.325, 22.976, -21.587 }, - { 72.532, -23.709, 57.255 }, - { 71.941, 19.363, 67.857 }, - { 28.778, 14.179, -50.297 }, - { 55.261, -38.342, 31.37 }, - { 42.101, 53.378, 28.19 }, - { 81.733, 4.039, 79.819 }, - { 51.935, 49.986, -14.574 }, - { 51.038, -28.631, -28.638 }, - { 96.539, -0.425, 1.186 }, - { 81.257, -0.638, -0.335 }, - { 66.766, -0.734, -0.504 }, - { 50.867, -0.153, -0.27 }, - { 35.656, -0.421, -1.231 }, - { 20.461, -0.079, -0.973 } }; - - static const uchar ColorChecker2005_COLORED_MASK[24] = { 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, - 0, 0, 0, 0, 0, 0 }; - static const double Vinyl_LAB_D50_2[18][3] = { { 100, 0.00520000001, -0.0104 }, - { 73.0833969, -0.819999993, -2.02099991 }, - { 62.493, 0.425999999, -2.23099995 }, - { 50.4640007, 0.446999997, -2.32399988 }, - { 37.7970009, 0.0359999985, -1.29700005 }, - { 0, 0, 0 }, - { 51.5880013, 73.5179977, 51.5690002 }, - { 93.6989975, -15.7340002, 91.9420013 }, - { 69.4079971, -46.5940018, 50.4869995 }, - { 66.61000060000001, -13.6789999, -43.1720009 }, - { 11.7110004, 16.9799995, -37.1759987 }, - { 51.973999, 81.9440002, -8.40699959 }, - { 40.5489998, 50.4399986, 24.8490009 }, - { 60.8160019, 26.0690002, 49.4420013 }, - { 52.2529984, -19.9500008, -23.9960003 }, - { 51.2859993, 48.4700012, -15.0579996 }, - { 68.70700069999999, 12.2959995, 16.2129993 }, - { 63.6839981, 10.2930002, 16.7639999 } }; - static const uchar Vinyl_COLORED_MASK[18] = { 0, 0, 0, 0, 0, 0, - 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1 }; - static const double DigitalSG_LAB_D50_2[140][3] = { { 96.55, -0.91, 0.57 }, - { 6.43, -0.06, -0.41 }, - { 49.7, -0.18, 0.03 }, - { 96.5, -0.89, 0.59 }, - { 6.5, -0.06, -0.44 }, - { 49.66, -0.2, 0.01 }, - { 96.52, -0.91, 0.58 }, - { 6.49, -0.02, -0.28 }, - { 49.72, -0.2, 0.04 }, - { 96.43, -0.91, 0.67 }, - { 49.72, -0.19, 0 }, - { 32.6, 51.58, -10.85 }, - { 60.75, 26.22, -18.6 }, - { 28.69, 48.28, -39 }, - { 49.38, -15.43, -48.48 }, - { 60.63, -30.77, -26.23 }, - { 19.29, -26.37, -6.15 }, - { 60.15, -41.77, -12.6 }, - { 21.42, 1.67, 8.79 }, - { 49.69, -0.2, 0.01 }, - { 6.5, -0.03, -0.67 }, - { 21.82, 17.33, -18.35 }, - { 41.53, 18.48, -37.26 }, - { 19.99, -0.16, -36.29 }, - { 60.16, -18.45, -31.42 }, - { 19.94, -17.92, -20.96 }, - { 60.68, -6.05, -32.81 }, - { 50.81, -49.8, -9.63 }, - { 60.65, -39.77, 20.76 }, - { 6.53, -0.03, -0.43 }, - { 96.56, -0.91, 0.59 }, - { 84.19, -1.95, -8.23 }, - { 84.75, 14.55, 0.23 }, - { 84.87, -19.07, -0.82 }, - { 85.15, 13.48, 6.82 }, - { 84.17, -10.45, 26.78 }, - { 61.74, 31.06, 36.42 }, - { 64.37, 20.82, 18.92 }, - { 50.4, -53.22, 14.62 }, - { 96.51, -0.89, 0.65 }, - { 49.74, -0.19, 0.03 }, - { 31.91, 18.62, 21.99 }, - { 60.74, 38.66, 70.97 }, - { 19.35, 22.23, -58.86 }, - { 96.52, -0.91, 0.62 }, - { 6.66, 0, -0.3 }, - { 76.51, 20.81, 22.72 }, - { 72.79, 29.15, 24.18 }, - { 22.33, -20.7, 5.75 }, - { 49.7, -0.19, 0.01 }, - { 6.53, -0.05, -0.61 }, - { 63.42, 20.19, 19.22 }, - { 34.94, 11.64, -50.7 }, - { 52.03, -44.15, 39.04 }, - { 79.43, 0.29, -0.17 }, - { 30.67, -0.14, -0.53 }, - { 63.6, 14.44, 26.07 }, - { 64.37, 14.5, 17.05 }, - { 60.01, -44.33, 8.49 }, - { 6.63, -0.01, -0.47 }, - { 96.56, -0.93, 0.59 }, - { 46.37, -5.09, -24.46 }, - { 47.08, 52.97, 20.49 }, - { 36.04, 64.92, 38.51 }, - { 65.05, 0, -0.32 }, - { 40.14, -0.19, -0.38 }, - { 43.77, 16.46, 27.12 }, - { 64.39, 17, 16.59 }, - { 60.79, -29.74, 41.5 }, - { 96.48, -0.89, 0.64 }, - { 49.75, -0.21, 0.01 }, - { 38.18, -16.99, 30.87 }, - { 21.31, 29.14, -27.51 }, - { 80.57, 3.85, 89.61 }, - { 49.71, -0.2, 0.03 }, - { 60.27, 0.08, -0.41 }, - { 67.34, 14.45, 16.9 }, - { 64.69, 16.95, 18.57 }, - { 51.12, -49.31, 44.41 }, - { 49.7, -0.2, 0.02 }, - { 6.67, -0.05, -0.64 }, - { 51.56, 9.16, -26.88 }, - { 70.83, -24.26, 64.77 }, - { 48.06, 55.33, -15.61 }, - { 35.26, -0.09, -0.24 }, - { 75.16, 0.25, -0.2 }, - { 44.54, 26.27, 38.93 }, - { 35.91, 16.59, 26.46 }, - { 61.49, -52.73, 47.3 }, - { 6.59, -0.05, -0.5 }, - { 96.58, -0.9, 0.61 }, - { 68.93, -34.58, -0.34 }, - { 69.65, 20.09, 78.57 }, - { 47.79, -33.18, -30.21 }, - { 15.94, -0.42, -1.2 }, - { 89.02, -0.36, -0.48 }, - { 63.43, 25.44, 26.25 }, - { 65.75, 22.06, 27.82 }, - { 61.47, 17.1, 50.72 }, - { 96.53, -0.89, 0.66 }, - { 49.79, -0.2, 0.03 }, - { 85.17, 10.89, 17.26 }, - { 89.74, -16.52, 6.19 }, - { 84.55, 5.07, -6.12 }, - { 84.02, -13.87, -8.72 }, - { 70.76, 0.07, -0.35 }, - { 45.59, -0.05, 0.23 }, - { 20.3, 0.07, -0.32 }, - { 61.79, -13.41, 55.42 }, - { 49.72, -0.19, 0.02 }, - { 6.77, -0.05, -0.44 }, - { 21.85, 34.37, 7.83 }, - { 42.66, 67.43, 48.42 }, - { 60.33, 36.56, 3.56 }, - { 61.22, 36.61, 17.32 }, - { 62.07, 52.8, 77.14 }, - { 72.42, -9.82, 89.66 }, - { 62.03, 3.53, 57.01 }, - { 71.95, -27.34, 73.69 }, - { 6.59, -0.04, -0.45 }, - { 49.77, -0.19, 0.04 }, - { 41.84, 62.05, 10.01 }, - { 19.78, 29.16, -7.85 }, - { 39.56, 65.98, 33.71 }, - { 52.39, 68.33, 47.84 }, - { 81.23, 24.12, 87.51 }, - { 81.8, 6.78, 95.75 }, - { 71.72, -16.23, 76.28 }, - { 20.31, 14.45, 16.74 }, - { 49.68, -0.19, 0.05 }, - { 96.48, -0.88, 0.68 }, - { 49.69, -0.18, 0.03 }, - { 6.39, -0.04, -0.33 }, - { 96.54, -0.9, 0.67 }, - { 49.72, -0.18, 0.05 }, - { 6.49, -0.03, -0.41 }, - { 96.51, -0.9, 0.69 }, - { 49.7, -0.19, 0.07 }, - { 6.47, 0, -0.38 }, - { 96.46, -0.89, 0.7 } }; - - switch (const_color) - { - - case cv::ccm::COLORCHECKER_Macbeth: - { - Mat ColorChecker2005_LAB_D50_2_ = GetColor::getColorChecker(*ColorChecker2005_LAB_D50_2, 24); - Mat ColorChecker2005_COLORED_MASK_ = GetColor::getColorCheckerMASK(ColorChecker2005_COLORED_MASK, 24); - std::shared_ptr Macbeth_D50_2 = std::make_shared(ColorChecker2005_LAB_D50_2_, COLOR_SPACE_Lab_D50_2, ColorChecker2005_COLORED_MASK_); - return Macbeth_D50_2; - } - - case cv::ccm::COLORCHECKER_Vinyl: - { - Mat Vinyl_LAB_D50_2__ = GetColor::getColorChecker(*Vinyl_LAB_D50_2, 18); - Mat Vinyl_COLORED_MASK__ = GetColor::getColorCheckerMASK(Vinyl_COLORED_MASK, 18); - std::shared_ptr Vinyl_D50_2 = std::make_shared(Vinyl_LAB_D50_2__, COLOR_SPACE_Lab_D50_2, Vinyl_COLORED_MASK__); - return Vinyl_D50_2; - } - - case cv::ccm::COLORCHECKER_DigitalSG: - { - Mat DigitalSG_LAB_D50_2__ = GetColor::getColorChecker(*DigitalSG_LAB_D50_2, 140); - std::shared_ptr DigitalSG_D50_2 = std::make_shared(DigitalSG_LAB_D50_2__, COLOR_SPACE_Lab_D50_2); - return DigitalSG_D50_2; - } - } - CV_Error(Error::StsNotImplemented, ""); -} - -} -} // namespace cv::ccm diff --git a/modules/mcc/src/color.hpp b/modules/mcc/src/color.hpp deleted file mode 100644 index 858fd428010..00000000000 --- a/modules/mcc/src/color.hpp +++ /dev/null @@ -1,118 +0,0 @@ -// 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. -// -// -// License Agreement -// For Open Source Computer Vision Library -// -// Copyright(C) 2020, Huawei Technologies Co.,Ltd. All rights reserved. -// Third party copyrights are property of their respective owners. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// -// Author: Longbu Wang -// Jinheng Zhang -// Chenqi Shan - -#ifndef __OPENCV_CCM_COLOR_HPP__ -#define __OPENCV_CCM_COLOR_HPP__ - -#include "distance.hpp" -#include "colorspace.hpp" -#include "opencv2/ccm.hpp" - -namespace cv { -namespace ccm { - -/** @brief Color defined by color_values and color space -*/ - -class Color -{ -public: - /** @param grays mask of grayscale color - @param colored mask of colored color - @param history storage of historical conversion - */ - Mat colors; - const ColorSpace& cs; - Mat grays; - Mat colored; - std::map> history; - Color(); - Color(Mat colors_, enum COLOR_SPACE cs); - Color(Mat colors_, enum COLOR_SPACE cs, Mat colored); - Color(Mat colors_, const ColorSpace& cs, Mat colored); - Color(Mat colors_, const ColorSpace& cs); - virtual ~Color() {}; - - /** @brief Change to other color space. - The conversion process incorporates linear transformations to speed up. - @param other type of ColorSpace. - @param method the chromatic adapation method. - @param save when save if True, get data from history first. - @return Color. - */ - Color to(COLOR_SPACE other, CAM method = BRADFORD, bool save = true); - Color to(const ColorSpace& other, CAM method = BRADFORD, bool save = true); - - /** @brief Channels split. - @return each channel. - */ - Mat channel(Mat m, int i); - - /** @brief To Gray. - */ - Mat toGray(IO io, CAM method = BRADFORD, bool save = true); - - /** @brief To Luminant. - */ - Mat toLuminant(IO io, CAM method = BRADFORD, bool save = true); - - /** @brief Diff without IO. - @param other type of Color. - @param method type of distance. - @return distance between self and other - */ - Mat diff(Color& other, DISTANCE_TYPE method = DISTANCE_CIE2000); - - /** @brief Diff with IO. - @param other type of Color. - @param io type of IO. - @param method type of distance. - @return distance between self and other - */ - Mat diff(Color& other, IO io, DISTANCE_TYPE method = DISTANCE_CIE2000); - - /** @brief Calculate gray mask. - */ - void getGray(double JDN = 2.0); - - /** @brief Operator for mask copy. - */ - Color operator[](Mat mask); -}; - -class GetColor -{ -public: - static std::shared_ptr getColor(CONST_COLOR const_color); - static Mat getColorChecker(const double* checker, int row); - static Mat getColorCheckerMASK(const uchar* checker, int row); -}; - -} -} // namespace cv::ccm - -#endif \ No newline at end of file diff --git a/modules/mcc/src/colorspace.cpp b/modules/mcc/src/colorspace.cpp deleted file mode 100644 index 59b7a068b53..00000000000 --- a/modules/mcc/src/colorspace.cpp +++ /dev/null @@ -1,787 +0,0 @@ -// 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. -// -// -// License Agreement -// For Open Source Computer Vision Library -// -// Copyright(C) 2020, Huawei Technologies Co.,Ltd. All rights reserved. -// Third party copyrights are property of their respective owners. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// -// Author: Longbu Wang -// Jinheng Zhang -// Chenqi Shan - -#include "precomp.hpp" - -#include "colorspace.hpp" -#include "operations.hpp" -#include "io.hpp" - -namespace cv { -namespace ccm { -static const std::vector& getIlluminants(const IO& io) -{ - static const std::map> illuminants = { - { IO::getIOs(A_2), { 1.098466069456375, 1, 0.3558228003436005 } }, - { IO::getIOs(A_10), { 1.111420406956693, 1, 0.3519978321919493 } }, - { IO::getIOs(D50_2), { 0.9642119944211994, 1, 0.8251882845188288 } }, - { IO::getIOs(D50_10), { 0.9672062750333777, 1, 0.8142801513128616 } }, - { IO::getIOs(D55_2), { 0.956797052643698, 1, 0.9214805860173273 } }, - { IO::getIOs(D55_10), { 0.9579665682254781, 1, 0.9092525159847462 } }, - { IO::getIOs(D65_2), { 0.95047, 1., 1.08883 } }, - { IO::getIOs(D65_10), { 0.94811, 1., 1.07304 } }, - { IO::getIOs(D75_2), { 0.9497220898840717, 1, 1.226393520724154 } }, - { IO::getIOs(D75_10), { 0.9441713925645873, 1, 1.2064272211720228 } }, - { IO::getIOs(E_2), { 1., 1., 1. } }, - { IO::getIOs(E_10), { 1., 1., 1. } }, - }; - auto it = illuminants.find(io); - CV_Assert(it != illuminants.end()); - return it->second; -}; - -/* @brief Basic class for ColorSpace. - */ -bool ColorSpace::relate(const ColorSpace& other) const -{ - return (type == other.type) && (io == other.io); -}; - -Operations ColorSpace::relation(const ColorSpace& /*other*/) const -{ - return Operations::get_IDENTITY_OPS(); -} - -bool ColorSpace::operator<(const ColorSpace& other) const -{ - return (io < other.io || (io == other.io && type < other.type) || (io == other.io && type == other.type && linear < other.linear)); -} - -/* @brief Base of RGB color space; - * the argument values are from AdobeRGB; - * Data from https://en.wikipedia.org/wiki/Adobe_RGB_color_space - */ -Operations RGBBase_::relation(const ColorSpace& other) const -{ - if (linear == other.linear) - { - return Operations::get_IDENTITY_OPS(); - } - if (linear) - { - return Operations({ Operation([this](Mat rgbl) -> Mat { return fromLFunc(rgbl); }) }); - } - return Operations({ Operation([this](Mat rgb) -> Mat { return toLFunc(rgb); })}); -} - -/* @brief Initial operations. - */ -void RGBBase_::init() -{ - setParameter(); - calLinear(); - calM(); - calOperations(); -} - -/* @brief Produce color space instance with linear and non-linear versions. - * @param rgbl type of RGBBase_. - */ -void RGBBase_::bind(RGBBase_& rgbl) -{ - init(); - rgbl.init(); - l = &rgbl; - rgbl.l = &rgbl; - nl = this; - rgbl.nl = this; -} - -/* @brief Calculation of M_RGBL2XYZ_base. - */ -void RGBBase_::calM() -{ - Mat XYZr, XYZg, XYZb, XYZ_rgbl, Srgb; - XYZr = Mat(xyY2XYZ({ xr, yr }), true); - XYZg = Mat(xyY2XYZ({ xg, yg }), true); - XYZb = Mat(xyY2XYZ({ xb, yb }), true); - merge(std::vector { XYZr, XYZg, XYZb }, XYZ_rgbl); - XYZ_rgbl = XYZ_rgbl.reshape(1, (int)XYZ_rgbl.total()); - Mat XYZw = Mat(getIlluminants(io), true); - XYZw = XYZw.reshape(1, (int)XYZw.total()); - solve(XYZ_rgbl, XYZw, Srgb); - merge(std::vector { Srgb.at(0) * XYZr, Srgb.at(1) * XYZg, - Srgb.at(2) * XYZb }, - M_to); - M_to = M_to.reshape(1, (int)M_to.total()); - M_from = M_to.inv(); -}; - -/* @brief operations to or from XYZ. - */ -void RGBBase_::calOperations() -{ - if (linear) - { - to = Operations({ Operation(M_to.t()) }); - from = Operations({ Operation(M_from.t()) }); - } - else - { - // rgb -> rgbl - to = Operations({ Operation([this](Mat rgb) -> Mat { return toLFunc(rgb); }), Operation(M_to.t()) }); - // rgbl -> rgb - from = Operations({ Operation(M_from.t()), Operation([this](Mat rgbl) -> Mat { return fromLFunc(rgbl); }) }); - } -} - -Mat RGBBase_::toLFunc(Mat& /*rgb*/) const { return Mat(); } - -Mat RGBBase_::fromLFunc(Mat& /*rgbl*/, Mat dst) const { return dst; } - -/* @brief Base of Adobe RGB color space; - */ - -Mat AdobeRGBBase_::toLFunc(Mat& rgb) const { return gammaCorrection(rgb, gamma); } - -Mat AdobeRGBBase_::fromLFunc(Mat& rgbl, Mat dst) const -{ - return gammaCorrection(rgbl, 1. / gamma, dst); -} - -/* @brief Base of sRGB color space; - */ - -void sRGBBase_::calLinear() -{ - alpha = a + 1; - K0 = a / (gamma - 1); - phi = (pow(alpha, gamma) * pow(gamma - 1, gamma - 1)) / (pow(a, gamma - 1) * pow(gamma, gamma)); - beta = K0 / phi; -} - -/* @brief Used by toLFunc. - */ -double sRGBBase_::toLFuncEW(double& x) const -{ - if (x > K0) - { - return pow(((x + alpha - 1) / alpha), gamma); - } - else if (x >= -K0) - { - return x / phi; - } - else - { - return -(pow(((-x + alpha - 1) / alpha), gamma)); - } -} - -/* @brief Linearization. - * @param rgb the input array, type of cv::Mat. - * @return the output array, type of cv::Mat. - */ -Mat sRGBBase_::toLFunc(Mat& rgb) const -{ - return elementWise(rgb, - [this](double a_) -> double { return toLFuncEW(a_); }); -} - -/* @brief Used by fromLFunc. - */ -double sRGBBase_::fromLFuncEW(const double& x) const -{ - if (x > beta) - { - return alpha * pow(x, 1 / gamma) - (alpha - 1); - } - else if (x >= -beta) - { - return x * phi; - } - else - { - return -(alpha * pow(-x, 1 / gamma) - (alpha - 1)); - } -} - -/* @brief Delinearization. - * @param rgbl the input array, type of cv::Mat. - * @return the output array, type of cv::Mat. - */ -Mat sRGBBase_::fromLFunc(Mat& rgbl, Mat dst) const -{ - return elementWise(rgbl, [this](double a_) -> double { return fromLFuncEW(a_); }, dst); -} - -/* @brief sRGB color space. - * data from https://en.wikipedia.org/wiki/SRGB. - */ -void sRGB_::setParameter() -{ - xr = 0.64; - yr = 0.33; - xg = 0.3; - yg = 0.6; - xb = 0.15; - yb = 0.06; - a = 0.055; - gamma = 2.4; -} - -/* @brief Adobe RGB color space. - */ -void AdobeRGB_::setParameter() -{ - xr = 0.64; - yr = 0.33; - xg = 0.21; - yg = 0.71; - xb = 0.15; - yb = 0.06; - gamma = 2.2; -} - -/* @brief Wide-gamut RGB color space. - * data from https://en.wikipedia.org/wiki/Wide-gamut_RGB_color_space. - */ -void WideGamutRGB_::setParameter() -{ - xr = 0.7347; - yr = 0.2653; - xg = 0.1152; - yg = 0.8264; - xb = 0.1566; - yb = 0.0177; - gamma = 2.2; -} - -/* @brief ProPhoto RGB color space. - * data from https://en.wikipedia.org/wiki/ProPhoto_RGB_color_space. - */ -void ProPhotoRGB_::setParameter() -{ - xr = 0.734699; - yr = 0.265301; - xg = 0.159597; - yg = 0.840403; - xb = 0.036598; - yb = 0.000105; - gamma = 1.8; -} - -/* @brief DCI-P3 RGB color space. - * data from https://en.wikipedia.org/wiki/DCI-P3. - */ - -void DCI_P3_RGB_::setParameter() -{ - xr = 0.68; - yr = 0.32; - xg = 0.265; - yg = 0.69; - xb = 0.15; - yb = 0.06; - gamma = 2.2; -} - -/* @brief Apple RGB color space. - * data from - * http://www.brucelindbloom.com/index.html?WorkingSpaceInfo.html. - */ -void AppleRGB_::setParameter() -{ - xr = 0.625; - yr = 0.34; - xg = 0.28; - yg = 0.595; - xb = 0.155; - yb = 0.07; - gamma = 1.8; -} - -/* @brief REC_709 RGB color space. - * data from https://en.wikipedia.org/wiki/Rec._709. - */ -void REC_709_RGB_::setParameter() -{ - xr = 0.64; - yr = 0.33; - xg = 0.3; - yg = 0.6; - xb = 0.15; - yb = 0.06; - a = 0.099; - gamma = 1 / 0.45; -} - -/* @brief REC_2020 RGB color space. - * data from https://en.wikipedia.org/wiki/Rec._2020. - */ - -void REC_2020_RGB_::setParameter() -{ - xr = 0.708; - yr = 0.292; - xg = 0.17; - yg = 0.797; - xb = 0.131; - yb = 0.046; - a = 0.09929682680944; - gamma = 1 / 0.45; -} - -Operations XYZ::cam(IO dio, CAM method) -{ - return (io == dio) ? Operations() - : Operations({ Operation(cam_(io, dio, method).t()) }); -} -Mat XYZ::cam_(IO sio, IO dio, CAM method) const -{ - static std::map, Mat> cams; - - if (sio == dio) - { - return Mat::eye(cv::Size(3, 3), CV_64FC1); - } - if (cams.count(std::make_tuple(dio, sio, method)) == 1) - { - return cams[std::make_tuple(dio, sio, method)]; - } - /* @brief XYZ color space. - * Chromatic adaption matrices. - */ - - static const Mat Von_Kries = (Mat_(3, 3) << 0.40024, 0.7076, -0.08081, -0.2263, 1.16532, 0.0457, 0., 0., 0.91822); - static const Mat Bradford = (Mat_(3, 3) << 0.8951, 0.2664, -0.1614, -0.7502, 1.7135, 0.0367, 0.0389, -0.0685, 1.0296); - static const std::map> MAs = { - { IDENTITY, { Mat::eye(Size(3, 3), CV_64FC1), Mat::eye(Size(3, 3), CV_64FC1) } }, - { VON_KRIES, { Von_Kries, Von_Kries.inv() } }, - { BRADFORD, { Bradford, Bradford.inv() } } - }; - - // Function from http://www.brucelindbloom.com/index.html?ColorCheckerRGB.html. - Mat XYZws = Mat(getIlluminants(dio)); - Mat XYZWd = Mat(getIlluminants(sio)); - XYZws = XYZws.reshape(1, (int)XYZws.total()); - XYZWd = XYZWd.reshape(1, (int)XYZWd.total()); - Mat MA = MAs.at(method)[0]; - Mat MA_inv = MAs.at(method)[1]; - Mat M = MA_inv * Mat::diag((MA * XYZws) / (MA * XYZWd)) * MA; - cams[std::make_tuple(dio, sio, method)] = M; - cams[std::make_tuple(sio, dio, method)] = M.inv(); - return M; -} - -std::shared_ptr XYZ::get(IO io) -{ - static std::map> xyz_cs; - - if (xyz_cs.count(io) == 1) - { - return xyz_cs[io]; - } - std::shared_ptr XYZ_CS = std::make_shared(io); - xyz_cs[io] = XYZ_CS; - return xyz_cs[io]; -} - -/* @brief Lab color space. - */ -Lab::Lab(IO io_) - : ColorSpace(io_, "Lab", true) -{ - to = { Operation([this](Mat src) -> Mat { return tosrc(src); }) }; - from = { Operation([this](Mat src) -> Mat { return fromsrc(src); }) }; -} - -Vec3d Lab::fromxyz(cv::Vec3d& xyz) -{ - auto& il = getIlluminants(io); - double x = xyz[0] / il[0], - y = xyz[1] / il[1], - z = xyz[2] / il[2]; - auto f = [](double t) -> double { - return t > t0 ? std::cbrt(t) : (m * t + c); - }; - double fx = f(x), fy = f(y), fz = f(z); - return { 116. * fy - 16., 500 * (fx - fy), 200 * (fy - fz) }; -} - -/* @brief Calculate From. - * @param src the input array, type of cv::Mat. - * @return the output array, type of cv::Mat - */ -Mat Lab::fromsrc(Mat& src) -{ - return channelWise(src, - [this](cv::Vec3d a) -> cv::Vec3d { return fromxyz(a); }); -} - -Vec3d Lab::tolab(cv::Vec3d& lab) -{ - auto f_inv = [](double t) -> double { - return t > delta ? pow(t, 3.0) : (t - c) / m; - }; - double L = (lab[0] + 16.) / 116., a = lab[1] / 500., b = lab[2] / 200.; - auto& il = getIlluminants(io); - return { il[0] * f_inv(L + a), - il[1] * f_inv(L), - il[2] * f_inv(L - b) }; -} - -/* @brief Calculate To. - * @param src the input array, type of cv::Mat. - * @return the output array, type of cv::Mat - */ -Mat Lab::tosrc(Mat& src) -{ - return channelWise(src, - [this](cv::Vec3d a) -> cv::Vec3d { return tolab(a); }); -} - -std::shared_ptr Lab::get(IO io) -{ - static std::map> lab_cs; - - if (lab_cs.count(io) == 1) - { - return lab_cs[io]; - } - std::shared_ptr Lab_CS(new Lab(io)); - lab_cs[io] = Lab_CS; - return lab_cs[io]; -} - -GetCS::GetCS() -{ - // nothing -} - -GetCS& GetCS::getInstance() -{ - static GetCS instance; - return instance; -} - -std::shared_ptr GetCS::get_rgb(enum COLOR_SPACE cs_name) -{ - switch (cs_name) - { - case cv::ccm::COLOR_SPACE_sRGB: - { - if (map_cs.count(cs_name) < 1) - { - std::shared_ptr sRGB_CS(new sRGB_(false)); - std::shared_ptr sRGBL_CS(new sRGB_(true)); - (*sRGB_CS).bind(*sRGBL_CS); - map_cs[COLOR_SPACE_sRGB] = sRGB_CS; - map_cs[COLOR_SPACE_sRGBL] = sRGBL_CS; - } - break; - } - case cv::ccm::COLOR_SPACE_AdobeRGB: - { - if (map_cs.count(cs_name) < 1) - { - std::shared_ptr AdobeRGB_CS(new AdobeRGB_(false)); - std::shared_ptr AdobeRGBL_CS(new AdobeRGB_(true)); - (*AdobeRGB_CS).bind(*AdobeRGBL_CS); - map_cs[COLOR_SPACE_AdobeRGB] = AdobeRGB_CS; - map_cs[COLOR_SPACE_AdobeRGBL] = AdobeRGBL_CS; - } - break; - } - case cv::ccm::COLOR_SPACE_WideGamutRGB: - { - if (map_cs.count(cs_name) < 1) - { - std::shared_ptr WideGamutRGB_CS(new WideGamutRGB_(false)); - std::shared_ptr WideGamutRGBL_CS(new WideGamutRGB_(true)); - (*WideGamutRGB_CS).bind(*WideGamutRGBL_CS); - map_cs[COLOR_SPACE_WideGamutRGB] = WideGamutRGB_CS; - map_cs[COLOR_SPACE_WideGamutRGBL] = WideGamutRGBL_CS; - } - break; - } - case cv::ccm::COLOR_SPACE_ProPhotoRGB: - { - if (map_cs.count(cs_name) < 1) - { - std::shared_ptr ProPhotoRGB_CS(new ProPhotoRGB_(false)); - std::shared_ptr ProPhotoRGBL_CS(new ProPhotoRGB_(true)); - (*ProPhotoRGB_CS).bind(*ProPhotoRGBL_CS); - map_cs[COLOR_SPACE_ProPhotoRGB] = ProPhotoRGB_CS; - map_cs[COLOR_SPACE_ProPhotoRGBL] = ProPhotoRGBL_CS; - } - break; - } - case cv::ccm::COLOR_SPACE_DCI_P3_RGB: - { - if (map_cs.count(cs_name) < 1) - { - std::shared_ptr DCI_P3_RGB_CS(new DCI_P3_RGB_(false)); - std::shared_ptr DCI_P3_RGBL_CS(new DCI_P3_RGB_(true)); - (*DCI_P3_RGB_CS).bind(*DCI_P3_RGBL_CS); - map_cs[COLOR_SPACE_DCI_P3_RGB] = DCI_P3_RGB_CS; - map_cs[COLOR_SPACE_DCI_P3_RGBL] = DCI_P3_RGBL_CS; - } - break; - } - case cv::ccm::COLOR_SPACE_AppleRGB: - { - if (map_cs.count(cs_name) < 1) - { - std::shared_ptr AppleRGB_CS(new AppleRGB_(false)); - std::shared_ptr AppleRGBL_CS(new AppleRGB_(true)); - (*AppleRGB_CS).bind(*AppleRGBL_CS); - map_cs[COLOR_SPACE_AppleRGB] = AppleRGB_CS; - map_cs[COLOR_SPACE_AppleRGBL] = AppleRGBL_CS; - } - break; - } - case cv::ccm::COLOR_SPACE_REC_709_RGB: - { - if (map_cs.count(cs_name) < 1) - { - std::shared_ptr REC_709_RGB_CS(new REC_709_RGB_(false)); - std::shared_ptr REC_709_RGBL_CS(new REC_709_RGB_(true)); - (*REC_709_RGB_CS).bind(*REC_709_RGBL_CS); - map_cs[COLOR_SPACE_REC_709_RGB] = REC_709_RGB_CS; - map_cs[COLOR_SPACE_REC_709_RGBL] = REC_709_RGBL_CS; - } - break; - } - case cv::ccm::COLOR_SPACE_REC_2020_RGB: - { - if (map_cs.count(cs_name) < 1) - { - std::shared_ptr REC_2020_RGB_CS(new REC_2020_RGB_(false)); - std::shared_ptr REC_2020_RGBL_CS(new REC_2020_RGB_(true)); - (*REC_2020_RGB_CS).bind(*REC_2020_RGBL_CS); - map_cs[COLOR_SPACE_REC_2020_RGB] = REC_2020_RGB_CS; - map_cs[COLOR_SPACE_REC_2020_RGBL] = REC_2020_RGBL_CS; - } - break; - } - case cv::ccm::COLOR_SPACE_sRGBL: - case cv::ccm::COLOR_SPACE_AdobeRGBL: - case cv::ccm::COLOR_SPACE_WideGamutRGBL: - case cv::ccm::COLOR_SPACE_ProPhotoRGBL: - case cv::ccm::COLOR_SPACE_DCI_P3_RGBL: - case cv::ccm::COLOR_SPACE_AppleRGBL: - case cv::ccm::COLOR_SPACE_REC_709_RGBL: - case cv::ccm::COLOR_SPACE_REC_2020_RGBL: - CV_Error(Error::StsBadArg, "linear RGB colorspaces are not supported, you should assigned as normal RGB color space"); - break; - - default: - CV_Error(Error::StsBadArg, "Only RGB color spaces are supported"); - } - return (std::dynamic_pointer_cast)(map_cs[cs_name]); -} - -std::shared_ptr GetCS::get_cs(enum COLOR_SPACE cs_name) -{ - switch (cs_name) - { - case cv::ccm::COLOR_SPACE_sRGB: - case cv::ccm::COLOR_SPACE_sRGBL: - { - if (map_cs.count(cs_name) < 1) - { - std::shared_ptr sRGB_CS(new sRGB_(false)); - std::shared_ptr sRGBL_CS(new sRGB_(true)); - (*sRGB_CS).bind(*sRGBL_CS); - map_cs[COLOR_SPACE_sRGB] = sRGB_CS; - map_cs[COLOR_SPACE_sRGBL] = sRGBL_CS; - } - break; - } - case cv::ccm::COLOR_SPACE_AdobeRGB: - case cv::ccm::COLOR_SPACE_AdobeRGBL: - { - if (map_cs.count(cs_name) < 1) - { - std::shared_ptr AdobeRGB_CS(new AdobeRGB_(false)); - std::shared_ptr AdobeRGBL_CS(new AdobeRGB_(true)); - (*AdobeRGB_CS).bind(*AdobeRGBL_CS); - map_cs[COLOR_SPACE_AdobeRGB] = AdobeRGB_CS; - map_cs[COLOR_SPACE_AdobeRGBL] = AdobeRGBL_CS; - } - break; - } - case cv::ccm::COLOR_SPACE_WideGamutRGB: - case cv::ccm::COLOR_SPACE_WideGamutRGBL: - { - if (map_cs.count(cs_name) < 1) - { - std::shared_ptr WideGamutRGB_CS(new WideGamutRGB_(false)); - std::shared_ptr WideGamutRGBL_CS(new WideGamutRGB_(true)); - (*WideGamutRGB_CS).bind(*WideGamutRGBL_CS); - map_cs[COLOR_SPACE_WideGamutRGB] = WideGamutRGB_CS; - map_cs[COLOR_SPACE_WideGamutRGBL] = WideGamutRGBL_CS; - } - break; - } - case cv::ccm::COLOR_SPACE_ProPhotoRGB: - case cv::ccm::COLOR_SPACE_ProPhotoRGBL: - { - if (map_cs.count(cs_name) < 1) - { - std::shared_ptr ProPhotoRGB_CS(new ProPhotoRGB_(false)); - std::shared_ptr ProPhotoRGBL_CS(new ProPhotoRGB_(true)); - (*ProPhotoRGB_CS).bind(*ProPhotoRGBL_CS); - map_cs[COLOR_SPACE_ProPhotoRGB] = ProPhotoRGB_CS; - map_cs[COLOR_SPACE_ProPhotoRGBL] = ProPhotoRGBL_CS; - } - break; - } - case cv::ccm::COLOR_SPACE_DCI_P3_RGB: - case cv::ccm::COLOR_SPACE_DCI_P3_RGBL: - { - if (map_cs.count(cs_name) < 1) - { - std::shared_ptr DCI_P3_RGB_CS(new DCI_P3_RGB_(false)); - std::shared_ptr DCI_P3_RGBL_CS(new DCI_P3_RGB_(true)); - (*DCI_P3_RGB_CS).bind(*DCI_P3_RGBL_CS); - map_cs[COLOR_SPACE_DCI_P3_RGB] = DCI_P3_RGB_CS; - map_cs[COLOR_SPACE_DCI_P3_RGBL] = DCI_P3_RGBL_CS; - } - break; - } - case cv::ccm::COLOR_SPACE_AppleRGB: - case cv::ccm::COLOR_SPACE_AppleRGBL: - { - if (map_cs.count(cs_name) < 1) - { - std::shared_ptr AppleRGB_CS(new AppleRGB_(false)); - std::shared_ptr AppleRGBL_CS(new AppleRGB_(true)); - (*AppleRGB_CS).bind(*AppleRGBL_CS); - map_cs[COLOR_SPACE_AppleRGB] = AppleRGB_CS; - map_cs[COLOR_SPACE_AppleRGBL] = AppleRGBL_CS; - } - break; - } - case cv::ccm::COLOR_SPACE_REC_709_RGB: - case cv::ccm::COLOR_SPACE_REC_709_RGBL: - { - if (map_cs.count(cs_name) < 1) - { - std::shared_ptr REC_709_RGB_CS(new REC_709_RGB_(false)); - std::shared_ptr REC_709_RGBL_CS(new REC_709_RGB_(true)); - (*REC_709_RGB_CS).bind(*REC_709_RGBL_CS); - map_cs[COLOR_SPACE_REC_709_RGB] = REC_709_RGB_CS; - map_cs[COLOR_SPACE_REC_709_RGBL] = REC_709_RGBL_CS; - } - break; - } - case cv::ccm::COLOR_SPACE_REC_2020_RGB: - case cv::ccm::COLOR_SPACE_REC_2020_RGBL: - { - if (map_cs.count(cs_name) < 1) - { - std::shared_ptr REC_2020_RGB_CS(new REC_2020_RGB_(false)); - std::shared_ptr REC_2020_RGBL_CS(new REC_2020_RGB_(true)); - (*REC_2020_RGB_CS).bind(*REC_2020_RGBL_CS); - map_cs[COLOR_SPACE_REC_2020_RGB] = REC_2020_RGB_CS; - map_cs[COLOR_SPACE_REC_2020_RGBL] = REC_2020_RGBL_CS; - } - break; - } - case cv::ccm::COLOR_SPACE_XYZ_D65_2: - return XYZ::get(IO::getIOs(D65_2)); - break; - case cv::ccm::COLOR_SPACE_XYZ_D50_2: - return XYZ::get(IO::getIOs(D50_2)); - break; - case cv::ccm::COLOR_SPACE_XYZ_D65_10: - return XYZ::get(IO::getIOs(D65_10)); - break; - case cv::ccm::COLOR_SPACE_XYZ_D50_10: - return XYZ::get(IO::getIOs(D50_10)); - break; - case cv::ccm::COLOR_SPACE_XYZ_A_2: - return XYZ::get(IO::getIOs(A_2)); - break; - case cv::ccm::COLOR_SPACE_XYZ_A_10: - return XYZ::get(IO::getIOs(A_10)); - break; - case cv::ccm::COLOR_SPACE_XYZ_D55_2: - return XYZ::get(IO::getIOs(D55_2)); - break; - case cv::ccm::COLOR_SPACE_XYZ_D55_10: - return XYZ::get(IO::getIOs(D55_10)); - break; - case cv::ccm::COLOR_SPACE_XYZ_D75_2: - return XYZ::get(IO::getIOs(D75_2)); - break; - case cv::ccm::COLOR_SPACE_XYZ_D75_10: - return XYZ::get(IO::getIOs(D75_10)); - break; - case cv::ccm::COLOR_SPACE_XYZ_E_2: - return XYZ::get(IO::getIOs(E_2)); - break; - case cv::ccm::COLOR_SPACE_XYZ_E_10: - return XYZ::get(IO::getIOs(E_10)); - break; - case cv::ccm::COLOR_SPACE_Lab_D65_2: - return Lab::get(IO::getIOs(D65_2)); - break; - case cv::ccm::COLOR_SPACE_Lab_D50_2: - return Lab::get(IO::getIOs(D50_2)); - break; - case cv::ccm::COLOR_SPACE_Lab_D65_10: - return Lab::get(IO::getIOs(D65_10)); - break; - case cv::ccm::COLOR_SPACE_Lab_D50_10: - return Lab::get(IO::getIOs(D50_10)); - break; - case cv::ccm::COLOR_SPACE_Lab_A_2: - return Lab::get(IO::getIOs(A_2)); - break; - case cv::ccm::COLOR_SPACE_Lab_A_10: - return Lab::get(IO::getIOs(A_10)); - break; - case cv::ccm::COLOR_SPACE_Lab_D55_2: - return Lab::get(IO::getIOs(D55_2)); - break; - case cv::ccm::COLOR_SPACE_Lab_D55_10: - return Lab::get(IO::getIOs(D55_10)); - break; - case cv::ccm::COLOR_SPACE_Lab_D75_2: - return Lab::get(IO::getIOs(D75_2)); - break; - case cv::ccm::COLOR_SPACE_Lab_D75_10: - return Lab::get(IO::getIOs(D75_10)); - break; - case cv::ccm::COLOR_SPACE_Lab_E_2: - return Lab::get(IO::getIOs(E_2)); - break; - case cv::ccm::COLOR_SPACE_Lab_E_10: - return Lab::get(IO::getIOs(E_10)); - break; - default: - break; - } - - return map_cs[cs_name]; -} - -} -} // namespace cv::ccm diff --git a/modules/mcc/src/colorspace.hpp b/modules/mcc/src/colorspace.hpp deleted file mode 100644 index f4e70c36ddb..00000000000 --- a/modules/mcc/src/colorspace.hpp +++ /dev/null @@ -1,362 +0,0 @@ -// 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. -// -// -// License Agreement -// For Open Source Computer Vision Library -// -// Copyright(C) 2020, Huawei Technologies Co.,Ltd. All rights reserved. -// Third party copyrights are property of their respective owners. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// -// Author: Longbu Wang -// Jinheng Zhang -// Chenqi Shan - -#ifndef __OPENCV_CCM_COLORSPACE_HPP__ -#define __OPENCV_CCM_COLORSPACE_HPP__ - -#include "operations.hpp" -#include "io.hpp" -#include "opencv2/ccm.hpp" - -namespace cv { -namespace ccm { - -/** @brief Basic class for ColorSpace. -*/ -class ColorSpace -{ -public: - typedef std::function MatFunc; - IO io; - std::string type; - bool linear; - Operations to; - Operations from; - ColorSpace* l; - ColorSpace* nl; - - ColorSpace() {}; - - ColorSpace(IO io_, std::string type_, bool linear_) - : io(io_) - , type(type_) - , linear(linear_) {}; - - virtual ~ColorSpace() - { - l = 0; - nl = 0; - }; - virtual bool relate(const ColorSpace& other) const; - - virtual Operations relation(const ColorSpace& /*other*/) const; - - bool operator<(const ColorSpace& other) const; -}; - -/** @brief Base of RGB color space; - the argument values are from AdobeRGB; - Data from https://en.wikipedia.org/wiki/Adobe_RGB_color_space -*/ - -class RGBBase_ : public ColorSpace -{ -public: - // primaries - double xr; - double yr; - double xg; - double yg; - double xb; - double yb; - Mat M_to; - Mat M_from; - - using ColorSpace::ColorSpace; - - /** @brief There are 3 kinds of relationships for RGB: - 1. Different types; - no operation - 1. Same type, same linear; - copy - 2. Same type, different linear, self is nonlinear; - 2 toL - 3. Same type, different linear, self is linear - 3 fromL - @param other type of ColorSpace. - @return Operations. - */ - Operations relation(const ColorSpace& other) const CV_OVERRIDE; - - /** @brief Initial operations. - */ - void init(); - /** @brief Produce color space instance with linear and non-linear versions. - @param rgbl type of RGBBase_. - */ - void bind(RGBBase_& rgbl); - - virtual Mat toLFunc(Mat& /*rgb*/) const; - - virtual Mat fromLFunc(Mat& /*rgbl*/, Mat dst=Mat()) const; -private: - virtual void setParameter() {}; - - /** @brief Calculation of M_RGBL2XYZ_base. - */ - virtual void calM(); - - /** @brief operations to or from XYZ. - */ - virtual void calOperations(); - - virtual void calLinear() {}; -}; - -/** @brief Base of Adobe RGB color space; -*/ -class AdobeRGBBase_ : public RGBBase_ - -{ -public: - using RGBBase_::RGBBase_; - double gamma; - -private: - Mat toLFunc(Mat& rgb) const CV_OVERRIDE; - Mat fromLFunc(Mat& rgbl, Mat dst=Mat()) const CV_OVERRIDE; -}; - -/** @brief Base of sRGB color space; -*/ -class sRGBBase_ : public RGBBase_ - -{ -public: - using RGBBase_::RGBBase_; - double a; - double gamma; - double alpha; - double beta; - double phi; - double K0; - -private: - /** @brief linearization parameters - */ - virtual void calLinear() CV_OVERRIDE; - /** @brief Used by toLFunc. - */ - double toLFuncEW(double& x) const; - - /** @brief Linearization. - @param rgb the input array, type of cv::Mat. - @return the output array, type of cv::Mat. - */ - Mat toLFunc(Mat& rgb) const CV_OVERRIDE; - - /** @brief Used by fromLFunc. - */ - double fromLFuncEW(const double& x) const; - - /** @brief Delinearization. - @param rgbl the input array, type of cv::Mat. - @return the output array, type of cv::Mat. - */ - Mat fromLFunc(Mat& rgbl, Mat dst=Mat()) const CV_OVERRIDE; -}; - -/** @brief sRGB color space. - data from https://en.wikipedia.org/wiki/SRGB. -*/ -class sRGB_ : public sRGBBase_ - -{ -public: - sRGB_(bool linear_) - : sRGBBase_(IO::getIOs(D65_2), "sRGB", linear_) {}; - -private: - void setParameter() CV_OVERRIDE; -}; - -/** @brief Adobe RGB color space. -*/ -class AdobeRGB_ : public AdobeRGBBase_ -{ -public: - AdobeRGB_(bool linear_ = false) - : AdobeRGBBase_(IO::getIOs(D65_2), "AdobeRGB", linear_) {}; - -private: - void setParameter() CV_OVERRIDE; -}; - -/** @brief Wide-gamut RGB color space. - data from https://en.wikipedia.org/wiki/Wide-gamut_RGB_color_space. -*/ -class WideGamutRGB_ : public AdobeRGBBase_ -{ -public: - WideGamutRGB_(bool linear_ = false) - : AdobeRGBBase_(IO::getIOs(D50_2), "WideGamutRGB", linear_) {}; - -private: - void setParameter() CV_OVERRIDE; -}; - -/** @brief ProPhoto RGB color space. - data from https://en.wikipedia.org/wiki/ProPhoto_RGB_color_space. -*/ - -class ProPhotoRGB_ : public AdobeRGBBase_ -{ -public: - ProPhotoRGB_(bool linear_ = false) - : AdobeRGBBase_(IO::getIOs(D50_2), "ProPhotoRGB", linear_) {}; - -private: - void setParameter() CV_OVERRIDE; -}; - -/** @brief DCI-P3 RGB color space. - data from https://en.wikipedia.org/wiki/DCI-P3. -*/ -class DCI_P3_RGB_ : public AdobeRGBBase_ -{ -public: - DCI_P3_RGB_(bool linear_ = false) - : AdobeRGBBase_(IO::getIOs(D65_2), "DCI_P3_RGB", linear_) {}; - -private: - void setParameter() CV_OVERRIDE; -}; - -/** @brief Apple RGB color space. - data from http://www.brucelindbloom.com/index.html?WorkingSpaceInfo.html. -*/ -class AppleRGB_ : public AdobeRGBBase_ -{ -public: - AppleRGB_(bool linear_ = false) - : AdobeRGBBase_(IO::getIOs(D65_2), "AppleRGB", linear_) {}; - -private: - void setParameter() CV_OVERRIDE; -}; - -/** @brief REC_709 RGB color space. - data from https://en.wikipedia.org/wiki/Rec._709. -*/ -class REC_709_RGB_ : public sRGBBase_ -{ -public: - REC_709_RGB_(bool linear_) - : sRGBBase_(IO::getIOs(D65_2), "REC_709_RGB", linear_) {}; - -private: - void setParameter() CV_OVERRIDE; -}; - -/** @brief REC_2020 RGB color space. - data from https://en.wikipedia.org/wiki/Rec._2020. -*/ -class REC_2020_RGB_ : public sRGBBase_ -{ -public: - REC_2020_RGB_(bool linear_) - : sRGBBase_(IO::getIOs(D65_2), "REC_2020_RGB", linear_) {}; - -private: - void setParameter() CV_OVERRIDE; -}; - -/** @brief Enum of the possible types of CAMs. -*/ -enum CAM -{ - IDENTITY, - VON_KRIES, - BRADFORD -}; - - -/** @brief XYZ color space. - Chromatic adaption matrices. -*/ -class XYZ : public ColorSpace -{ -public: - XYZ(IO io_) - : ColorSpace(io_, "XYZ", true) {}; - Operations cam(IO dio, CAM method = BRADFORD); - static std::shared_ptr get(IO io); - -private: - /** @brief Get cam. - @param sio the input IO of src. - @param dio the input IO of dst. - @param method type of CAM. - @return the output array, type of cv::Mat. - */ - Mat cam_(IO sio, IO dio, CAM method = BRADFORD) const; -}; - -/** @brief Lab color space. -*/ -class Lab : public ColorSpace -{ -public: - Lab(IO io); - static std::shared_ptr get(IO io); - -private: - static constexpr double delta = (6. / 29.); - static constexpr double m = 1. / (3. * delta * delta); - static constexpr double t0 = delta * delta * delta; - static constexpr double c = 4. / 29.; - - Vec3d fromxyz(Vec3d& xyz); - - /** @brief Calculate From. - @param src the input array, type of cv::Mat. - @return the output array, type of cv::Mat - */ - Mat fromsrc(Mat& src); - - Vec3d tolab(Vec3d& lab); - - /** @brief Calculate To. - @param src the input array, type of cv::Mat. - @return the output array, type of cv::Mat - */ - Mat tosrc(Mat& src); -}; - -class GetCS -{ -protected: - std::map> map_cs; - - GetCS(); // singleton, use getInstance() -public: - static GetCS& getInstance(); - - std::shared_ptr get_rgb(enum COLOR_SPACE cs_name); - std::shared_ptr get_cs(enum COLOR_SPACE cs_name); -}; - -} -} // namespace cv::ccm - -#endif \ No newline at end of file diff --git a/modules/mcc/src/distance.cpp b/modules/mcc/src/distance.cpp deleted file mode 100644 index c5eb1b59514..00000000000 --- a/modules/mcc/src/distance.cpp +++ /dev/null @@ -1,223 +0,0 @@ -// 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. -// -// -// License Agreement -// For Open Source Computer Vision Library -// -// Copyright(C) 2020, Huawei Technologies Co.,Ltd. All rights reserved. -// Third party copyrights are property of their respective owners. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// -// Author: Longbu Wang -// Jinheng Zhang -// Chenqi Shan - -#include "distance.hpp" - -namespace cv { -namespace ccm { - -double deltaCIE76(const Vec3d& lab1, const Vec3d& lab2) { return norm(lab1 - lab2); }; - -double deltaCIE94(const Vec3d& lab1, const Vec3d& lab2, const double& kH, - const double& kC, const double& kL, const double& k1, const double& k2) -{ - double dl = lab1[0] - lab2[0]; - double c1 = sqrt(pow(lab1[1], 2) + pow(lab1[2], 2)); - double c2 = sqrt(pow(lab2[1], 2) + pow(lab2[2], 2)); - double dc = c1 - c2; - double da = lab1[1] - lab2[1]; - double db = lab1[2] - lab2[2]; - double dh = pow(da, 2) + pow(db, 2) - pow(dc, 2); - double sc = 1.0 + k1 * c1; - double sh = 1.0 + k2 * c1; - double sl = 1.0; - double res = pow(dl / (kL * sl), 2) + pow(dc / (kC * sc), 2) + dh / pow(kH * sh, 2); - - return res > 0 ? sqrt(res) : 0; -} - -double deltaCIE94GraphicArts(const Vec3d& lab1, const Vec3d& lab2) -{ - return deltaCIE94(lab1, lab2); -} - -double toRad(const double& degree) { return degree / 180 * CV_PI; }; - -double deltaCIE94Textiles(const Vec3d& lab1, const Vec3d& lab2) -{ - return deltaCIE94(lab1, lab2, 1.0, 1.0, 2.0, 0.048, 0.014); -} - -double deltaCIEDE2000_(const Vec3d& lab1, const Vec3d& lab2, const double& kL, - const double& kC, const double& kH) -{ - double delta_L_apo = lab2[0] - lab1[0]; - double l_bar_apo = (lab1[0] + lab2[0]) / 2.0; - double C1 = sqrt(pow(lab1[1], 2) + pow(lab1[2], 2)); - double C2 = sqrt(pow(lab2[1], 2) + pow(lab2[2], 2)); - double C_bar = (C1 + C2) / 2.0; - double G = sqrt(pow(C_bar, 7) / (pow(C_bar, 7) + pow(25, 7))); - double a1_apo = lab1[1] + lab1[1] / 2.0 * (1.0 - G); - double a2_apo = lab2[1] + lab2[1] / 2.0 * (1.0 - G); - double C1_apo = sqrt(pow(a1_apo, 2) + pow(lab1[2], 2)); - double C2_apo = sqrt(pow(a2_apo, 2) + pow(lab2[2], 2)); - double C_bar_apo = (C1_apo + C2_apo) / 2.0; - double delta_C_apo = C2_apo - C1_apo; - - double h1_apo; - if (C1_apo == 0) - { - h1_apo = 0.0; - } - else - { - h1_apo = atan2(lab1[2], a1_apo); - if (h1_apo < 0.0) - h1_apo += 2. * CV_PI; - } - - double h2_apo; - if (C2_apo == 0) - { - h2_apo = 0.0; - } - else - { - h2_apo = atan2(lab2[2], a2_apo); - if (h2_apo < 0.0) - h2_apo += 2. * CV_PI; - } - - double delta_h_apo; - if (abs(h2_apo - h1_apo) <= CV_PI) - { - delta_h_apo = h2_apo - h1_apo; - } - else if (h2_apo <= h1_apo) - { - delta_h_apo = h2_apo - h1_apo + 2. * CV_PI; - } - else - { - delta_h_apo = h2_apo - h1_apo - 2. * CV_PI; - } - - double H_bar_apo; - if (C1_apo == 0 || C2_apo == 0) - { - H_bar_apo = h1_apo + h2_apo; - } - else if (abs(h1_apo - h2_apo) <= CV_PI) - { - H_bar_apo = (h1_apo + h2_apo) / 2.0; - } - else if (h1_apo + h2_apo < 2. * CV_PI) - { - H_bar_apo = (h1_apo + h2_apo + 2. * CV_PI) / 2.0; - } - else - { - H_bar_apo = (h1_apo + h2_apo - 2. * CV_PI) / 2.0; - } - - double delta_H_apo = 2.0 * sqrt(C1_apo * C2_apo) * sin(delta_h_apo / 2.0); - double T = 1.0 - 0.17 * cos(H_bar_apo - toRad(30.)) + 0.24 * cos(2.0 * H_bar_apo) + 0.32 * cos(3.0 * H_bar_apo + toRad(6.0)) - 0.2 * cos(4.0 * H_bar_apo - toRad(63.0)); - double sC = 1.0 + 0.045 * C_bar_apo; - double sH = 1.0 + 0.015 * C_bar_apo * T; - double sL = 1.0 + ((0.015 * pow(l_bar_apo - 50.0, 2.0)) / sqrt(20.0 + pow(l_bar_apo - 50.0, 2.0))); - double R_C = 2.0 * sqrt(pow(C_bar_apo, 7.0) / (pow(C_bar_apo, 7.0) + pow(25, 7))); - double RT = -sin(toRad(60.0) * exp(-pow((H_bar_apo - toRad(275.0)) / toRad(25.0), 2.0))) * R_C; - double res = (pow(delta_L_apo / (kL * sL), 2.0) + pow(delta_C_apo / (kC * sC), 2.0) + pow(delta_H_apo / (kH * sH), 2.0) + RT * (delta_C_apo / (kC * sC)) * (delta_H_apo / (kH * sH))); - return res > 0 ? sqrt(res) : 0; -} - -double deltaCIEDE2000(const Vec3d& lab1, const Vec3d& lab2) -{ - return deltaCIEDE2000_(lab1, lab2); -} - -double deltaCMC(const Vec3d& lab1, const Vec3d& lab2, const double& kL, const double& kC) -{ - double dL = lab2[0] - lab1[0]; - double da = lab2[1] - lab1[1]; - double db = lab2[2] - lab1[2]; - double C1 = sqrt(pow(lab1[1], 2.0) + pow(lab1[2], 2.0)); - double C2 = sqrt(pow(lab2[1], 2.0) + pow(lab2[2], 2.0)); - double dC = C2 - C1; - double dH = sqrt(pow(da, 2) + pow(db, 2) - pow(dC, 2)); - - double H1; - if (C1 == 0.) - { - H1 = 0.0; - } - else - { - H1 = atan2(lab1[2], lab1[1]); - if (H1 < 0.0) - H1 += 2. * CV_PI; - } - - double F = pow(C1, 2) / sqrt(pow(C1, 4) + 1900); - double T = (H1 > toRad(164) && H1 <= toRad(345)) - ? 0.56 + abs(0.2 * cos(H1 + toRad(168))) - : 0.36 + abs(0.4 * cos(H1 + toRad(35))); - double sL = lab1[0] < 16. ? 0.511 : (0.040975 * lab1[0]) / (1.0 + 0.01765 * lab1[0]); - double sC = (0.0638 * C1) / (1.0 + 0.0131 * C1) + 0.638; - double sH = sC * (F * T + 1.0 - F); - - return sqrt(pow(dL / (kL * sL), 2.0) + pow(dC / (kC * sC), 2.0) + pow(dH / sH, 2.0)); -} - -double deltaCMC1To1(const Vec3d& lab1, const Vec3d& lab2) -{ - return deltaCMC(lab1, lab2); -} - -double deltaCMC2To1(const Vec3d& lab1, const Vec3d& lab2) -{ - return deltaCMC(lab1, lab2, 2, 1); -} - -Mat distance(Mat src, Mat ref, DISTANCE_TYPE distance_type) -{ - switch (distance_type) - { - case cv::ccm::DISTANCE_CIE76: - return distanceWise(src, ref, deltaCIE76); - case cv::ccm::DISTANCE_CIE94_GRAPHIC_ARTS: - return distanceWise(src, ref, deltaCIE94GraphicArts); - case cv::ccm::DISTANCE_CIE94_TEXTILES: - return distanceWise(src, ref, deltaCIE94Textiles); - case cv::ccm::DISTANCE_CIE2000: - return distanceWise(src, ref, deltaCIEDE2000); - case cv::ccm::DISTANCE_CMC_1TO1: - return distanceWise(src, ref, deltaCMC1To1); - case cv::ccm::DISTANCE_CMC_2TO1: - return distanceWise(src, ref, deltaCMC2To1); - case cv::ccm::DISTANCE_RGB: - return distanceWise(src, ref, deltaCIE76); - case cv::ccm::DISTANCE_RGBL: - return distanceWise(src, ref, deltaCIE76); - default: - CV_Error(Error::StsBadArg, "Wrong distance_type!" ); - break; - } -}; - -} -} // namespace ccm \ No newline at end of file diff --git a/modules/mcc/src/distance.hpp b/modules/mcc/src/distance.hpp deleted file mode 100644 index 0fbc533778a..00000000000 --- a/modules/mcc/src/distance.hpp +++ /dev/null @@ -1,99 +0,0 @@ -// 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. -// -// -// License Agreement -// For Open Source Computer Vision Library -// -// Copyright(C) 2020, Huawei Technologies Co.,Ltd. All rights reserved. -// Third party copyrights are property of their respective owners. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// -// Author: Longbu Wang -// Jinheng Zhang -// Chenqi Shan - -#ifndef __OPENCV_CCM_DISTANCE_HPP__ -#define __OPENCV_CCM_DISTANCE_HPP__ - -#include "utils.hpp" -#include "opencv2/ccm.hpp" - -namespace cv { -namespace ccm { -/** possibale functions to calculate the distance between - colors.see https://en.wikipedia.org/wiki/Color_difference for details;*/ - -/** @brief distance between two points in formula CIE76 - @param lab1 a 3D vector - @param lab2 a 3D vector - @return distance between lab1 and lab2 -*/ - -double deltaCIE76(const Vec3d& lab1, const Vec3d& lab2); - -/** @brief distance between two points in formula CIE94 - @param lab1 a 3D vector - @param lab2 a 3D vector - @param kH Hue scale - @param kC Chroma scale - @param kL Lightness scale - @param k1 first scale parameter - @param k2 second scale parameter - @return distance between lab1 and lab2 -*/ - -double deltaCIE94(const Vec3d& lab1, const Vec3d& lab2, const double& kH = 1.0, - const double& kC = 1.0, const double& kL = 1.0, const double& k1 = 0.045, - const double& k2 = 0.015); - -double deltaCIE94GraphicArts(const Vec3d& lab1, const Vec3d& lab2); - -double toRad(const double& degree); - -double deltaCIE94Textiles(const Vec3d& lab1, const Vec3d& lab2); - -/** @brief distance between two points in formula CIE2000 - @param lab1 a 3D vector - @param lab2 a 3D vector - @param kL Lightness scale - @param kC Chroma scale - @param kH Hue scale - @return distance between lab1 and lab2 -*/ -double deltaCIEDE2000_(const Vec3d& lab1, const Vec3d& lab2, const double& kL = 1.0, - const double& kC = 1.0, const double& kH = 1.0); -double deltaCIEDE2000(const Vec3d& lab1, const Vec3d& lab2); - -/** @brief distance between two points in formula CMC - @param lab1 a 3D vector - @param lab2 a 3D vector - @param kL Lightness scale - @param kC Chroma scale - @return distance between lab1 and lab2 -*/ - -double deltaCMC(const Vec3d& lab1, const Vec3d& lab2, const double& kL = 1, const double& kC = 1); - -double deltaCMC1To1(const Vec3d& lab1, const Vec3d& lab2); - -double deltaCMC2To1(const Vec3d& lab1, const Vec3d& lab2); - -Mat distance(Mat src,Mat ref, DISTANCE_TYPE distance_type); - -} -} // namespace cv::ccm - -#endif \ No newline at end of file diff --git a/modules/mcc/src/io.cpp b/modules/mcc/src/io.cpp deleted file mode 100644 index c9c5c2026aa..00000000000 --- a/modules/mcc/src/io.cpp +++ /dev/null @@ -1,133 +0,0 @@ -// 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. -// -// -// License Agreement -// For Open Source Computer Vision Library -// -// Copyright(C) 2020, Huawei Technologies Co.,Ltd. All rights reserved. -// Third party copyrights are property of their respective owners. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// -// Author: Longbu Wang -// Jinheng Zhang -// Chenqi Shan - -#include "io.hpp" -namespace cv { -namespace ccm { -IO::IO(std::string illuminant_, std::string observer_) - : illuminant(illuminant_) - , observer(observer_) {}; - -bool IO::operator<(const IO& other) const -{ - return (illuminant < other.illuminant || ((illuminant == other.illuminant) && (observer < other.observer))); -} - -bool IO::operator==(const IO& other) const -{ - return illuminant == other.illuminant && observer == other.observer; -}; - -IO IO::getIOs(IO_TYPE io) -{ - switch (io) - { - case cv::ccm::A_2: - { - IO A_2_IO("A", "2"); - return A_2_IO; - break; - } - case cv::ccm::A_10: - { - IO A_1O_IO("A", "10"); - return A_1O_IO; - break; - } - case cv::ccm::D50_2: - { - IO D50_2_IO("D50", "2"); - return D50_2_IO; - break; - } - case cv::ccm::D50_10: - { - IO D50_10_IO("D50", "10"); - return D50_10_IO; - break; - } - case cv::ccm::D55_2: - { - IO D55_2_IO("D55", "2"); - return D55_2_IO; - break; - } - case cv::ccm::D55_10: - { - IO D55_10_IO("D55", "10"); - return D55_10_IO; - break; - } - case cv::ccm::D65_2: - { - IO D65_2_IO("D65", "2"); - return D65_2_IO; - } - case cv::ccm::D65_10: - { - IO D65_10_IO("D65", "10"); - return D65_10_IO; - break; - } - case cv::ccm::D75_2: - { - IO D75_2_IO("D75", "2"); - return D75_2_IO; - break; - } - case cv::ccm::D75_10: - { - IO D75_10_IO("D75", "10"); - return D75_10_IO; - break; - } - case cv::ccm::E_2: - { - IO E_2_IO("E", "2"); - return E_2_IO; - break; - } - case cv::ccm::E_10: - { - IO E_10_IO("E", "10"); - return E_10_IO; - break; - } - default: - return IO(); - break; - } -} -// data from https://en.wikipedia.org/wiki/Standard_illuminant. -std::vector xyY2XYZ(const std::vector& xyY) -{ - double Y = xyY.size() >= 3 ? xyY[2] : 1; - return { Y * xyY[0] / xyY[1], Y, Y / xyY[1] * (1 - xyY[0] - xyY[1]) }; -} - -} -} // namespace cv::ccm diff --git a/modules/mcc/src/io.hpp b/modules/mcc/src/io.hpp deleted file mode 100644 index 4fa9dce4665..00000000000 --- a/modules/mcc/src/io.hpp +++ /dev/null @@ -1,72 +0,0 @@ -// 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. -// -// -// License Agreement -// For Open Source Computer Vision Library -// -// Copyright(C) 2020, Huawei Technologies Co.,Ltd. All rights reserved. -// Third party copyrights are property of their respective owners. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// -// Author: Longbu Wang -// Jinheng Zhang -// Chenqi Shan - -#ifndef __OPENCV_CCM_IO_HPP__ -#define __OPENCV_CCM_IO_HPP__ - -#include -#include - -namespace cv { -namespace ccm { - -enum IO_TYPE -{ - A_2, - A_10, - D50_2, - D50_10, - D55_2, - D55_10, - D65_2, - D65_10, - D75_2, - D75_10, - E_2, - E_10 -}; - -/** @brief Io is the meaning of illuminant and observer. See notes of ccm.hpp - for supported list for illuminant and observer*/ -class IO -{ -public: - std::string illuminant; - std::string observer; - IO() {}; - IO(std::string illuminant, std::string observer); - virtual ~IO() {}; - bool operator<(const IO& other) const; - bool operator==(const IO& other) const; - static IO getIOs(IO_TYPE io); -}; -std::vector xyY2XYZ(const std::vector& xyY); - -} -} // namespace cv::ccm - -#endif \ No newline at end of file diff --git a/modules/mcc/src/linearize.cpp b/modules/mcc/src/linearize.cpp deleted file mode 100644 index 3a48a560eb8..00000000000 --- a/modules/mcc/src/linearize.cpp +++ /dev/null @@ -1,130 +0,0 @@ -// 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. -// -// -// License Agreement -// For Open Source Computer Vision Library -// -// Copyright(C) 2020, Huawei Technologies Co.,Ltd. All rights reserved. -// Third party copyrights are property of their respective owners. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// -// Author: Longbu Wang -// Jinheng Zhang -// Chenqi Shan - -#include "linearize.hpp" - -namespace cv { -namespace ccm { - -Polyfit::Polyfit(Mat x, Mat y, int deg_) - : deg(deg_) -{ - int n = x.cols * x.rows * x.channels(); - x = x.reshape(1, n); - y = y.reshape(1, n); - Mat_ A = Mat_::ones(n, deg + 1); - for (int i = 0; i < n; ++i) - { - for (int j = 1; j < A.cols; ++j) - { - A.at(i, j) = x.at(i) * A.at(i, j - 1); - } - } - Mat y_(y); - cv::solve(A, y_, p, DECOMP_SVD); -} - -Mat Polyfit::operator()(const Mat& inp) -{ - return elementWise(inp, [this](double x) -> double { return fromEW(x); }); -}; - -double Polyfit::fromEW(double x) -{ - double res = 0; - for (int d = 0; d <= deg; ++d) - { - res += pow(x, d) * p.at(d, 0); - } - return res; -}; - -LogPolyfit::LogPolyfit(Mat x, Mat y, int deg_) - : deg(deg_) -{ - Mat mask_ = (x > 0) & (y > 0); - Mat src_, dst_, s_, d_; - src_ = maskCopyTo(x, mask_); - dst_ = maskCopyTo(y, mask_); - log(src_, s_); - log(dst_, d_); - p = Polyfit(s_, d_, deg); -} - -Mat LogPolyfit::operator()(const Mat& inp) -{ - Mat mask_ = inp >= 0; - Mat y, y_, res; - log(inp, y); - y = p(y); - exp(y, y_); - y_.copyTo(res, mask_); - return res; -}; - -Mat Linear::linearize(Mat inp) -{ - return inp; -}; - -Mat LinearGamma::linearize(Mat inp) -{ - return gammaCorrection(inp, gamma); -}; - -std::shared_ptr getLinear(double gamma, int deg, Mat src, Color dst, Mat mask, RGBBase_ cs, LINEAR_TYPE linear_type) -{ - std::shared_ptr p = std::make_shared(); - switch (linear_type) - { - case cv::ccm::LINEARIZATION_IDENTITY: - p.reset(new LinearIdentity()); - break; - case cv::ccm::LINEARIZATION_GAMMA: - p.reset(new LinearGamma(gamma)); - break; - case cv::ccm::LINEARIZATION_COLORPOLYFIT: - p.reset(new LinearColor(deg, src, dst, mask, cs)); - break; - case cv::ccm::LINEARIZATION_COLORLOGPOLYFIT: - p.reset(new LinearColor(deg, src, dst, mask, cs)); - break; - case cv::ccm::LINEARIZATION_GRAYPOLYFIT: - p.reset(new LinearGray(deg, src, dst, mask, cs)); - break; - case cv::ccm::LINEARIZATION_GRAYLOGPOLYFIT: - p.reset(new LinearGray(deg, src, dst, mask, cs)); - break; - default: - CV_Error(Error::StsBadArg, "Wrong linear_type!" ); - break; - } - return p; -}; - -} -} // namespace cv::ccm \ No newline at end of file diff --git a/modules/mcc/src/linearize.hpp b/modules/mcc/src/linearize.hpp deleted file mode 100644 index 7f5d516dce5..00000000000 --- a/modules/mcc/src/linearize.hpp +++ /dev/null @@ -1,209 +0,0 @@ -// 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. -// -// -// License Agreement -// For Open Source Computer Vision Library -// -// Copyright(C) 2020, Huawei Technologies Co.,Ltd. All rights reserved. -// Third party copyrights are property of their respective owners. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// -// Author: Longbu Wang -// Jinheng Zhang -// Chenqi Shan - -#ifndef __OPENCV_CCM_LINEARIZE_HPP__ -#define __OPENCV_CCM_LINEARIZE_HPP__ - -#include -#include -#include "color.hpp" -#include "opencv2/ccm.hpp" -namespace cv { -namespace ccm { - -/** @brief Polyfit model. -*/ -class Polyfit -{ -public: - int deg; - Mat p; - Polyfit() {}; - - /** @brief Polyfit method. - https://en.wikipedia.org/wiki/Polynomial_regression - polynomial: yi = a0 + a1*xi + a2*xi^2 + ... + an*xi^deg (i = 1,2,...,n) - and deduct: Ax = y - */ - Polyfit(Mat x, Mat y, int deg); - virtual ~Polyfit() {}; - Mat operator()(const Mat& inp); - -private: - double fromEW(double x); -}; - -/** @brief Logpolyfit model. -*/ -class LogPolyfit - -{ -public: - int deg; - Polyfit p; - - LogPolyfit() {}; - - /** @brief Logpolyfit method. - */ - LogPolyfit(Mat x, Mat y, int deg); - virtual ~LogPolyfit() {}; - Mat operator()(const Mat& inp); -}; - -/** @brief Linearization base. -*/ - -class Linear -{ -public: - Linear() {}; - virtual ~Linear() {}; - - /** @brief Inference. - @param inp the input array, type of cv::Mat. - */ - virtual Mat linearize(Mat inp); - /* *\brief Evaluate linearization model. - */ - virtual void value(void) {}; -}; - -/** @brief Linearization identity. - make no change. -*/ -class LinearIdentity : public Linear -{}; - -/** @brief Linearization gamma correction. -*/ -class LinearGamma : public Linear -{ -public: - double gamma; - - LinearGamma(double gamma_) - : gamma(gamma_) {}; - - Mat linearize(Mat inp) CV_OVERRIDE; -}; - -/** @brief Linearization. - Grayscale polynomial fitting. -*/ -template -class LinearGray : public Linear -{ -public: - int deg; - T p; - LinearGray(int deg_, Mat src, Color dst, Mat mask, RGBBase_ cs) - : deg(deg_) - { - dst.getGray(); - Mat lear_gray_mask = mask & dst.grays; - - // the grayscale function is approximate for src is in relative color space. - src = rgb2gray(maskCopyTo(src, lear_gray_mask)); - Mat dst_ = maskCopyTo(dst.toGray(cs.io), lear_gray_mask); - calc(src, dst_); - } - - /** @brief monotonically increase is not guaranteed. - @param src the input array, type of cv::Mat. - @param dst the input array, type of cv::Mat. - */ - void calc(const Mat& src, const Mat& dst) - { - p = T(src, dst, deg); - }; - - Mat linearize(Mat inp) CV_OVERRIDE - { - return p(inp); - }; -}; - -/** @brief Linearization. - Fitting channels respectively. -*/ -template -class LinearColor : public Linear -{ -public: - int deg; - T pr; - T pg; - T pb; - - LinearColor(int deg_, Mat src_, Color dst, Mat mask, RGBBase_ cs) - : deg(deg_) - { - Mat src = maskCopyTo(src_, mask); - Mat dst_ = maskCopyTo(dst.to(*cs.l).colors, mask); - calc(src, dst_); - } - - void calc(const Mat& src, const Mat& dst) - { - Mat schannels[3]; - Mat dchannels[3]; - split(src, schannels); - split(dst, dchannels); - pr = T(schannels[0], dchannels[0], deg); - pg = T(schannels[1], dchannels[1], deg); - pb = T(schannels[2], dchannels[2], deg); - }; - - Mat linearize(Mat inp) CV_OVERRIDE - { - Mat channels[3]; - split(inp, channels); - std::vector channel; - Mat res; - merge(std::vector { pr(channels[0]), pg(channels[1]), pb(channels[2]) }, res); - return res; - }; -}; - -/** @brief Get linearization method. - used in ccm model. - @param gamma used in LinearGamma. - @param deg degrees. - @param src the input array, type of cv::Mat. - @param dst the input array, type of cv::Mat. - @param mask the input array, type of cv::Mat. - @param cs type of RGBBase_. - @param linear_type type of linear. -*/ - -std::shared_ptr getLinear(double gamma, int deg, Mat src, Color dst, Mat mask, RGBBase_ cs, LINEAR_TYPE linear_type); - -} -} // namespace cv::ccm - -#endif diff --git a/modules/mcc/src/operations.cpp b/modules/mcc/src/operations.cpp deleted file mode 100644 index e4e76a2a270..00000000000 --- a/modules/mcc/src/operations.cpp +++ /dev/null @@ -1,90 +0,0 @@ -// 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. -// -// -// License Agreement -// For Open Source Computer Vision Library -// -// Copyright(C) 2020, Huawei Technologies Co.,Ltd. All rights reserved. -// Third party copyrights are property of their respective owners. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// -// Author: Longbu Wang -// Jinheng Zhang -// Chenqi Shan - -#include "operations.hpp" -#include "utils.hpp" -namespace cv { -namespace ccm { - -Mat Operation::operator()(Mat& abc) -{ - if (!linear) - { - return f(abc); - } - if (M.empty()) - { - return abc; - } - return multiple(abc, M); -}; - -void Operation::add(const Operation& other) -{ - if (M.empty()) - { - M = other.M.clone(); - } - else - { - M = M * other.M; - } -}; - -void Operation::clear() -{ - M = Mat(); -}; - -Operations& Operations::add(const Operations& other) -{ - ops.insert(ops.end(), other.ops.begin(), other.ops.end()); - return *this; -}; - -Mat Operations::run(Mat abc) -{ - Operation hd; - for (auto& op : ops) - { - if (op.linear) - { - hd.add(op); - } - else - { - abc = hd(abc); - hd.clear(); - abc = op(abc); - } - } - abc = hd(abc); - return abc; -}; - -} -} // namespace cv::ccm \ No newline at end of file diff --git a/modules/mcc/src/operations.hpp b/modules/mcc/src/operations.hpp deleted file mode 100644 index 994c4b1c39a..00000000000 --- a/modules/mcc/src/operations.hpp +++ /dev/null @@ -1,102 +0,0 @@ -// 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. -// -// -// License Agreement -// For Open Source Computer Vision Library -// -// Copyright(C) 2020, Huawei Technologies Co.,Ltd. All rights reserved. -// Third party copyrights are property of their respective owners. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// -// Author: Longbu Wang -// Jinheng Zhang -// Chenqi Shan - -#ifndef __OPENCV_CCM_OPERATIONS_HPP__ -#define __OPENCV_CCM_OPERATIONS_HPP__ - -#include "utils.hpp" - -namespace cv { -namespace ccm { - -/** @brief Operation class contains some operarions used for color space - conversion containing linear transformation and non-linear transformation - */ -class Operation -{ -public: - typedef std::function MatFunc; - bool linear; - Mat M; - MatFunc f; - - Operation() - : linear(true) - , M(Mat()) {}; - Operation(Mat M_) - : linear(true) - , M(M_) {}; - Operation(MatFunc f_) - : linear(false) - , f(f_) {}; - virtual ~Operation() {}; - - /** @brief operator function will run operation - */ - Mat operator()(Mat& abc); - - /** @brief add function will conbine this operation - with other linear transformation operation - */ - void add(const Operation& other); - - void clear(); - static Operation& get_IDENTITY_OP() - { - static Operation identity_op([](Mat x) { return x; }); - return identity_op; - } -}; - -class Operations -{ -public: - std::vector ops; - Operations() - : ops {} {}; - Operations(std::initializer_list op) - : ops { op } {}; - virtual ~Operations() {}; - - /** @brief add function will conbine this operation with other transformation operations - */ - Operations& add(const Operations& other); - - /** @brief run operations to make color conversion - */ - Mat run(Mat abc); - static const Operations& get_IDENTITY_OPS() - { - static Operations Operation_op {Operation::get_IDENTITY_OP()}; - return Operation_op; - } -}; - -} -} // namespace cv::ccm - -#endif \ No newline at end of file diff --git a/modules/mcc/src/precomp.hpp b/modules/mcc/src/precomp.hpp deleted file mode 100644 index 3cbd7bfd5e6..00000000000 --- a/modules/mcc/src/precomp.hpp +++ /dev/null @@ -1,44 +0,0 @@ -// 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. - -/* - * MIT License - * - * Copyright (c) 2018 Pedro Diamel Marrero Fernández - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#ifndef _CCM_PRECOMP_HPP -#define _CCM_PRECOMP_HPP - -#include - -#include -#include -#include -#include - -#include -#include - -#include "opencv2/ccm.hpp" - -#endif //_CCM_PRECOMP_HPP diff --git a/modules/mcc/src/utils.cpp b/modules/mcc/src/utils.cpp deleted file mode 100644 index ceac095a5ab..00000000000 --- a/modules/mcc/src/utils.cpp +++ /dev/null @@ -1,119 +0,0 @@ -// 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. -// -// -// License Agreement -// For Open Source Computer Vision Library -// -// Copyright(C) 2020, Huawei Technologies Co.,Ltd. All rights reserved. -// Third party copyrights are property of their respective owners. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// -// Author: Longbu Wang -// Jinheng Zhang -// Chenqi Shan - -#include "utils.hpp" - -namespace cv { -namespace ccm { - -inline double gammaCorrection_(const double& element, const double& gamma) -{ - return (element >= 0 ? pow(element, gamma) : -pow((-element), gamma)); -} - -Mat gammaCorrection(const Mat& src, const double& gamma, Mat dst) -{ - return elementWise(src, [gamma](double element) -> double { return gammaCorrection_(element, gamma); }, dst); -} - -Mat maskCopyTo(const Mat& src, const Mat& mask) -{ - Mat dst(countNonZero(mask), 1, src.type()); - const int channel = src.channels(); - auto it_mask = mask.begin(); - switch (channel) - { - case 1: - { - auto it_src = src.begin(), end_src = src.end(); - auto it_dst = dst.begin(); - for (; it_src != end_src; ++it_src, ++it_mask) - { - if (*it_mask) - { - (*it_dst) = (*it_src); - ++it_dst; - } - } - break; - } - case 3: - { - auto it_src = src.begin(), end_src = src.end(); - auto it_dst = dst.begin(); - for (; it_src != end_src; ++it_src, ++it_mask) - { - if (*it_mask) - { - (*it_dst) = (*it_src); - ++it_dst; - } - } - break; - } - default: - CV_Error(Error::StsBadArg, "Wrong channel!" ); - break; - } - return dst; -} - -Mat multiple(const Mat& xyz, const Mat& ccm) -{ - Mat tmp = xyz.reshape(1, xyz.rows * xyz.cols); - Mat res = tmp * ccm; - res = res.reshape(res.cols, xyz.rows); - return res; -} - -Mat saturate(Mat& src, const double& low, const double& up) -{ - Mat dst = Mat::ones(src.size(), CV_8UC1); - MatIterator_ it_src = src.begin(), end_src = src.end(); - MatIterator_ it_dst = dst.begin(); - for (; it_src != end_src; ++it_src, ++it_dst) - { - for (int i = 0; i < 3; ++i) - { - if ((*it_src)[i] > up || (*it_src)[i] < low) - { - *it_dst = 0; - break; - } - } - } - return dst; -} - -Mat rgb2gray(const Mat& rgb) -{ - const Matx31d m_gray(0.2126, 0.7152, 0.0722); - return multiple(rgb, Mat(m_gray)); -} - -} -} // namespace cv::ccm diff --git a/modules/mcc/src/utils.hpp b/modules/mcc/src/utils.hpp deleted file mode 100644 index c7823c8b721..00000000000 --- a/modules/mcc/src/utils.hpp +++ /dev/null @@ -1,172 +0,0 @@ -// 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. -// -// -// License Agreement -// For Open Source Computer Vision Library -// -// Copyright(C) 2020, Huawei Technologies Co.,Ltd. All rights reserved. -// Third party copyrights are property of their respective owners. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// -// Author: Longbu Wang -// Jinheng Zhang -// Chenqi Shan - -#ifndef __OPENCV_CCM_UTILS_HPP__ -#define __OPENCV_CCM_UTILS_HPP__ - -#include - -namespace cv { -namespace ccm { - -double gammaCorrection_(const double& element, const double& gamma); - -/** @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. - @param dst the output array, type of Mat. - */ -Mat gammaCorrection(const Mat& src, const double& gamma, Mat dst=Mat()); - -/** @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, const double& low, const double& up); - -/** @brief rgb2gray it is an approximation grayscale function for relative RGB - color space - @param rgb the input array,type of Mat. - */ -Mat rgb2gray(const Mat& rgb); - -/** @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 \ No newline at end of file diff --git a/modules/mcc/test/test_ccm.cpp b/modules/mcc/test/test_ccm.cpp deleted file mode 100644 index 71bd5b7c528..00000000000 --- a/modules/mcc/test/test_ccm.cpp +++ /dev/null @@ -1,227 +0,0 @@ -// 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. - -#include "test_precomp.hpp" - -namespace opencv_test -{ -namespace -{ - -Mat s = (Mat_(24, 1) << - Vec3d(214.11, 98.67, 37.97), - Vec3d(231.94, 153.1, 85.27), - Vec3d(204.08, 143.71, 78.46), - Vec3d(190.58, 122.99, 30.84), - Vec3d(230.93, 148.46, 100.84), - Vec3d(228.64, 206.97, 97.5), - Vec3d(229.09, 137.07, 55.29), - Vec3d(189.21, 111.22, 92.66), - Vec3d(223.5, 96.42, 75.45), - Vec3d(201.82, 69.71, 50.9), - Vec3d(240.52, 196.47, 59.3), - Vec3d(235.73, 172.13, 54.), - Vec3d(131.6, 75.04, 68.86), - Vec3d(189.04, 170.43, 42.05), - Vec3d(222.23, 74., 71.95), - Vec3d(241.01, 199.1, 61.15), - Vec3d(224.99, 101.4, 100.24), - Vec3d(174.58, 152.63, 91.52), - Vec3d(248.06, 227.69, 140.5), - Vec3d(241.15, 201.38, 115.58), - Vec3d(236.49, 175.87, 88.86), - Vec3d(212.19, 133.49, 54.79), - Vec3d(181.17, 102.94, 36.18), - Vec3d(115.1, 53.77, 15.23)); - -TEST(CV_ccmRunColorCorrection, test_model) -{ - - ColorCorrectionModel model(s / 255, COLORCHECKER_Macbeth); - model.run(); - Mat src_rgbl = (Mat_(24, 1) << - Vec3d(0.68078957, 0.12382801, 0.01514889), - Vec3d(0.81177942, 0.32550452, 0.089818), - Vec3d(0.61259378, 0.2831933, 0.07478902), - Vec3d(0.52696493, 0.20105976, 0.00958657), - Vec3d(0.80402284, 0.30419523, 0.12989841), - Vec3d(0.78658646, 0.63184111, 0.12062068), - Vec3d(0.78999637, 0.25520249, 0.03462853), - Vec3d(0.51866697, 0.16114393, 0.1078387), - Vec3d(0.74820768, 0.11770076, 0.06862177), - Vec3d(0.59776825, 0.05765816, 0.02886627), - Vec3d(0.8793145, 0.56346033, 0.0403954), - Vec3d(0.84124847, 0.42120746, 0.03287592), - Vec3d(0.23333214, 0.06780408, 0.05612276), - Vec3d(0.5176423, 0.41210976, 0.01896255), - Vec3d(0.73888613, 0.06575388, 0.06181293), - Vec3d(0.88326036, 0.58018751, 0.04321991), - Vec3d(0.75922531, 0.13149072, 0.1282041), - Vec3d(0.4345097, 0.32331019, 0.10494139), - Vec3d(0.94110142, 0.77941419, 0.26946323), - Vec3d(0.88438952, 0.5949049 , 0.17536928), - Vec3d(0.84722687, 0.44160449, 0.09834799), - Vec3d(0.66743106, 0.24076803, 0.03394333), - Vec3d(0.47141286, 0.13592419, 0.01362205), - Vec3d(0.17377101, 0.03256864, 0.00203026)); - ASSERT_MAT_NEAR(src_rgbl, model.get_src_rgbl(), 1e-4); - - Mat dst_rgbl = (Mat_(24, 1) << - Vec3d(0.17303173, 0.08211037, 0.05672686), - Vec3d(0.56832031, 0.29269488, 0.21835529), - Vec3d(0.10365019, 0.19588357, 0.33140475), - Vec3d(0.10159676, 0.14892193, 0.05188294), - Vec3d(0.22159627, 0.21584476, 0.43461196), - Vec3d(0.10806379, 0.51437196, 0.41264213), - Vec3d(0.74736423, 0.20062878, 0.02807988), - Vec3d(0.05757947, 0.10516793, 0.40296109), - Vec3d(0.56676218, 0.08424805, 0.11969461), - Vec3d(0.11099515, 0.04230796, 0.14292554), - Vec3d(0.34546869, 0.50872001, 0.04944204), - Vec3d(0.79461323, 0.35942459, 0.02051968), - Vec3d(0.01710416, 0.05022043, 0.29220674), - Vec3d(0.05598012, 0.30021149, 0.06871162), - Vec3d(0.45585457, 0.03033727, 0.04085654), - Vec3d(0.85737614, 0.56757335, 0.0068503), - Vec3d(0.53348585, 0.08861148, 0.30750446), - Vec3d(-0.0374061, 0.24699498, 0.40041217), - Vec3d(0.91262695, 0.91493909, 0.89367049), - Vec3d(0.57981916, 0.59200418, 0.59328881), - Vec3d(0.35490581, 0.36544831, 0.36755375), - Vec3d(0.19007357, 0.19186587, 0.19308397), - Vec3d(0.08529188, 0.08887994, 0.09257601), - Vec3d(0.0303193, 0.03113818, 0.03274845)); - ASSERT_MAT_NEAR(dst_rgbl, model.get_dst_rgbl(), 1e-4); - - Mat mask = Mat::ones(24, 1, CV_8U); - ASSERT_MAT_NEAR(model.getMask(), mask, 0.0); - - - Mat ccm = (Mat_(3, 3) << - 0.37406520, 0.02066507, 0.05804047, - 0.12719672, 0.77389268, -0.01569404, - -0.27627010, 0.00603427, 2.74272981); - ASSERT_MAT_NEAR(model.getCCM(), ccm, 1e-4); -} -TEST(CV_ccmRunColorCorrection, test_masks_weights_1) -{ - Mat weights_list_ = (Mat_(24, 1) << - 1.1, 0, 0, 1.2, 0, 0, - 1.3, 0, 0, 1.4, 0, 0, - 0.5, 0, 0, 0.6, 0, 0, - 0.7, 0, 0, 0.8, 0, 0); - ColorCorrectionModel model1(s / 255,COLORCHECKER_Macbeth); - model1.setColorSpace(COLOR_SPACE_sRGB); - model1.setCCM_TYPE(CCM_3x3); - model1.setDistance(DISTANCE_CIE2000); - model1.setLinear(LINEARIZATION_GAMMA); - model1.setLinearGamma(2.2); - model1.setLinearDegree(3); - model1.setSaturatedThreshold(0, 0.98); - model1.setWeightsList(weights_list_); - model1.setWeightCoeff(1.5); - model1.run(); - Mat weights = (Mat_(8, 1) << - 1.15789474, 1.26315789, 1.36842105, 1.47368421, - 0.52631579, 0.63157895, 0.73684211, 0.84210526); - ASSERT_MAT_NEAR(model1.getWeights(), weights, 1e-4); - - Mat mask = (Mat_(24, 1) << - true, false, false, true, false, false, - true, false, false, true, false, false, - true, false, false, true, false, false, - true, false, false, true, false, false); - ASSERT_MAT_NEAR(model1.getMask(), mask, 0.0); -} - -TEST(CV_ccmRunColorCorrection, test_masks_weights_2) -{ - ColorCorrectionModel model2(s / 255, COLORCHECKER_Macbeth); - model2.setCCM_TYPE(CCM_3x3); - model2.setDistance(DISTANCE_CIE2000); - model2.setLinear(LINEARIZATION_GAMMA); - model2.setLinearGamma(2.2); - model2.setLinearDegree(3); - model2.setSaturatedThreshold(0.05, 0.93); - model2.setWeightsList(Mat()); - model2.setWeightCoeff(1.5); - model2.run(); - Mat weights = (Mat_(20, 1) << - 0.65554256, 1.49454705, 1.00499244, 0.79735434, 1.16327759, - 1.68623868, 1.37973155, 0.73213388, 1.0169629, 0.47430246, - 1.70312161, 0.45414218, 1.15910007, 0.7540434, 1.05049802, - 1.04551645, 1.54082353, 1.02453421, 0.6015915, 0.26154558); - ASSERT_MAT_NEAR(model2.getWeights(), weights, 1e-4); - - Mat mask = (Mat_(24, 1) << - true, true, true, true, true, true, - true, true, true, true, false, true, - true, true, true, false, true, true, - false, false, true, true, true, true); - ASSERT_MAT_NEAR(model2.getMask(), mask, 0.0); -} - -TEST(CV_mcc_ccm_test, compute_ccm) -{ - // read gold chartsRGB - string path = cvtest::findDataFile("mcc/mcc_ccm_test.yml"); - FileStorage fs(path, FileStorage::READ); - Mat chartsRGB; - FileNode node = fs["chartsRGB"]; - node >> chartsRGB; - - // compute CCM - ColorCorrectionModel model(chartsRGB.col(1).clone().reshape(3, chartsRGB.rows/3) / 255., COLORCHECKER_Macbeth); - model.run(); - - // read gold CCM - node = fs["ccm"]; - ASSERT_FALSE(node.empty()); - Mat gold_ccm; - node >> gold_ccm; - fs.release(); - - // check CCM - Mat ccm = model.getCCM(); - EXPECT_MAT_NEAR(gold_ccm, ccm, 1e-8); - - const double gold_loss = 4.6386569120323129; - // check loss - const double loss = model.getLoss(); - EXPECT_NEAR(gold_loss, loss, 1e-8); -} - -TEST(CV_mcc_ccm_test, infer) -{ - string path = cvtest::findDataFile("mcc/mcc_ccm_test.jpg"); - Mat img = imread(path, IMREAD_COLOR); - // read gold calibrate img - path = cvtest::findDataFile("mcc/mcc_ccm_test_res.png"); - Mat gold_img = imread(path); - - // read gold chartsRGB - path = cvtest::findDataFile("mcc/mcc_ccm_test.yml"); - FileStorage fs(path, FileStorage::READ); - Mat chartsRGB; - FileNode node = fs["chartsRGB"]; - node >> chartsRGB; - fs.release(); - - // compute CCM - ColorCorrectionModel model(chartsRGB.col(1).clone().reshape(3, chartsRGB.rows/3) / 255., COLORCHECKER_Macbeth); - model.run(); - - // compute calibrate image - Mat calibratedImage; - cvtColor(img, calibratedImage, COLOR_BGR2RGB); - calibratedImage.convertTo(calibratedImage, CV_64F, 1. / 255.); - calibratedImage = model.infer(calibratedImage); - calibratedImage.convertTo(calibratedImage, CV_8UC3, 255.); - cvtColor(calibratedImage, calibratedImage, COLOR_RGB2BGR); - // check calibrated image - EXPECT_MAT_NEAR(gold_img, calibratedImage, 0.1); -} - -} // namespace -} // namespace opencv_test diff --git a/modules/mcc/test/test_main.cpp b/modules/mcc/test/test_main.cpp deleted file mode 100644 index 556b026ac58..00000000000 --- a/modules/mcc/test/test_main.cpp +++ /dev/null @@ -1,7 +0,0 @@ -// 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. - -#include "test_precomp.hpp" - -CV_TEST_MAIN("cv") diff --git a/modules/mcc/test/test_precomp.hpp b/modules/mcc/test/test_precomp.hpp deleted file mode 100644 index b6be71df3fd..00000000000 --- a/modules/mcc/test/test_precomp.hpp +++ /dev/null @@ -1,17 +0,0 @@ -// 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. - -#ifndef __OPENCV_TEST_PRECOMP_HPP__ -#define __OPENCV_TEST_PRECOMP_HPP__ - -#include "opencv2/ts.hpp" -#include "opencv2/ts/cuda_test.hpp" -#include "opencv2/ccm.hpp" - -namespace opencv_test -{ -using namespace cv::ccm; -} - -#endif diff --git a/modules/mcc/tutorials/basic_ccm/color_correction_model.markdown b/modules/mcc/tutorials/basic_ccm/color_correction_model.markdown deleted file mode 100644 index f1f2687a0b0..00000000000 --- a/modules/mcc/tutorials/basic_ccm/color_correction_model.markdown +++ /dev/null @@ -1,116 +0,0 @@ -Color Correction Model{#tutorial_ccm_color_correction_model} -=========================== - -In this tutorial you will learn how to use the 'Color Correction Model' to do a color correction in a image. - -Reference ----- - -See details of ColorCorrection Algorithm at https://github.com/riskiest/color_calibration/tree/v4/doc/pdf/English/Algorithm - -Building ----- - -When building OpenCV, run the following command to build all the contrib modules: - -```make -cmake -D OPENCV_EXTRA_MODULES_PATH=/modules/ -``` - -Or only build the ccm module: - -```make -cmake -D OPENCV_EXTRA_MODULES_PATH=/modules/ccm -``` - -Or make sure you check the ccm module in the GUI version of CMake: cmake-gui. - -Source Code of the sample ------------ - -The sample has two parts of code, the first is the color checker detector model, see details at @ref tutorial_macbeth_chart_detection, the second part is to make collor calibration. - -``` -Here are the parameters for ColorCorrectionModel - src : - detected colors of ColorChecker patches; - NOTICE: the color type is RGB not BGR, and the color values are in [0, 1]; - constcolor : - the Built-in color card; - Supported list: - Macbeth: Macbeth ColorChecker ; - Vinyl: DKK ColorChecker ; - DigitalSG: DigitalSG ColorChecker with 140 squares; - Mat colors : - the reference color values - and corresponding color space - NOTICE: the color values are in [0, 1] - ref_cs : - the corresponding color space - If the color type is some RGB, the format is RGB not BGR; - Supported Color Space: - Supported list of RGB color spaces: - COLOR_SPACE_sRGB; - COLOR_SPACE_AdobeRGB; - COLOR_SPACE_WideGamutRGB; - COLOR_SPACE_ProPhotoRGB; - COLOR_SPACE_DCI_P3_RGB; - COLOR_SPACE_AppleRGB; - COLOR_SPACE_REC_709_RGB; - COLOR_SPACE_REC_2020_RGB; - Supported list of linear RGB color spaces: - COLOR_SPACE_sRGBL; - COLOR_SPACE_AdobeRGBL; - COLOR_SPACE_WideGamutRGBL; - COLOR_SPACE_ProPhotoRGBL; - COLOR_SPACE_DCI_P3_RGBL; - COLOR_SPACE_AppleRGBL; - COLOR_SPACE_REC_709_RGBL; - COLOR_SPACE_REC_2020_RGBL; - Supported list of non-RGB color spaces: - COLOR_SPACE_Lab_D50_2; - COLOR_SPACE_Lab_D65_2; - COLOR_SPACE_XYZ_D50_2; - COLOR_SPACE_XYZ_D65_2; - COLOR_SPACE_XYZ_D65_10; - COLOR_SPACE_XYZ_D50_10; - COLOR_SPACE_XYZ_A_2; - COLOR_SPACE_XYZ_A_10; - COLOR_SPACE_XYZ_D55_2; - COLOR_SPACE_XYZ_D55_10; - COLOR_SPACE_XYZ_D75_2; - COLOR_SPACE_XYZ_D75_10; - COLOR_SPACE_XYZ_E_2; - COLOR_SPACE_XYZ_E_10; - COLOR_SPACE_Lab_D65_10; - COLOR_SPACE_Lab_D50_10; - COLOR_SPACE_Lab_A_2; - COLOR_SPACE_Lab_A_10; - COLOR_SPACE_Lab_D55_2; - COLOR_SPACE_Lab_D55_10; - COLOR_SPACE_Lab_D75_2; - COLOR_SPACE_Lab_D75_10; - COLOR_SPACE_Lab_E_2; - COLOR_SPACE_Lab_E_10; -``` - - -## Code - -@snippet samples/color_correction_model.cpp tutorial - -## Explanation - -The first part is to detect the ColorChecker position which can be done with the help of MCC module. - -@snippet samples/color_correction_model.cpp get_ccm_Matrix -For every ColorChecker, we can compute a ccm matrix for color correction. Model1 is an object of ColorCorrectionModel class. The parameters should be changed to get the best effect of color correction. See other parameters' detail at the Parameters. - -@snippet samples/color_correction_model.cpp reference_color_values -If you use a customized ColorChecker, you can use your own reference color values and corresponding color space as shown above. - -@snippet samples/color_correction_model.cpp make_color_correction -The member function infer_image is to make correction correction using ccm matrix. - -@snippet samples/color_correction_model.cpp Save_calibrated_image -Save the calibrated image. diff --git a/modules/mcc/tutorials/table_of_content_ccm.markdown b/modules/mcc/tutorials/table_of_content_ccm.markdown deleted file mode 100644 index 178f309b993..00000000000 --- a/modules/mcc/tutorials/table_of_content_ccm.markdown +++ /dev/null @@ -1,8 +0,0 @@ -Color Correction Model {#tutorial_table_of_content_ccm} -=========================== - -- @subpage tutorial_ccm_color_correction_model - - *Author:* riskiest, shanchenqi, JinhengZhang - - How to do color correction, using Color Correction Model. \ No newline at end of file