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