File indexing completed on 2025-01-19 03:57:41
0001 /* ============================================================ 0002 * 0003 * This file is a part of digiKam 0004 * 0005 * Date : 2012-01-03 0006 * Description : Calculates the TanTriggs Preprocessing as described in: 0007 * Tan, X., and Triggs, B. "Enhanced local texture feature sets for face 0008 * recognition under difficult lighting conditions.". IEEE Transactions 0009 * on Image Processing 19 (2010), 1635–650. 0010 * Default parameters are taken from the paper. 0011 * 0012 * SPDX-FileCopyrightText: 2012-2013 by Marcel Wiesweg <marcel dot wiesweg at gmx dot de> 0013 * SPDX-FileCopyrightText: 2012 Philipp Wagner <bytefish at gmx dot de> 0014 * 0015 * SPDX-License-Identifier: GPL-2.0-or-later 0016 * 0017 * ============================================================ */ 0018 0019 #include "tantriggspreprocessor.h" 0020 0021 namespace Digikam 0022 { 0023 0024 TanTriggsPreprocessor::TanTriggsPreprocessor() 0025 : alpha (0.1f), 0026 tau (10.0f), 0027 gamma (0.2f), 0028 sigma0(1), 0029 sigma1(2) 0030 { 0031 } 0032 0033 cv::Mat TanTriggsPreprocessor::preprocess(const cv::Mat& inputImage) 0034 { 0035 return normalize(preprocessRaw(inputImage)); 0036 } 0037 0038 cv::Mat TanTriggsPreprocessor::preprocessRaw(const cv::Mat& inputImage) 0039 { 0040 cv::Mat X = inputImage; 0041 0042 // Ensure it's grayscale 0043 0044 if (X.channels() > 1) 0045 { 0046 cvtColor(X, X, CV_RGB2GRAY); 0047 } 0048 0049 // Convert to floating point: 0050 0051 X.convertTo(X, CV_32FC1); 0052 0053 // Start preprocessing: 0054 0055 cv::Mat I; 0056 0057 // Gamma correction 0058 0059 cv::pow(X, gamma, I); 0060 0061 // Calculate the DOG (Difference of Gaussian) Image. 0062 0063 { 0064 cv::Mat gaussian0, gaussian1; 0065 0066 // Kernel Size: 0067 0068 int kernel_sz0 = (int)(3*sigma0); 0069 int kernel_sz1 = (int)(3*sigma1); 0070 0071 // Make them odd for OpenCV: 0072 0073 kernel_sz0 += ((kernel_sz0 % 2) == 0) ? 1 : 0; 0074 kernel_sz1 += ((kernel_sz1 % 2) == 0) ? 1 : 0; 0075 cv::GaussianBlur(I, gaussian0, cv::Size(kernel_sz0,kernel_sz0), sigma0, sigma0, cv::BORDER_CONSTANT); 0076 cv::GaussianBlur(I, gaussian1, cv::Size(kernel_sz1,kernel_sz1), sigma1, sigma1, cv::BORDER_CONSTANT); 0077 cv::subtract(gaussian0, gaussian1, I); 0078 } 0079 0080 { 0081 double meanI = 0.0; 0082 0083 { 0084 cv::Mat tmp; 0085 cv::pow(cv::abs(I), alpha, tmp); 0086 meanI = cv::mean(tmp).val[0]; 0087 } 0088 0089 I = I / cv::pow(meanI, 1.0/alpha); 0090 } 0091 0092 { 0093 double meanI = 0.0; 0094 0095 { 0096 cv::Mat tmp; 0097 cv::pow(cv::min(cv::abs(I), tau), alpha, tmp); 0098 meanI = cv::mean(tmp).val[0]; 0099 } 0100 0101 I = I / cv::pow(meanI, 1.0/alpha); 0102 } 0103 0104 // Squash into the tanh: 0105 0106 { 0107 for (int r = 0 ; r < I.rows ; ++r) 0108 { 0109 for (int c = 0 ; c < I.cols ; ++c) 0110 { 0111 I.at<float>(r, c) = tanh(I.at<float>(r, c) / tau); 0112 } 0113 } 0114 0115 I = tau * I; 0116 } 0117 0118 return I; 0119 } 0120 0121 /** 0122 * Normalizes a given image into a value range between 0 and 255. 0123 */ 0124 cv::Mat TanTriggsPreprocessor::normalize(const cv::Mat& src) 0125 { 0126 // Create and return normalized image. 0127 0128 cv::Mat dst; 0129 0130 switch (src.channels()) 0131 { 0132 case 1: 0133 cv::normalize(src, dst, 0, 255, cv::NORM_MINMAX, CV_8UC1); 0134 break; 0135 case 3: 0136 cv::normalize(src, dst, 0, 255, cv::NORM_MINMAX, CV_8UC3); 0137 break; 0138 default: 0139 src.copyTo(dst); 0140 break; 0141 } 0142 0143 return dst; 0144 } 0145 0146 } // namespace Digikam