1: #include < GL/glut.h > 2: #include < stdlib.h > 3: #include < stdio.h > 4: #include < string.h > 5: #include < math.h > 6: #include < iostream.h > 7: 8: #define Round(v) ((int)(v+0.5)) 9: #define MAX 800 10: #define MAX_FILE_LENGTH 256 11: 12: #define LOW_VALUE 0 13: #define HIGH_VALUE 255 14: 15: #define TRUE 1 16: #define FALSE 0 17: 18: /*number of chain codes stored*/ 19: #define MAX_CHAINS 20 20: 21: /*cartesian coordinate type*/ 22: typedef struct {int x; 23: int y;}coord; 24: 25: /*RGB color struct with floats*/ 26: /*typedef struct {float red; 27: float green; 28: float blue; 29: }RGB; 30: */ 31: /*RGB color struct with ints*/ 32: typedef struct {int red; 33: int green; 34: int blue; 35: }RGB_INT; 36: 37: /*These constant values are the chain code directions*/ 38: #define NONE -1 39: #define EAST 0 40: #define NORTHEAST 1 41: #define NORTH 2 42: #define NORTHWEST 3 43: #define WEST 4 44: #define SOUTHWEST 5 45: #define SOUTH 6 46: #define SOUTHEAST 7 47: 48: typedef struct chainCode* chain_t; 49: typedef struct chainCode 50: { 51: chain_t prev; 52: int code; 53: coord location; //absolute pixel location for starting point 54: chain_t next; 55: }; 56: 57: 58: struct PGMstructure 59: { 60: int maxVal; 61: int width; 62: int height; 63: RGB_INT data[MAX][MAX]; 64: }; 65: 66: typedef struct PGMstructure PGMImage; 67: 68: /*Evil globals, but not do-able otherwise.*/ 69: static PGMImage *img_cur; 70: static PGMImage *img0; /*original*/ 71: static PGMImage *img1; /*current*/ 72: static PGMImage *img2; /*current*/ 73: static int HSIZE; 74: static int VSIZE; 75: static int MVAL; 76: 77: 78: 79: 80: /**************Drawing funcitions************************************/ 81: /********************************************************************/ 82: 83: void setCPixel(int ix, int iy, RGB_INT color) 84: /*Same as setIPixel except that the last parameter is an RGB color*/ 85: { 86: float x = (ix*2.0)/HSIZE - 1.0; 87: float y = (iy*2.0)/VSIZE - 1.0; 88: 89: float red = (float)color.red/(float)MVAL; 90: float green = (float)color.green/(float)MVAL; 91: float blue = (float)color.blue/(float)MVAL; 92: 93: glColor3f(red, green, blue); 94: 95: glBegin(GL_POINTS); 96: glVertex2f (x, y); 97: glEnd(); 98: } 99: 100: void setCLines(int ix1, int iy1, int ix2, int iy2, RGB_INT color) 101: /*Similar as setIPixel except that this one draws a line between the first set 102: of points given and the second set in the RGB color specified*/ 103: { 104: float x1 = (ix1*2.0)/HSIZE - 1.0; 105: float y1 = (iy1*2.0)/VSIZE - 1.0; 106: float x2 = (ix2*2.0)/HSIZE - 1.0; 107: float y2 = (iy2*2.0)/VSIZE - 1.0; 108: 109: float red = (float)color.red/(float)MVAL; 110: float green = (float)color.green/(float)MVAL; 111: float blue = (float)color.blue/(float)MVAL; 112: 113: glColor3f(red, green, blue); 114: 115: glBegin(GL_LINES); 116: glVertex2f (x1, y1); 117: glVertex2f (x2, y2); 118: glEnd(); 119: } 120: 121: void pxlcpy(PGMImage *dest, int dest_row, int dest_col, 122: PGMImage *src, int src_row, int src_col) 123: { 124: /*make sure values are within bounds*/ 125: if(dest_col > 0 && dest_col < (*dest).width 126: && dest_row > 0 && dest_row < (*dest).height 127: && src_col > 0 && src_col < (*src).width 128: && src_row > 0 && src_row < (*src).height) 129: { 130: (*dest).data[dest_row][dest_col].red = 131: (*src).data[src_row][src_col].red; 132: 133: (*dest).data[dest_row][dest_col].green = 134: (*src).data[src_row][src_col].green; 135: 136: (*dest).data[dest_row][dest_col].blue = 137: (*src).data[src_row][src_col].blue; 138: } 139: } 140: 141: bool pxlcmp(RGB_INT pxl1, RGB_INT pxl2, int range) 142: { 143: return ((abs(pxl1.red - pxl2.red) < range) && 144: (abs(pxl1.green - pxl2.green) < range) && 145: (abs(pxl1.blue - pxl2.blue) < range)); 146: } 147: 148: int rgb_avg(RGB_INT cur_pxl) 149: { 150: /*convert each RGB to the average of the original*/ 151: return ((cur_pxl.red + cur_pxl.green + cur_pxl.blue) / 3); 152: } 153: 154: /******CHAIN CODE************************************************ 155: ****************************************************************/ 156: 157: /*returns NONE if the chain code loops around itself, otherwise false*/ 158: int checkCode(chainCode* beginning, int x_current, int y_current, int x_check, 159: int y_check, int dir) 160: { 161: chainCode* currentNode = beginning; 162: 163: while(currentNode && currentNode- >next) 164: { 165: if((currentNode- >location.x == x_current) && 166: (currentNode- >location.y == y_current) && 167: (currentNode- >code == dir) && 168: (currentNode- >next- >location.x == x_check) && 169: (currentNode- >next- >location.y == y_check)) 170: return NONE; 171: else 172: currentNode = currentNode- >next; 173: } 174: return FALSE; 175: 176: } 177: 178: /*This function is the intermediate function call during the recursion of the 179: chain code calculation. 180: Preconditions: 181: 1st parameter: integer value containing the current direction code. 182: 2nd parameter: integer value containing the potentially new direction code. 183: 3rd parameter: integer value containing the current x coordinate. 184: 4th parameter: integer value containing the current y coordinate. 185: 5th parameter: pointer to the linked list of the chain code. 186: 6th parameter: pointer to the pgm image being used. 187: Postconditions: The pixel is drawn and if the checked pixel is a boarder pixel 188: true is returned, otherwise false is returned.*/ 189: int checkThings(int *dir, int next, int x_current, int y_current, int x_check, 190: int y_check, chainCode **theChain, PGMImage *img, chainCode **beginning) 191: { 192: chainCode *temp; 193: const RGB_INT chainColor = {0, 0, 255}; 194: 195: /*check for being in bounds*/ 196: if((x_check < 0) || (y_check < 0) || (x_check >= (*img).width) || 197: (y_check >= (*img).height)) 198: return FALSE; 199: 200: /*test condition for the end.*/ 201: else if(checkCode(*beginning, x_current, y_current, x_check, y_check, 202: *dir) == NONE) 203: { 204: *dir = NONE; 205: return FALSE; 206: } 207: 208: /*tests if the next pixel is a boundry pixel. If so does stuff*/ 209: if(pxlcmp((*img).data[y_current][x_current], 210: (*img).data[y_check][x_check], 20)) 211: { 212: setCPixel(x_check, y_check, chainColor); 213: glFlush(); 214: *dir = next; 215: temp = (chain_t)malloc(sizeof(chainCode)); 216: temp- >next = NULL; 217: temp- >code = *dir; 218: temp- >location.x = x_check; 219: temp- >location.y = y_check; 220: temp- >prev = *theChain; 221: if(*theChain) 222: (*theChain)- >next = temp; /*now this is a good thing to set.*/ 223: *theChain = temp; /*advance one*/ 224: 225: if(*beginning == NULL) 226: *beginning = *theChain;/*set this for the first node in the list once*/ 227: return TRUE; 228: } 229: return FALSE; 230: } 231: 232: /*determines the chain code for a starting pixel*/ 233: /*this chain code uses 8 connectivity*/ 234: /*Note: There are many different coordinate systems at work in this function.*/ 235: /*The (*img).data[][] are column major and have are therefore [y][x] or [j][i]*//* This is also asuming (0,0) is bottom left, where the other code assumes 236: /* top left is (0, 0). If it looks strange, look harder!!!*/ 237: /*Preconditions: 238: 1st parameter: pointer to the pgm image being used. 239: 2nd parameter: integer value containing the current x coordinate. 240: 3rd parameter: integer value containing the current y coordinate. 241: 4th parameter: integer value containing the current direction code. 242: 5th parameter: pointer to the linked list of the chain code.*/ 243: 244: /*This function assumes the (0, 0) point is in the lower left*/ 245: 246: int chaincode(PGMImage *img, int x, int y, int dir, chainCode** theChain, 247: chainCode** beginning) 248: { 249: int i; /*loop counting*/ 250: int initial, next, finished; 251: 252: if(dir % 2) /*if dir is odd*/ 253: initial = (dir + 6) % 8; 254: else /*if dir is even*/ 255: initial = (dir + 7) % 8; 256: 257: next = initial; /*set the next direction to search*/ 258: /*printf("next: %d x: %d y: %d\n", next, x, y); */ 259: for(i = 0; i < 8; i++) 260: { 261: if(next == EAST) 262: { 263: if(checkThings(&dir, EAST, x, y, x + 1, y, theChain, img, beginning)) 264: finished = chaincode(img, x + 1, y, dir, theChain, beginning); 265: } 266: else if(next == NORTHEAST) 267: { 268: 269: if(checkThings(&dir, NORTHEAST, x, y, x + 1, y + 1, theChain, img, 270: beginning)) 271: finished = chaincode(img, x + 1, y + 1, dir, theChain, beginning); 272: } 273: else if(next == NORTH) 274: { 275: if(checkThings(&dir, NORTH, x, y, x, y + 1, theChain, img, 276: beginning)) 277: finished = chaincode(img, x, y + 1, dir, theChain, beginning); 278: } 279: else if(next == NORTHWEST) 280: { 281: if(checkThings(&dir, NORTHWEST, x, y, x - 1, y + 1, theChain, img, 282: beginning)) 283: finished = chaincode(img, x - 1, y + 1, dir, theChain, beginning); 284: } 285: else if(next == WEST) 286: { 287: if(checkThings(&dir, WEST, x, y, x - 1, y, theChain, img, beginning)) 288: finished = chaincode(img, x - 1, y, dir, theChain, beginning); 289: } 290: else if(next == SOUTHWEST) 291: { 292: if(checkThings(&dir, SOUTHWEST, x, y, x - 1, y - 1, theChain, img, 293: beginning)) 294: finished = chaincode(img, x - 1, y - 1, dir, theChain, beginning); 295: } 296: else if(next == SOUTH) 297: { 298: if(checkThings(&dir, SOUTH, x, y, x, y - 1, theChain, img,beginning)) 299: finished = chaincode(img, x, y - 1, dir, theChain, beginning); 300: } 301: else if(next == SOUTHEAST) 302: { 303: if(checkThings(&dir, SOUTHEAST, x, y, x + 1, y - 1, theChain, img, 304: beginning)) 305: finished = chaincode(img, x + 1, y - 1, dir, theChain, beginning); 306: } 307: 308: /*if the next chaincode function in the recursion or the current state 309: is the final state of the the chain code; recursively returns DONE 310: back through all the levels to stop the chain code.*/ 311: if(dir == NONE || finished == NONE) 312: return NONE; 313: /*set next for next iteration*/ 314: next = (next + 1) % 8; 315: } 316: 317: } 318: 319: /*returns true if the point is already in one of the chains, false otherwise*/ 320: int alreadyFound(int initThreashFlag, int i, int j, PGMImage* img, 321: chainCode** found, int count) 322: { 323: int k; 324: chainCode* temp; 325: /*this if statement determines if a pixel is not the background*/ 326: if(initThreashFlag != rgb_avg((*img).data[j][i])) /*collumn major*/ 327: { 328: /*Now search to determine if the pixel has been found already*/ 329: for(k = 0; k < = count; k++) 330: { 331: temp = (found[k]); 332: while(temp) 333: {/* if point has already been found*/ 334: if((temp- >location.x == i) && (temp- >location.y == j)) 335: { 336: j = 0; /*does this work?*/ 337: return TRUE; 338: break; 339: } 340: temp = temp- >next; 341: } 342: } 343: } 344: return FALSE; 345: } 346: 347: /*saves a chain code to file. Was usefull during debuging now is just 348: a cool thing to leave in*/ 349: /*1st: pointer to beginning of a chaincode 350: 2nd: the index of the chain code for destiqushing the 'chain' files*/ 351: void saveChainCode(chainCode* saveChain, int count) 352: { 353: chainCode* temp = saveChain; 354: char filename[12]; 355: FILE* outfile; 356: sprintf(filename, "chain%d", count); 357: outfile = fopen(filename, "w"); /*output file for chaincode*/ 358: printf("Writing chain code to file %s.\n", filename); 359: 360: while(temp) 361: { 362: 363: fprintf(outfile, "%d %d %d\n",temp- >location.x,temp- >location.y, 364: temp- >code); 365: temp = temp- >next; 366: } 367: fclose(outfile); 368: } 369: 370: chainCode** showChain(PGMImage *original) 371: { 372: int i, j; /*loop counting*/ 373: int initThreashFlag = 128, foundFlag = TRUE; 374: RGB_INT chainColor = {255, 0, 255}, tempColor = {255, 0, 0}; 375: chainCode** beginning, *chain = NULL, *temp, *next_tmep, *temp_loop; 376: beginning = (chainCode**) malloc (MAX_CHAINS * sizeof(chainCode*)); 377: int count = 0; /*array index holder*/ 378: /*Need a temporary threasholded image*/ 379: /*PGMImage *threashed = (PGMImage*) malloc(sizeof(PGMImage)); 380: */ 381: glPointSize(4); /*make points more visible*/ 382: 383: /*showThreashold(original, threashed);*/ 384: 385: /*Use starting pixel as defualt. This is partially based on the fact that 386: most likely a corner will be background and not an object.*/ 387: /*the image assumes that (0, 0) is in the bottom left, I assume that 388: (0, 0) is in the upper left. This is handled here.*/ 389: /*initThreashFlag = (*threashed).data[(*threashed).height - 1][0];*/ 390: 391: for(i = 0; i < 10; i++) beginning[i] = NULL;/*initailize pointer array.*/ 392: 393: /*search image until a pixel is found with threasholded value of the 394: object. i & j will then contain the starting coordinate.*/ 395: for(i = 0; i < (*original).width; i++) 396: { 397: for(j = (*original).height - 1; j >= 0; j--) 398: { 399: /*skip to the next iteration*/ 400: if(rgb_avg((*original).data[j][i]) < initThreashFlag) 401: { 402: continue; 403: } 404: /*skip to the next iteration, which will be at the top of the next 405: collumn*/ 406: else if(alreadyFound(initThreashFlag, i, j, original, beginning, 407: count)) 408: { 409: j = 0; /*reseting to make this the last iteration without reseting 410: search to the top of next collumn*/ 411: continue; 412: } 413: else 414: { 415: printf("chaincode: %d\n", count); 416: /*printf("The starting coordinate is (x, y): (%d, %d)\n", i, j);*/ 417: chain = NULL; /*reset this to seperate the chaincodes*/ 418: /*find the chaincode for the current starting pixel*/ 419: chaincode(original, i, j, SOUTHEAST, &chain, &beginning[count]); 420: if(beginning[count] != NULL) /*avoid writing zero length chains*/ 421: { 422: saveChainCode(beginning[count], count); 423: count++; /*advance the beginning counter*/ 424: } 425: /*force end of loops, leaving code when finished looping 426: to still execute*/ 427: if(count >= MAX_CHAINS) 428: i = (*original).width; 429: j = 0; /*reset search to start at top on next pass. This the 430: setting for stopping condition for the current j loop.*/ 431: break; /*Quick fix?*/ 432: } 433: } 434: } 435: printf("Done finding chain code(s). %d were found.\n", count); 436: return beginning; 437: } 438: 439: 440: /**********************File I/O functions*******************************/ 441: /***********************************************************************/ 442: 443: /*Gets an ascii color pgm image file (type P3).*/ 444: void getPGMfile (char filename[], PGMImage *img) 445: { 446: FILE *in_file; 447: char ch; 448: int row, col; 449: 450: in_file = fopen(filename, "r"); 451: if (in_file == NULL) 452: { 453: fprintf(stderr, "Error: Unable to open file %s\n\n", filename); 454: exit(8); 455: } 456: 457: printf("\nReading image file: %s", filename); 458: 459: do /* skip header identifier */ 460: ch = getc(in_file); 461: while (ch != '\n'); 462: 463: do /* skip comments lines */ 464: { 465: while (ch != '\n') ch = getc(in_file); /* flush to end of line */ 466: ch = getc(in_file); 467: } while (ch == '#'); 468: 469: fseek(in_file, -1, SEEK_CUR); /* backup one character */ 470: 471: fscanf(in_file,"%d", &((*img).width)); 472: fscanf(in_file,"%d", &((*img).height)); 473: fscanf(in_file,"%d", &((*img).maxVal)); 474: 475: printf("\n width = %d",(*img).width); 476: printf("\n height = %d",(*img).height); 477: printf("\n maxVal = %d",(*img).maxVal); 478: printf("\n"); 479: 480: if (((*img).width > MAX) || ((*img).height > MAX)) 481: { 482: printf("\n\n***ERROR - image too big for current image structure***\n\n"); 483: exit(0); 484: } 485: 486: for (row=(*img).height-1; row >=0; row--) 487: for (col=0; col< (*img).width; col++) 488: { 489: fscanf(in_file,"%d", &((*img).data[row][col].red) ); 490: fscanf(in_file,"%d", &((*img).data[row][col].green)); 491: fscanf(in_file,"%d", &((*img).data[row][col].blue)); 492: } 493: fclose(in_file); 494: printf("\nDone reading file.\n"); 495: } 496: 497: 498: void save(PGMImage *img) 499: { 500: int i, j, nr, nc, k; 501: int red, green, blue; 502: FILE *iop; 503: 504: nr = img- >height; 505: nc = img- >width; 506: 507: iop = fopen("image1.pgm", "w"); 508: fprintf(iop, "P3\n"); 509: fprintf(iop, "%d %d\n", nc, nr); 510: fprintf(iop, "255\n"); 511: 512: k = 1; 513: for(i = nr - 1; i >= 0; i--) 514: { 515: for(j = 0; j < nc; j++) 516: { 517: red = img- >data[i][j].red; 518: green = img- >data[i][j].green; 519: blue = img- >data[i][j].blue; 520: if(red < 0) 521: { 522: printf("IMG_WRITE: Found value %d at row %d col %d\n", red, i, j); 523: printf(" Setting red to zero\n"); 524: red = 0; 525: } 526: if(green < 0) 527: { 528: printf("IMG_WRITE: Found value %d at row %d col %d\n", green,i, j); 529: printf(" Setting green to zero\n"); 530: green = 0; 531: } 532: if(blue < 0) 533: { 534: printf("IMG_WRITE: Found value %d at row %d col %d\n", blue, i, j); 535: printf(" Setting green to zero\n"); 536: blue = 0; 537: } 538: if(red > 255) 539: { 540: printf("IMG_WRITE: Found value %d at row %d col %d\n", red, i, j); 541: printf(" Setting red to 255\n"); 542: red = 255; 543: } 544: if(green > 255) 545: { 546: printf("IMG_WRITE: Found value %d at row %d col %d\n", green,i, j); 547: printf(" Setting green to 255\n"); 548: green = 255; 549: } 550: if(blue > 255) 551: { 552: printf("IMG_WRITE: Found value %d at row %d col %d\n", blue, i, j); 553: printf(" Setting blue to 255\n"); 554: blue = 255; 555: } 556: 557: if(k % 10) 558: { 559: fprintf(iop, "%d ", red); 560: fprintf(iop, "%d ", green); 561: fprintf(iop, "%d ", blue); 562: } 563: else /*for newline*/ 564: { 565: fprintf(iop, "%d\n", red); 566: fprintf(iop, "%d\n", green); 567: fprintf(iop, "%d\n", blue); 568: } 569: k++; 570: } 571: } 572: fprintf(iop, "\n"); 573: fclose(iop); 574: } 575: 576: 577: 578: 579: /****Calculation & drawing functions of the image translations********** 580: ***********************************************************************/ 581: 582: 583: void showColor (PGMImage *img) 584: { 585: int row, col; /*y, x*/ 586: /*for (row=(*img).height-1; row >=0; row--) 587: for (col=0; col< (*img).width; col++) 588: { 589: 590: setCPixel(col, row, (*img).data[row][col]); 591: }*/ 592: 593: int i, j; /*loop counting: i = x, j = y*/ 594: int mid_width = ((*img).width / 2); 595: int mid_height = ((*img).height / 2); 596: 597: for(i = 0; i < mid_width / 2; i++) 598: { 599: for(j = 0; j < mid_height; j++) 600: { 601: /*inorder they are: 602: bottom left, bottom middle right, top left, top m right, 603: bottom middle left, bottom right, top middle left, top right.*/ 604: 605: setCPixel(i, j, (*img).data[j][i]); 606: setCPixel(i + mid_width, j, (*img).data[j][i + mid_width]); 607: setCPixel(i, j + mid_height, (*img).data[j + mid_height][i]); 608: setCPixel(i + mid_width, j + mid_height, 609: (*img).data[j + mid_height][i + mid_width]); 610: 611: setCPixel(mid_width - i - 1, j, 612: (*img).data[j][mid_width - i - 1]); 613: setCPixel((*img).width - i - 1, j, 614: (*img).data[j][(*img).width - i - 1]); 615: setCPixel(mid_width - i - 1, (*img).height - j - 1, 616: (*img).data[(*img).height - j - 1][mid_width - i - 1]); 617: setCPixel((*img).width - i - 1, (*img).height - j - 1, 618: (*img).data[(*img).height - j - 1][(*img).width - i - 1]); 619: } 620: } 621: 622: glFlush (); 623: } 624: 625: void camera_correction(PGMImage* new_img, PGMImage* org_img) 626: { 627: int row, col, img_row, img_col; /*loop counting*/ 628: 629: /*camera parameters*/ 630: float height = 30; /*height of camera in cm*/ 631: float gamma = 0, theta = .698; /*camera angles = 40 degrees in rad*/ 632: float aperture = 1.1968, alpha = .598; /*aperature = 2 * alpha*/ 633: 634: /*temporary varaibles*/ 635: float angular_height_corr; 636: float angular_side_corr; 637: int x_coord, y_coord; 638: 639: memset(new_img, 0, sizeof(PGMImage)); 640: (*new_img).height = (*org_img).height; 641: (*new_img).width = (*org_img).width; 642: (*new_img).maxVal = (*org_img).maxVal; 643: 644: for (row=(*org_img).height-1; row >=0; row--) 645: for (col=0; col< (*org_img).width; col++) 646: { 647: /*img_row -= (*org_img).height / 2; 648: img_col = col - (*org_img).width / 2;*/ 649: 650: angular_height_corr = 651: (theta - alpha) + col * (aperture / ((float)((*org_img).width) - 1)); 652: angular_side_corr = 653: (gamma - alpha) + row * (aperture / ((float)((*org_img).height) - 1)); 654: 655: angular_height_corr /= 2; 656: /*angular_side_corr /= 2;*/ 657: /*height *= 2;*/ 658: height = 150; 659: 660: x_coord = (int) 661: height * (1 / tan(angular_height_corr)) * cos(angular_side_corr); 662: y_coord = (int) 663: height * (1 / tan(angular_height_corr)) * sin(angular_side_corr); 664: 665: /*x_coord += (*org_img).width / 2;*/ 666: y_coord += (*org_img).height / 2; 667: 668: /*printf("org: (%d, %d) new: (%d, %d)\n\n", row, col, y_coord, x_coord);*/ 669: 670: pxlcpy(new_img, y_coord, x_coord, org_img, row, col); 671: } 672: } 673: 674: void new_corr(PGMImage* new_img, PGMImage* org_img) 675: { 676: /*i and j are the left half, k and l are the right half*/ 677: float i, k; /*loop counting*/ 678: int j, l, row; /*loop counting*/ 679: int old_i, old_k; 680: 681: float ins_s = 2; /*insert constant starting value*/ 682: float ins_k = ins_s; /*insert constant*/ 683: 684: /*The halfway marks in the width.*/ 685: int mid_width_left = ((*new_img).width / 2) - 1; 686: int mid_width_right = ((*new_img).width / 2); 687: 688: /*just to be thourough clear the memory and reset maxes*/ 689: memset(new_img, 0, sizeof(PGMImage)); 690: (*new_img).height = (*org_img).height; 691: (*new_img).width = (*org_img).width; 692: (*new_img).maxVal = (*org_img).maxVal; 693: 694: /*Loop through each row from top to bottom...*/ 695: for(row = ((*new_img).height - 1); row >= 0; row--) 696: { 697: /*...reset moire interference removal counter...*/ 698: old_i = ((*new_img).width / 2) - 1; 699: old_k = ((*new_img).width / 2); 700: 701: /*...so each half is ajusted to remove perspective effect...*/ 702: for(i = j = mid_width_left, k = l = mid_width_right 703: ; i >= 0, j >= 0, k < (*new_img).width, l < (*new_img).width 704: ; i -= ins_k, j--, k += ins_k, l++) 705: { 706: for(;old_i >= (int)i; old_i--) /*...in the left half...*/ 707: pxlcpy(new_img, row, old_i, org_img, row, j); 708: for(;old_k < = (int)k; old_k++) /*...in the right half.*/ 709: pxlcpy(new_img, row, old_k, org_img, row, l); 710: } 711: /*Move the new image x_coord pixel counter to next new image pixel*/ 712: ins_k -= ((ins_s - 1.0) / (*new_img).height); 713: } 714: } 715: 716: void color_to_gray(PGMImage* new_img, PGMImage* org_img) 717: { 718: int row, col; /*loop counting*/ 719: RGB_INT cur_pxl; /*current pixel*/ 720: 721: (*new_img).height = (*org_img).height; 722: (*new_img).width = (*org_img).width; 723: (*new_img).maxVal = (*org_img).maxVal; 724: 725: /*Starting with the top row...*/ 726: for(row = (*new_img).height - 1; row >= 0; row--) 727: for(col = 0; col < (*new_img).width - 1; col++) 728: { 729: cur_pxl = (*org_img).data[row][col]; /*more readable*/ 730: 731: /*convert each RGB to the average of the original*/ 732: (*new_img).data[row][col].red = rgb_avg(cur_pxl); 733: (*new_img).data[row][col].green = rgb_avg(cur_pxl); 734: (*new_img).data[row][col].blue = rgb_avg(cur_pxl); 735: } 736: } 737: 738: void moravec(PGMImage* new_img, PGMImage* org_img) 739: { 740: int row, col; /*loop counting*/ 741: int i, j, k, l; /*Sanka, Hlavac & Boyle; p. 97 f. 4.73*/ 742: int running_sum; 743: float K = .5; /*.125 according to org. formula, but .5 is brighter*/ 744: int max_val = 0, row_max, col_max; /* max porportion value in image*/ 745: RGB_INT corner_color = {0, 255, 0}; 746: 747: memset(new_img, 0, sizeof(PGMImage)); 748: (*new_img).height = (*org_img).height; 749: (*new_img).width = (*org_img).width; 750: (*new_img).maxVal = (*org_img).maxVal; 751: 752: /*starting at the top row*/ 753: for(row = (*new_img).height - 1 - 1; row > 0; row--) 754: for(col = 1; col < (*new_img).width - 1; col++) /*left col start*/ 755: { 756: i = row; 757: j = col; 758: running_sum = 0; 759: 760: /*Sanka, Hlavac & Boyle; p. 97 f. 4.73*/ 761: for(k = i - 1; k < = i + 1; k++) /*row*/ 762: for(l = j - 1; l < = j + 1; l++) /*column*/ 763: running_sum += abs(rgb_avg((*org_img).data[k][l]) - 764: rgb_avg((*org_img).data[i][j])); 765: 766: /*assign the new pixel value*/ 767: (*new_img).data[row][col].red = (int)(K * running_sum); 768: (*new_img).data[row][col].green = (int)(K * running_sum); 769: (*new_img).data[row][col].blue = (int)(K * running_sum); 770: } 771: } 772: 773: void detect_corners(PGMImage* org_img) 774: { 775: chainCode **chain_codes; 776: 777: chain_codes = showChain(org_img); 778: } 779: 780: /* ================================================================= 781: * Callback functions. 782: * 783: * color = displayed graphics in window 784: * menu = menu event handling 785: * keyboard = deyboard event handling 786: * ----------------------------------------------------------------- */ 787: void color(void) 788: { 789: /*glClear (GL_COLOR_BUFFER_BIT);*/ 790: 791: /* printf("\nDrawing Original image...\n");*/ 792: showColor(img_cur); 793: 794: /*glFlush();*/ 795: } 796: 797: #define RESTART 0 798: #define CAMERA_CORRECTION 1 799: #define X2_C_CORR 2 800: #define NEW_CORR 3 801: #define COLOR_TO_GRAY 4 802: #define MORAVEC 5 803: #define CORNERS 6 804: 805: void menu(int selection) 806: { 807: if(selection == RESTART) 808: { 809: memcpy(img1, img0, sizeof(PGMImage)); 810: img_cur = img0; 811: } 812: if(selection == CAMERA_CORRECTION) 813: { 814: printf("Starting camera correction\n"); 815: camera_correction(img1, img0); 816: img_cur = img1; 817: } 818: if(selection == X2_C_CORR) 819: { 820: printf("Starting camera correction\n"); 821: camera_correction(img1, img0); 822: camera_correction(img2, img1); 823: img_cur = img2; 824: } 825: if(selection == NEW_CORR) 826: { 827: new_corr(img1, img0); 828: img_cur = img1; 829: } 830: if(selection == COLOR_TO_GRAY) 831: { 832: color_to_gray(img1, img0); 833: img_cur = img1; 834: } 835: if(selection == MORAVEC) 836: { 837: moravec(img1, img0); 838: img_cur = img1; 839: } 840: if(selection == CORNERS) 841: { 842: /*new_corr(img1, img0); 843: moravec(img2, img1);*/ 844: detect_corners(img0); 845: img_cur = img0; 846: return; 847: } 848: /*glClear (GL_COLOR_BUFFER_BIT);*/ 849: showColor(img_cur); 850: glutPostRedisplay(); 851: } 852: 853: void keyboard(unsigned char key, int x, int y) 854: { 855: switch (key) 856: { 857: case 27: 858: exit(0); 859: break; 860: } 861: } 862: 863: /* ================================================================= 864: * init - initializes graphics viewport 865: * 866: * You should not have to change this function for the first few 867: * projects we have. It will become more important when we move to 868: * 3D graphics. 869: * ----------------------------------------------------------------- */ 870: void init (void) 871: { 872: 873: /* 874: * select clearing color - white 875: */ 876: glClearColor (1.0, 1.0, 1.0, 0.0); 877: 878: /* 879: * initialize viewport values 880: */ 881: glMatrixMode(GL_PROJECTION); 882: glLoadIdentity(); 883: glOrtho(-1.0, 1.0, -1.0, 1.0, -1.0, 1.0); 884: 885: /*add menus*/ 886: glutCreateMenu(menu); 887: glutAddMenuEntry("Restart", RESTART); 888: glutAddMenuEntry("Camera Correction", CAMERA_CORRECTION); 889: glutAddMenuEntry("2x C. Corr.", X2_C_CORR); 890: glutAddMenuEntry("new corr", NEW_CORR); 891: glutAddMenuEntry("color to gray", COLOR_TO_GRAY); 892: glutAddMenuEntry("moravec", MORAVEC); 893: glutAddMenuEntry("corners", CORNERS); 894: glutAttachMenu(GLUT_RIGHT_BUTTON); 895: } 896: 897: int main(int argc, char** argv) 898: { 899: char PGMfileName[MAX_FILE_LENGTH]; 900: 901: int WindowID; 902: 903: int i; /*looping variable*/ 904: 905: /*parse the command line*/ 906: if(argc == 1) 907: { 908: printf("To few parameters.\n"); 909: printf("Usage: research < file.pgm >\n"); 910: exit(1); 911: } 912: else if(argc == 2) 913: strcpy(PGMfileName, argv[1]); 914: else 915: { 916: printf("To many parameters.\n"); 917: printf("Usage: research < file.pgm >\n"); 918: exit(1); 919: } 920: /* 921: * Read in image file. - note: sets our global values, too. 922: * ----------------------------------------------------------------- */ 923: 924: img0 = (PGMImage*) malloc(sizeof(PGMImage)); 925: getPGMfile(PGMfileName, img0); 926: HSIZE = (*img0).width; 927: VSIZE = (*img0).height; 928: MVAL = (*img0).maxVal; 929: 930: img_cur = img0; /*VERY IMPORTANT to set this*/ 931: 932: /*allocate memory for second image*/ 933: img1 = (PGMImage*) malloc(sizeof(PGMImage)); 934: memcpy(img1, img0, sizeof(PGMImage)); 935: /*(*img1).width = HSIZE; 936: (*img1).height = VSIZE; 937: (*img1).maxVal = 255;*/ 938: 939: img2 = (PGMImage*) malloc(sizeof(PGMImage)); 940: memcpy(img2, img0, sizeof(PGMImage)); 941: 942: /* 943: * Initialize the glut package. 944: * ----------------------------------------------------------------- */ 945: glutInit(&argc, argv); 946: glutInitDisplayMode (GLUT_SINGLE | GLUT_RGB); 947: /* 948: * Define a new window (its size, position and title). 949: * ----------------------------------------------------------------- */ 950: glutInitWindowSize (HSIZE, VSIZE); /*size*/ 951: glutInitWindowPosition (10, 10); /*position*/ 952: WindowID = glutCreateWindow (PGMfileName); /*title*/ 953: glutSetWindow(WindowID); 954: glutDisplayFunc(color); 955: 956: /* 957: * Call our init function to define viewing parameters. 958: * ----------------------------------------------------------------- */ 959: init (); 960: 961: glutKeyboardFunc(keyboard); 962: glutMainLoop(); 963: 964: /* 965: * When we reach here, we've left the event loop and are ready to 966: * exit. 967: * ----------------------------------------------------------------- */ 968: return 0; 969: } 970: 971: 972: 973: 974: 975: 976: 977: 978: 979: 980: 981: 982: