00001 #include "ImageShapeFinder.h" 00002 #include <qmessagebox.h> 00003 //#include <qprogressbar.h> 00004 #include <qdialog.h> 00005 #include <qlayout.h> 00006 00007 ImageShapeFinder::ImageShapeFinder(int x, int y, int w, int h, std::vector<double>* vals){ 00008 00009 lowx = x ; 00010 lowy = y ; 00011 width = w ; 00012 height = h ; 00013 curDir = 0 ; 00014 pathsFilled = false ; 00015 00016 if(vals->size() != (unsigned int)(width * height)) 00017 QMessageBox::information( 0, "ImageShapeFinder Error", "Input vector size does not match expected." ); 00018 00019 layer = vals; 00020 00021 } 00022 00023 ImageShapeFinder::~ImageShapeFinder(){ 00024 for (unsigned int i = 0 ; i < selections.size() ; i++) { 00025 if (selections[i] != NULL) { 00026 delete (selections[i]) ; 00027 } 00028 } 00029 } 00030 00031 void ImageShapeFinder::setSelectedValues(std::vector<double> sel){ 00032 inSelection = sel ; 00033 doSelecting(); 00034 } 00035 00036 std::vector<ImageSelectionCube*> ImageShapeFinder::getSelections(){ 00037 return selections; 00038 } 00039 00040 00041 double ImageShapeFinder::getValueAtLocal(int x, int y, int z){ 00042 int t = z ; t++ ; // just to turn off compiler warning 00043 return (*layer)[((y*(width))+(x))]; 00044 } 00045 00046 00047 double ImageShapeFinder::getValueAtOverall(int x, int y, int z){ 00048 int nx = x-lowx; 00049 int ny = y-lowy; 00050 00051 return getValueAtLocal(nx, ny, z); 00052 00053 } 00054 00055 00056 void ImageShapeFinder::doSelecting(){ 00057 00058 // this is really slow, so we'll provide a progress bar to entertain the user 00059 /* 00060 QWidget *progressDlg = new QWidget( NULL, NULL, true ); 00061 QVBoxLayout *vbl = new QVBoxLayout( progressDlg, 10, 10 ); 00062 vbl->setAutoAdd( true ); 00063 new QLabel( "Creating polygons. Patience is a virtue.", progressDlg ); 00064 QProgressBar *progressBar = new QProgressBar( progressDlg ); 00065 float progress = 0.0 ; 00066 progressDlg->show(); 00067 progressBar->setProgress(1) ; 00068 */ 00069 00070 00071 std::vector<bool> * flags = new std::vector<bool>(layer->size(), false) ; 00072 00073 for(unsigned int i = 0; i < layer->size(); i++){//run through the layer 00074 if(isSelectable((*layer)[i])){ 00075 00076 // check the four pixels touching 00077 // if one is not selectable, change this to true in flags 00078 // to denote this pixel is on the edge. Same goes for 00079 // a pixel on the edge of the image. 00080 std::vector<bool> legal = checkLegalAdjacents(i); 00081 00082 //check above 00083 if(legal[1]){ 00084 if(!isSelectable((*layer)[i-width])) { 00085 (*flags)[i] = true; 00086 continue; 00087 } 00088 } 00089 else { 00090 (*flags)[i] = true; 00091 continue; 00092 } 00093 00094 //check right 00095 if(legal[3]){ 00096 if(!isSelectable((*layer)[i+1])) { 00097 (*flags)[i] = true; 00098 continue; 00099 } 00100 } 00101 else { 00102 (*flags)[i] = true; 00103 continue; 00104 } 00105 00106 //check below 00107 if(legal[5]){ 00108 if(!isSelectable((*layer)[i+width])){ 00109 (*flags)[i] = true; 00110 continue; 00111 } 00112 } 00113 else { 00114 (*flags)[i] = true; 00115 continue; 00116 } 00117 00118 //check left 00119 if(legal[7]){ 00120 if(!isSelectable((*layer)[i-1])){ 00121 (*flags)[i] = true; 00122 continue; 00123 } 00124 } 00125 else { 00126 (*flags)[i] = true; 00127 continue; 00128 } 00129 00130 } 00131 } 00132 00133 00134 // debugging - write out raw image (edge selections) 00135 fstream flagsFile ; 00136 flagsFile.open ("shapeFinderEdgeFlags.raw", fstream::out | fstream::binary) ; 00137 if (flagsFile.is_open()) { 00138 for (int hei = 0 ; hei < height ; hei++) { 00139 for (int wid = 0 ; wid < width ; wid++) { 00140 flagsFile << (int) ((*flags)[width * hei + wid]) ; 00141 } 00142 } 00143 flagsFile.close() ; 00144 } 00145 // end debugging 00146 00147 00148 // debugging - write out raw image (adjacency count) 00149 flagsFile.open ("shapeFinderAdjacentCount.raw", fstream::out | fstream::binary) ; 00150 if (flagsFile.is_open()) { 00151 for (int hei = 0 ; hei < height ; hei++) { 00152 for (int wid = 0 ; wid < width ; wid++) { 00153 if ((*flags)[width * hei + wid]) { 00154 flagsFile << adjacentBorderPixs(width * hei + wid, *flags) ; 00155 } 00156 else { 00157 flagsFile << 0 ; 00158 } 00159 } 00160 } 00161 flagsFile.close() ; 00162 } 00163 // end debugging 00164 00165 //first handle only lone points 00166 //these are just getting wiped, so we don't add them 00167 for (unsigned int j = 0; j < flags->size() ; j++){ 00168 if((*flags)[j] == true) 00169 if(adjacentBorderPixs(j, (*flags)) == 0) { 00170 (*flags)[j] = false; 00171 } 00172 } 00173 00174 00175 /* 00176 //next handle lines, if a line splits we stop and will pick 00177 //it up with another line later 00178 for (unsigned int k = 0 ; k < flags->size() ; k++){ 00179 if((*flags)[k] == true) 00180 if(adjacentBorderPixs(k, (*flags)) == 1) { 00181 handleLine(k, (*flags)); 00182 } 00183 } 00184 */ 00185 00186 //finally, anything left should be a polygon...we hope 00187 //if not, it will handle lines too 00188 for (unsigned int l = 0 ; l < flags->size() ; l++){ 00189 /* 00190 progress = ((float)l / (float)(flags->size())) * 100.0 ; 00191 progressBar->setProgress ((int)progress) ; 00192 */ 00193 00194 if((*flags)[l] == true) { 00195 paths = new std::vector<int>(layer->size(), false) ; 00196 handlePoly(l, (*flags)); 00197 pathsFilled = false ; 00198 delete paths ; 00199 } 00200 } 00201 00202 //delete progressDlg ; 00203 delete flags; 00204 } 00205 00206 00207 int ImageShapeFinder::nextBorderPoint(int i, std::vector<bool> &flags ){ 00208 int num = adjacentBorderPixs(i, flags) ; 00209 00211 // start new algorithm (Tweak 2) 00212 if (num > 1) { 00213 if (algorithm == 2) { 00214 return findLongestPath (i, flags) ; 00215 } 00216 } 00217 // end new algorithm (Tweak 2) 00218 00219 00220 std::vector<bool> legal = checkLegalAdjacents(i) ; 00221 int curDirTemp = curDir ; 00222 00224 bool newAlgorithm ; 00225 if (algorithm == 0) { 00226 newAlgorithm = false ; 00227 } 00228 else { 00229 newAlgorithm = true ; 00230 } 00231 00232 // start new algorithm (Tweak 1) 00233 // looks for next step in same direction as last step, 00234 // moving increasingly clockwise and counterclockwise 00235 // away from that direction searching for a valid path to follow 00236 for (int j = 1 ; newAlgorithm && j <= 4 ; j++) { 00237 switch (curDir) { 00238 case 0: 00239 if(legal[0]){ 00240 if(flags[(i-1)-width]) return (i-1)-width; 00241 } 00242 break; 00243 case 1: 00244 if(legal[1]){ 00245 if(flags[i-width]) return i-width; 00246 } 00247 break; 00248 case 2: 00249 if(legal[2]){ 00250 if(flags[(i+1)-width]) return (i+1)-width; 00251 } 00252 break; 00253 case 3: 00254 if(legal[3]){ 00255 if(flags[i+1]) return i+1; 00256 } 00257 break; 00258 case 4: 00259 if(legal[4]){ 00260 if(flags[(i+1)+width]) return (i+1)+width; 00261 } 00262 break; 00263 case 5: 00264 if(legal[5]){ 00265 if(flags[i+width]) return i+width; 00266 } 00267 break; 00268 case 6: 00269 if(legal[6]){ 00270 if(flags[(i-1)+width]) return (i-1)+width; 00271 } 00272 break; 00273 case 7: 00274 if(legal[7]){ 00275 if(flags[i-1]) return i-1; 00276 } 00277 break; 00278 } 00279 00280 curDir = (curDirTemp + j) % 8 ; 00281 switch (curDir) { 00282 case 0: 00283 if(legal[0]){ 00284 if(flags[(i-1)-width]) return (i-1)-width; 00285 } 00286 break; 00287 case 1: 00288 if(legal[1]){ 00289 if(flags[i-width]) return i-width; 00290 } 00291 break; 00292 case 2: 00293 if(legal[2]){ 00294 if(flags[(i+1)-width]) return (i+1)-width; 00295 } 00296 break; 00297 case 3: 00298 if(legal[3]){ 00299 if(flags[i+1]) return i+1; 00300 } 00301 break; 00302 case 4: 00303 if(legal[4]){ 00304 if(flags[(i+1)+width]) return (i+1)+width; 00305 } 00306 break; 00307 case 5: 00308 if(legal[5]){ 00309 if(flags[i+width]) return i+width; 00310 } 00311 break; 00312 case 6: 00313 if(legal[6]){ 00314 if(flags[(i-1)+width]) return (i-1)+width; 00315 } 00316 break; 00317 case 7: 00318 if(legal[7]){ 00319 if(flags[i-1]) return i-1; 00320 } 00321 break; 00322 } 00323 curDir = (curDirTemp - j + 8) % 8 ; 00324 } 00325 // end new algorithm (Tweak 1) 00326 00327 // start old algorithm (Basic Drawing Algorithm) 00328 // starts with vertical and horizontal "strong" paths, 00329 // then looks for paths to follow along the diagonals. 00330 if (!newAlgorithm) { 00331 if(legal[1]){ 00332 if(flags[i-width]) return i-width; 00333 } 00334 00335 if(legal[2]){ 00336 if(flags[(i+1)-width]) return (i+1)-width; 00337 } 00338 00339 if(legal[3]){ 00340 if(flags[i+1]) return i+1; 00341 } 00342 00343 if(legal[4]){ 00344 if(flags[(i+1)+width]) return (i+1)+width; 00345 } 00346 00347 if(legal[5]){ 00348 if(flags[i+width]) return i+width; 00349 } 00350 00351 if(legal[6]){ 00352 if(flags[(i-1)+width]) return (i-1)+width; 00353 } 00354 00355 if(legal[7]){ 00356 if(flags[i-1]) return i-1; 00357 } 00358 00359 if(legal[0]){ 00360 if(flags[(i-1)-width]) return (i-1)-width; 00361 } 00362 } 00363 // end original algorithm 00364 00365 00366 00367 curDir = curDirTemp ; 00368 return -1; 00369 } 00370 00371 00372 bool ImageShapeFinder::isSelectable(double val){ 00373 for(unsigned int j = 0; j < inSelection.size(); j++){ 00374 if (inSelection[j] == val) return true; 00375 } 00376 00377 return false; 00378 } 00379 00380 00381 int ImageShapeFinder::adjacentBorderPixs(int i, std::vector<bool> &flags){ 00382 std::vector<bool> legal = checkLegalAdjacents(i); 00383 00384 int count = 0; 00385 00386 if(legal[0]){ 00387 if(flags[(i-1)-width]) count++; 00388 } 00389 00390 if(legal[1]){ 00391 if(flags[i-width]) count++; 00392 } 00393 00394 if(legal[2]){ 00395 if(flags[(i+1)-width]) count++; 00396 } 00397 00398 if(legal[3]){ 00399 if(flags[i+1]) count++; 00400 } 00401 00402 if(legal[4]){ 00403 if(flags[(i+1)+width]) count++; 00404 } 00405 00406 if(legal[5]){ 00407 if(flags[i+width]) count++; 00408 } 00409 00410 if(legal[6]){ 00411 if(flags[(i-1)+width]) count++; 00412 } 00413 00414 if(legal[7]){ 00415 if(flags[i-1]) count++; 00416 } 00417 00418 return count; 00419 } 00420 00421 00422 00423 int ImageShapeFinder::findLongestPath(int i, std::vector<bool> &flags) { 00424 std::vector<bool> legal = checkLegalAdjacents(i); 00425 int length = 0 ; 00426 int longest = -1 ; 00427 int longestCount = 0 ; 00428 00429 if(legal[0]){ 00430 length = 0 ; 00431 if(flags[(i-1)-width]) { 00432 length = findLongestPathLength((i-1)-width, flags, i) ; 00433 if (length > longestCount) { 00434 longestCount = length ; 00435 longest = (i-1)-width ; 00436 } 00437 } 00438 } 00439 00440 if(legal[1]){ 00441 length = 0 ; 00442 if(flags[i-width]) { 00443 length = findLongestPathLength(i-width, flags, i) ; 00444 if (length > longestCount) { 00445 longestCount = length ; 00446 longest = i-width ; 00447 } 00448 } 00449 } 00450 00451 if(legal[2]){ 00452 length = 0 ; 00453 if(flags[(i+1)-width]) { 00454 length = findLongestPathLength((i+1)-width, flags, i) ; 00455 if (length > longestCount) { 00456 longestCount = length ; 00457 longest = i-width ; 00458 } 00459 } 00460 } 00461 00462 if(legal[3]){ 00463 length = 0 ; 00464 if(flags[i+1]) { 00465 length = findLongestPathLength(i+1, flags, i) ; 00466 if (length > longestCount) { 00467 longestCount = length ; 00468 longest = i+1 ; 00469 } 00470 } 00471 } 00472 00473 if(legal[4]){ 00474 length = 0 ; 00475 if(flags[(i+1)+width]) { 00476 length = findLongestPathLength((i+1)+width, flags, i) ; 00477 if (length > longestCount) { 00478 longestCount = length ; 00479 longest = (i+1)+width ; 00480 } 00481 } 00482 } 00483 00484 if(legal[5]){ 00485 length = 0 ; 00486 if(flags[i+width]) { 00487 length = findLongestPathLength(i+width, flags, i) ; 00488 if (length > longestCount) { 00489 longestCount = length ; 00490 longest = i+width ; 00491 } 00492 } 00493 } 00494 00495 if(legal[6]){ 00496 length = 0 ; 00497 if(flags[(i-1)+width]) { 00498 length = findLongestPathLength((i-1)+width, flags, i) ; 00499 if (length > longestCount) { 00500 longestCount = length ; 00501 longest = (i-1)+width ; 00502 } 00503 } 00504 } 00505 00506 if(legal[7]){ 00507 length = 0 ; 00508 if(flags[i-1]) { 00509 length = findLongestPathLength(i-1, flags, i) ; 00510 if (length > longestCount) { 00511 longestCount = length ; 00512 longest = i-1 ; 00513 } 00514 } 00515 } 00516 00517 return longest ; 00518 00519 00520 } 00521 00522 int ImageShapeFinder::findLongestPathLength(int i, std::vector<bool> &flags, int source) { 00523 std::vector<bool> legal = checkLegalAdjacents(i); 00524 int num = adjacentBorderPixs(i, flags) ; 00525 int length = 0 ; 00526 int longestCount = 0 ; 00527 00528 00529 00530 // temporarily disable this pixel so it's not revisited 00531 flags[i] = false ; 00532 00533 if (num == 0) { 00534 // re-enable this pixel 00535 flags[i] = true ; 00536 return 1 ; 00537 } 00538 00539 int index = 0 ; 00540 00541 if(legal[0]){ 00542 length = 0 ; 00543 index = (i - 1) - width ; 00544 00545 if(flags[index] && index != source) { 00546 if (pathsFilled) { 00547 length = (*paths)[index] ; 00548 } 00549 else { 00550 length = findLongestPathLength(index, flags, source) ; 00551 (*paths)[index] = length ; 00552 } 00553 if (length > longestCount) { 00554 longestCount = length ; 00555 } 00556 } 00557 } 00558 00559 if(legal[1]){ 00560 length = 0 ; 00561 index = i - width ; 00562 00563 if(flags[index] && index != source) { 00564 if (pathsFilled) { 00565 length = (*paths)[index] ; 00566 } 00567 else { 00568 length = findLongestPathLength(index, flags, source) ; 00569 (*paths)[index] = length ; 00570 } 00571 if (length > longestCount) { 00572 longestCount = length ; 00573 } 00574 } 00575 } 00576 00577 if(legal[2]){ 00578 length = 0 ; 00579 index = (i + 1) - width ; 00580 00581 if(flags[index] && index != source) { 00582 if (pathsFilled) { 00583 length = (*paths)[index] ; 00584 } 00585 else { 00586 length = findLongestPathLength(index, flags, source) ; 00587 (*paths)[index] = length ; 00588 } 00589 if (length > longestCount) { 00590 longestCount = length ; 00591 } 00592 } 00593 } 00594 00595 if(legal[3]){ 00596 length = 0 ; 00597 index = i + 1 ; 00598 00599 if(flags[index] && index != source) { 00600 if (pathsFilled) { 00601 length = (*paths)[index] ; 00602 } 00603 else { 00604 length = findLongestPathLength(index, flags, source) ; 00605 (*paths)[index] = length ; 00606 } 00607 if (length > longestCount) { 00608 longestCount = length ; 00609 } 00610 } 00611 } 00612 00613 if(legal[4]){ 00614 length = 0 ; 00615 index = (i + 1) + width ; 00616 00617 if(flags[index] && index != source) { 00618 if (pathsFilled) { 00619 length = (*paths)[index] ; 00620 } 00621 else { 00622 length = findLongestPathLength(index, flags, source) ; 00623 (*paths)[index] = length ; 00624 } 00625 if (length > longestCount) { 00626 longestCount = length ; 00627 } 00628 } 00629 } 00630 00631 if(legal[5]){ 00632 length = 0 ; 00633 index = i + width ; 00634 00635 if(flags[index] && index != source) { 00636 if (pathsFilled) { 00637 length = (*paths)[index] ; 00638 } 00639 else { 00640 length = findLongestPathLength(index, flags, source) ; 00641 (*paths)[index] = length ; 00642 } 00643 if (length > longestCount) { 00644 longestCount = length ; 00645 } 00646 } 00647 } 00648 00649 00650 if(legal[6]){ 00651 length = 0 ; 00652 index = (i - 1) + width ; 00653 00654 if(flags[index] && index != source) { 00655 if (pathsFilled) { 00656 length = (*paths)[index] ; 00657 } 00658 else { 00659 length = findLongestPathLength(index, flags, source) ; 00660 (*paths)[index] = length ; 00661 } 00662 if (length > longestCount) { 00663 longestCount = length ; 00664 } 00665 } 00666 } 00667 00668 00669 if(legal[4]){ 00670 length = 0 ; 00671 index = i - 1 ; 00672 00673 if(flags[index] && index != source) { 00674 if (pathsFilled) { 00675 length = (*paths)[index] ; 00676 } 00677 else { 00678 length = findLongestPathLength(index, flags, source) ; 00679 (*paths)[index] = length ; 00680 } 00681 if (length > longestCount) { 00682 longestCount = length ; 00683 } 00684 } 00685 } 00686 00687 00688 pathsFilled = true ; 00689 00690 // re-enable this pixel 00691 flags[i] = true ; 00692 00693 return ++longestCount ; 00694 00695 } 00696 00697 00698 00699 /* for reference 00700 * 0 1 2 00701 * 7 X 3 00702 * 6 5 4 00703 */ 00704 00705 std::vector<bool> ImageShapeFinder::checkLegalAdjacents(int i){ 00706 std::vector<bool> legals(8, true); 00707 00708 //check the values above 00709 // if the value is in the top line of the image, set values above to false 00710 if (i < width) { 00711 legals[0] = false; 00712 legals[1] = false; 00713 legals[2] = false; 00714 } 00715 00716 //check the values below 00717 // if the value is in the bottom line of the image, set values below to false 00718 if( i > (int)(layer->size() - width)){ 00719 legals[4] = false; 00720 legals[5] = false; 00721 legals[6] = false; 00722 } 00723 00724 //check the left edge 00725 // if the value is in the first sample of the image, set values left to false 00726 if( (i % width) == 0){ 00727 legals[0] = false; 00728 legals[7] = false; 00729 legals[6] = false; 00730 } 00731 00732 //check the right edge 00733 if( (i % width) == (width - 1) ){ 00734 // if the value is in the last sample of the image, set values right to false 00735 legals[2] = false; 00736 legals[3] = false; 00737 legals[4] = false; 00738 } 00739 00740 return legals; 00741 00742 } 00743 00744 00745 void ImageShapeFinder::handlePoint(int i, std::vector<bool> &flags){ 00746 //std::vector<ImageCube::Pixel> temp = *(new std::vector<ImageCube::Pixel>()); 00747 std::vector<ImageCube::Pixel> temp; 00748 00749 //create a pixel for this 00750 ImageCube::Pixel fpix; 00751 fpix.x = (i % width); 00752 fpix.y = (i / width); 00753 00754 //push it into a vector 00755 temp.push_back(fpix); 00756 00757 //remove it from flags 00758 flags[i] = false; 00759 00760 //create a cube for this 00761 ImageSelectionCube* cube = (new ImageSelectionCube(fpix.x, fpix.y, 1, 1)); 00762 //ImageSelectionCube cube(fpix.x, fpix.y, 1, 1); 00763 cube->setSelection(temp); 00764 00765 00766 selections.push_back(cube); 00767 00768 } 00769 00770 00771 void ImageShapeFinder::handleLine(int i, std::vector<bool> &flags){ 00772 00773 if (adjacentBorderPixs(i, flags) == 0) return; 00774 00775 std::vector<ImageCube::Pixel> temp; 00776 00777 int j = i; 00778 00779 int num = adjacentBorderPixs(j, flags) ; 00780 00781 int hx, lx, hy, ly; 00782 00783 hx = lx = (j % width); 00784 hy = ly = (j / width); 00785 00786 //while each borderPixel has only one adjacent we have a line 00787 while((j!=-1) && num == 1) { 00788 00789 //create a Pixel for this 00790 ImageCube::Pixel fpix; 00791 fpix.x = (j % width); 00792 fpix.y = (j / width); 00793 00794 //push it 00795 temp.push_back(fpix); 00796 00797 flags[j] = false; 00798 00799 //use for determining the box that contains this line 00800 if(fpix.x > hx) { 00801 hx = fpix.x; 00802 } 00803 else if (fpix.x < lx) { 00804 lx = fpix.x; 00805 } 00806 00807 if(fpix.y > hy) { 00808 hy = fpix.y; 00809 } 00810 else if (fpix.y < ly) { 00811 ly = fpix.y; 00812 } 00813 00814 j = nextBorderPoint(j, flags); 00815 num = adjacentBorderPixs(j, flags) ; 00816 } 00817 00818 //if we've reached a point where there's no adjacent border pix, it's the end 00819 if(num == 0){ 00820 00821 ImageCube::Pixel fpix; 00822 fpix.x = (j % width); 00823 fpix.y = (j / width); 00824 00825 temp.push_back(fpix); 00826 00827 flags[j] = false; 00828 00829 } 00830 00831 //create cube 00832 ImageSelectionCube* cube = (new ImageSelectionCube(lx-1, ly-1, (hx-lx)+1, (hy-ly)+1)); 00833 cube->setSelection(temp); 00834 selections.push_back(cube); 00835 00836 } 00837 00838 00839 void ImageShapeFinder::handlePoly(int i, std::vector<bool> &flags){ 00840 std::vector<ImageCube::Pixel> temp; 00841 00842 int j = i; 00843 int num = adjacentBorderPixs(j, flags) ; 00844 int hx, lx, hy, ly; 00845 00846 00847 // set l and h x/y to the current pixel location 00848 // (convert from 1-dimensional array coordinates to 00849 // 2-dimensional image coordinates) 00850 hx = lx = (j % width); 00851 hy = ly = (j / width); 00852 00853 //bool leavelast = true; 00854 00855 // push the first pixel into the polygon structure 00856 ImageCube::Pixel fpix; 00857 fpix.x = (j % width); 00858 fpix.y = (j / width); 00859 00860 temp.push_back(fpix); 00861 00862 // get border pixel next to input 00863 j = nextBorderPoint(j, flags); 00864 num = adjacentBorderPixs(j, flags) ; 00865 00866 //while each borderPixel has at least one adjacent, we're tracing a poly 00867 while((j!=-1) && num != 0 ){ 00868 00869 // set mpix to the current pixel location 00870 // (convert from 1-dimensional array coordinates to 00871 // 2-dimensional image coordinates) 00872 ImageCube::Pixel mpix; 00873 mpix.x = (j % width); 00874 mpix.y = (j / width); 00875 00876 temp.push_back(mpix); 00877 00878 //** 00879 //if the line splits, or this is the beginning, 00880 //we may need this pixel later. so we only kill it 00881 //if there's only one direction to go 00882 00883 //flags[j] = false; 00884 00885 if(num <= 1) { 00886 flags[j] = false; 00887 } 00888 00889 /* 00890 else if(leavelast && num == 2){ 00891 flags[j] = false; 00892 leavelast = false; 00893 } 00894 00895 else if(num > 1) { 00896 leavelast = true; 00897 flags[j] = true; 00898 } 00899 */ 00900 00901 flags[j] = false; 00902 00903 //use for determining bounding box 00904 // (mpix is current pixel, l/h x/y were set to input pixel) 00905 if(mpix.x > hx) { 00906 hx = mpix.x; 00907 } 00908 else if (mpix.x < lx) { 00909 lx = mpix.x; 00910 } 00911 00912 if(mpix.y > hy) { 00913 hy = mpix.y; 00914 } 00915 else if (mpix.y < ly) { 00916 ly = mpix.y; 00917 } 00918 00919 // get the border pixel next to the current one 00920 j = nextBorderPoint(j, flags); 00921 num = adjacentBorderPixs(j, flags) ; 00922 00923 // if this is the end of the line and we're not close to the starting pixel, walk 00924 // back to where we branched off and chop this section off as its own line 00925 if (num == 0 && (abs(fpix.x - (j % width)) <= 2 && abs(fpix.y - (j / width)) <= 2) ) { 00926 00927 flags[j] = false ; 00928 std::vector<ImageCube::Pixel> templine ; 00929 00930 // prepare to walk backwards in case we've reached the end 00931 // and check for other routes to trace 00932 int t = j ; 00933 int tNum = adjacentBorderPixs(t, flags) ; 00934 vector<ImageCube::Pixel>::iterator stepback = temp.end () - 1 ; 00935 vector<ImageCube::Pixel>::iterator stepbackPrev = stepback ; 00936 00937 // walk backwards until a pixel with adj border pixels is found 00938 // and start processing from there to pick up the funny corners 00939 // and dangling hairs 00940 while (tNum == 0 && stepback >= temp.begin()) { 00941 t = ( (*stepback).y * width + (*stepback).x ) ; 00942 tNum = adjacentBorderPixs(t, flags) ; 00943 00944 templine.push_back(*stepback) ; 00945 00946 stepback = temp.end() - 1 ; 00947 if (stepback == stepbackPrev) { 00948 break ; 00949 } 00950 stepbackPrev = stepback ; 00951 //temp.erase(stepbackPrev, stepbackPrev) ; 00952 } 00953 00954 // push line chopped off our polygon into selections 00955 if (templine.size() >= 2) { 00956 ImageSelectionCube* cube = (new ImageSelectionCube(lx-1, ly-1, (hx-lx)+1, (hy-ly)+1)); 00957 cube->setSelection(templine); 00958 selections.push_back(cube); 00959 } 00960 00961 // reset values to pixel found during step-back search 00962 if (tNum != 0) { 00963 j = t ; 00964 num = adjacentBorderPixs(j, flags) ; 00965 } 00966 } 00967 00968 } // end while 00969 00970 //if we've reached a point where there's no adjacent border pix, it's the end 00971 // todo dls didn't we push this pixel already? should this be the starting pixel? 00972 00973 //if(num == 0 && j >= 0) { 00974 ImageCube::Pixel lpix; 00975 lpix.x = (j % width) ; 00976 lpix.y = (j / width) ; 00977 00978 temp.push_back(lpix) ; 00979 flags[j] = false ; 00980 //} 00981 00982 // if the last pixel is close to the first pixel, close the polygon 00983 // by pushing the first pixel into the selection 00984 if (abs(lpix.x - fpix.x) <= 10 && abs(lpix.y - fpix.y) <= 10 ) { 00985 temp.push_back(fpix) ; 00986 } 00987 00988 00989 00990 //temp.push_back(fpix); 00991 00992 00993 ImageSelectionCube* cube = (new ImageSelectionCube(lx-1, ly-1, (hx-lx)+1, (hy-ly)+1)); 00994 cube->setSelection(temp); 00995 selections.push_back(cube); 00996 00997 } 00998 00999 01000
Home |
Search |
Disclaimers & Privacy |
Contact Us GLIMSView Maintainer: dsoltesz@usgs.gov |