00001 #ifndef Impala_Core_Array_Trait_QbWatershed_h
00002 #define Impala_Core_Array_Trait_QbWatershed_h
00003
00004 #include "Core/Geometry/PointZ.h"
00005 #include "Core/Array/Pattern/FcvArray.h"
00006 #include "Core/Array/Pattern/QCollection.h"
00007 #include "Core/Array/Pattern/Array2D.h"
00008 #include "Core/Array/Arrays.h"
00009
00010 namespace Impala
00011 {
00012 namespace Core
00013 {
00014 namespace Array
00015 {
00016 namespace Trait
00017 {
00018
00019
00020 const int CONTOURVAL = -3;
00021 const int MASKVAL = -2;
00022 const int INITVAL = -1;
00023 const int WSHEDVAL = 0;
00024
00025
00026 template<class DstArrayT, class Src1ArrayT, class Src2ArrayT>
00027 class QbWatershed {
00028
00029 typedef typename DstArrayT::ArithType DstArithT;
00030 typedef typename Src1ArrayT::ArithType Src1ArithT;
00031 typedef typename Src2ArrayT::ArithType Src2ArithT;
00032
00033 public:
00034
00035 typedef struct structPointValue {
00036 DstArithT arith;
00037 Src1ArithT img;
00038 Src1ArithT mask;
00039 Geometry::PointZ point;
00040 int cost;
00041 int lastDist;
00042
00043 bool
00044 less(const struct structPointValue &rhs) const
00045 {
00046 if (cost<rhs.cost)
00047 return true;
00048 if (cost>rhs.cost)
00049 return false;
00050
00051 return localOrderCounter < rhs.localOrderCounter;
00052 }
00053
00054 bool
00055 operator < (const struct structPointValue &rhs) const
00056 {
00057
00058 return less(rhs);
00059 }
00060
00061 unsigned localOrderCounter;
00062 } PointValueT;
00063
00064 typedef Pattern::Qset<PointValueT> QT;
00065
00066 typedef struct {
00067 Geometry::PointZ point;
00068 DstArithT arith;
00069 Src1ArithT img;
00070 Src1ArithT mask;
00071 } NeighborsT;
00072
00073 typedef Pattern::FcvArray<NeighborsT> VecNeighborsT;
00074
00075 QbWatershed(int width, int height, int minVal, int maxVal,
00076 Array2dScalarInt32* exportDistImage = 0)
00077 : costImage(width, height, 0), distImage(width, height, 0)
00078 {
00079 labelcode=0;
00080 globalOrderCounter=0;
00081 curdist=1;
00082 h = hmin = minVal;
00083 hmax = maxVal;
00084 for(int i=0;i<256;i++)
00085 hist[i]=false;
00086 exportDistIm = exportDistImage;
00087 }
00088
00089 bool
00090 GlobalPixelInit(PointValueT&vp, DstArithT& arith, Src1ArithT img, Src1ArithT)
00091 {
00092 arith = INITVAL;
00093 return false;
00094 }
00095
00096 bool
00097 WantAnotherLoop()
00098 {
00099 h++;
00100 if (h<=hmax)
00101 return true;
00102 else {
00103
00104 if (exportDistIm) {
00105 for (int y=0 ; y<distImage.getDim(1) ; y++)
00106 for (int x=0 ; x<distImage.getDim(0) ; x++)
00107 *Pattern::ArrayCPB(exportDistIm, x, y) = distImage(x, y);
00108 }
00109 return false;
00110 }
00111 }
00112
00113 bool
00114 WantFreshStartLocalPixelInit()
00115 {
00116 return true;
00117 }
00118
00119 bool
00120 LocalPixelInit(PointValueT& vp, DstArithT& arith, Src1ArithT img,
00121 Src1ArithT mask, bool& continua)
00122 {
00123 vp.arith=arith;
00124 vp.img=img;
00125 vp.mask=mask;
00126 continua = true;
00127 bool q=false;
00128
00129
00130 if (h==hmin) {
00131 hist[img]=true;
00132 }
00133
00134 if (h!=hmin && !hist[h] ) {
00135 continua = false;
00136 return q;
00137 }
00138
00139
00140 if (img == h && arith == INITVAL && arith != CONTOURVAL ) {
00141 q=true;
00142 distImage(vp.point.mX, vp.point.mY)=0;
00143
00144 costImage(vp.point.mX, vp.point.mY)=1;
00145 vp.arith = MASKVAL;
00146 vp.lastDist = 0;
00147 }
00148
00149 if (img==h && (arith == CONTOURVAL || arith == WSHEDVAL) ) {
00150 distImage(vp.point.mX, vp.point.mY)= 1;
00151 costImage(vp.point.mX, vp.point.mY)= -2;
00152 curdist=1;
00153 vp.lastDist=1;
00154 q=true;
00155 }
00156
00157 if (q) {
00158 vp.localOrderCounter=globalOrderCounter++;
00159
00160 vp.cost=costImage(vp.point.mX, vp.point.mY);
00161 }
00162 arith=vp.arith;
00163 return q;
00164 }
00165
00166
00167 void
00168 First(const PointValueT& val, DstArithT arith, Src1ArithT img, Src1ArithT)
00169 {
00170 center=val;
00171 center.arith=arith;
00172 }
00173
00174
00175
00176 Pattern::QAction
00177 Result()
00178 {
00179 if (index>=neighboursout.size())
00180 return Pattern::STOP;
00181 resultVP=neighboursout[index];
00182 Pattern::QAction action=actionsout[index];
00183 index++;
00184 return action;
00185 }
00186
00187 void
00188 GetItemToQueue(PointValueT& vp)
00189 {
00190 vp=resultVP;
00191 }
00192
00193
00194
00195 void
00196 GetItemToRemove(PointValueT& lower, PointValueT& upper)
00197 {
00198 lower.cost=upper.cost=resultVP.cost;
00199 lower.localOrderCounter=0;
00200 upper.localOrderCounter=4000000000;
00201 }
00202
00203 bool
00204 KillThisOne(const PointValueT& vp)
00205 {
00206 if (resultVP.cost==vp.cost && resultVP.point==vp.point)
00207 return true;
00208 return false;
00209 }
00210
00211 void
00212 GetItemToWrite(Geometry::PointZ& point, DstArithT& arith)
00213 {
00214 point=resultVP.point;
00215 arith=resultVP.arith;
00216 }
00217
00218 void
00219 Calculate(VecNeighborsT& neighboursin)
00220 {
00221 index=0;
00222 neighboursout.clear();
00223 actionsout.clear();
00224
00225 int i;
00226 bool step2=false;
00227
00228 if (!neighboursin.empty() && (center.arith == CONTOURVAL)) {
00229
00230
00231 if (center.lastDist > curdist) {
00232 curdist++;
00233 }
00234
00235 step2=true;
00236 for (i=0; i<neighboursin.size(); i++) {
00237 NeighborsT val=neighboursin[i];
00238 PointValueT neighbor;
00239 neighbor.point=val.point;
00240 neighbor.arith=val.arith;
00241 neighbor.img=val.img;
00242 neighbor.mask=val.mask;
00243 neighbor.cost=costImage(neighbor.point.mX, neighbor.point.mY);
00244 int dn= distImage(neighbor.point.mX, neighbor.point.mY);
00245 if ((neighbor.arith > 0 || neighbor.arith == WSHEDVAL
00246 || neighbor.arith == CONTOURVAL)) {
00247 if (neighbor.arith > 0) {
00248 if (center.arith == WSHEDVAL
00249 || center.arith == CONTOURVAL ) {
00250 center.arith = neighbor.arith;
00251 neighboursout.push_back(center);
00252 actionsout.push_back(Pattern::WRITE);
00253 } else if (center.arith != neighbor.arith) {
00254 center.arith = WSHEDVAL;
00255 neighboursout.push_back(center);
00256 actionsout.push_back(Pattern::WRITE);
00257 }
00258 } else if (center.arith < 0 && center.img == h) {
00259 center.arith = WSHEDVAL;
00260 neighboursout.push_back(center);
00261 actionsout.push_back(Pattern::WRITE);
00262 }
00263 }
00264 else if((neighbor.arith <0 && neighbor.img == h)
00265 && distImage(neighbor.point.mX, neighbor.point.mY) == 0) {
00266
00267
00268
00269
00270 distImage(neighbor.point.mX, neighbor.point.mY)=curdist+1;
00271 neighbor.lastDist=distImage(neighbor.point.mX, neighbor.point.mY);
00272 costImage(neighbor.point.mX, neighbor.point.mY) = -1;
00273 neighbor.localOrderCounter=globalOrderCounter++;
00274
00275 neighbor.cost=costImage(neighbor.point.mX, neighbor.point.mY);
00276 neighboursout.push_back(neighbor);
00277 actionsout.push_back(Pattern::QUEUE);
00278
00279 neighbor.arith = CONTOURVAL;
00280 neighboursout.push_back(neighbor);
00281 actionsout.push_back(Pattern::WRITE);
00282
00283 }
00284
00285
00286 if (neighbor.img!=center.img && center.img==h
00287 && neighbor.arith<0) {
00288
00289
00290 neighbor.arith=CONTOURVAL;
00291 distImage(neighbor.point.mX, neighbor.point.mY)= 1;
00292 costImage(neighbor.point.mX, neighbor.point.mY)= -2;
00293 neighbor.localOrderCounter=globalOrderCounter++;
00294
00295 neighbor.cost=costImage(neighbor.point.mX, neighbor.point.mY);
00296 neighboursout.push_back(neighbor);
00297 actionsout.push_back(Pattern::WRITE);
00298 }
00299
00300 }
00301 }
00302
00303
00304
00305
00306
00307
00308 if (!step2) {
00309
00310 if(!neighboursin.empty() && center.arith == MASKVAL) {
00311 labelcode++;
00312 center.arith = labelcode;
00313 neighboursout.push_back(center);
00314 actionsout.push_back(Pattern::WRITE);
00315 }
00316
00317 if(!neighboursin.empty() && center.arith > 0) {
00318 for (i=0; i<neighboursin.size(); i++) {
00319 NeighborsT val=neighboursin[i];
00320 PointValueT neighbor;
00321 neighbor.point=val.point;
00322 neighbor.arith=val.arith;
00323 neighbor.img=val.img;
00324 neighbor.mask=val.mask;
00325 neighbor.cost=costImage(neighbor.point.mX, neighbor.point.mY);
00326
00327 if(neighbor.arith == MASKVAL
00328 || neighbor.arith == INITVAL )
00329
00330
00331
00332 {
00333 if(neighbor.img==center.img && center.img==h ) {
00334 neighbor.arith=center.arith;
00335 costImage(neighbor.point.mX, neighbor.point.mY)= 0;
00336 neighbor.localOrderCounter=globalOrderCounter++;
00337
00338 neighbor.cost=costImage(neighbor.point.mX,
00339 neighbor.point.mY);
00340 neighboursout.push_back(neighbor);
00341 actionsout.push_back(Pattern::WRITE);
00342 neighboursout.push_back(neighbor);
00343 actionsout.push_back(Pattern::QUEUE);
00344 }
00345 else if(neighbor.img!=center.img && neighbor.arith<0) {
00346
00347
00348
00349 neighbor.arith=CONTOURVAL;
00350 distImage(neighbor.point.mX, neighbor.point.mY)= 1;
00351 costImage(neighbor.point.mX, neighbor.point.mY)= -2;
00352 neighbor.localOrderCounter=globalOrderCounter++;
00353
00354 neighbor.cost=costImage(neighbor.point.mX,
00355 neighbor.point.mY);
00356 neighboursout.push_back(neighbor);
00357 actionsout.push_back(Pattern::WRITE);
00358 }
00359 }
00360 }
00361 }
00362 }
00363
00364
00365 }
00366
00367 private:
00368
00369 PointValueT center;
00370 Pattern::FcvArray<PointValueT> neighboursout;
00371 Pattern::FcvArray<Pattern::QAction> actionsout;
00372 int index;
00373 int labelcode;
00374 int curdist;
00375 PointValueT resultVP;
00376
00377 int h;
00378 int hmin, hmax;
00379
00380
00381 bool hist[256];
00382
00383 unsigned globalOrderCounter;
00384 Pattern::Array2D<int> costImage;
00385 Pattern::Array2D<int> distImage;
00386 Array2dScalarInt32* exportDistIm;
00387 };
00388
00389 }
00390 }
00391 }
00392 }
00393
00394 #endif