00001 #ifndef Impala_Core_Feature_GetColorChannels_h
00002 #define Impala_Core_Feature_GetColorChannels_h
00003
00004 #include "Core/Array/RGB2Intensity.h"
00005 #include "Core/Array/Rgb2Ooo.h"
00006 #include "Core/Array/RGB2rg.h"
00007 #include "Core/Array/ColorSpace.h"
00008 #include "Core/Array/ProjectRange.h"
00009 #include "Core/Array/PixSum.h"
00010 #include "Core/Array/PixMax.h"
00011 #include "Core/Array/Add.h"
00012 #include "Core/Array/Sub.h"
00013 #include "Core/Array/Div.h"
00014 #include "Core/Array/Mul.h"
00015 #include "Core/Array/MulVal.h"
00016 #include "Core/Array/AddVal.h"
00017 #include "Core/Array/Atan2.h"
00018 #include "Core/Array/ProjectParameterizedColor.h"
00019 #include "Core/Array/Element/Color.h"
00020 #include "Util/StringParser.h"
00021
00022 #include <set>
00023
00024 namespace Impala
00025 {
00026 namespace Core
00027 {
00028 namespace Feature
00029 {
00030
00031 void
00032 Normalize(Array::Array2dScalarReal64* im)
00033 {
00034 Real64 maxVal = PixMax(im);
00035 if(abs(maxVal) < 0.000001)
00036 maxVal = 1.0;
00037 MulVal(im, im, 1. / maxVal);
00038 }
00039
00040 std::vector<Array::Array2dScalarReal64*>
00041 GetColorChannels(Array::Array2dVec3Real64* input, String colorModel)
00042 {
00043 ILOG_FUNCTION(Impala.Core.Feature.GetColorChannels);
00044 ILOG_DEBUG("colorModel="<< colorModel);
00045 std::vector<Array::Array2dScalarReal64*> output;
00046 if((colorModel == "") || (colorModel == "no") ||
00047 (colorModel == "rg") || (colorModel == "hsv"))
00048 {
00049 Array::Array2dScalarReal64* imIntensity = 0;
00050 RGB2Intensity(imIntensity, input);
00051
00052
00053 Normalize(imIntensity);
00054 output.push_back(imIntensity);
00055 }
00056 if(colorModel == "rg")
00057 {
00058 Array::Array2dVec3Real64* rg = 0;
00059 RGB2rg(rg, input);
00060 Array::Array2dScalarReal64* r = 0;
00061 ProjectRange(r, rg, 1);
00062 output.push_back(r);
00063 Array::Array2dScalarReal64* g = 0;
00064 ProjectRange(g, rg, 2);
00065 output.push_back(g);
00066 delete rg;
00067 }
00068 if(colorModel == "opponent")
00069 {
00070 Array::Array2dVec3Real64* ooo = 0;
00071 Rgb2Ooo(ooo, input);
00072
00073 Array::Array2dScalarReal64* intensity = 0;
00074 ProjectRange(intensity, ooo, 1);
00075 Normalize(intensity);
00076 output.push_back(intensity);
00077
00078 Array::Array2dScalarReal64* redGreen = 0;
00079 ProjectRange(redGreen, ooo, 2);
00080 MulVal(redGreen, redGreen, 1 / 80.0);
00081 AddVal(redGreen, redGreen, 0.5);
00082 output.push_back(redGreen);
00083
00084 Array::Array2dScalarReal64* blueYellow = 0;
00085 ProjectRange(blueYellow, ooo, 3);
00086 MulVal(blueYellow, blueYellow, 1 / 80.0);
00087 AddVal(blueYellow, blueYellow, 0.5);
00088 output.push_back(blueYellow);
00089 delete ooo;
00090 }
00091 if((colorModel == "w") || (colorModel == "c"))
00092 {
00093 Array::Array2dVec3Real64* ooo = 0;
00094 Rgb2Ooo(ooo, input);
00095
00096 Array::Array2dScalarReal64* intensity = 0;
00097 ProjectRange(intensity, ooo, 1);
00098 Real64 maxVal = PixMax(intensity);
00099 if(abs(maxVal) < 0.000001)
00100 maxVal = 1.0;
00101 AddVal(intensity, intensity, 1.0);
00102 MulVal(intensity, intensity, 1 / maxVal);
00103 output.push_back(intensity);
00104
00105 Array::Array2dScalarReal64* redGreen = 0;
00106 ProjectRange(redGreen, ooo, 2);
00107 Div(redGreen, redGreen, intensity);
00108 MulVal(redGreen, redGreen, 1 / 900.0);
00109 AddVal(redGreen, redGreen, 0.5);
00110 output.push_back(redGreen);
00111
00112 Array::Array2dScalarReal64* blueYellow = 0;
00113 ProjectRange(blueYellow, ooo, 3);
00114 Div(blueYellow, blueYellow, intensity);
00115 MulVal(blueYellow, blueYellow, 1 / 900.0);
00116 AddVal(blueYellow, blueYellow, 0.5);
00117 output.push_back(blueYellow);
00118 delete ooo;
00119 }
00120 if(colorModel == "hsv")
00121 {
00122
00123 Array::Array2dVec3Real64* hsv = 0;
00124 ColorSpace(hsv, input, Array::Element::RGB, Array::Element::HSI);
00125
00126 Array::Array2dScalarReal64* hue = 0;
00127 ProjectRange(hue, hsv, 1);
00128 MulVal(hue, hue, 1 / (2 * 3.14159265));
00129 output.push_back(hue);
00130
00131 Array::Array2dScalarReal64* saturation = 0;
00132 ProjectRange(saturation, hsv, 2);
00133 output.push_back(saturation);
00134 delete hsv;
00135 }
00136 if(colorModel == "transformedcolor")
00137 {
00138 for (int d=1 ; d<=input->ElemSize() ; d++)
00139 {
00140 Array::Array2dScalarReal64* comp = 0;
00141 ProjectRange(comp, input, d);
00142 Real64 pixelCount = comp->CW() * comp->CH();
00143 Real64 mu = PixSum(comp) / pixelCount;
00144 AddVal(comp, comp, -mu);
00145 Array::Array2dScalarReal64* stddev = 0;
00146 Mul(stddev, comp, comp);
00147 Real64 standardDeviation = sqrt(PixSum(stddev) / pixelCount);
00148 delete stddev;
00149 if(standardDeviation < 0.00001)
00150 standardDeviation = 1.0;
00151
00152 MulVal(comp, comp, (1.0 / standardDeviation) / 4.0);
00153 AddVal(comp, comp, 0.5);
00154 output.push_back(comp);
00155 }
00156 }
00157 if(colorModel == "rgb")
00158 {
00159 for(int channel=1 ; channel<=input->ElemSize() ; ++channel)
00160 {
00161 Array::Array2dScalarReal64* a = 0;
00162 ProjectRange(a, input, channel);
00163 output.push_back(a);
00164 }
00165 }
00166 if(colorModel.substr(0, 7) == "tunergb")
00167 {
00168 Array::Array2dVec3Real64* realImage = 0;
00169 MulVal(realImage, input, 1.0);
00170 Util::StringParser sp(colorModel.substr(7, colorModel.size()));
00171 while(!sp.TheEnd())
00172 {
00173 String colorChannel = sp.GetString('+', false);
00174 Util::StringParser sp2(colorChannel);
00175 Real64 a = sp2.GetDouble('x', true, true);
00176 Real64 b = sp2.GetDouble('x', true, true);
00177 Real64 c = sp2.GetDouble('x', true, true);
00178 Real64 d = sp2.GetDouble('x', true, true);
00179 Real64 e = sp2.GetDouble('x', true, true);
00180 Real64 f = sp2.GetDouble('x', true, true);
00181 Real64 g = sp2.GetDouble('x', false);
00182 Array::Array2dScalarReal64* channel = 0;
00183 ProjectParameterizedColor(channel, realImage, a, b, c, d, e, f, g);
00184 output.push_back(channel);
00185 }
00186 delete realImage;
00187 }
00188 if(colorModel.substr(0, 9) == "tunechan-")
00189 {
00190 Util::StringParser sp(colorModel.substr(9, colorModel.size()));
00191 std::set<String> channels;
00192 std::vector<String> orderedChannels;
00193 while(!sp.TheEnd())
00194 {
00195 String colorChannel = sp.GetString('-', false);
00196 channels.insert(colorChannel);
00197 orderedChannels.push_back(colorChannel);
00198 }
00199 if(channels.find("i") != channels.end())
00200 {
00201
00202 Array::Array2dScalarReal64* intensity = 0;
00203 RGB2Intensity(intensity, input);
00204 Normalize(intensity);
00205 output.push_back(intensity);
00206 }
00207 if(channels.find("r") != channels.end())
00208 {
00209 Array::Array2dScalarReal64* r = 0;
00210 ProjectRange(r, input, 1);
00211 output.push_back(r);
00212 }
00213 if(channels.find("g") != channels.end())
00214 {
00215 Array::Array2dScalarReal64* g = 0;
00216 ProjectRange(g, input, 2);
00217 output.push_back(g);
00218 }
00219 if(channels.find("b") != channels.end())
00220 {
00221 Array::Array2dScalarReal64* b = 0;
00222 ProjectRange(b, input, 3);
00223 output.push_back(b);
00224 }
00225 if((channels.find("rg") != channels.end()) ||
00226 (channels.find("rb") != channels.end()) ||
00227 (channels.find("rm") != channels.end()) ||
00228 (channels.find("ry") != channels.end()) ||
00229 (channels.find("gb") != channels.end()) ||
00230 (channels.find("gy") != channels.end()))
00231 {
00232 Array::Array2dScalarReal64* r = 0;
00233 ProjectRange(r, input, 1);
00234 Array::Array2dScalarReal64* g = 0;
00235 ProjectRange(g, input, 2);
00236 Array::Array2dScalarReal64* b = 0;
00237 ProjectRange(b, input, 3);
00238 if(channels.find("rg") != channels.end())
00239 {
00240 Array::Array2dScalarReal64* rg = 0;
00241 Sub(rg, r, g);
00242 output.push_back(rg);
00243 }
00244 if(channels.find("rb") != channels.end())
00245 {
00246 Array::Array2dScalarReal64* rb = 0;
00247 Sub(rb, r, b);
00248 output.push_back(rb);
00249 }
00250 if(channels.find("gb") != channels.end())
00251 {
00252 Array::Array2dScalarReal64* gb = 0;
00253 Sub(gb, g, b);
00254 output.push_back(gb);
00255 }
00256 if(channels.find("rm") != channels.end())
00257 {
00258 Array::Array2dScalarReal64* rm = 0;
00259 Add(rm, r, g);
00260 output.push_back(rm);
00261 }
00262 if(channels.find("ry") != channels.end())
00263 {
00264 Array::Array2dScalarReal64* ry = 0;
00265 Add(ry, r, b);
00266 output.push_back(ry);
00267 }
00268 if(channels.find("gy") != channels.end())
00269 {
00270 Array::Array2dScalarReal64* gy = 0;
00271 Add(gy, g, b);
00272 output.push_back(gy);
00273 }
00274 delete r;
00275 delete g;
00276 delete b;
00277 }
00278 if(channels.find("o1") != channels.end() ||
00279 channels.find("o2") != channels.end())
00280 {
00281 Array::Array2dVec3Real64* ooo = 0;
00282 Rgb2Ooo(ooo, input);
00283 if(channels.find("o1") != channels.end())
00284 {
00285 Array::Array2dScalarReal64* redGreen = 0;
00286 ProjectRange(redGreen, ooo, 2);
00287 MulVal(redGreen, redGreen, 1 / 80.0);
00288 AddVal(redGreen, redGreen, 0.5);
00289 output.push_back(redGreen);
00290 }
00291 if(channels.find("o2") != channels.end())
00292 {
00293 Array::Array2dScalarReal64* blueYellow = 0;
00294 ProjectRange(blueYellow, ooo, 3);
00295 MulVal(blueYellow, blueYellow, 1 / 80.0);
00296 AddVal(blueYellow, blueYellow, 0.5);
00297 output.push_back(blueYellow);
00298 }
00299 delete ooo;
00300 }
00301 if(channels.find("c1") != channels.end() ||
00302 channels.find("c2") != channels.end())
00303 {
00304 Array::Array2dVec3Real64* ooo = 0;
00305 Rgb2Ooo(ooo, input);
00306
00307 Array::Array2dScalarReal64* intensity = 0;
00308 ProjectRange(intensity, ooo, 1);
00309 Real64 maxVal = PixMax(intensity);
00310 if(abs(maxVal) < 0.000001)
00311 maxVal = 1.0;
00312 AddVal(intensity, intensity, 1.0);
00313 MulVal(intensity, intensity, 1 / maxVal);
00314 if(channels.find("c1") != channels.end())
00315 {
00316 Array::Array2dScalarReal64* redGreen = 0;
00317 ProjectRange(redGreen, ooo, 2);
00318 Div(redGreen, redGreen, intensity);
00319 MulVal(redGreen, redGreen, 1 / 900.0);
00320 AddVal(redGreen, redGreen, 0.5);
00321 output.push_back(redGreen);
00322 }
00323 if(channels.find("c2") != channels.end())
00324 {
00325 Array::Array2dScalarReal64* blueYellow = 0;
00326 ProjectRange(blueYellow, ooo, 3);
00327 Div(blueYellow, blueYellow, intensity);
00328 MulVal(blueYellow, blueYellow, 1 / 900.0);
00329 AddVal(blueYellow, blueYellow, 0.5);
00330 output.push_back(blueYellow);
00331 }
00332 delete intensity;
00333 delete ooo;
00334 }
00335
00336 if(channels.find("nr") != channels.end() ||
00337 channels.find("ng") != channels.end() ||
00338 channels.find("nb") != channels.end())
00339 {
00340 Array::Array2dVec3Real64* rg = 0;
00341 RGB2rg(rg, input);
00342 if(channels.find("nr") != channels.end())
00343 {
00344 Array::Array2dScalarReal64* r = 0;
00345 ProjectRange(r, rg, 1);
00346 output.push_back(r);
00347 }
00348 if(channels.find("ng") != channels.end())
00349 {
00350 Array::Array2dScalarReal64* g = 0;
00351 ProjectRange(g, rg, 2);
00352 output.push_back(g);
00353 }
00354 if(channels.find("nb") != channels.end())
00355 {
00356 Array::Array2dScalarReal64* b = 0;
00357 ProjectRange(b, rg, 3);
00358 output.push_back(b);
00359 }
00360 delete rg;
00361 }
00362
00363 if(channels.find("p1") != channels.end())
00364 {
00365
00366 Array::Array2dScalarReal64* r = 0;
00367 ProjectRange(r, input, 1);
00368 Array::Array2dScalarReal64* g = 0;
00369 ProjectRange(g, input, 2);
00370 Array::Array2dScalarReal64* ratio = 0;
00371 Atan2(ratio, r, g);
00372 output.push_back(ratio);
00373 delete r;
00374 delete g;
00375 }
00376 if(channels.find("p2") != channels.end())
00377 {
00378
00379 Array::Array2dScalarReal64* r = 0;
00380 ProjectRange(r, input, 1);
00381 Array::Array2dScalarReal64* b = 0;
00382 ProjectRange(b, input, 3);
00383 Array::Array2dScalarReal64* ratio = 0;
00384 Atan2(ratio, r, b);
00385 output.push_back(ratio);
00386 delete r;
00387 delete b;
00388 }
00389 if(channels.find("p3") != channels.end())
00390 {
00391
00392 Array::Array2dScalarReal64* g = 0;
00393 ProjectRange(g, input, 2);
00394 Array::Array2dScalarReal64* b = 0;
00395 ProjectRange(b, input, 3);
00396 Array::Array2dScalarReal64* ratio = 0;
00397 Atan2(ratio, g, b);
00398 output.push_back(ratio);
00399 delete g;
00400 delete b;
00401 }
00402 for(std::vector<String>::iterator iter = orderedChannels.begin();
00403 iter != orderedChannels.end(); iter++)
00404 {
00405 String chan = *iter;
00406 if(StringStartsWith(chan,"seed"))
00407 {
00408
00409 Util::StringParser sp2(chan.substr(4,chan.size()));
00410 String A = sp2.GetString(',', true);
00411 String B = sp2.GetString(',', true);
00412 String C = sp2.GetString(',', false);
00413 Real64 a = 0;
00414 Real64 b = 0;
00415 Real64 c = 0;
00416 if(A[0] == 'm')
00417 a = -atof(A.substr(1,A.size()));
00418 else
00419 a = atof(A);
00420
00421 if(B[0] == 'm')
00422 b = -atof(B.substr(1,B.size()));
00423 else
00424 b = atof(B);
00425
00426 if(C[0] == 'm')
00427 c = -atof(C.substr(1,C.size()));
00428 else
00429 c = atof(C);
00430
00431 ILOG_DEBUG("Seed a " << a << " b " << b << " c " << c);
00432 Array::Array2dScalarReal64* channel = 0;
00433 ProjectParameterizedColor(channel, input, a, b, c, 0, 0, 0, 1);
00434 output.push_back(channel);
00435 }
00436 }
00437 }
00438 return output;
00439 }
00440
00441 std::vector<Array::Array2dScalarReal64*>
00442 GetColorChannels(Array::Array2dVec3UInt8* inputInt, String colorModel)
00443 {
00444 Array::Array2dVec3Real64* input = 0;
00445 MulVal(input, inputInt, 1.0);
00446 std::vector<Array::Array2dScalarReal64*> output =
00447 GetColorChannels(input, colorModel);
00448 delete input;
00449 return output;
00450 }
00451
00452 }
00453 }
00454 }
00455
00456 #endif