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 #include "VFAT/segmentImage.H"
00039
00040 #include "Util/Assert.H"
00041 #include <iostream>
00042 #include <vector>
00043 #include <cstdio>
00044 #include <cstdlib>
00045
00046
00047
00048
00049
00050
00051
00052 void segmentImage::findCandidatesRGB()
00053 {
00054 PixRGB<float> pix;
00055
00056 for(unsigned int x = 0; x < masterVec.size(); x++)
00057 masterVec[x] = -1;
00058
00059 for(int x = frameX1; x < frameX2; x++)
00060 {
00061 for(int y = frameY1; y < frameY2; y++)
00062 {
00063 pix = workImage.getVal(x,y);
00064 candidatePixels.setVal(x,y,false);
00065
00066
00067 if ((pix.red() < redUT) &&
00068 (pix.green() < greenUT) &&
00069 (pix.blue() < blueUT) &&
00070 (pix.red() > redLT) &&
00071 (pix.green() > greenLT) &&
00072 (pix.blue() > blueLT))
00073 {
00074 candidatePixels.setVal(x,y,true);
00075
00076 }
00077 }
00078 }
00079 }
00080
00081
00082
00083
00084
00085 void segmentImage::findCandidatesHSV()
00086 {
00087 PixRGB<float> pix;
00088
00089 for(unsigned int x = 0; x < masterVec.size(); x++)
00090 masterVec[x] = -1;
00091
00092 for(int x = frameX1; x < frameX2; x++)
00093 {
00094 for(int y = frameY1; y < frameY2; y++)
00095 {
00096 float pixH,pixS,pixV;
00097 pix = workImage.getVal(x,y);
00098 PixHSV<float>(pix).getHSV(pixH,pixS,pixV);
00099 candidatePixels.setVal(x,y,false);
00100
00101
00102
00103
00104 if ((pixS < SUT) &&
00105 (pixV < VUT) &&
00106 (pixS > SLT) &&
00107 (pixV > VLT))
00108 {
00109
00110 if((pixH < HUT) && (pixH > HLT))
00111
00112
00113 {
00114 if(preCandidatePixels.getVal(x,y) == true)
00115 {
00116
00117 candidatePixels.setVal(x,y,true);
00118 }
00119 preCandidatePixels.setVal(x,y,true);
00120 }
00121 else
00122 {
00123 preCandidatePixels.setVal(x,y,false);
00124 }
00125 }
00126 }
00127 }
00128 }
00129
00130
00131
00132
00133
00134
00135 void segmentImage::findCandidatesGREY()
00136 {
00137 float pix;
00138
00139 for(unsigned int x = 0; x < masterVec.size(); x++)
00140 masterVec[x] = -1;
00141
00142 for(int x = frameX1; x < frameX2; x++)
00143 {
00144 for(int y = frameY1; y < frameY2; y++)
00145 {
00146 pix = workImageGREY.getVal(x,y);
00147 candidatePixels.setVal(x,y,false);
00148
00149
00150 if ((pix < VUT) && (pix > VLT))
00151 {
00152 candidatePixels.setVal(x,y,true);
00153 }
00154 }
00155 }
00156 }
00157
00158
00159
00160
00161
00162 void segmentImage::removeSingles()
00163 {
00164 for(int x = frameX1; x < frameX2; x++)
00165 {
00166 for(int y = frameY1; y < frameY2; y++)
00167 {
00168 if(candidatePixels.getVal(x,y))
00169 {
00170 int kill = 0;
00171 int XLeft = x - 1;
00172 int XRight = x + 1;
00173 int YTop = y - 1;
00174 int YBottom = y + 1;
00175 if((XLeft >= 0) && (candidatePixels.getVal(XLeft,y)))
00176 kill++;
00177 if((XRight < candidatePixels.getWidth())
00178 && (candidatePixels.getVal(XRight,y)))
00179 kill++;
00180 if((YTop >= 0) && (candidatePixels.getVal(x,YTop)))
00181 kill++;
00182 if((YBottom < candidatePixels.getHeight())
00183 && (candidatePixels.getVal(x,YBottom)))
00184 kill++;
00185 if(kill < 2)
00186 candidatePixels.setVal(x,y,false);
00187 }
00188 }
00189 }
00190 }
00191
00192
00193
00194
00195
00196
00197 void segmentImage::discreteLinking()
00198 {
00199
00200 bool trace = false;
00201 long pixID = 0;
00202 long lastNeighbor;
00203 masters = 0;
00204 mastersCount = 0;
00205 for(int x = frameX1; x < frameX2; x++)
00206 {
00207 trace = false;
00208 lastNeighbor = -2;
00209 for(int y = frameY1; y < frameY2; y++)
00210 {
00211 if(candidatePixels.getVal(x,y))
00212 {
00213 if(!trace)
00214 {
00215 pixID++;
00216 trace = true;
00217 lastNeighbor = -2;
00218 }
00219 blobID.setVal(x,y,pixID);
00220 if((x-1) > frameX1)
00221 {
00222 if(candidatePixels.getVal(x-1,y))
00223 {
00224
00225 long check = blobID.getVal((x-1),y);
00226 if(check != lastNeighbor)
00227 {
00228 backwardLink(pixID,check);
00229 lastNeighbor = check;
00230 }
00231 }
00232 else
00233 {
00234 lastNeighbor = -2;
00235 }
00236 }
00237 else
00238 {
00239 backwardLink(pixID,pixID);
00240 }
00241 }
00242 else
00243 {
00244 trace = false;
00245 blobID.setVal(x,y,0);
00246 lastNeighbor = -2;
00247 }
00248 }
00249 }
00250
00251
00252 num = pixID;
00253 }
00254
00255
00256
00257
00258
00259
00260
00261 void segmentImage::backwardLink(long slave, long master)
00262 {
00263 long *masterVecMaster = &masterVec[master];
00264 long *masterVecSlave = &masterVec[slave];
00265
00266 if(*masterVecMaster == -1)
00267 {
00268
00269 if(*masterVecSlave == -1)
00270 {
00271
00272 *masterVecMaster = masters;
00273 *masterVecSlave = masters;
00274 masters++;
00275 mastersCount++;
00276 }
00277
00278 else
00279 {
00280
00281 *masterVecMaster = *masterVecSlave;
00282 }
00283 }
00284
00285 else
00286 {
00287
00288 if(*masterVecSlave == -1)
00289 {
00290
00291 *masterVecSlave = *masterVecMaster;
00292 }
00293
00294 else
00295 {
00296
00297 mastersCount--;
00298 for(int i = 0; i < slave; i++)
00299 {
00300 if(masterVec[i] == *masterVecMaster)
00301 {
00302
00303 masterVec[i] = *masterVecSlave;
00304 }
00305 }
00306 }
00307 }
00308 }
00309
00310
00311
00312 void segmentImage::combine()
00313 {
00314 totalBlobs = 0;
00315 for(int x = frameX1; x < frameX2; x++)
00316 {
00317 for(int y = frameY1; y < frameY2; y++)
00318 {
00319 if(candidatePixels.getVal(x,y))
00320 {
00321 blobID.setVal(x,y,masterVec[blobID.getVal(x,y)]);
00322 }
00323 }
00324 }
00325 for(int x = 0; x < num; x++)
00326 {
00327 bool add = true;
00328
00329 for(int y = 0; y < totalBlobs; y++)
00330 {
00331 if(reOrderVec[y] == masterVec[x])
00332 add = false;
00333 }
00334
00335 if((add) && (masterVec[x] != -1))
00336 {
00337
00338 reOrderVec[totalBlobs] = masterVec[x];
00339 reverseOrderVec[masterVec[x]] = totalBlobs;
00340 reset[totalBlobs] = true;
00341 totalBlobs++;
00342 }
00343 }
00344
00345 }
00346
00347 void segmentImage::doSegment()
00348 {
00349
00350 if(doType == 1)
00351 {
00352 ASSERT(set1); ASSERT(set2); ASSERT(set3); ASSERT(set4);
00353 findCandidatesRGB();
00354 }
00355 if(doType == 2)
00356 {
00357 ASSERT(set1); ASSERT(set2); ASSERT(set3); ASSERT(set4);
00358 findCandidatesHSV();
00359 }
00360 if(doType == 3)
00361 {
00362 ASSERT(set3); ASSERT(set4);
00363 findCandidatesGREY();
00364 }
00365
00366 removeSingles();
00367
00368 discreteLinking();
00369
00370 combine();
00371
00372 }
00373
00374
00375
00376
00377
00378 segmentImage::segmentImage(int imageType)
00379 {
00380 doType = imageType;
00381 set1 = false; set2 = false; set3 = false; set4 = false;
00382 LINFO("CREATED");
00383 }
00384
00385 segmentImage::segmentImage()
00386 {
00387 doType = HSV;
00388 set1 = false; set2 = false; set3 = false; set4 = false;
00389 LINFO("CREATED");
00390 }
00391
00392 segmentImage::~segmentImage()
00393 {}
00394
00395
00396
00397
00398
00399 void segmentImage::setRed(int val, int thresh = 1, int skew = 0)
00400 {
00401 ASSERT(doType == 1);
00402 red = val;
00403 if(skew <= 0)
00404 {
00405 redLT = val - thresh + skew;
00406 redUT = val + thresh;
00407 }
00408 else
00409 {
00410 redLT = val - thresh;
00411 redUT = val + thresh + skew;
00412 }
00413 set1 = true;
00414 }
00415
00416 void segmentImage::setGreen(int val, int thresh = 1, int skew = 0)
00417 {
00418 ASSERT(doType == 1);
00419 green = val;
00420 if(skew <= 0)
00421 {
00422 greenLT = val - thresh + skew;
00423 greenUT = val + thresh;
00424 }
00425 else
00426 {
00427 greenLT = val - thresh;
00428 greenUT = val + thresh + skew;
00429 }
00430 set2 = true;
00431 }
00432
00433 void segmentImage::setBlue(int val, int thresh = 1, int skew = 0)
00434 {
00435 ASSERT(doType == 1);
00436 blue = val;
00437 if(skew <= 0)
00438 {
00439 blueLT = val - thresh + skew;
00440 blueUT = val + thresh;
00441 }
00442 else
00443 {
00444 blueLT = val - thresh;
00445 blueUT = val + thresh + skew;
00446 }
00447 set3 = true;
00448 }
00449
00450 void segmentImage::setHue(double val, double thresh = 1, double skew = 0)
00451 {
00452 ASSERT(doType == 2);
00453 H = val;
00454 if(skew <= 0)
00455 {
00456 HLT = val - thresh + skew;
00457 HUT = val + thresh;
00458 }
00459 else
00460 {
00461 HLT = val - thresh;
00462 HUT = val + thresh + skew;
00463 }
00464 set1 = true;
00465 }
00466
00467 void segmentImage::setSat(double val, double thresh = 1, double skew = 0)
00468 {
00469 ASSERT(doType == 2);
00470 S = val;
00471 if(skew <= 0)
00472 {
00473 SLT = val - thresh + skew;
00474 SUT = val + thresh;
00475 }
00476 else
00477 {
00478 SLT = val - thresh;
00479 SUT = val + thresh + skew;
00480 }
00481 set2 = true;
00482 }
00483
00484 void segmentImage::setVal(double val, double thresh = 1, double skew = 0)
00485 {
00486 ASSERT((doType == 2) || (doType == 3));
00487 V = val;
00488 if(skew <= 0)
00489 {
00490 VLT = val - thresh + skew;
00491 VUT = val + thresh;
00492 }
00493 else
00494 {
00495 VLT = val - thresh;
00496 VUT = val + thresh + skew;
00497 }
00498 set3 = true;
00499 }
00500
00501
00502
00503 void segmentImage::setFrame(int x1, int y1, int x2, int y2,
00504 int realX, int realY)
00505 {
00506 frameX1 = x1;
00507 frameX2 = x2;
00508 frameY1 = y1;
00509 frameY2 = y2;
00510 masterVec.resize(((x2-x1)*(y2-y1)),-1);
00511 reOrderVec.resize(((x2-x1)*(y2-y1)));
00512 reverseOrderVec.resize(((x2-x1)*(y2-y1)));
00513 centerX.resize(((x2-x1)*(y2-y1)));
00514 centerY.resize(((x2-x1)*(y2-y1)));
00515 Xsum.resize(((x2-x1)*(y2-y1)));
00516 Ysum.resize(((x2-x1)*(y2-y1)));
00517 mass.resize(((x2-x1)*(y2-y1)));
00518 xmin.resize(((x2-x1)*(y2-y1)));
00519 xmax.resize(((x2-x1)*(y2-y1)));
00520 ymin.resize(((x2-x1)*(y2-y1)));
00521 ymax.resize(((x2-x1)*(y2-y1)));
00522 reset.resize(((x2-x1)*(y2-y1)));
00523 LINFO("SETTING WIDTH %d, HEIGHT %d",realX,realY);
00524 blobID.resize(realX,realY,-1);
00525 candidatePixels.resize(realX,realY,false);
00526 preCandidatePixels.resize(realX,realY,false);
00527 set4 = true;
00528 }
00529
00530 void segmentImage::setHSVavg(long doAvg)
00531 {
00532 Havg.resize(doAvg,0);
00533 Savg.resize(doAvg,0);
00534 Vavg.resize(doAvg,0);
00535 Hstdd.resize(doAvg,0);
00536 Sstdd.resize(doAvg,0);
00537 Vstdd.resize(doAvg,0);
00538 HSVN.resize(doAvg,0);
00539 HSViter = doAvg;
00540 HSVcount = 0;
00541 }
00542
00543
00544
00545
00546
00547
00548
00549
00550
00551
00552 void segmentImage::segment(Image<PixRGB<float> > &image)
00553 {
00554 struct timezone tz;
00555 struct timeval start, stop;
00556 tz.tz_minuteswest = 0;
00557 tz.tz_dsttime = 0;
00558 gettimeofday(&start, &tz);
00559
00560 workImage.resize(1,1);
00561 workImage = lowPass5(image);
00562
00563 doSegment();
00564
00565 gettimeofday(&stop,&tz);
00566
00567
00568 }
00569
00570 void segmentImage::segment(Image<float> &image)
00571 {
00572 struct timezone tz;
00573 struct timeval start, stop;
00574 tz.tz_minuteswest = 0;
00575 tz.tz_dsttime = 0;
00576 gettimeofday(&start, &tz);
00577
00578 workImageGREY.resize(1,1);
00579 workImageGREY = lowPass5(image);
00580
00581 doSegment();
00582
00583 gettimeofday(&stop,&tz);
00584
00585
00586 }
00587
00588
00589
00590
00591
00592 Image<long> segmentImage::createMother(Image<long> &img)
00593 {
00594 Image<long> mother;
00595 mother.resize(img.getWidth(),img.getHeight(),ZEROS);
00596 for(int x = frameX1; x < frameX2; x++)
00597 {
00598 for(int y = frameY1; y < frameY2; y++)
00599 {
00600 if(img.getVal(x,y) != 0)
00601 mother.setVal(x,y,1);
00602 else
00603 mother.setVal(x,y,0);
00604 }
00605 }
00606 return mother;
00607 }
00608
00609
00610
00611
00612 Image<long> segmentImage::returnBlobs()
00613 {
00614 return blobID;
00615 }
00616
00617 Image<bool> segmentImage::returnCandidates()
00618 {
00619 return candidatePixels;
00620 }
00621
00622 Image<float> segmentImage::returnNormalizedCandidates()
00623 {
00624 Image<float> NC;
00625 NC.resize(candidatePixels.getWidth(),candidatePixels.getHeight());
00626 for(int x = 0; x < candidatePixels.getWidth(); x++)
00627 {
00628 for(int y = 0; y < candidatePixels.getHeight(); y++)
00629 {
00630 if(candidatePixels.getVal(x,y))
00631 NC.setVal(x,y,255.0F);
00632 else
00633 NC.setVal(x,y,0.0F);
00634 }
00635 }
00636 return NC;
00637 }
00638
00639 Image<PixRGB<float> > segmentImage::returnWorkImage()
00640 {
00641 ASSERT((doType == 1) || (doType == 2));
00642 return workImage;
00643 }
00644
00645 Image<float> segmentImage::returnWorkImageGREY()
00646 {
00647 ASSERT(doType == 3);
00648 return workImageGREY;
00649 }
00650
00651
00652 int segmentImage::numberBlobs()
00653 {
00654 return totalBlobs;
00655 }
00656
00657 std::vector<long> segmentImage::getBlobMap()
00658 {
00659 return reOrderVec;
00660 }
00661
00662 void segmentImage::calcMassCenter()
00663 {
00664 for(int x = frameX1; x < frameX2; x++)
00665 {
00666 for(int y = frameY1; y < frameY2; y++)
00667 {
00668 if((candidatePixels.getVal(x,y)) && (blobID.getVal(x,y) != -1))
00669 {
00670
00671 long *indexBlob = &reverseOrderVec[blobID.getVal(x,y)];
00672 if(reset[*indexBlob])
00673 {
00674 reset[*indexBlob] = false;
00675 Xsum[*indexBlob] = x;
00676 Ysum[*indexBlob] = y;
00677 mass[*indexBlob] = 1;
00678 xmin[*indexBlob] = x;
00679 ymin[*indexBlob] = y;
00680 xmax[*indexBlob] = x;
00681 ymax[*indexBlob] = y;
00682 }
00683 else
00684 {
00685 Xsum[*indexBlob] += x;
00686 Ysum[*indexBlob] += y;
00687 mass[*indexBlob]++;
00688 if(x <= xmin[*indexBlob])
00689 xmin[*indexBlob] = x;
00690 if(x >= xmax[*indexBlob])
00691 xmax[*indexBlob] = x;
00692 if(y <= ymin[*indexBlob])
00693 ymin[*indexBlob] = y;
00694 if(y >= ymax[*indexBlob])
00695 ymax[*indexBlob] = y;
00696 }
00697 }
00698 }
00699 }
00700
00701 for(int x = 0; x < totalBlobs; x++)
00702 {
00703
00704 if(mass[x] > 0)
00705 {
00706 centerX[x] = Xsum[x]/mass[x];
00707 centerY[x] = Ysum[x]/mass[x];
00708 }
00709 }
00710 }
00711
00712 float segmentImage::getCenterX(long blob)
00713 {
00714 return centerX[blob];
00715 }
00716
00717 float segmentImage::getCenterY(long blob)
00718 {
00719 return centerY[blob];
00720 }
00721
00722 long segmentImage::getMass(long blob)
00723 {
00724 return mass[blob];
00725 }
00726
00727 int segmentImage::getXmin(long blob)
00728 {
00729 return xmin[blob];
00730 }
00731
00732
00733
00734 int segmentImage::getXmax(long blob)
00735 {
00736 return xmax[blob];
00737 }
00738
00739
00740
00741 int segmentImage::getYmin(long blob)
00742 {
00743 return ymin[blob];
00744 }
00745
00746
00747
00748 int segmentImage::getYmax(long blob)
00749 {
00750 return ymax[blob];
00751 }
00752
00753
00754 int segmentImage::getImageSizeX()
00755 {
00756 return candidatePixels.getWidth();
00757 }
00758
00759 int segmentImage::getImageSizeY()
00760 {
00761 return candidatePixels.getHeight();
00762 }
00763
00764 void segmentImage::getHSVvalue(long blob, float *H, float *S, float *V,
00765 float *Hstd, float *Sstd, float *Vstd)
00766 {
00767 float totH = 0.0F, totS = 0.0F, totV = 0.0F;
00768 float ssH = 0.0F, ssS = 0.0F, ssV = 0.0F;
00769 PixRGB<float> pix;
00770 for(int x = frameX1; x < frameX2; x++)
00771 {
00772 for(int y = frameY1; y < frameY2; y++)
00773 {
00774 if((candidatePixels.getVal(x,y)) && (blobID.getVal(x,y) != -1))
00775 {
00776 if(reverseOrderVec[blobID.getVal(x,y)] == blob)
00777 {
00778 float pixH,pixS,pixV;
00779 pix = workImage.getVal(x,y);
00780 PixHSV<float>(pix).getHSV(pixH,pixS,pixV);
00781 totH +=pixH; totS += pixS; totV += pixV;
00782 ssH += (pow(pixH,2))/mass[blob];
00783 ssS += (pow(pixS,2))/mass[blob];
00784 ssV += (pow(pixV,2))/mass[blob];
00785 }
00786 }
00787 }
00788 }
00789 if(mass[blob] > 0)
00790 {
00791 *H = totH/mass[blob];
00792 *S = totS/mass[blob];
00793 *V = totV/mass[blob];
00794 *Hstd = sqrt(ssH - pow(*H,2));
00795 *Sstd = sqrt(ssS - pow(*S,2));
00796 *Vstd = sqrt(ssV - pow(*V,2));
00797 }
00798 }
00799
00800 void segmentImage::getHSVvalueMean(long blob, float *H, float *S, float *V,
00801 float *Hstd, float *Sstd, float *Vstd)
00802 {
00803 double massSum = 0;
00804 if(HSVcount == HSViter)
00805 HSVcount = 0;
00806 getHSVvalue(blob, &Havg[HSVcount], &Savg[HSVcount], &Vavg[HSVcount]
00807 ,&Hstdd[HSVcount], &Sstdd[HSVcount], &Vstdd[HSVcount]);
00808 HSVN[HSVcount] = mass[blob];
00809 HSVcount++;
00810 for(int i = 0; i < HSViter; i++)
00811 {
00812 massSum += HSVN[i];
00813 *H += Havg[i]*HSVN[i];
00814 *S += Savg[i]*HSVN[i];
00815 *V += Vavg[i]*HSVN[i];
00816 *Hstd += Hstdd[i]*HSVN[i];
00817 *Sstd += Sstdd[i]*HSVN[i];
00818 *Vstd += Vstdd[i]*HSVN[i];
00819 }
00820 if(massSum > 0)
00821 {
00822 *H = *H/massSum;
00823 *S = *S/massSum;
00824 *V = *V/massSum;
00825 *Hstd = *Hstd/massSum;
00826 *Sstd = *Sstd/massSum;
00827 *Vstd = *Vstd/massSum;
00828 }
00829 }
00830
00831
00832
00833
00834
00835