00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "OmniFastLookupTable.hh"
00022
00023
00024
00025
00026
00027 OmniFastLookupTable::OmniFastLookupTable( int min_radius,
00028 int max_radius,
00029 int omni_center_x_pixel,
00030 int omni_center_y_pixel,
00031 double theta_step,
00032 bool flipped_mode ) :
00033 _min_radius( min_radius ),
00034 _max_radius( max_radius ),
00035 _omni_center_x_rgb( omni_center_x_pixel*3 ),
00036 _omni_center_y_rgb( omni_center_y_pixel ),
00037 _omni_center_x( omni_center_x_pixel ),
00038 _omni_center_y( omni_center_y_pixel ),
00039 _flipped_mode( flipped_mode )
00040 {
00041 _is_valid = false;
00042
00043 if ( theta_step == 0 ) {
00044 if ( max_radius == 0 || min_radius == 0 )
00045 return;
00046
00047
00048 _theta_step = 1 / (double)max_radius;
00049 }
00050
00051
00052 if ( _max_radius % 2 != 0 )
00053 _max_radius++;
00054 if ( _min_radius % 2 != 0 )
00055 _min_radius++;
00056
00057 _min_to_max_radius_range = _max_radius - _min_radius;
00058 _theta_max = (int)ceil( 2 * CV_PI * (double)_max_radius );
00059
00060
00061 _is_valid = omnipano_lookup_table_make();
00062
00063 }
00064
00065
00066
00067
00068 OmniFastLookupTable::~OmniFastLookupTable() {
00069
00070 int i;
00071
00072
00073 for ( i=0; i < omni_bounds.theta_length; i++ ) {
00074 free( omni_bounds.omni_data[i] );
00075 }
00076
00077 free( omni_bounds.omni_data );
00078
00079
00080 for ( i=0; i < pano_bounds.width; i++ ) {
00081 free( pano_bounds.pano_data[i] );
00082 }
00083 free( pano_bounds.pano_data );
00084
00085 }
00086
00087
00088
00089
00090
00091 bool OmniFastLookupTable::is_initialized () {
00092 return _is_valid;
00093 }
00094
00095
00096
00097
00098
00099 void OmniFastLookupTable::angle_type_conversion( const OmniAngle<double>& angle_in,
00100 OmniAngle<int>& angle_out ) {
00101
00102 int theta, steps;
00103 double rad_angle_start, rad_angle_end;
00104
00105 rad_angle_start = angle_in.angle_start;
00106 rad_angle_end = angle_in.angle_end;
00107
00108
00109 if ( !is_initialized () )
00110 return;
00111
00112
00113
00114 if ( rad_angle_start < 0 )
00115 rad_angle_start = 2 * CV_PI + rad_angle_start;
00116
00117 if ( rad_angle_end < 0 )
00118 rad_angle_end = 2 * CV_PI + rad_angle_end;
00119
00120
00121 if ( rad_angle_end < rad_angle_start ) {
00122 theta = (int)ceil( rad_angle_start * (double)_max_radius );
00123
00124
00125 steps = (int)ceil( rad_angle_end *(double)_max_radius ) +
00126 (_theta_max - theta);
00127 }
00128 else if ( rad_angle_end > rad_angle_start ) {
00129 theta = (int)ceil( rad_angle_start * (double)_max_radius );
00130 steps = (int)ceil( rad_angle_end * (double)_max_radius ) - theta;
00131 }
00132 else {
00133 steps = _theta_max;
00134 theta = 0;
00135 }
00136
00137
00138 angle_out.range = steps;
00139 angle_out.angle_start = theta;
00140 angle_out.angle_end = (theta + steps) % _theta_max;
00141 }
00142
00143
00144
00145
00146
00147
00148 IplImage* OmniFastLookupTable::omni2pano( IplImage *frame,
00149 const OmniAngle<int>& IN_interval ) {
00150
00151 IplImage *image;
00152 IplImage *result ;
00153 int radius, theta;
00154 int steps, step_count;
00155
00156
00157 if ( !is_initialized () ) {
00158 DEBUG_PRINT ("lookup table not initialized\n");
00159 return NULL;
00160 }
00161
00162 image = frame;
00163 theta = IN_interval.angle_start;
00164 steps = IN_interval.range;
00165
00166 int pano_coord_tmp = (PANO_COORD( steps-1, _max_radius-_min_radius -1 ).x_rgb)/3;
00167
00168
00169
00170
00171
00172
00173
00174 int adjusted_pano_coord = pano_coord_tmp;
00175 int tmp_val = pano_coord_tmp % 32;
00176 if ( tmp_val != 0 )
00177 adjusted_pano_coord += 32 - tmp_val;
00178
00179 result = cvCreateImage( cvSize( adjusted_pano_coord, _max_radius - _min_radius ),
00180 IPL_DEPTH_8U, 3 );
00181
00182
00183
00184
00185
00186 for ( theta, step_count = 0;
00187 step_count < steps;
00188 step_count++, theta = (++theta % _theta_max) ) {
00189
00190 if ( theta == _theta_max )
00191 continue;
00192
00193 for ( radius = 0; radius < (_max_radius - _min_radius); radius++ ) {
00194 unsigned char* tmp_ptr;
00195 int original_r;
00196 int original_g;
00197 int original_b;
00198 int omni_x, omni_y, pano_x, pano_y;
00199
00200 omni_x = OMNI_COORD( theta, radius ).x_rgb;
00201 omni_y = OMNI_COORD( theta, radius ).y_rgb;
00202
00203
00204 tmp_ptr = &(CV_IMAGE_ELEM (image, unsigned char, omni_y, omni_x));
00205 original_r = tmp_ptr[0];
00206 original_g = tmp_ptr[1];
00207 original_b = tmp_ptr[2];
00208
00209 pano_x = PANO_COORD( step_count, radius ).x_rgb;
00210 if ( _flipped_mode )
00211 pano_y = PANO_COORD( step_count, (_min_to_max_radius_range -1) - radius ).y_rgb;
00212 else
00213 pano_y = PANO_COORD( step_count, radius ).y_rgb;
00214
00215
00216 tmp_ptr = &(CV_IMAGE_ELEM (result, unsigned char, pano_y, pano_x));
00217 tmp_ptr[0] = original_r;
00218 tmp_ptr[1] = original_g;
00219 tmp_ptr[2] = original_b;
00220 }
00221 }
00222
00223 return result;
00224 }
00225
00226
00227
00228
00229
00230
00231
00232 bool OmniFastLookupTable::omnipano_lookup_table_make( ) {
00233 int i, j;
00234
00235 if ( _max_radius <= _min_radius ) {
00236 DEBUG_PRINT("returning false from OmniFastLookupTable::omnipano_lookup_table_make,"
00237 "_max_radius %d <= _min_radius %d\n", _max_radius, _min_radius);
00238 return false;
00239 }
00240
00241 int steps = (int)ceil( 2 * CV_PI / _theta_step );
00242
00243 omni_bounds.theta_length = steps;
00244 omni_bounds.radius_length = _max_radius - _min_radius;
00245
00246
00247 omni_bounds.omni_data = (omni_coord_xy**)calloc( steps, sizeof(omni_coord_xy*));
00248 for ( i=0; i < steps; i++ ) {
00249 omni_bounds.omni_data[i] =
00250 (omni_coord_xy*)calloc( omni_bounds.radius_length, sizeof(omni_coord_xy));
00251 }
00252
00253
00254 pano_bounds.width = (int)ceil(2 * CV_PI * _max_radius);
00255 pano_bounds.height = _max_radius - _min_radius;
00256
00257 pano_bounds.pano_data =
00258 (pano_coord_xy**)calloc( pano_bounds.width*3, sizeof(pano_coord_xy*) * pano_bounds.width );
00259 for ( i=0; i < pano_bounds.width*3; i++ ) {
00260 pano_bounds.pano_data[i] =
00261 (pano_coord_xy*)calloc( pano_bounds.height, sizeof(pano_coord_xy));
00262 }
00263
00264
00265 for ( i=0; i < steps; i++ ) {
00266 for ( j=_min_radius; j < _max_radius; j++ ) {
00267 double curr_theta = i * _theta_step;
00268 omni_bounds.omni_data[i][j - _min_radius].x_rgb =
00269 (int)(j * cos(curr_theta) + _omni_center_x_rgb)*3;
00270 omni_bounds.omni_data[i][j - _min_radius].y_rgb =
00271 (int)(j * sin(curr_theta) + _omni_center_y_rgb);
00272 }
00273 }
00274
00275
00276 int tmp_pano_x = 0;
00277 for ( i=0; i < pano_bounds.width; i++ ) {
00278 for ( j=0; j < pano_bounds.height; j++ ) {
00279 int curr_pano_x = (int)(i * _theta_step *j);
00280 tmp_pano_x = MAX( curr_pano_x, tmp_pano_x );
00281 pano_bounds.pano_data[i][j].x_rgb = tmp_pano_x*3;
00282
00283 pano_bounds.pano_data[i][j].y_rgb = j;
00284 }
00285 }
00286
00287 return true;
00288 }
00289
00290
00291
00292
00293
00294
00295
00296
00297
00298
00299 void OmniFastLookupTable::pano2omni_xy( CvPoint *pano_point,
00300 int theta_start,
00301 CvPoint *omni_point )
00302 {
00303 omni_point->x = (int)((double)(pano_point->y + _min_radius ) *
00304 cos( (double)(theta_start + pano_point->x) / (double)_max_radius ));
00305
00306 omni_point->y = (int)((double)(pano_point->y + _min_radius ) *
00307 sin( (double)(theta_start + pano_point->x) / (double)_max_radius ));
00308
00309 omni_point->x += _omni_center_x;
00310 omni_point->y += _omni_center_y;
00311 }
00312
00313
00314
00315
00316
00317 int OmniFastLookupTable::get_min_radius() {
00318 return _min_radius;
00319 }
00320
00321
00322
00323
00324 int OmniFastLookupTable::get_max_radius() {
00325 return _max_radius;
00326 }
00327
00328
00329
00330
00331 int OmniFastLookupTable::get_omni_center_x() {
00332 return _omni_center_x;
00333 }
00334
00335
00336
00337
00338 int OmniFastLookupTable::get_omni_center_y() {
00339 return _omni_center_y;
00340 }
00341
00342