RemapFilter: projection.c

File projection.c, 10.6 KB (added by fsluiter, 18 months ago)

Example to generate pgm files for front projection

Line 
1#include <stdio.h>
2#include <stdlib.h>
3#include <libgen.h>
4#include <string.h>
5#include <getopt.h>
6#include <math.h>
7
8
9
10/* Compile with: gcc projection.c -Wall -o project -lm
11 * math.h does not like to be linked directly...
12 */
13
14/* Flag set by ‘--verbose’. */
15static int verbose_flag;
16
17typedef struct double2{
18    double x;
19    double y;
20}double2;
21typedef struct double3{
22    double x;
23    double y;
24    double z;
25}double3;
26
27
28enum CameraMode {
29    FRONT,
30    FRONT235,
31    BACK,
32    UP,
33    DOWN,
34    SAMSUNG_GEAR_360,
35    THETAS
36};
37
38typedef struct configuration {
39    char* xmap_filename;
40    char* ymap_filename; 
41    int xmap_set;
42    int ymap_set;
43    int rows; // target
44    int cols; // target
45    int height; //source
46    int width;//source
47    int rows_set;
48    int cols_set;
49    int height_set;
50    int width_set;
51    int crop;
52    enum CameraMode mode;
53} configuration;
54
55configuration parse_options(int argc, char **argv){
56  int c;
57  configuration po; //to hold parsed options
58  po.xmap_filename=NULL;
59  po.ymap_filename=NULL;
60  po.xmap_set=0;
61  po.ymap_set=0;
62  po.rows=0;
63  po.cols=0;
64  po.rows_set=0;
65  po.cols_set=0;
66  po.height_set=0;
67  po.width_set=0;
68  po.mode=FRONT; //default
69
70  while (1)
71    {
72      static struct option long_options[] =
73        {
74          /* These options set a flag. */
75          {"verbose", no_argument,       &verbose_flag, 1},
76          {"brief",   no_argument,       &verbose_flag, 0},
77
78          /* These options don’t set a flag.
79             We distinguish them by their indices. */
80          {"help",  no_argument,       0, 'q'},
81
82          /* options with arg*/
83          {"xmap",    required_argument, 0, 'x'},
84          {"ymap",    required_argument, 0, 'y'},
85          {"rows",    required_argument, 0, 'r'},//target
86          {"cols",    required_argument, 0, 'c'},//target
87          {"height",  required_argument, 0, 'h'},//source
88          {"width",   required_argument, 0, 'w'},//source
89          {"mode",    required_argument, 0, 'm'},
90          {"crop",    required_argument, 0, 'b'},
91
92          {0, 0, 0, 0}
93        };
94      /* getopt_long stores the option index here. */
95      int option_index = 0;
96
97      c = getopt_long (argc, argv, "qx:y:r:c:h:w:m:b:",
98                       long_options, &option_index);
99
100      /* Detect the end of the options. */
101      if (c == -1)
102        break;
103
104      switch (c)
105        {
106        case 0:
107          /* If this option set a flag, do nothing else now. */
108          if (long_options[option_index].flag != 0)
109            break;
110          printf ("option %s", long_options[option_index].name);
111          if (optarg)
112            printf (" with arg %s", optarg);
113          printf ("\n");
114          break;
115
116        case 'x':
117          po.xmap_filename = optarg;
118          po.xmap_set++;
119          break;
120
121        case 'y':
122          po.ymap_filename = optarg;
123          po.ymap_set++;
124          break;
125        case 'h':
126          po.height = atoi(optarg);
127          po.height_set++;
128          break;
129        case 'w':
130          po.width = atoi(optarg);
131          po.width_set++;
132          break;
133        case 'c':
134          po.cols = atoi(optarg);
135          po.cols_set++;
136          break;
137        case 'r':
138          po.rows = atoi(optarg);
139          po.rows_set++;
140          break;
141        case 'b':
142          po.crop = atoi(optarg);
143          break;
144        case 'm':
145          if (strcmp(optarg, "front") == 0) 
146          {
147            po.mode = FRONT;
148          } 
149          else if (strcmp(optarg, "front235") == 0) 
150          {
151            po.mode = FRONT235;
152          } 
153          else if (strcmp(optarg, "down") == 0) 
154          {
155            po.mode = DOWN;
156          } 
157          else if (strcmp(optarg, "samsung_gear_360") == 0)
158          {
159            po.mode = SAMSUNG_GEAR_360;
160          }
161          else if (strcmp(optarg, "thetas") == 0)
162          {
163            po.mode = THETAS;
164          }
165          /* more else if clauses */
166          else /* default: */
167          {
168             printf("Camera mode %s not implemented \n",optarg); exit(1);
169          }
170          break;
171
172        case '?':
173          /* getopt_long already printed an error message. */
174        case 'q':
175          printf ("Usage: %s -x|--xmap FILE_x.pgm -y|--ymap FILE_y.pgm -h|--height 300 -w|--width 400 -r|--rows 600 -c|--cols 800 \n", argv[0]);
176          printf ("h,w is source size, r,c is targetsize \n");
177          exit(1);
178          break;
179
180        default:
181          abort ();
182        }
183    }
184
185  /* Instead of reporting ‘--verbose’
186     and ‘--brief’ as they are encountered,
187     we report the final status resulting from them. */
188  if(verbose_flag){
189    switch(po.mode){
190      case FRONT:   printf("Camera: Front proj\n"); break;
191      case FRONT235:   printf("Camera: Front 235 proj\n"); break;
192      case DOWN:   printf("Camera: Down proj\n"); break;
193      case SAMSUNG_GEAR_360: printf("Camera: samsung_gear_360\n"); break;
194      case THETAS: printf("Camera: Theta S\n"); break;
195      default: printf("Camera mode not in verbose, exiting\n"); exit(1);
196    }
197  }
198    /* Print any remaining command line arguments (not options). */
199    if (optind < argc)
200    {
201      printf ("ERROR: non-option ARGV-elements: ");
202      while (optind < argc)
203        printf ("%s ", argv[optind++]);
204      putchar ('\n');
205      exit(1);
206    }
207 
208    if(po.xmap_set!=1||po.ymap_set!=1){ printf("ERROR: Xmap and ymap are mandatory arguments and have to appear only once!\ntry --help for help\n\n ");exit(-1);}
209    if(po.rows_set!=1||po.cols_set!=1){ printf("ERROR: Target Rows and Cols are mandatory arguments and have to appear only once!\ntry --help for help\n\n ");exit(-1);}
210    if(po.height_set!=1||po.width_set!=1){ printf("ERROR: Source Height and Width are mandatory arguments and have to appear only once!\ntry --help for help\n\n ");exit(-1);}
211    return po;
212}
213
214#define MAXROWS 4500
215#define MAXCOLS 4500
216
217int pgmWrite_ASCII(char* filename, int rows,int cols,
218             int **image,char* comment_string) {
219      FILE* file;        /* pointer to the file buffer */
220//      int maxval;        /* maximum value in the image array */
221      long nwritten = 0; /* counter for the number of pixels written */
222      long x,y;          /* for loop counters */
223
224      /* return 0 if the dimensions are larger than the image array. */
225      if (rows > MAXROWS || cols > MAXCOLS) {
226           printf ("ERROR: row/col specifications larger than image array:\n");
227           return (0);
228      }
229
230      /* open the file; write header and comments specified by the user. */
231      if ((file = fopen(filename, "w")) == NULL)        {
232           printf("ERROR: file open failed\n");
233           return(0);
234      }
235      fprintf(file,"P2\n");
236
237      if (comment_string != NULL) fprintf(file,"# %s \n", comment_string);
238   
239      /* write the dimensions of the image */   
240      fprintf(file,"%i %i \n", cols, rows);
241
242      /* NOTE: MAXIMUM VALUE IS WHITE; COLOURS ARE SCALED FROM 0 - */
243      /* MAXVALUE IN A .PGM FILE. */
244     
245      /* WRITE MAXIMUM VALUE TO FILE */
246      fprintf(file, "%d\n", (int)65535);
247
248      /* Write data */
249
250  for (y = 0; y<rows;y++){
251    for (x = 0; x < cols; x++){
252      fprintf(file,"%i ",image[y][x]);
253      nwritten++;
254    }
255  fprintf(file,"\n");
256  }
257  fprintf(file,"\n");
258
259     
260      printf ("\nNumber of pixels total(from rows*cols): %i\n",rows*cols);
261      printf ("Number of pixels written in file %s: %ld\n\n",filename,nwritten); 
262
263      fclose(file);
264      return(1);
265}
266
267
268
269
270/* So, to get the x’,y’ position for the circular image we will have to first pass the
271 * coordinates x,y from the rectangular output image to spherical coordinates using the
272 * first coordinate system, then those to the second shown spherical coordinate system,
273 * then those to the polar projection and then pass the polar system to cardinal x’,y’.
274 */
275double2 evaluatePixel_Front(double2 outCoord, double2 srcSize)
276{
277        double2 o;
278        double theta,phi;
279        double3 sphericCoords;
280        double phi2_over_pi;
281        double theta2;
282        double2 inCentered;
283
284//convert outcoords to radians (180 = pi, so half a sphere)
285        o.x = outCoord.x / srcSize.x; 
286        o.y = outCoord.y / srcSize.y; 
287        theta = (1.0-o.x) * M_PI; 
288        phi = o.y * M_PI;
289
290//Convert outcoords to spherical (x,y,z on unisphere)
291        sphericCoords.x = cos(theta)*sin(phi);
292        sphericCoords.y = sin(theta)*sin(phi);
293        sphericCoords.z = cos(phi);
294       
295//Convert spherical to input coordinates...
296        theta2 = atan2(-sphericCoords.z,sphericCoords.x);
297        phi2_over_pi = acos(sphericCoords.y)/(M_PI);
298       
299        inCentered.x = ((phi2_over_pi*cos(theta2))+0.5)*srcSize.x;
300        inCentered.y = ((phi2_over_pi*sin(theta2))+0.5)*srcSize.y;
301       
302        return inCentered;
303}
304
305
306void gen_front_maps(configuration cfg,int** image_x,int** image_y ){
307    int x,y;
308
309  printf("Front proj\n");
310  for (y = 0; y<cfg.rows;y++){
311    for (x = 0; x < cfg.cols; x++){
312      double2 o = evaluatePixel_Front((double2){((double)x/((double)cfg.cols)) * ((cfg.width)-(2*cfg.crop)),
313                                                ((double)y/(double)cfg.rows)   * ((cfg.height)  -(2*cfg.crop))}, 
314                                      (double2){(cfg.width)-(2*cfg.crop), cfg.height-(2*cfg.crop)});
315      image_x[y][x] = (int)round(o.x)+cfg.crop;
316      image_y[y][x] = (int)round(o.y)+cfg.crop;
317    }
318  }
319}
320
321
322int
323main (int argc, char **argv)
324{
325    int y;
326    int** image_x;
327    int** image_y;
328    configuration cfg = parse_options(argc,argv);
329
330
331    if(cfg.xmap_filename)  printf("xmapfile: %s\n",cfg.xmap_filename);
332    if(cfg.ymap_filename)  printf("ymapfile: %s\n",cfg.ymap_filename);
333
334      image_x = malloc((cfg.rows)*sizeof(*image_x));
335      for(y=0;y<(cfg.rows);y++) image_x[y]= malloc((cfg.cols)*sizeof(*(image_x[y])));
336      image_y = malloc((cfg.rows)*sizeof(*image_y));
337      for(y=0;y<(cfg.rows);y++) image_y[y]= malloc((cfg.cols)*sizeof(*(image_y[y])));
338
339
340    switch(cfg.mode){
341      case FRONT:    gen_front_maps(cfg,image_x,image_y); break;
342/*      case FRONT235:    gen_front235_maps(cfg,image_x,image_y); break;
343      case DOWN:    gen_down_maps(cfg,image_x,image_y); break;
344      case SAMSUNG_GEAR_360: gen_samsung_gear_360_maps(cfg,image_x,image_y); break;
345      case THETAS: gen_thetas_maps(cfg,image_x,image_y); break;
346*/
347      default: printf("Camera mode not implemented\n"); exit(1);
348
349    }
350
351
352
353
354  printf("Writing files\n");
355  pgmWrite_ASCII(cfg.ymap_filename, cfg.rows,cfg.cols,image_y,cfg.ymap_filename);
356  pgmWrite_ASCII(cfg.xmap_filename, cfg.rows,cfg.cols,image_x,cfg.xmap_filename);
357
358    if(image_y){
359         for (y = 0; y<cfg.rows;y++) free(image_y[y]);
360       free(image_y);
361    }
362    if(image_x){
363         for (y = 0; y<cfg.rows;y++) free(image_x[y]);
364       free(image_x);
365    }
366
367
368    exit (0);
369}