Home | History | Annotate | Download | only in xcore
      1 /*
      2  * xcam_utils.h - xcam utilities
      3  *
      4  *  Copyright (c) 2014-2015 Intel Corporation
      5  *
      6  * Licensed under the Apache License, Version 2.0 (the "License");
      7  * you may not use this file except in compliance with the License.
      8  * You may obtain a copy of the License at
      9  *
     10  *      http://www.apache.org/licenses/LICENSE-2.0
     11  *
     12  * Unless required by applicable law or agreed to in writing, software
     13  * distributed under the License is distributed on an "AS IS" BASIS,
     14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     15  * See the License for the specific language governing permissions and
     16  * limitations under the License.
     17  *
     18  * Author: Wind Yuan <feng.yuan (at) intel.com>
     19  * Author: Zong Wei <wei.zong (at) intel.com>
     20  * Author: Junkai Wu <junkai.wu (at) intel.com>
     21  * Author: Yinhang Liu <yinhangx.liu (at) intel.com>
     22  */
     23 
     24 #include "xcam_utils.h"
     25 #include "video_buffer.h"
     26 #include "image_file_handle.h"
     27 
     28 namespace XCam {
     29 
     30 static float
     31 transform_bowl_coord_to_image_x (
     32     const float bowl_x, const float bowl_y,
     33     const uint32_t img_width)
     34 {
     35     float offset_radian = (bowl_x < 0.0f) ? PI : ((bowl_y >= 0.0f) ? 2.0f * PI : 0.0f);
     36     float arctan_radian = (bowl_x != 0.0f) ? atan (-bowl_y / bowl_x) : ((bowl_y >= 0.0f) ? -PI / 2.0f : PI / 2.0f);
     37 
     38     float img_x = arctan_radian + offset_radian;
     39     img_x *= img_width / (2.0f * PI);
     40     return XCAM_CLAMP (img_x, 0.0f, img_width - 1.0f);
     41 }
     42 
     43 static float
     44 transform_bowl_coord_to_image_y (
     45     const BowlDataConfig &config,
     46     const float bowl_x, const float bowl_y, const float bowl_z,
     47     const uint32_t img_height)
     48 {
     49     float wall_image_height = config.wall_height / (config.wall_height + config.ground_length) * img_height;
     50     float ground_image_height = img_height - wall_image_height;
     51     float img_y = 0.0f;
     52 
     53     if (bowl_z > 0.0f) {
     54         img_y = (config.wall_height - bowl_z) * wall_image_height / config.wall_height;
     55         img_y = XCAM_CLAMP (img_y, 0.0f, wall_image_height - 1.0f);
     56     } else {
     57         float max_semimajor = config.b *
     58                               sqrt (1 - config.center_z * config.center_z / (config.c * config.c));
     59         float min_semimajor = max_semimajor - config.ground_length;
     60         XCAM_ASSERT (min_semimajor >= 0);
     61         XCAM_ASSERT (max_semimajor > min_semimajor);
     62         float step = ground_image_height / (max_semimajor - min_semimajor);
     63 
     64         float axis_ratio = config.a / config.b;
     65         float cur_semimajor = sqrt (bowl_x * bowl_x + bowl_y * bowl_y * axis_ratio * axis_ratio) / axis_ratio;
     66         cur_semimajor = XCAM_CLAMP (cur_semimajor, min_semimajor, max_semimajor);
     67 
     68         img_y = (max_semimajor - cur_semimajor) * step + wall_image_height;
     69         img_y = XCAM_CLAMP (img_y, wall_image_height, img_height - 1.0f);
     70     }
     71     return img_y;
     72 }
     73 
     74 PointFloat2 bowl_view_coords_to_image (
     75     const BowlDataConfig &config,
     76     const PointFloat3 &bowl_pos,
     77     const uint32_t img_width, const uint32_t img_height)
     78 {
     79     PointFloat2 img_pos;
     80     img_pos.x = transform_bowl_coord_to_image_x (bowl_pos.x, bowl_pos.y, img_width);
     81     img_pos.y = transform_bowl_coord_to_image_y (config, bowl_pos.x, bowl_pos.y, bowl_pos.z, img_height);
     82 
     83     return img_pos;
     84 }
     85 
     86 PointFloat3 bowl_view_image_to_world (
     87     const BowlDataConfig &config,
     88     const uint32_t img_width, const uint32_t img_height,
     89     const PointFloat2 &img_pos)
     90 {
     91     PointFloat3 world;
     92     float angle;
     93 
     94     float a = config.a;
     95     float b = config.b;
     96     float c = config.c;
     97 
     98     float wall_image_height = config.wall_height / (float)(config.wall_height + config.ground_length) * (float)img_height;
     99     float ground_image_height = (float)img_height - wall_image_height;
    100 
    101     float z_step = (float)config.wall_height / wall_image_height;
    102     float angle_step = fabs(config.angle_end - config.angle_start) / img_width;
    103 
    104     if(img_pos.y < wall_image_height) {
    105         world.z = config.wall_height - img_pos.y * z_step; // TODO world.z
    106         angle = degree2radian (config.angle_start + img_pos.x * angle_step);
    107         float r2 = 1 - (world.z - config.center_z) * (world.z - config.center_z) / (c * c);
    108 
    109         if(XCAM_DOUBLE_EQUAL_AROUND (angle, PI / 2)) {
    110             world.x = 0.0f;
    111             world.y = -sqrt(r2 * b * b);
    112         } else if (XCAM_DOUBLE_EQUAL_AROUND (angle, PI * 3 / 2)) {
    113             world.x = 0.0f;
    114             world.y = sqrt(r2 * b * b);
    115         } else if((angle < PI / 2) || (angle > PI * 3 / 2)) {
    116             world.x = sqrt(r2 * a * a * b * b / (b * b + a * a * tan(angle) * tan(angle)));
    117             world.y = -world.x * tan(angle);
    118         } else {
    119             world.x = -sqrt(r2 * a * a * b * b / (b * b + a * a * tan(angle) * tan(angle)));
    120             world.y = -world.x * tan(angle);
    121         }
    122     } else {
    123         a = a * sqrt(1 - config.center_z * config.center_z / (c * c));
    124         b = b * sqrt(1 - config.center_z * config.center_z / (c * c));
    125 
    126         float ratio_ab = b / a;
    127 
    128         float step_b = config.ground_length / ground_image_height;
    129 
    130         b = b - (img_pos.y - wall_image_height) * step_b;
    131         a = b / ratio_ab;
    132 
    133         angle = degree2radian (config.angle_start + img_pos.x * angle_step);
    134 
    135         if(XCAM_DOUBLE_EQUAL_AROUND (angle, PI / 2)) {
    136             world.x = 0.0f;
    137             world.y = -b;
    138         } else if (XCAM_DOUBLE_EQUAL_AROUND (angle, PI * 3 / 2)) {
    139             world.x = 0.0f;
    140             world.y = b;
    141         } else if((angle < PI / 2) || (angle > PI * 3 / 2)) {
    142             world.x = a * b / sqrt(b * b + a * a * tan(angle) * tan(angle));
    143             world.y = -world.x * tan(angle);
    144         } else {
    145             world.x = -a * b / sqrt(b * b + a * a * tan(angle) * tan(angle));
    146             world.y = -world.x * tan(angle);
    147         }
    148         world.z = 0.0f;
    149     }
    150 
    151     return world;
    152 }
    153 
    154 void centralize_bowl_coord_from_cameras (
    155     ExtrinsicParameter &front_cam, ExtrinsicParameter &right_cam,
    156     ExtrinsicParameter &rear_cam, ExtrinsicParameter &left_cam,
    157     PointFloat3 &bowl_coord_offset)
    158 {
    159     bowl_coord_offset.x = (front_cam.trans_x + rear_cam.trans_x) / 2.0f;
    160     bowl_coord_offset.y = (right_cam.trans_y + left_cam.trans_y) / 2.0f;
    161     bowl_coord_offset.z = 0.0f;
    162 
    163     front_cam.trans_x -= bowl_coord_offset.x;
    164     front_cam.trans_y -= bowl_coord_offset.y;
    165 
    166     right_cam.trans_x -= bowl_coord_offset.x;
    167     right_cam.trans_y -= bowl_coord_offset.y;
    168 
    169     rear_cam.trans_x -= bowl_coord_offset.x;
    170     rear_cam.trans_y -= bowl_coord_offset.y;
    171 
    172     left_cam.trans_x -= bowl_coord_offset.x;
    173     left_cam.trans_y -= bowl_coord_offset.y;
    174 }
    175 
    176 double
    177 linear_interpolate_p2 (
    178     double value_start, double value_end,
    179     double ref_start, double ref_end,
    180     double ref_curr)
    181 {
    182     double weight_start = 0;
    183     double weight_end = 0;
    184     double dist_start = 0;
    185     double dist_end = 0;
    186     double dist_sum = 0;
    187     double value = 0;
    188 
    189     dist_start = abs(ref_curr - ref_start);
    190     dist_end = abs(ref_end - ref_curr);
    191     dist_sum = dist_start + dist_end;
    192 
    193     if (dist_start == 0) {
    194         weight_start = 10000000.0;
    195     } else {
    196         weight_start = ((double)dist_sum / dist_start);
    197     }
    198 
    199     if (dist_end == 0) {
    200         weight_end = 10000000.0;
    201     } else {
    202         weight_end = ((double)dist_sum / dist_end);
    203     }
    204 
    205     value = (value_start * weight_start + value_end * weight_end) / (weight_start + weight_end);
    206     return value;
    207 }
    208 
    209 double
    210 linear_interpolate_p4(
    211     double value_lt, double value_rt,
    212     double value_lb, double value_rb,
    213     double ref_lt_x, double ref_rt_x,
    214     double ref_lb_x, double ref_rb_x,
    215     double ref_lt_y, double ref_rt_y,
    216     double ref_lb_y, double ref_rb_y,
    217     double ref_curr_x, double ref_curr_y)
    218 {
    219     double weight_lt = 0;
    220     double weight_rt = 0;
    221     double weight_lb = 0;
    222     double weight_rb = 0;
    223     double dist_lt = 0;
    224     double dist_rt = 0;
    225     double dist_lb = 0;
    226     double dist_rb = 0;
    227     double dist_sum = 0;
    228     double value = 0;
    229 
    230     dist_lt = (double)abs(ref_curr_x - ref_lt_x) + (double)abs(ref_curr_y - ref_lt_y);
    231     dist_rt = (double)abs(ref_curr_x - ref_rt_x) + (double)abs(ref_curr_y - ref_rt_y);
    232     dist_lb = (double)abs(ref_curr_x - ref_lb_x) + (double)abs(ref_curr_y - ref_lb_y);
    233     dist_rb = (double)abs(ref_curr_x - ref_rb_x) + (double)abs(ref_curr_y - ref_rb_y);
    234     dist_sum = dist_lt + dist_rt + dist_lb + dist_rb;
    235 
    236     if (dist_lt == 0) {
    237         weight_lt = 10000000.0;
    238     } else {
    239         weight_lt = ((float)dist_sum / dist_lt);
    240     }
    241     if (dist_rt == 0) {
    242         weight_rt = 10000000.0;
    243     } else {
    244         weight_rt = ((float)dist_sum / dist_rt);
    245     }
    246     if (dist_lb == 0) {
    247         weight_lb = 10000000.0;
    248     } else {
    249         weight_lb = ((float)dist_sum / dist_lb);
    250     }
    251     if (dist_rb == 0) {
    252         weight_rb = 10000000.0;
    253     } else {
    254         weight_rb = ((float)dist_sum / dist_rt);
    255     }
    256 
    257     value = (double)floor ( (value_lt * weight_lt + value_rt * weight_rt +
    258                              value_lb * weight_lb + value_rb * weight_rb) /
    259                             (weight_lt + weight_rt + weight_lb + weight_rb) + 0.5 );
    260     return value;
    261 }
    262 
    263 void
    264 get_gauss_table (uint32_t radius, float sigma, std::vector<float> &table, bool normalize)
    265 {
    266     uint32_t i;
    267     uint32_t scale = radius * 2 + 1;
    268     float dis = 0.0f, sum = 1.0f;
    269 
    270     //XCAM_ASSERT (scale < 512);
    271     table.resize (scale);
    272     table[radius] = 1.0f;
    273 
    274     for (i = 0; i < radius; i++)  {
    275         dis = ((float)i - radius) * ((float)i - radius);
    276         table[i] = table[scale - i - 1] = exp(-dis / (2.0f * sigma * sigma));
    277         sum += table[i] * 2.0f;
    278     }
    279 
    280     if (!normalize)
    281         return;
    282 
    283     for(i = 0; i < scale; i++)
    284         table[i] /= sum;
    285 }
    286 
    287 void
    288 dump_buf_perfix_path (const SmartPtr<VideoBuffer> buf, const char *prefix_name)
    289 {
    290     char file_name[256];
    291     XCAM_ASSERT (prefix_name);
    292     XCAM_ASSERT (buf.ptr ());
    293 
    294     const VideoBufferInfo &info = buf->get_video_info ();
    295     snprintf (
    296         file_name, 256, "%s-%dx%d.%s",
    297         prefix_name, info.width, info.height, xcam_fourcc_to_string (info.format));
    298 
    299     dump_video_buf (buf, file_name);
    300 }
    301 
    302 bool
    303 dump_video_buf (const SmartPtr<VideoBuffer> buf, const char *file_name)
    304 {
    305     ImageFileHandle file;
    306     XCAM_ASSERT (file_name);
    307 
    308     XCamReturn ret = file.open (file_name, "wb");
    309     XCAM_FAIL_RETURN (
    310         ERROR, xcam_ret_is_ok (ret), false,
    311         "dump buffer failed when open file: %s", file_name);
    312 
    313     ret = file.write_buf (buf);
    314     XCAM_FAIL_RETURN (
    315         ERROR, xcam_ret_is_ok (ret), false,
    316         "dump buffer to file: %s failed", file_name);
    317 
    318     return true;
    319 }
    320 
    321 }
    322