├── BlakeAlgorithm └── main.cpp ├── FaugerasAlgorithm └── main.cpp ├── HomomorphicFilter └── main.cpp ├── HornAlgorithm └── main.cpp ├── Makefile ├── MooreAlgorithm └── main.cpp ├── README.md ├── RahmanAlgorithm └── main.cpp └── clcnst ├── clcnst.cpp └── clcnst.h /BlakeAlgorithm/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | using namespace std; 4 | 5 | #include 6 | 7 | #include "../clcnst/clcnst.h" 8 | 9 | float threshold; 10 | string ifname, ofname; 11 | 12 | int main(int argc, char** argv) { 13 | // Load input file 14 | cout << "[BlakeAlgorithm] input file name: "; 15 | cin >> ifname; 16 | 17 | cv::Mat img = cv::imread(ifname, CV_LOAD_IMAGE_COLOR); 18 | if(img.empty()) { 19 | cout << "Failed to load file \"" << ifname << "\"." << endl; 20 | return -1; 21 | } 22 | int width = img.cols; 23 | int height = img.rows; 24 | int channel = img.channels(); 25 | img.convertTo(img, CV_32FC3, 1.0 / 255.0); 26 | 27 | // Obtain threshold value by keyborad interaction 28 | cout << "[BlakeAlgorithm] input threshold value (default = 0.10): "; 29 | cin >> threshold; 30 | 31 | // Compute logarithm of input image 32 | cv::Mat out; 33 | clcnst::logarithm(img, out); 34 | 35 | // Laplacian filter divided by thresholding 36 | cv::Mat laplace = cv::Mat::zeros(height, width, CV_32FC3); 37 | for(int c=0; c(y, (x+1)*channel+c) - out.at(y, x*channel+c); 43 | float dy = out.at(y+1, x*channel+c) - out.at(y, x*channel+c); 44 | if(fabs(dx) > threshold) { 45 | grad.at(y, x*2+0) = dx; 46 | } 47 | 48 | if(fabs(dy) > threshold) { 49 | grad.at(y, x*2+1) = dy; 50 | } 51 | } 52 | } 53 | 54 | // Compute gradient again 55 | for(int y=1; y(y, x*2+0) - grad.at(y, (x-1)*2+0); 58 | float ddy = grad.at(y, x*2+1) - grad.at(y-1, x*2+1); 59 | laplace.at(y, x*channel+c) = ddx + ddy; 60 | } 61 | } 62 | } 63 | 64 | // Gauss Seidel method 65 | clcnst::gauss_seidel(out, laplace, 20); 66 | 67 | // Normalization 68 | clcnst::normalize(out, out); 69 | 70 | // Compute exponential 71 | clcnst::exponential(out, out); 72 | 73 | // Display result 74 | cv::namedWindow("Input"); 75 | cv::namedWindow("Output"); 76 | cv::imshow("Input", img); 77 | cv::imshow("Output", out); 78 | cv::waitKey(0); 79 | cv::destroyAllWindows(); 80 | 81 | // Save output 82 | cout << "[BlakeAlgorithm] save as: "; 83 | cin >> ofname; 84 | out.convertTo(out, CV_8UC3, 255.0); 85 | cv::imwrite(ofname, out); 86 | 87 | } -------------------------------------------------------------------------------- /FaugerasAlgorithm/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | using namespace std; 4 | 5 | #include 6 | 7 | #include "../clcnst/clcnst.h" 8 | 9 | int ns; 10 | float sigma, scale; 11 | string ifname, ofname; 12 | 13 | void hef_faugeras(cv::Mat& input, cv::Mat& output) { 14 | cv::Mat* i_ptr = &input; 15 | int width = i_ptr->cols; 16 | int height = i_ptr->rows; 17 | int channel = i_ptr->channels(); 18 | 19 | cv::Mat* o_ptr = &output; 20 | if(i_ptr != o_ptr) { 21 | *o_ptr = cv::Mat(height, width, CV_MAKETYPE(CV_32F, channel)); 22 | } 23 | 24 | for(int y=0; yat(y, x*channel+c) = coeff * i_ptr->at(y, x*channel+c); 30 | } 31 | } 32 | } 33 | } 34 | 35 | int main(int argc, char** argv) { 36 | // Load input image 37 | cout << "[FaugerasAlgorithm] input file name to load: "; 38 | cin >> ifname; 39 | cv::Mat img = cv::imread(ifname, CV_LOAD_IMAGE_COLOR); 40 | if(img.empty()) { 41 | cout << "Failed to load file \"" << ifname << "\"." << endl; 42 | return -1; 43 | } 44 | int width = img.cols; 45 | int height = img.rows; 46 | int channel = img.channels(); 47 | img.convertTo(img, CV_32FC3, 1.0 / 255.0); 48 | 49 | // Convert color space 50 | cv::Mat hvs; 51 | cv::cvtColor(img, hvs, CV_BGR2Lab); 52 | 53 | // Homomophic filtering 54 | vector chs, spc(channel, cv::Mat(height, width, CV_32FC1)); 55 | cv::split(hvs, chs); 56 | 57 | for(int c=1; c> ofname; 79 | out.convertTo(out, CV_8UC3, 255.0); 80 | cv::imwrite(ofname, out); 81 | } -------------------------------------------------------------------------------- /HomomorphicFilter/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | using namespace std; 6 | 7 | #include 8 | 9 | #include "../clcnst/clcnst.h" 10 | 11 | string ifname, ofname, isp; 12 | float lower, upper, threshold; 13 | 14 | int main(int argc, char** argv) { 15 | // Load input image 16 | cout << "[HomomorphicFilter] input file name to load: "; 17 | cin >> ifname; 18 | 19 | cv::Mat img = cv::imread(ifname, CV_LOAD_IMAGE_COLOR); 20 | if(img.empty()) { 21 | cout << "Failed to load file \"" << ifname << "\"." << endl; 22 | return -1; 23 | } 24 | int width = img.cols; 25 | int height = img.rows; 26 | int channel = img.channels(); 27 | img.convertTo(img, CV_32FC3, 1.0 / 255.0); 28 | 29 | // Obtain parameters from command line arguments 30 | cout << "[HomomorphicFilter] you want to specify parameters? (y/n): "; 31 | cin >> isp; 32 | if(isp == "y") { 33 | cout << " scale for low frequency (default = 0.5): "; 34 | cin >> lower; 35 | cout << " scale for high frequency (default = 2.0): "; 36 | cin >> upper; 37 | cout << " threshold value for frequency domain (default = 7.5):"; 38 | cin >> threshold; 39 | } else { 40 | lower = 0.5f; 41 | upper = 2.0f; 42 | threshold = 7.5f; 43 | } 44 | 45 | // Perform DFT, high emphasis filter and IDFT 46 | vector chs, spc(channel, cv::Mat(height, width, CV_32FC1)); 47 | cv::split(img, chs); 48 | 49 | for(int c=0; c> ofname; 68 | out.convertTo(out, CV_8UC3, 255.0); 69 | cv::imwrite(ofname, out); 70 | } 71 | -------------------------------------------------------------------------------- /HornAlgorithm/main.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tatsy/ColorConstancy/d6ba97e3b32b5ae2c664a47103bf825c970af33e/HornAlgorithm/main.cpp -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | CC = g++ 2 | BINDIR = ./bin/ 3 | SRCS = ./clcnst/clcnst.cpp 4 | SOBJ = $(BINDIR)libclcnst.so 5 | OBJ = main.o 6 | INC = -I/usr/local/include -I./clcnst 7 | CFLAGS = -fPIC 8 | LDFLAGS = -L/usr/local/lib/opencv -L./bin 9 | LIBS = -lopencv_core -lopencv_highgui -lopencv_imgproc 10 | LIB_CLCNST = -lclcnst 11 | HORN = $(BINDIR)HornAlrogithm 12 | BLAKE = $(BINDIR)BlakeAlgorithm 13 | MOORE = $(BINDIR)MooreAlgorithm 14 | RAHMAN = $(BINDIR)RahmanAlgorithm 15 | HOMO = $(BINDIR)HomomorphicFilter 16 | FAUG = $(BINDIR)FaugerasAlgorithm 17 | PROGRAMS = $(SOBJ) $(HORN) $(BLAKE) $(MOORE) $(RAHMAN) $(HOMO) $(FAUG) 18 | 19 | all: $(PROGRAMS) 20 | 21 | # build .so 22 | $(SOBJ): $(SRCS) 23 | mkdir -p $(BINDIR) 24 | $(CC) -shared $(CFLAGS) -o $(SOBJ) $(SRCS) $(INC) $(LDFLAGS) $(LIBS) 25 | 26 | # Horn's algorithm 27 | SRC_HORN = ./HornAlgorithm/main.cpp 28 | $(HORN): $(SRC_HORN) 29 | $(CC) -o $(HORN) $(SRC_HORN) $(INC) $(LDFLAGS) $(LIBS) $(LIB_CLCNST) 30 | 31 | # Blake's algorithm 32 | SRC_BLAKE = ./BlakeAlgorithm/main.cpp 33 | $(BLAKE): $(SRC_BLAKE) 34 | $(CC) -o $(BLAKE) $(SRC_BLAKE) $(INC) $(LDFLAGS) $(LIBS) $(LIB_CLCNST) 35 | 36 | # Moore's algorithm 37 | SRC_MOORE = ./MooreAlgorithm/main.cpp 38 | $(MOORE): $(SRC_MOORE) 39 | $(CC) -o $(MOORE) $(SRC_MOORE) $(INC) $(LDFLAGS) $(LIBS) $(LIB_CLCNST) 40 | 41 | # Rahman's algorithm 42 | SRC_RAHMAN = ./RahmanAlgorithm/main.cpp 43 | $(RAHMAN): $(SRC_RAHMAN) 44 | $(CC) -o $(RAHMAN) $(SRC_RAHMAN) $(INC) $(LDFLAGS) $(LIBS) $(LIB_CLCNST) 45 | 46 | # Homomorphic Filter 47 | SRC_HOMO = ./HomomorphicFilter/main.cpp 48 | $(HOMO): $(SRC_HOMO) 49 | $(CC) -o $(HOMO) $(SRC_HOMO) $(INC) $(LDFLAGS) $(LIBS) $(LIB_CLCNST) 50 | 51 | # Faugeras Filter 52 | SRC_FAUG = ./FaugerasAlgorithm/main.cpp 53 | $(FAUG): $(SRC_FAUG) 54 | $(CC) -o $(FAUG) $(SRC_FAUG) $(INC) $(LDFLAGS) $(LIBS) $(LIB_CLCNST) 55 | 56 | clean: 57 | rm -rf ./bin -------------------------------------------------------------------------------- /MooreAlgorithm/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | using namespace std; 4 | 5 | #include 6 | 7 | #include "../clcnst/clcnst.h" 8 | 9 | float sigma; 10 | string ifname, ofname, isex; 11 | 12 | int main(int argc, char** argv) { 13 | // Load input image 14 | cout << "[MooreAlgorithm] input file name to load: "; 15 | cin >> ifname; 16 | 17 | cv::Mat img = cv::imread(ifname, CV_LOAD_IMAGE_COLOR); 18 | if(img.empty()) { 19 | cout << "Failed to load file \"" << ifname << "\"." << endl; 20 | return -1; 21 | } 22 | int width = img.cols; 23 | int height = img.rows; 24 | int channel = img.channels(); 25 | img.convertTo(img, CV_32FC3, 1.0 / 255.0); 26 | 27 | // Apply Gaussian filter 28 | cout << "[MooreAlgorithm] input sigma value for Gaussian: "; 29 | cin >> sigma; 30 | sigma = sigma * max(width, height); 31 | 32 | cv::Mat gauss; 33 | cv::GaussianBlur(img, gauss, cv::Size(0, 0), sigma); 34 | 35 | // Additional process for extended Moore 36 | cout << "[MooreAlgorithm] use extended algorithm? (y/n): "; 37 | cin >> isex; 38 | if(isex == "y") { 39 | cv::Mat gray; 40 | cv::cvtColor(img, gray, CV_BGR2GRAY); 41 | 42 | cv::Mat edge = cv::Mat::zeros(height, width, CV_32FC1); 43 | for(int y=1; y(y, x+1) - gray.at(y, x-1)) / 2.0f; 46 | float dy = (gray.at(y+1, x) - gray.at(y-1, x)) / 2.0f; 47 | edge.at(y, x) = sqrt(dx * dx + dy * dy); 48 | } 49 | } 50 | 51 | cv::GaussianBlur(edge, edge, cv::Size(0, 0), sigma); 52 | cv::namedWindow("Edge"); 53 | cv::imshow("Edge", edge); 54 | 55 | for(int y=0; y(y, x*channel+c) *= edge.at(y, x); 59 | } 60 | } 61 | } 62 | } 63 | 64 | // Subtraction 65 | cv::Mat out; 66 | cv::subtract(img, gauss, out); 67 | 68 | // Offset reflectance 69 | out.convertTo(out, CV_32FC3, 1.0, -1.0); 70 | 71 | // Normalization 72 | clcnst::normalize(out, out, 0.0f, 1.0f); 73 | 74 | // Display result 75 | cv::namedWindow("Input"); 76 | cv::namedWindow("Output"); 77 | cv::imshow("Input", img); 78 | cv::imshow("Output", out); 79 | cv::waitKey(0); 80 | cv::destroyAllWindows(); 81 | 82 | // Save output image 83 | cout << "[MooreAlgorithm] save as: "; 84 | cin >> ofname; 85 | out.convertTo(out, CV_8UC3, 255.0); 86 | cv::imwrite(ofname, out); 87 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Color Constancy Algorithms 2 | --- 3 | 4 | > Implementations of several color constancy algorithms. 5 | 6 | ## Infomation 7 | 8 | Some of the algorithms are imported to an image editing library [lime](https://github.com/tatsy/lime). 9 | As this library includes only headers, you can test the algorithms more easily :-) 10 | 11 | ## Overview 12 | 13 | This contains following algorithms: 14 | * Horn's algorithm [Horn 1974, 1986] 15 | * Blake's algorithm [Blake 1985] 16 | * Moore's algorithm [Moore 1991] 17 | * Rahman's algorithm [Rahman et al. 1991] 18 | * Homomorphic filtering [Stockham Jr. 1972] 19 | 20 | All of the codes are dependent on OpenCV 2.4 (maybe it 21 | will work with older varsions as well). Each folder named 22 | with aforementioned algorithm containes "main.cpp." 23 | These programes include header "clcnst.h" that is 24 | in the folder named "clcnst". 25 | 26 | ## Installation 27 | 28 | Please execute following command. 29 | 30 | ```shell 31 | make all 32 | LD_LIBRARY_PATH=${LD_LIBRARY_PATH}:`pwd`/bin/ 33 | export LD_LIBRARY_PATH 34 | ``` 35 | 36 | ## Copyright 37 | 38 | MIT License, Copyright 2013-2015, tatsy. 39 | -------------------------------------------------------------------------------- /RahmanAlgorithm/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | using namespace std; 4 | 5 | #include 6 | 7 | #include "../clcnst/clcnst.h" 8 | 9 | int ns; 10 | float sigma, scale; 11 | string ifname, ofname, isp; 12 | 13 | int main(int argc, char** argv) { 14 | // Load input image 15 | cout << "[RahmanAlgorithm] input file name to load: "; 16 | cin >> ifname; 17 | cv::Mat img = cv::imread(ifname, CV_LOAD_IMAGE_COLOR); 18 | if(img.empty()) { 19 | cout << "Failed to load file \"" << ifname << "\"." << endl; 20 | return -1; 21 | } 22 | int width = img.cols; 23 | int height = img.rows; 24 | int channel = img.channels(); 25 | img.convertTo(img, CV_32FC3, 1.0 / 255.0); 26 | 27 | // Obtain parameters by keyboard interaction 28 | cout << "[RahmanAlgorithm] you want to specify parameters? (y/n): "; 29 | cin >> isp; 30 | if(isp == "y") { 31 | cout << " sigma = "; 32 | cin >> sigma; 33 | cout << " number of sigmas = "; 34 | cin >> ns; 35 | cout << " scales for sigmas = "; 36 | cin >> scale; 37 | } else { 38 | sigma = 1.0f; 39 | ns = 3; 40 | scale = 0.16f; 41 | } 42 | 43 | vector sigmas = vector(ns); 44 | sigmas[0] = sigma * (float)max(height, width); 45 | for(int i=1; i> ofname; 81 | out.convertTo(out, CV_8UC3, 255.0); 82 | cv::imwrite(ofname, out); 83 | } 84 | -------------------------------------------------------------------------------- /clcnst/clcnst.cpp: -------------------------------------------------------------------------------- 1 | #define __DLL_EXPORT 2 | #include "clcnst.h" 3 | 4 | #include 5 | using namespace std; 6 | 7 | const int clcnst::offset[4][2] = { {-1, 0}, {1, 0}, {0, -1}, {0, 1} }; 8 | 9 | const float clcnst::eps = 0.0001f; 10 | 11 | __PORT void clcnst::exponential(cv::Mat& input, cv::Mat& output) { 12 | cv::Mat* i_ptr = &input; 13 | int width = i_ptr->cols; 14 | int height = i_ptr->rows; 15 | int channel = i_ptr->channels(); 16 | 17 | cv::Mat* o_ptr = &output; 18 | if(i_ptr != o_ptr) { 19 | *o_ptr = cv::Mat(height, width, CV_MAKETYPE(CV_32F, channel)); 20 | } 21 | 22 | for(int y=0; yat(y, x*channel+c) = exp(i_ptr->at(y, x*channel+c)) - clcnst::eps; 26 | } 27 | } 28 | } 29 | } 30 | 31 | __PORT void clcnst::logarithm(cv::Mat& input, cv::Mat& output) { 32 | cv::Mat* i_ptr = &input; 33 | int width = i_ptr->cols; 34 | int height = i_ptr->rows; 35 | int channel = i_ptr->channels(); 36 | 37 | cv::Mat* o_ptr = &output; 38 | if(i_ptr != o_ptr) { 39 | *o_ptr = cv::Mat(height, width, CV_MAKETYPE(CV_32F, channel)); 40 | } 41 | 42 | for(int y=0; yat(y, x*channel+c) = log(i_ptr->at(y, x*channel+c) + clcnst::eps); 46 | } 47 | } 48 | } 49 | } 50 | 51 | __PORT void clcnst::gauss_seidel(cv::Mat& I, cv::Mat& L, int maxiter) { 52 | int width = I.cols; 53 | int height = I.rows; 54 | int channel = I.channels(); 55 | assert(width == L.cols && height == L.rows && channel == L.channels()); 56 | 57 | while(maxiter--) { 58 | for(int c=0; c= 0 && yy >= 0 && xx < width && yy < height) { 67 | sum += I.at(yy, xx*channel+c); 68 | count += 1; 69 | } 70 | } 71 | I.at(y, x*channel+c) = (sum - L.at(y, x*channel+c)) / (float)count; 72 | } 73 | } 74 | } 75 | } 76 | } 77 | 78 | __PORT void clcnst::laplacian(cv::Mat&input, cv::Mat& output) { 79 | cv::Mat* i_ptr = &input; 80 | int width = i_ptr->cols; 81 | int height = i_ptr->rows; 82 | int channel = i_ptr->channels(); 83 | 84 | cv::Mat* o_ptr = &output; 85 | if(i_ptr != o_ptr) { 86 | *o_ptr = cv::Mat(height, width, CV_MAKETYPE(CV_32F, channel)); 87 | } 88 | 89 | for(int c=0; c= 0 && yy >= 0 && xx < width && yy < height) { 98 | count += 1; 99 | sum += i_ptr->at(yy, xx*channel+c); 100 | } 101 | } 102 | o_ptr->at(y, x*channel+c) = sum - (float)count * i_ptr->at(y, x*channel+c); 103 | } 104 | } 105 | } 106 | } 107 | 108 | __PORT void clcnst::gaussian(cv::Mat& input, cv::Mat& output, float sigma, int ksize) { 109 | cv::Mat* i_ptr = &input; 110 | cv::Mat* o_ptr = &output; 111 | assert(i_ptr != o_ptr); 112 | 113 | int width = i_ptr->cols; 114 | int height = i_ptr->rows; 115 | int channel = i_ptr->channels(); 116 | float s2 = 2.0f * sigma * sigma; 117 | 118 | vector table(ksize+1, 0.0f); 119 | for(int i=0; i<=ksize; i++) { 120 | table[i] = exp(-(i * i) / s2); 121 | } 122 | 123 | *o_ptr = cv::Mat(height, width, CV_MAKETYPE(CV_32F,channel)); 124 | for(int c=0; c= 0 && yy >= 0 && xx < width && yy < height) { 134 | float w = table[abs(dx)] * table[abs(dy)]; 135 | sum += i_ptr->at(yy, xx*channel+c) * w; 136 | weight += w; 137 | } 138 | } 139 | } 140 | o_ptr->at(y, x*channel+c) = weight != 0.0f ? sum / weight : 0.0f; 141 | } 142 | } 143 | } 144 | } 145 | 146 | __PORT void clcnst::threshold(cv::Mat& input, cv::Mat& output, float threshold) { 147 | cv::Mat* i_ptr = &input; 148 | int width = i_ptr->cols; 149 | int height = i_ptr->rows; 150 | int channel = i_ptr->channels(); 151 | 152 | cv::Mat* o_ptr = &output; 153 | if(i_ptr != o_ptr) { 154 | *o_ptr = cv::Mat(height, width, CV_MAKETYPE(CV_32F, channel)); 155 | } 156 | 157 | for(int c=0; cat(y, x*channel+c)) < threshold) { 161 | o_ptr->at(y, x*channel+c) = 0.0f; 162 | } else { 163 | o_ptr->at(y, x*channel+c) = i_ptr->at(y, x*channel+c); 164 | } 165 | } 166 | } 167 | } 168 | } 169 | 170 | __PORT void clcnst::normalize(cv::Mat& input, cv::Mat& output) { 171 | cv::Mat* i_ptr = &input; 172 | int width = i_ptr->cols; 173 | int height = i_ptr->rows; 174 | int channel = i_ptr->channels(); 175 | 176 | cv::Mat* o_ptr = &output; 177 | if(i_ptr != o_ptr) { 178 | *o_ptr = cv::Mat(height, width, CV_MAKETYPE(CV_32F, channel)); 179 | } 180 | 181 | for(int c=0; cat(y, x*channel+c)) { 186 | maxval = i_ptr->at(y, x*channel+c); 187 | } 188 | } 189 | } 190 | 191 | for(int y=0; yat(y, x*channel+c) = i_ptr->at(y, x*channel+c) - maxval; 194 | } 195 | } 196 | } 197 | } 198 | 199 | __PORT void clcnst::normalize(cv::Mat& input, cv::Mat& output, float lower, float upper) { 200 | cv::Mat* i_ptr = &input; 201 | int width = i_ptr->cols; 202 | int height = i_ptr->rows; 203 | int channel = i_ptr->channels(); 204 | 205 | cv::Mat* o_ptr = &output; 206 | if(i_ptr != o_ptr) { 207 | *o_ptr = cv::Mat(height, width, CV_MAKETYPE(CV_32F, channel)); 208 | } 209 | 210 | float minval = 100000.0f; 211 | float maxval = -100000.0f; 212 | for(int c=0; cat(y, x*channel+c); 216 | minval = min(minval, value); 217 | maxval = max(maxval, value); 218 | } 219 | } 220 | } 221 | 222 | float ratio = (upper - lower) / (maxval - minval); 223 | for(int c=0; cat(y, x*channel+c); 227 | o_ptr->at(y, x*channel+c) = (value - minval) * ratio + lower; 228 | } 229 | } 230 | } 231 | } 232 | 233 | __PORT void clcnst::hef(cv::Mat& input, cv::Mat& output, float lower, float upper, float threshold) { 234 | cv::Mat* i_ptr = &input; 235 | int width = i_ptr->cols; 236 | int height = i_ptr->rows; 237 | int channel = i_ptr->channels(); 238 | 239 | cv::Mat* o_ptr = &output; 240 | if(i_ptr != o_ptr) { 241 | *o_ptr = cv::Mat(height, width, CV_MAKETYPE(CV_32F, channel)); 242 | } 243 | 244 | for(int y=0; yat(y, x*channel+c) = coeff * i_ptr->at(y, x*channel+c); 250 | } 251 | } 252 | } 253 | } 254 | -------------------------------------------------------------------------------- /clcnst/clcnst.h: -------------------------------------------------------------------------------- 1 | #ifndef _CLCNST_H_ 2 | #define _CLCNST_H_ 3 | 4 | #include 5 | #include 6 | 7 | #if defined(WIN32) // MS Windows 8 | #define IDAAPI __stdcall 9 | #ifdef __DLL_EXPORT 10 | #define __PORT __declspec(dllexport) 11 | #else 12 | #define __PORT __declspec(dllimport) 13 | #endif 14 | #else 15 | #define __PORT 16 | #endif 17 | 18 | // Utility functions for color constancy projects 19 | class clcnst { 20 | private: 21 | static const int offset[4][2]; 22 | static const float eps; 23 | 24 | public: 25 | // Compute exp of cv::Mat. 26 | // Input and output can be the same instance. 27 | // Type of arguments must be CV_32F. 28 | __PORT static void exponential(cv::Mat& input, cv::Mat& output); 29 | 30 | // Compute log of cv::Mat. 31 | // Input and output can be the same instance. 32 | // Type of arguments must be CV_32F. 33 | __PORT static void logarithm(cv::Mat& input, cv::Mat& output); 34 | 35 | // Solve poisson equation using Gauss-Seldel method. 36 | __PORT static void gauss_seidel(cv::Mat& I, cv::Mat& L, int maxiter); 37 | 38 | // Apply Laplacian filter. 39 | // Input and output can be the same instance. 40 | // Type of arguments must be CV_32FC. 41 | __PORT static void laplacian(cv::Mat& input, cv::Mat& output); 42 | 43 | // Apply Gaussian filter. 44 | __PORT static void gaussian(cv::Mat& input, cv::Mat& output, float sigma, int ksize); 45 | 46 | // Apply thresholding operation. 47 | __PORT static void threshold(cv::Mat& input, cv::Mat& output, float threshold); 48 | 49 | // Normalize output range as the maximum value come to be 1. 50 | __PORT static void normalize(cv::Mat& input, cv::Mat& output); 51 | 52 | // Normalize output range into [lower, upper] 53 | __PORT static void normalize(cv::Mat& input, cv::Mat& output, float lower, float upper); 54 | 55 | // High emphasis filter 56 | __PORT static void hef(cv::Mat& input, cv::Mat& output, float lower, float upper, float threshold); 57 | }; 58 | 59 | #endif 60 | --------------------------------------------------------------------------------