00001 #ifndef Impala_Core_Array_ColorMomentsKoen_h
00002 #define Impala_Core_Array_ColorMomentsKoen_h
00003
00004 #include <vector>
00005 #include "Core/Array/Arrays.h"
00006 #include "Core/Array/ArraySet.h"
00007 #include "Core/Array/Rgb2Ooo.h"
00008 #include "Core/Array/Set.h"
00009 #include "Core/Array/PixSum.h"
00010 #include "Core/Array/Add.h"
00011 #include "Core/Array/Sub.h"
00012 #include "Core/Array/Div.h"
00013 #include "Core/Array/Mul.h"
00014 #include "Core/Array/Norm2.h"
00015 #include "Core/Array/Threshold.h"
00016 #include "Core/Array/PixStat.h"
00017 #include "Core/Array/PrintData.h"
00018 #include "Core/Array/ProjectRange.h"
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040 namespace Impala
00041 {
00042 namespace Core
00043 {
00044 namespace Array
00045 {
00046
00047 class ColorMoments {
00048
00049 public:
00050 int mShiftX;
00051 int mShiftY;
00052
00053 ColorMoments() : mShiftX(0), mShiftY(0) {}
00054
00055
00056 void
00057 SetCoordinateShift(int shiftX, int shiftY)
00058 {
00059
00060
00061 mShiftX = shiftX;
00062 mShiftY = shiftY;
00063 }
00064
00065
00066 void
00067 FillMomentCache(Array2dVec3Real64* rgb, int order, int degree, bool useBinaryMask=false, Array2dScalarReal64* binaryMask=0, bool blur=true, double sigma=10.0)
00068 {
00069
00070
00071
00072
00073 mMomentCache.clear();
00074
00075 Real64 TotalPixels = rgb->CW()*rgb->CH();
00076 if(useBinaryMask) {
00077
00078 TotalPixels = PixSum(binaryMask);
00079 }
00080
00081 ArraySet<Array2dScalarReal64>* X=new ArraySet<Array2dScalarReal64>(order+1);
00082 ArraySet<Array2dScalarReal64>* Y=new ArraySet<Array2dScalarReal64>(order+1);
00083
00084 ArraySet<Array2dScalarReal64>* R=new ArraySet<Array2dScalarReal64>(degree+1);
00085 ArraySet<Array2dScalarReal64>* G=new ArraySet<Array2dScalarReal64>(degree+1);
00086 ArraySet<Array2dScalarReal64>* B=new ArraySet<Array2dScalarReal64>(degree+1);
00087
00088 X->Array(0)=new Array2dScalarReal64(rgb->CW(),rgb->CH(),0,0);
00089 Y->Array(0)=new Array2dScalarReal64(rgb->CW(),rgb->CH(),0,0);
00090 R->Array(0)=new Array2dScalarReal64(rgb->CW(),rgb->CH(),0,0);
00091 G->Array(0)=new Array2dScalarReal64(rgb->CW(),rgb->CH(),0,0);
00092 B->Array(0)=new Array2dScalarReal64(rgb->CW(),rgb->CH(),0,0);
00093
00094
00095 SetVal(X->Array(0),1);
00096 SetVal(Y->Array(0),1);
00097 SetVal(R->Array(0),1);
00098 SetVal(G->Array(0),1);
00099 SetVal(B->Array(0),1);
00100
00101
00102 if(order > 0) {
00103
00104 X->Array(1)=new Array2dScalarReal64(rgb->CW(),rgb->CH(),0,0);
00105 Y->Array(1)=new Array2dScalarReal64(rgb->CW(),rgb->CH(),0,0);
00106 for(int i=0;i<rgb->CW();i++) {
00107 for(int j=0;j<rgb->CH();j++) {
00108 X->Array(1)->SetValue(i+mShiftX+1,i,j);
00109 Y->Array(1)->SetValue(j+mShiftY+1,i,j);
00110 }
00111 }
00112 }
00113
00114 ProjectRange(R->Array(1),rgb,1);
00115 ProjectRange(G->Array(1),rgb,2);
00116 ProjectRange(B->Array(1),rgb,3);
00117
00118 if(blur){
00119 Array2dScalarReal64* tmp=0;
00120 RecGauss(tmp,R->Array(1),sigma,sigma,0,0,1);
00121 Set(R->Array(1),tmp);
00122 delete tmp;tmp=0;
00123 RecGauss(tmp,G->Array(1),sigma,sigma,0,0,1);
00124 Set(G->Array(1),tmp);
00125 delete tmp;tmp=0;
00126 RecGauss(tmp,B->Array(1),sigma,sigma,0,0,1);
00127 Set(B->Array(1),tmp);
00128 delete tmp;tmp=0;
00129 }
00130
00131 for(int o=2;o<=order;o++){
00132 Mul(X->Array(o),X->Array(o-1),X->Array(1));
00133 Mul(Y->Array(o),Y->Array(o-1),Y->Array(1));
00134 }
00135 for(int d=2;d<=degree;d++){
00136 Mul(R->Array(d),R->Array(d-1),R->Array(1));
00137 Mul(G->Array(d),G->Array(d-1),G->Array(1));
00138 Mul(B->Array(d),B->Array(d-1),B->Array(1));
00139 }
00140 for(int o=0;o<=order;o++){
00141 for (int p=0;p<=o;p++){
00142 for (int q=0;q<=o;q++){
00143 if( p+q == o) {
00144 for(int d=0;d<=degree;d++){
00145 for(int r=0;r<=d;r++){
00146 for(int g=0;g<=d;g++){
00147 for(int b=0;b<=d;b++){
00148 if(r+g+b==d){
00149 Array2dScalarReal64* m = 0;
00150 Set(m,R->Array(r));
00151 if(g!=0)
00152 Mul(m,m,G->Array(g));
00153 if(b!=0)
00154 Mul(m,m,B->Array(b));
00155 if(p!=0)
00156 Mul(m,m,X->Array(p));
00157 if(q!=0)
00158 Mul(m,m,Y->Array(q));
00159 if(useBinaryMask) {
00160
00161 Mul(m,m,binaryMask);
00162 }
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173 Real64 moment = PixSum(m)/TotalPixels;
00174
00175 delete m;
00176 mMomentCache.push_back(ColorMoment(p,q,r,g,b,moment));
00177 }
00178 }
00179 }
00180 }
00181 }
00182 }
00183 }
00184 }
00185 }
00186 for(int o=0;o<=order;o++){
00187 delete X->Array(o);
00188 delete Y->Array(o);
00189 }
00190 for(int d=0;d<=degree;d++){
00191 delete R->Array(d);
00192 delete G->Array(d);
00193 delete B->Array(d);
00194 }
00195 delete X,Y,R,G,B;
00196 }
00197
00198
00199 void
00200 GetMoments(std::vector<Real64>& moments, Array2dVec3UInt8* rgb,
00201 int order, int degree, bool useBinaryMask=false, Array2dScalarReal64* binaryMask=0, bool blur=false, double sigma=10.0)
00202 {
00203 Array2dVec3Real64* tmp = 0;
00204
00205
00206
00207 MulVal(tmp, rgb, 1);
00208 MulVal(tmp, tmp, 1 / 255.0);
00209 GetMoments(moments, tmp, order, degree, useBinaryMask, binaryMask, blur, sigma);
00210 delete tmp;
00211 }
00212
00213
00214 void
00215 GetMoments(std::vector<Real64>& moments, Array2dVec3Real64* rgb,
00216 int order, int degree, bool useBinaryMask=false, Array2dScalarReal64* binaryMask=0, bool blur=false, double sigma=10.0)
00217 {
00218
00219 FillMomentCache(rgb, order, degree, useBinaryMask, binaryMask, blur, sigma);
00220
00221 GetAllMoments(moments);
00222 }
00223
00224 void
00225 GetInvariants(std::vector<Real64>& momentInvariants, Array2dVec3UInt8* rgb,
00226 bool useBinaryMask=false, Array2dScalarReal64* binaryMask=0, bool blur=false, double sigma=10.0)
00227 {
00228 Array2dVec3Real64* tmp = 0;
00229
00230
00231
00232 MulVal(tmp, rgb, 1);
00233 MulVal(tmp, tmp, 1 / 255.0);
00234 GetInvariants(momentInvariants, tmp, useBinaryMask, binaryMask, blur, sigma);
00235 delete tmp;
00236 }
00237
00238 void
00239 GetInvariants(std::vector<Real64>& momentInvariants,Array2dVec3Real64* rgb,
00240 bool useBinaryMask=false, Array2dScalarReal64* binaryMask=0, bool blur=false, double sigma=10.0)
00241 {
00242
00243 FillMomentCache(rgb, 1, 2, useBinaryMask, binaryMask, blur, sigma);
00244
00245 momentInvariants.push_back(B02('R'));
00246 momentInvariants.push_back(B02('G'));
00247 momentInvariants.push_back(B02('B'));
00248 momentInvariants.push_back(C02("RG"));
00249 momentInvariants.push_back(C02("RB"));
00250 momentInvariants.push_back(C02("GB"));
00251 momentInvariants.push_back(C02tilde("RG"));
00252 momentInvariants.push_back(C02tilde("RB"));
00253 momentInvariants.push_back(C02tilde("GB"));
00254
00255 momentInvariants.push_back(C11("RG"));
00256 momentInvariants.push_back(C11("RB"));
00257 momentInvariants.push_back(C11("GB"));
00258 momentInvariants.push_back(B12('R'));
00259 momentInvariants.push_back(B12('G'));
00260 momentInvariants.push_back(B12('B'));
00261 momentInvariants.push_back(C12_1("RG"));
00262 momentInvariants.push_back(C12_1("RB"));
00263 momentInvariants.push_back(C12_1("GB"));
00264 momentInvariants.push_back(C12_2("RG"));
00265 momentInvariants.push_back(C12_2("RB"));
00266 momentInvariants.push_back(C12_2("GB"));
00267
00268 momentInvariants.push_back(C12_3("RG"));
00269 momentInvariants.push_back(C12_3("GB"));
00270 momentInvariants.push_back(C12_4("RB"));
00271 }
00272
00273 private:
00274
00275 class ColorMoment {
00276 public:
00277
00278 ColorMoment(int x, int y, int r, int g, int b, Real64 val)
00279 : p(x), q(y), a(r), b(g), c(b), value(val) {}
00280
00281 int p;
00282 int q;
00283
00284 int a;
00285 int b;
00286 int c;
00287
00288 Real64 value;
00289 };
00290
00291 std::vector<ColorMoment> mMomentCache;
00292
00293 void GetAllMoments(std::vector<Real64>& output) {
00294 for(int i = 0; i < mMomentCache.size(); i++) {
00295 ColorMoment& m = mMomentCache[i];
00296 output.push_back(m.value);
00297 }
00298 }
00299
00300 Real64 GetMoment(int p, int q, int a, int b, int c)
00301 {
00302 for(int i = 0; i < mMomentCache.size(); i++) {
00303 ColorMoment& out = mMomentCache[i];
00304 if ((out.p == p)&&
00305 (out.q == q)&&
00306 (out.a == a)&&
00307 (out.b == b)&&
00308 (out.c == c))
00309 return out.value;
00310 }
00311 return 0;
00312 }
00313
00314
00315
00316 inline Real64 SB(int p, int q, char band, int degree){
00317 if(band=='R')
00318 return GetMoment(p,q,degree,0,0);
00319 if(band=='G')
00320 return GetMoment(p,q,0,degree,0);
00321 if(band=='B')
00322 return GetMoment(p,q,0,0,degree);
00323 return 0;
00324 }
00325
00326 inline Real64 DB(int p, int q, std::string band, int degree1,int degree2){
00327 if(band=="RG")
00328 return GetMoment(p,q,degree1,degree2,0);
00329 if(band=="RB")
00330 return GetMoment(p,q,degree1,0,degree2);
00331 if(band=="GB")
00332 return GetMoment(p,q,0,degree1,degree2);
00333 return 0;
00334 }
00335
00336 Real64 B02(char band){
00337 return (SB(0 ,0,band,0)*SB(0,0,band,2))/(SB(0,0,band,1)*SB(0,0,band,1));
00338 }
00339
00340 Real64 B12(char band){
00341 Real64 res =
00342 SB(1 ,0,band,1)*SB(0,1,band,2)*SB(0,0,band,0)+
00343 SB(1 ,0,band,2)*SB(0,1,band,0)*SB(0,0,band,1)+
00344 SB(1,0,band,0)*SB(0,1,band,1)*SB(0,0,band,2)-
00345 SB(1,0,band,0)*SB(0,1,band,2)*SB(0,0,band,1)-
00346 SB(1,0,band,1)*SB(0,1,band,0)*SB(0,0,band,2)-
00347 SB(1,0,band,2)*SB(0,1,band,1)*SB(0,0,band,0);
00348
00349 res/=(SB(0,0,band,2)*SB(0,0,band,1)*SB(0,0,band,0));
00350 return res;
00351 }
00352
00353 Real64 C02(std::string band){
00354 return (DB(0,0,band,1,1)*DB(0,0,band,0,0))/(DB(0,0,band,0,1)*DB(0,0,band,1,0));
00355 }
00356
00357 Real64 C02tilde(std::string band){
00358 return (DB(0,0,band,2,0)*DB(0,0,band,0,2))/(DB(0,0,band,1,1)*DB(0,0,band,1,1));
00359 }
00360
00361 Real64 C11(std::string band){
00362 return((DB(1,0,band,1,0)*DB(0,1,band,0,1)*DB(0,0,band,0,0) +
00363 DB(1,0,band,0,1)*DB(0,1,band,0,0)*DB(0,0,band,1,0) +
00364 DB(1,0,band,0,0)*DB(0,1,band,1,0)*DB(0,0,band,0,1) -
00365 DB(1,0,band,0,0)*DB(0,1,band,0,1)*DB(0,0,band,1,0) -
00366 DB(1,0,band,1,0)*DB(0,1,band,0,0)*DB(0,0,band,0,1) -
00367 DB(1,0,band,0,1)*DB(0,1,band,1,0)*DB(0,0,band,0,0) )/
00368 (DB(0,0,band,1,0)*DB(0,0,band,0,1)*DB(0,0,band,0,0)));
00369 }
00370 Real64 C12_1(std::string band){
00371 return((DB(1,0,band,1,0)*DB(0,1,band,1,1)*DB(0,0,band,0,0) +
00372 DB(1,0,band,1,1)*DB(0,1,band,0,0)*DB(0,0,band,1,0) +
00373 DB(1,0,band,0,0)*DB(0,1,band,1,0)*DB(0,0,band,1,1) -
00374 DB(1,0,band,0,0)*DB(0,1,band,1,1)*DB(0,0,band,1,0) -
00375 DB(1,0,band,1,0)*DB(0,1,band,0,0)*DB(0,0,band,1,1) -
00376 DB(1,0,band,1,1)*DB(0,1,band,1,0)*DB(0,0,band,0,0) )/
00377 (DB(0,0,band,1,1)*DB(0,0,band,1,0)*DB(0,0,band,0,0)));
00378
00379 }
00380 Real64 C12_2(std::string band){
00381 return((DB(1,0,band,0,1)*DB(0,1,band,1,1)*DB(0,0,band,0,0) +
00382 DB(1,0,band,1,1)*DB(0,1,band,0,0)*DB(0,0,band,0,1) +
00383 DB(1,0,band,0,0)*DB(0,1,band,0,1)*DB(0,0,band,1,1) -
00384 DB(1,0,band,0,0)*DB(0,1,band,1,1)*DB(0,0,band,0,1) -
00385 DB(1,0,band,0,1)*DB(0,1,band,0,0)*DB(0,0,band,1,1) -
00386 DB(1,0,band,1,1)*DB(0,1,band,0,1)*DB(0,0,band,0,0) )/
00387 (DB(0,0,band,1,1)*DB(0,0,band,0,1)*DB(0,0,band,0,0)));
00388 }
00389 Real64 C12_3(std::string band){
00390 return((DB(1,0,band,1,0)*DB(0,1,band,0,2)*DB(0,0,band,0,0) +
00391 DB(1,0,band,0,2)*DB(0,1,band,0,0)*DB(0,0,band,1,0) +
00392 DB(1,0,band,0,0)*DB(0,1,band,1,0)*DB(0,0,band,0,2) -
00393 DB(1,0,band,0,0)*DB(0,1,band,0,2)*DB(0,0,band,1,0) -
00394 DB(1,0,band,1,0)*DB(0,1,band,0,0)*DB(0,0,band,0,2) -
00395 DB(1,0,band,0,2)*DB(0,1,band,1,0)*DB(0,0,band,0,0) )/
00396 (DB(0,0,band,1,0)*DB(0,0,band,0,2)*DB(0,0,band,0,0)));
00397 }
00398
00399 Real64 C12_4(std::string band){
00400 return((DB(1,0,band,2,0)*DB(0,1,band,0,1)*DB(0,0,band,0,0) +
00401 DB(1,0,band,0,1)*DB(0,1,band,0,0)*DB(0,0,band,2,0) +
00402 DB(1,0,band,0,0)*DB(0,1,band,2,0)*DB(0,0,band,0,1) -
00403 DB(1,0,band,0,0)*DB(0,1,band,0,1)*DB(0,0,band,2,0) -
00404 DB(1,0,band,2,0)*DB(0,1,band,0,0)*DB(0,0,band,0,1) -
00405 DB(1,0,band,0,1)*DB(0,1,band,2,0)*DB(0,0,band,0,0) )/
00406 (DB(0,0,band,2,0)*DB(0,0,band,0,1)*DB(0,0,band,0,0)));
00407 }
00408
00409 };
00410
00411 }
00412 }
00413 }
00414
00415 #endif