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