00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042 #include <queue>
00043 #include <sstream>
00044
00045 #include <qgarlib/DilatedImage.H>
00046 #include <qgarlib/GeodesicRecEroImage.H>
00047 #include <qgarlib/QgarErrorDomain.H>
00048
00049
00050
00051 using namespace std;
00052
00053
00054 namespace qgar
00055 {
00056
00057
00058
00059
00060
00061 GeodesicRecEroImage::GeodesicRecEroImage(GreyLevelImage& aMarkImg,
00062 GreyLevelImage& aResImg)
00063 throw(QgarErrorDomain)
00064 : GreyLevelImage(aMarkImg)
00065 {
00066 if ( (aMarkImg.width() != aResImg.width())
00067 || (aMarkImg.height() != aResImg.height()))
00068 {
00069 std::ostringstream os;
00070 os << "Marker image size ["
00071 << aMarkImg.width()
00072 << " X "
00073 << aMarkImg.height()
00074 << "] does not match result image size ["
00075 << aResImg.width()
00076 << " X "
00077 << aResImg.height()
00078 << "]";
00079 throw QgarErrorDomain(__FILE__, __LINE__,
00080 "qgar::GeodesicRecEroImage::GeodesicRecEroImage(qgar::GreyLevelImage&, qgar::GreyLevelImage&)",
00081
00082 os.str());
00083 }
00084
00085 perform(this, &aResImg);
00086 }
00087
00088
00089
00090
00091
00092 void GeodesicRecEroImage::perform(GreyLevelImage* aMarkImg,
00093 GreyLevelImage* aResImg)
00094 {
00095 int width = aMarkImg->width();
00096 int height = aMarkImg->height();
00097
00098
00099
00100
00101
00102
00103 queue< long > boundary;
00104
00105 long indice;
00106 GreyLevelImage::value_type minimum;
00107 GreyLevelImage::value_type* Jp;
00108 GreyLevelImage::value_type* Ip;
00109 GreyLevelImage::value_type* Jq;
00110 GreyLevelImage::value_type* Iq;
00111
00112 GreyLevelImage::value_type* markerPixMap = aMarkImg->pPixMap();
00113 GreyLevelImage::value_type* goalPixMap = aResImg->pPixMap();
00114
00115 int minK, minL;
00116 int maxK, maxL;
00117
00118
00119
00120 Jp = markerPixMap;
00121 Ip = goalPixMap;
00122
00123 for (int i = 0; i < height; ++i)
00124 {
00125 for (int j = 0; j < width; ++j, ++Jp, ++Ip)
00126 {
00127
00128 minimum = *Jp;
00129
00130
00131 if (i)
00132 {
00133
00134 if (!j)
00135 {
00136 Jq = Jp - width;
00137 if (minimum > *Jq)
00138 {
00139 minimum = *Jq;
00140 }
00141 ++Jq;
00142 if (minimum > *Jq)
00143 {
00144 minimum = *Jq;
00145 }
00146 }
00147
00148 else if (j == width - 1)
00149 {
00150 Jq = Jp - 1;
00151 if (minimum > *Jq)
00152 {
00153 minimum = *Jq;
00154 }
00155 Jq -= width;
00156 if (minimum > *Jq)
00157 {
00158 minimum = *Jq;
00159 }
00160 ++Jq;
00161 if (minimum > *Jq)
00162 {
00163 minimum = *Jq;
00164 }
00165 }
00166
00167 else
00168 {
00169 for (int k = -1; k < 1; ++k)
00170 {
00171 for (int l = -1 ; l < 1 - k; ++l)
00172 {
00173 Jq = Jp + k*width + l;
00174 if (minimum > *Jq)
00175 {
00176 minimum = *Jq;
00177 }
00178 }
00179 }
00180 }
00181 }
00182 else if (j > 0)
00183 {
00184 Jq = Jp - 1;
00185 if (minimum > *Jq)
00186 {
00187 minimum = *Jq;
00188 }
00189 }
00190
00191 *Jp = (minimum > *Ip ? minimum : *Ip);
00192 }
00193 }
00194
00195
00196
00197 --Jp;
00198 --Ip;
00199 for (int i = 0; i < height; ++i)
00200 {
00201 for (int j = 0; j < width; ++j, --Jp, --Ip)
00202 {
00203
00204 minimum = *Jp;
00205
00206
00207 if (i != 0)
00208 {
00209
00210 if (j == 0)
00211 {
00212 Jq = Jp + width;
00213 if (minimum > *Jq)
00214 {
00215 minimum = *Jq;
00216 }
00217 --Jq;
00218 if (minimum > *Jq)
00219 {
00220 minimum = *Jq;
00221 }
00222
00223 *Jp = (minimum > *Ip ? minimum : *Ip);
00224 Jq = Jp + width;
00225 Iq = Ip + width;
00226
00227 if ((*Jq > *Jp) && (*Jq > *Iq))
00228 {
00229 boundary.push(Jp - markerPixMap);
00230 }
00231 else
00232 {
00233 --Iq;
00234 --Iq;
00235 if ((*Jq > *Jp) && (*Jq > *Iq))
00236 {
00237 boundary.push(Jp - markerPixMap);
00238 }
00239 }
00240 }
00241
00242
00243 else if (j == width - 1)
00244 {
00245 Jq = Jp + 1;
00246 if (minimum > *Jq)
00247 {
00248 minimum = *Jq;
00249 }
00250
00251 Jq += width;
00252 if (minimum > *Jq)
00253 {
00254 minimum = *Jq;
00255 }
00256
00257 --Jq;
00258 if (minimum > *Jq)
00259 {
00260 minimum = *Jq;
00261 }
00262
00263 *Jp = (minimum > *Ip ? minimum : *Ip);
00264 Jq = Jp + 1;
00265 Iq = Ip + 1;
00266 if ((*Jq > *Jp) && (*Jq > *Iq))
00267 {
00268 boundary.push(Jp - markerPixMap);
00269 }
00270 else
00271 {
00272 Iq += width;
00273 Iq += width;
00274 if ((*Jq > *Jp) && (*Jq > *Iq))
00275 {
00276 boundary.push(Jp - markerPixMap);
00277 }
00278 else
00279 {
00280 --Iq;
00281 --Iq;
00282 if ((*Jq > *Jp) && (*Jq > *Iq))
00283 {
00284 boundary.push(Jp - markerPixMap);
00285 }
00286 }
00287 }
00288 }
00289
00290
00291 else
00292 {
00293 for (int k = 1; k > -1; --k)
00294 {
00295 for (int l = 1 ; l > -(1 + k); --l)
00296 {
00297 Jq = Jp + k*width + l;
00298 if (minimum > *Jq)
00299 {
00300 minimum = *Jq;
00301 }
00302 }
00303 }
00304
00305 *Jp = (minimum > *Ip ? minimum : *Ip);
00306
00307 for (int k = 1; k > -1; --k)
00308 {
00309 for (int l = 1 ; l > -(1 + k); --l)
00310 {
00311 indice = k*width + l;
00312 Jq = Jp + indice;
00313 Iq = Ip + indice;
00314 if ((*Jq > *Jp) && (*Jq > *Iq))
00315 {
00316 boundary.push(Jp - markerPixMap);
00317
00318
00319
00320 k = -1;
00321 break;
00322
00323 }
00324
00325 }
00326 }
00327 }
00328 }
00329
00330 else if (j > 0)
00331 {
00332 Jq = Jp + 1;
00333 if (minimum > *Jq)
00334 {
00335 minimum = *Jq;
00336 }
00337
00338 *Jp = (minimum > *Ip ? minimum : *Ip);
00339 Iq = Ip + 1;
00340 if ((*Jq > *Jp) && (*Jq > *Iq))
00341 {
00342 boundary.push(Jp - markerPixMap);
00343 }
00344 }
00345 else
00346 {
00347 *Jp = (minimum > *Ip ? minimum : *Ip);
00348 }
00349
00350 }
00351 }
00352
00353
00354
00355
00356
00357
00358
00359 while (!boundary.empty())
00360 {
00361 indice = boundary.front();
00362 boundary.pop();
00363
00364 Jp = markerPixMap + indice;
00365 Ip = goalPixMap + indice;
00366
00367
00368
00369
00370 if ( (Jp > markerPixMap + width - 1) &&
00371 (Jp < markerPixMap + (height - 1)*width) )
00372 {
00373 minK = -1;
00374 maxK = 2;
00375
00376
00377 if ((Jp - markerPixMap) % width == 0)
00378 {
00379 minL = 0;
00380 maxL = 2;
00381 }
00382
00383 else if ((Jp - markerPixMap) % width == width - 1)
00384 {
00385 minL = -1;
00386 maxL = 1;
00387 }
00388
00389 else
00390 {
00391 minL = -1;
00392 maxL = 2;
00393 }
00394 }
00395
00396 else if (Jp == markerPixMap)
00397 {
00398 minK = minL = 0;
00399 maxK = maxL = 2;
00400 }
00401
00402 else if (Jp < markerPixMap + width - 1)
00403 {
00404 minK = 0;
00405 minL = -1;
00406 maxK = maxL = 2;
00407 }
00408
00409 else if (Jp == markerPixMap + width - 1)
00410 {
00411 minK = 0;
00412 minL = -1;
00413 maxK = 2;
00414 maxL = 1;
00415 }
00416
00417 else if (Jp == markerPixMap + (height - 1)*width)
00418 {
00419 minK = -1;
00420 minL = 0;
00421 maxK = 1;
00422 maxL = 2;
00423 }
00424
00425 else if (Jp < markerPixMap + height*width - 1)
00426 {
00427 minK = minL = -1;
00428 maxL = 2;
00429 maxK = 1;
00430 }
00431
00432 else
00433 {
00434 minL = minK = -1;
00435 maxL = maxK = 1;
00436 }
00437
00438 for (int k = minK; k < maxK; ++k)
00439 {
00440 for (int l = minL ; l < maxL; ++l)
00441 {
00442 indice = k*width + l;
00443 Jq = Jp + indice;
00444 Iq = Ip + indice;
00445
00446 if ( (*Jq > *Jp) && (*Iq != *Jq) )
00447 {
00448 *Jq = (*Jp > *Iq ? *Jp : *Iq);
00449 boundary.push(Jq - markerPixMap);
00450 }
00451
00452 }
00453 }
00454
00455 }
00456 }
00457
00458
00459
00460 }