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