SRUtils.cpp
Go to the documentation of this file.
00001 #include "shape_reconstruction/SRUtils.h"
00002 
00003 #include <opencv2/imgproc/imgproc.hpp>
00004 #include <opencv2/video/tracking.hpp>
00005 #include <opencv2/highgui/highgui.hpp>
00006 #include <opencv2/video/tracking.hpp>
00007 
00008 #include "shape_reconstruction/RangeImagePlanar.hpp"
00009 
00010 typedef unsigned char uint8_t;
00011 
00012 namespace omip
00013 {
00014 void RangeImagePlanar2DepthMap(const pcl::RangeImagePlanar::Ptr& rip, cv::Mat& depth_map_mat)
00015 {
00016     for(int i=0; i<IMG_WIDTH; i++)
00017     {
00018         for(int j=0; j<IMG_HEIGHT; j++)
00019         {
00020             depth_map_mat.at< float >(j,i)  = rip->points.at(j*IMG_WIDTH+i).z;
00021         }
00022     }
00023 }
00024 
00025 void RangeImagePlanar2PointCloud(const pcl::RangeImagePlanar::Ptr& rip, SRPointCloud::Ptr& pc)
00026 {
00027     for(int i=0; i<IMG_WIDTH; i++)
00028     {
00029         for(int j=0; j<IMG_HEIGHT; j++)
00030         {
00031             pc->points.at(j*IMG_WIDTH+i).x  = rip->points.at(j*IMG_WIDTH+i).x;
00032             pc->points.at(j*IMG_WIDTH+i).y  = rip->points.at(j*IMG_WIDTH+i).y;
00033             pc->points.at(j*IMG_WIDTH+i).z  = rip->points.at(j*IMG_WIDTH+i).z;
00034         }
00035     }
00036 }
00037 
00038 void OrganizedPC2DepthMap(const SRPointCloud::Ptr organized_pc, cv::Mat& depth_map_mat)
00039 {
00040     float* data_ptr = (float*)depth_map_mat.data;
00041     size_t elem_step = depth_map_mat.step / sizeof(float);
00042 
00043 //    std::cout << organized_pc->height << std::endl;
00044 //    std::cout << organized_pc->width << std::endl;
00045     for(int v=0; v< organized_pc->height; v++)
00046     {
00047         for(int u=0; u< organized_pc->width; u++)
00048         {
00049             if(pcl::isFinite(organized_pc->points[v*organized_pc->width + u]))
00050                 data_ptr[v*elem_step + u] = organized_pc->points[v*organized_pc->width + u].z;
00051             else
00052                 data_ptr[v*elem_step + u] = nanf("");
00053         }
00054     }
00055 }
00056 
00057 void OrganizedPC2DepthMapAlternative(const SRPointCloud::Ptr organized_pc, const cv::Ptr<cv::Mat>& depth_map_mat_ptr)
00058 {
00059     float* data_ptr = (float*)depth_map_mat_ptr->data;
00060     size_t elem_step = depth_map_mat_ptr->step / sizeof(float);
00061 
00062     for(int v=0; v< organized_pc->height; v++)
00063     {
00064         for(int u=0; u< organized_pc->width; u++)
00065         {
00066             if(pcl::isFinite(organized_pc->points[v*organized_pc->width + u]))
00067                 data_ptr[v*elem_step + u] = organized_pc->points[v*organized_pc->width + u].z;
00068             else
00069                 data_ptr[v*elem_step + u] = nanf("");
00070         }
00071     }
00072 }
00073 
00074 void OrganizedPC2ColorMap(const SRPointCloud::Ptr organized_pc, cv::Mat& depth_map_mat)
00075 {
00076     for (int h=0; h<depth_map_mat.rows; h++) {
00077         for (int w=0; w<depth_map_mat.cols; w++) {
00078             pcl::PointXYZRGB point = organized_pc->at(w, h);
00079 
00080             Eigen::Vector3i rgb = point.getRGBVector3i();
00081 
00082             depth_map_mat.at<cv::Vec3b>(h,w)[0] = rgb[2];
00083             depth_map_mat.at<cv::Vec3b>(h,w)[1] = rgb[1];
00084             depth_map_mat.at<cv::Vec3b>(h,w)[2] = rgb[0];
00085         }
00086     }
00087 }
00088 
00089 void UnorganizedPC2DepthMap(const SRPointCloud::Ptr& organized_pc,
00090                             const int& width,
00091                             const int& height,
00092                             cv::Mat& depth_map,
00093                             ::shape_reconstruction::RangeImagePlanar::Ptr& rip,
00094                             const float& noiseLevel,
00095                             const float& minRange) {
00096     Eigen::Affine3f sensor_pose;
00097     sensor_pose.matrix() = Eigen::Matrix4f::Identity(); // this->_current_HTransform_inv.cast<float>();
00098     pcl::RangeImagePlanar::CoordinateFrame coordinate_frame = pcl::RangeImagePlanar::CAMERA_FRAME;
00099 
00100     rip->createFromPointCloudWithFixedSizeAndStorePoints(*organized_pc,
00101                                                          width,
00102                                                          height,
00103                                                          width/2 -0.5, //319.5
00104                                                          height/2 - 0.5, // 239.5,
00105                                                          525, 525,
00106                                                          sensor_pose,
00107                                                          coordinate_frame,
00108                                                          noiseLevel,
00109                                                          minRange);
00110 
00111     RangeImagePlanar2DepthMap(rip, depth_map);
00112 }
00113 
00114 void DepthImage2CvImage(const cv::Mat& depth_image_raw, sensor_msgs::ImagePtr& depth_msg) {
00115     cv::Mat depth_image(depth_image_raw.rows, depth_image_raw.cols, CV_8UC1);
00116     cv::convertScaleAbs(depth_image_raw, depth_image, 100, 0);
00117     depth_msg = cv_bridge::CvImage(std_msgs::Header(), "mono8", depth_image).toImageMsg();
00118 }
00119 
00120 void Image8u2Indices(const cv::Mat& image_8u, pcl::PointIndices::Ptr indices_ptr)
00121 {
00122     int total_count = 0;
00123     int indices_count = 0;
00124     indices_ptr->indices.clear();
00125     for(int j=0; j<image_8u.rows; j++)
00126     {
00127         for(int i=0; i<image_8u.cols; i++)
00128         {
00129             if(image_8u.at<uchar>(j,i))
00130             {
00131                 indices_ptr->indices.push_back(j*image_8u.cols + i);
00132                 indices_count++;
00133             }
00134             total_count++;
00135         }
00136     }
00137     //std::cout << indices_count << " points of the " << total_count << " detected as candidates." << std::endl;
00138 }
00139 
00140 void Indices2Image8u(const std::vector<int>& indices, cv::Mat& image_8u)
00141 {
00142     image_8u.setTo(0);
00143     for(int i=0; i<indices.size() ; i++)
00144     {
00145         image_8u.at<uchar>(floor(indices.at(i)/image_8u.cols),indices.at(i)%image_8u.cols) = 255;
00146     }
00147     //std::cout << indices_count << " points of the " << total_count << " detected as candidates." << std::endl;
00148 }
00149 
00150 void drawOptFlowMap(const cv::Mat& flow, cv::Mat& cflowmap, int step,
00151                     double scale, const cv::Scalar& color)
00152 {
00153     for(int y = 0; y < cflowmap.rows; y += step)
00154         for(int x = 0; x < cflowmap.cols; x += step)
00155         {
00156             const cv::Point2f& fxy = flow.at<cv::Point2f>(y, x);
00157             line(cflowmap, cv::Point(x,y), cv::Point(cvRound(x+fxy.x), cvRound(y+fxy.y)),
00158                  color);
00159             circle(cflowmap, cv::Point(x,y), 2, color, -1);
00160         }
00161 }
00162 
00163 void drawOpticalFlowModule(const cv::Mat& optical_flow, cv::Mat& optical_flow_module)
00164 {
00165     if((optical_flow_module.cols != optical_flow.cols) || (optical_flow_module.rows != optical_flow.rows))
00166     {
00167         ROS_ERROR_STREAM_NAMED("drawOpticalFlowModule", "The sizes of the optical flow and the optical flow module images are different!");
00168         return;
00169     }
00170 
00171     for(int j = 0; j < optical_flow_module.rows; j++)
00172     {
00173         for(int i = 0; i < optical_flow_module.cols; i++)
00174         {
00175             const cv::Point2f& flow_ij = optical_flow.at<cv::Point2f>(j, i);
00176             optical_flow_module.at<float>(j, i) = std::sqrt(flow_ij.x*flow_ij.x + flow_ij.y*flow_ij.y);
00177         }
00178     }
00179 }
00180 
00181 cv::Mat filled_img_full;
00182 ros::Time previous_query_time;
00183 
00184 void fillNaNsCBF(const sensor_msgs::Image& color_img, const cv::Mat& depth_img, cv::Mat& filled_depth_img, ros::Time query_time)
00185 {
00186     if(query_time == previous_query_time)
00187     {
00188         filled_depth_img = filled_img_full;
00189     }else{
00190         cv_bridge::CvImagePtr cv_ptr;
00191         cv_ptr = cv_bridge::toCvCopy(color_img, color_img.encoding);
00192 
00193         cv::Mat cv_gray;
00194         cv::cvtColor(cv_ptr->image, cv_gray, CV_RGB2GRAY);
00195 
00196         // NOTE: CBF not only fills the NaNs but also modifies the not NaN values
00197         // We do not want this: we want to keep the measured depth for the not NaN values!
00198         filled_img_full = fill_depth_cbf(cv_gray, depth_img, 0, 0);
00199 
00200         depth_img.copyTo(filled_depth_img);
00201         filled_img_full.copyTo(filled_depth_img, depth_img!=depth_img);
00202 
00203         previous_query_time = query_time;
00204     }
00205 }
00206 
00207 void removeDuplicateIndices(std::vector<int>& vec) {
00208     std::set<int> s;
00209     unsigned size = vec.size();
00210     for( unsigned i = 0; i < size; ++i ) s.insert( vec[i] );
00211     vec.assign( s.begin(), s.end() );
00212 }
00213 
00214 // Uncomment this define for intermediate filtering results.
00215 // #define DEBUG
00216 
00217 #define PI 3.14159
00218 
00219 #define MAX_UCHAR 255
00220 
00221 // Make sure these are consistent!!
00222 #define FILTER_RAD 5
00223 #define FILTER_LEN 11
00224 #define FILTER_SIZE 121
00225 
00226 void toc(const char* message, clock_t start) {
00227 #ifdef DEBUG
00228     double d = clock() - start;
00229     d = 1000 * d / CLOCKS_PER_SEC;
00230     printf("[%s] %10.0f\n", message, d);
00231 #endif
00232 }
00233 
00234 // Args:
00235 //   filter_size - the number of pixels in the filter.
00236 void create_offset_array(int* offsets_h, int img_height) {
00237     int kk = 0;
00238     for (int yy = -FILTER_RAD; yy <= FILTER_RAD; ++yy) {
00239         for (int xx = -FILTER_RAD; xx <= FILTER_RAD; ++xx, ++kk) {
00240             offsets_h[kk] = yy + img_height * xx;
00241         }
00242     }
00243 }
00244 
00245 void calc_pyr_sizes(int* heights, int* widths, int* pyr_offsets) {
00246     int offset = 0;
00247     for (int scale = 0; scale < NUM_SCALES; ++scale) {
00248         pyr_offsets[scale] = offset;
00249 
00250         // Calculate the size of the downsampled images.
00251         heights[scale] = static_cast<int>(IMG_HEIGHT / pow((float)2, scale));
00252         widths[scale] = static_cast<int>(IMG_WIDTH / pow((float)2, scale));
00253         offset += heights[scale] * widths[scale];
00254     }
00255 
00256 #ifdef DEBUG
00257     for (int ii = 0; ii < NUM_SCALES; ++ii) {
00258         printf("Scale %d: [%d x %d], offset=%d\n", ii, heights[ii], widths[ii], pyr_offsets[ii]);
00259     }
00260 #endif
00261 }
00262 
00263 int get_pyr_size(int* heights, int* widths) {
00264     int total_pixels = 0;
00265     for (int ii = 0; ii < NUM_SCALES; ++ii) {
00266         total_pixels += heights[ii] * widths[ii];
00267     }
00268     return total_pixels;
00269 }
00270 
00271 // We're upsampling from the result matrix (which is small) to the depth matrix,
00272 // which is larger.
00273 //
00274 // For example, dst could be 480x640 and src may be 240x320.
00275 //
00276 // Args:
00277 //   depth_dst - H1xW1 matrix where H1 and W1 are equal to height_dst and
00278 //               width_dst.
00279 void upsample_cpu(float* depth_dst,
00280                   bool* mask_dst,
00281                   bool* valid_dst,
00282                   float* depth_src,
00283                   float* result_src,
00284                   bool* mask_src,
00285                   bool* valid_src,
00286                   int height_src,
00287                   int width_src,
00288                   int height_dst,
00289                   int width_dst,
00290                   int dst_img_ind) {
00291 
00292     int num_threads = height_dst * width_dst;
00293 
00294     // Dont bother if the upsampled one isnt missing.
00295     if (!mask_dst[dst_img_ind]) {
00296         return;
00297     }
00298 
00299     int x_dst = static_cast<int>(floorf((float) dst_img_ind / height_dst));
00300     int y_dst = static_cast<int>(fmodf(dst_img_ind, height_dst));
00301 
00302     int y_src = static_cast<int>((float) y_dst * height_src / height_dst);
00303     int x_src = static_cast<int>((float) x_dst * width_src / width_dst);
00304 
00305     // Finally, convert to absolute coords.
00306     int src_img_ind = y_src + height_src * x_src;
00307 
00308     if (!mask_src[src_img_ind]) {
00309         depth_dst[dst_img_ind] = depth_src[src_img_ind];
00310     } else {
00311         depth_dst[dst_img_ind] = result_src[src_img_ind];
00312     }
00313 
00314     valid_dst[dst_img_ind] = valid_src[src_img_ind];
00315 }
00316 
00317 // Args:
00318 //   depth - the depth image, a HxW vector
00319 //   intensity - the intensity image, a HxW vector.
00320 //   is_missing - a binary mask specifying whether each pixel is missing
00321 //                (and needs to be filled in) or not.
00322 //   valid_in - a mask specifying which of the input values are allowed
00323 //              to be used for filtering.
00324 //   valid_out - a mask specifying which of the output values are allowed
00325 //               to be used for future filtering.
00326 //   result - the result of the filtering operation, a HxW matrix.
00327 //   abs_inds - the absolute indices (into depth, intensity, etc) which
00328 //              need filtering.
00329 //   offsets - vector of offsets from the current abs_ind to be used for
00330 //             filtering.
00331 //   guassian - the values (weights) of the gaussian filter corresponding
00332 //              to the offset matrix.
00333 void cbf_cpu(const float* depth, const float* intensity, bool* is_missing,
00334              bool* valid_in, bool* valid_out, float* result,
00335              const int* abs_inds,
00336              const int* offsets,
00337              const float* gaussian_space,
00338              int height,
00339              int width,
00340              float sigma_s,
00341              float sigma_r,
00342              int numThreads,
00343              int idx) {
00344 
00345     int abs_ind = abs_inds[idx];
00346 
00347     int src_Y = abs_ind % height;
00348     int src_X = abs_ind / height;
00349 
00350     float weight_sum = 0;
00351     float value_sum = 0;
00352 
00353     float weight_intensity_sum = 0;
00354 
00355     float gaussian_range[FILTER_SIZE];
00356     float gaussian_range_sum = 0;
00357 
00358     for (int ii = 0; ii < FILTER_SIZE; ++ii) {
00359         // Unfortunately we need to double check that the radii are correct
00360         // unless we add better processing of borders.
00361 
00362         int abs_offset = abs_ind + offsets[ii]; // THESE ARE CALC TWICE.
00363 
00364         int dst_Y = abs_offset % height;
00365         int dst_X = abs_offset / height;
00366 
00367         if (abs_offset < 0 || abs_offset >= (height * width)
00368                 || abs(src_Y-dst_Y) > FILTER_RAD || abs(src_X-dst_X) > FILTER_RAD) {
00369             continue;
00370 
00371             // The offsets are into ANY part of the image. So they MAY be accessing
00372             // a pixel that was originally missing. However, if that pixel has been
00373             // filled in, then we can still use it.
00374         } else if (is_missing[abs_offset] && !valid_in[abs_offset]) {
00375             continue;
00376         }
00377 
00378         float vv = intensity[abs_offset] - intensity[abs_ind];
00379 
00380         gaussian_range[ii] = exp(-(vv * vv) / (2*sigma_r * sigma_r));
00381         gaussian_range_sum += gaussian_range[ii];
00382     }
00383 
00384     int count = 0;
00385 
00386     for (int ii = 0; ii < FILTER_SIZE; ++ii) {
00387         // Get the Absolute offset into the image (1..N where N=H*W)
00388         int abs_offset = abs_ind + offsets[ii];
00389         int dst_Y = abs_offset % height;
00390         int dst_X = abs_offset / height;
00391         if (abs_offset < 0 || abs_offset >= (height * width)
00392                 || abs(src_Y-dst_Y) > FILTER_RAD || abs(src_X-dst_X) > FILTER_RAD) {
00393             continue;
00394         } else if (is_missing[abs_offset] && !valid_in[abs_offset]) {
00395             continue;
00396         }
00397 
00398         ++count;
00399 
00400         weight_sum += gaussian_space[ii] * gaussian_range[ii];
00401         value_sum += depth[abs_offset] * gaussian_space[ii] * gaussian_range[ii];
00402     }
00403 
00404     if (weight_sum == 0) {
00405         return;
00406     }
00407 
00408     if (isnan(weight_sum)) {
00409         printf("*******************\n");
00410         printf(" Weight sum is NaN\n");
00411         printf("*******************\n");
00412     }
00413 
00414     value_sum /= weight_sum;
00415     result[abs_ind] = value_sum;
00416     valid_out[abs_ind] = 1;
00417 }
00418 
00419 // Args:
00420 //   filter_size - the number of pixels in the filter.
00421 void create_spatial_gaussian(float sigma_s, float* gaussian_h) {
00422     float sum = 0;
00423     int kk = 0;
00424     for (int yy = -FILTER_RAD; yy <= FILTER_RAD; ++yy) {
00425         for (int xx = -FILTER_RAD; xx <= FILTER_RAD; ++xx, ++kk) {
00426             gaussian_h[kk] = exp(-(xx*xx + yy*yy) / (2*sigma_s * sigma_s));
00427             sum += gaussian_h[kk];
00428         }
00429     }
00430 
00431     for (int ff = 0; ff < FILTER_SIZE; ++ff) {
00432         gaussian_h[ff] /= sum;
00433     }
00434 }
00435 
00436 // Counts the number of missing pixels in the given mask. Note that the mask
00437 // MUST already be in the appropriate offset location.
00438 //
00439 // Args:
00440 //   height - the heigh of the image at the current scale.
00441 //   width - the width of the image at the current scale.
00442 //   mask - pointer into the mask_ms_d matrix. The offset has already been
00443 //          calculated.
00444 //   abs_inds_h - pre-allocated GPU memory location.
00445 int get_missing_pixel_coords(int height, int width, bool* mask, int* abs_inds_to_filter_h) {
00446     int num_pixels = height * width;
00447 
00448     int num_missing_pixels = 0;
00449     for (int nn = 0; nn < num_pixels; ++nn) {
00450         if (mask[nn]) {
00451             abs_inds_to_filter_h[num_missing_pixels] = nn;
00452             ++num_missing_pixels;
00453         }
00454     }
00455 
00456     return num_missing_pixels;
00457 }
00458 
00459 static void savePGM(bool* imf, const char *name, int height, int width) {
00460     uint8_t im[IMG_HEIGHT * IMG_WIDTH];
00461 
00462     for (int nn = 0; nn < IMG_HEIGHT * IMG_HEIGHT; ++nn) {
00463         // First convert to X,Y
00464         int y = nn % height;
00465         int x = static_cast<int>(floor(nn / static_cast<double>(height)));
00466 
00467         // Then back to Abs Inds
00468         int mm = y * width + x;
00469         im[mm] = uint8_t(255*imf[nn]);
00470     }
00471 
00472     std::ofstream file(name, std::ios::out | std::ios::binary);
00473 
00474     file << "P5\n" << width << " " << height << "\n" << MAX_UCHAR << "\n";
00475     file.write((char *)&im, width * height * sizeof(uint8_t));
00476 }
00477 
00478 static void savePGM(float* imf, const char *name, int height, int width) {
00479     uint8_t im[IMG_HEIGHT * IMG_WIDTH];
00480 
00481     for (int nn = 0; nn < IMG_HEIGHT * IMG_WIDTH; ++nn) {
00482         // First convert to X,Y
00483         int y = nn % height;
00484         int x = static_cast<int>(floor(nn / static_cast<double>(height)));
00485 
00486         // Then back to Abs Inds
00487         int mm = y * width + x;
00488 
00489         im[mm] = uint8_t(255*imf[nn]);
00490     }
00491 
00492     std::ofstream file(name, std::ios::out | std::ios::binary);
00493 
00494     file << "P5\n" << width << " " << height << "\n" << MAX_UCHAR << "\n";
00495     file.write((char *)&im, width * height * sizeof(uint8_t));
00496 }
00497 
00498 void filter_at_scale(float* depth_h,
00499                      float* intensity_h,
00500                      bool* mask_h,
00501                      bool* valid_h,
00502                      float* result_h,
00503                      int* abs_inds_to_filter_h,
00504                      int height,
00505                      int width,
00506                      float sigma_s,
00507                      float sigma_r) {
00508 
00509     // Create the offset array.
00510     int* offsets_h = (int*) malloc(FILTER_SIZE * sizeof(int));
00511     create_offset_array(offsets_h, height);
00512 
00513     // Create the gaussian.
00514     float* gaussian_h = (float*) malloc(FILTER_SIZE * sizeof(float));
00515     create_spatial_gaussian(sigma_s, gaussian_h);
00516 
00517     // ************************************************
00518     // We need to be smart about how we do this, so rather
00519     // than execute the filter for EVERY point in the image,
00520     // we will only do it for the points missing depth information.
00521     // ************************************************
00522 
00523     int num_missing_pixels = get_missing_pixel_coords(height, width, mask_h, abs_inds_to_filter_h);
00524     printf("[Depth filling with CBF. INFO] Num NaN depth values at this resolution scale: %d\n", num_missing_pixels);
00525 
00526     clock_t start_filter = clock();
00527 
00528     // We should not be writing into the same value for 'valid' that we're passing in.
00529     bool* valid_in = (bool*) malloc(height * width * sizeof(bool));
00530     for (int i = 0; i < height * width; ++i) {
00531         valid_in[i] = valid_h[i];
00532     }
00533 
00534     for (int i = 0; i < num_missing_pixels; ++i) {
00535         cbf_cpu(depth_h,
00536                 intensity_h,
00537                 mask_h,
00538                 valid_in,
00539                 valid_h,
00540                 result_h,
00541                 abs_inds_to_filter_h,
00542                 offsets_h,
00543                 gaussian_h,
00544                 height,
00545                 width,
00546                 sigma_s,
00547                 sigma_r,
00548                 num_missing_pixels,
00549                 i);
00550     }
00551 
00552     toc("FILTER OP", start_filter);
00553 
00554     free(valid_in);
00555     free(offsets_h);
00556     free(gaussian_h);
00557 }
00558 
00559 void cbf(uint8_t* depth, uint8_t* intensity, bool* mask_h, uint8_t* result, double* sigma_s, double* sigma_r)
00560 {
00561 
00562     clock_t start_func = clock();
00563 
00564     int pyr_heights[NUM_SCALES];
00565     int pyr_widths[NUM_SCALES];
00566     int pyr_offsets[NUM_SCALES];
00567     calc_pyr_sizes(&pyr_heights[0], &pyr_widths[0], &pyr_offsets[0]);
00568 
00569     // Allocate the memory needed for the absolute missing pixel indices. We'll
00570     // allocate the number of bytes required for the largest image, since the
00571     // smaller ones obviously fit inside of it.
00572     int N = IMG_HEIGHT * IMG_WIDTH;
00573     int* abs_inds_to_filter_h = (int*) malloc(N * sizeof(int));
00574 
00575     int pyr_size = get_pyr_size(&pyr_heights[0], &pyr_widths[0]);
00576 
00577     // ************************
00578     //   CREATING THE PYRAMID
00579     // ************************
00580     clock_t     start_pyr = clock();
00581 
00582     // NEG TIME.
00583     float* depth_ms_h = (float*) malloc(pyr_size * sizeof(float));
00584     float* intensity_ms_h = (float*) malloc(pyr_size * sizeof(float));
00585     bool* mask_ms_h = (bool*) malloc(pyr_size * sizeof(bool));
00586     float* result_ms_h = (float*) malloc(pyr_size * sizeof(float));
00587     bool* valid_ms_h = (bool*) malloc(pyr_size * sizeof(bool));
00588 
00589     for (int nn = 0; nn < N; ++nn)
00590     {
00591         depth_ms_h[nn] = depth[nn] / 255.0f;
00592         intensity_ms_h[nn] = intensity[nn] / 255.0f;
00593         mask_ms_h[nn] = mask_h[nn];
00594         valid_ms_h[nn] = !mask_h[nn];
00595         result_ms_h[nn] = 0;
00596     }
00597 
00598     float* depth_ms_h_p = depth_ms_h + pyr_offsets[1];
00599     float* intensity_ms_h_p     = intensity_ms_h + pyr_offsets[1];
00600     bool* mask_ms_h_p   = mask_ms_h + pyr_offsets[1];
00601     bool* valid_ms_h_p = valid_ms_h + pyr_offsets[1];
00602     float* result_ms_h_p = result_ms_h + pyr_offsets[1];
00603 
00604     for (unsigned int scale = 1; scale < NUM_SCALES; ++scale) {
00605         for (int xx = 0; xx < pyr_widths[scale]; ++xx) {
00606             for (int yy = 0; yy < pyr_heights[scale]; ++yy, ++depth_ms_h_p, ++intensity_ms_h_p, ++mask_ms_h_p, ++result_ms_h_p, ++valid_ms_h_p) {
00607                 int abs_yy = static_cast<int>(((float)yy / pyr_heights[scale]) * IMG_HEIGHT);
00608                 int abs_xx = static_cast<int>(((float)xx / pyr_widths[scale]) * IMG_WIDTH);
00609                 int img_offset = abs_yy + IMG_HEIGHT * abs_xx;
00610                 *depth_ms_h_p = depth_ms_h[img_offset];
00611                 *intensity_ms_h_p = intensity_ms_h[img_offset];
00612                 *mask_ms_h_p = mask_h[img_offset];
00613                 *valid_ms_h_p = !mask_h[img_offset];
00614                 *result_ms_h_p = 0;
00615             }
00616         }
00617     }
00618 
00619     // *********************************
00620     //   RUN THE ACTUAL FILTERING CODE
00621     // *********************************
00622 
00623     for (int scale = NUM_SCALES - 1; scale >= 0; --scale) {
00624         //printf("Filtering at scale %d, [%dx%d]\n", scale, pyr_heights[scale], pyr_widths[scale]);
00625 
00626 #ifdef DEBUG
00627         char filename1[50];
00628         sprintf(filename1, "missing_pixels_before_filtering_scale%d.pgm", scale);
00629         // Now that we've performed the filtering, save the intermediate image.
00630         savePGM(mask_ms_h + pyr_offsets[scale], filename1, pyr_heights[scale], pyr_widths[scale]);
00631 
00632         char filename2[50];
00633         sprintf(filename2, "valid_pixels_before_filtering_scale%d.pgm", scale);
00634         // Now that we've performed the filtering, save the intermediate image.
00635         savePGM(valid_ms_h + pyr_offsets[scale], filename2, pyr_heights[scale], pyr_widths[scale]);
00636 
00637         sprintf(filename2, "valid_intensity_before_filtering_scale%d.pgm", scale);
00638         // Now that we've performed the filtering, save the intermediate image.
00639         savePGM(intensity_ms_h + pyr_offsets[scale], filename2, pyr_heights[scale], pyr_widths[scale]);
00640 
00641         sprintf(filename2, "depth_before_filtering_scale%d.pgm", scale);
00642         // Now that we've performed the filtering, save the intermediate image.
00643         savePGM(depth_ms_h + pyr_offsets[scale], filename2, pyr_heights[scale], pyr_widths[scale]);
00644 #endif
00645 
00646         filter_at_scale(depth_ms_h + pyr_offsets[scale],
00647                         intensity_ms_h + pyr_offsets[scale],
00648                         mask_ms_h + pyr_offsets[scale],
00649                         valid_ms_h + pyr_offsets[scale],
00650                         result_ms_h + pyr_offsets[scale],
00651                         abs_inds_to_filter_h,
00652                         pyr_heights[scale],
00653                         pyr_widths[scale],
00654                         sigma_s[scale],
00655                         sigma_r[scale]);
00656 
00657 
00658 #ifdef DEBUG
00659         sprintf(filename2, "valid_pixels_after_filtering_scale%d.pgm", scale);
00660         // Now that we've performed the filtering, save the intermediate image.
00661         savePGM(valid_ms_h + pyr_offsets[scale], filename2, pyr_heights[scale], pyr_widths[scale]);
00662 #endif
00663 
00664 #ifdef DEBUG
00665         char filename[50];
00666         sprintf(filename, "depth_after_filtering_scale%d.pgm", scale);
00667         // Now that we've performed the filtering, save the intermediate image.
00668         savePGM(result_ms_h + pyr_offsets[scale], filename, pyr_heights[scale], pyr_widths[scale]);
00669 #endif
00670 
00671         if (scale == 0) {
00672             continue;
00673         }
00674 
00675         // Now, we need to upsample the resulting depth and store it in the next
00676         // highest location.
00677         int num_missing_pixels = pyr_heights[scale-1] * pyr_widths[scale-1];
00678 
00679         //printf("Upsampling %d\n", num_missing_pixels);
00680         for (int i = 0; i < num_missing_pixels; ++i) {
00681             upsample_cpu(depth_ms_h + pyr_offsets[scale-1],
00682                     mask_ms_h + pyr_offsets[scale-1],
00683                     valid_ms_h + pyr_offsets[scale-1],
00684                     depth_ms_h + pyr_offsets[scale],
00685                     result_ms_h + pyr_offsets[scale],
00686                     mask_ms_h + pyr_offsets[scale],
00687                     valid_ms_h + pyr_offsets[scale],
00688                     pyr_heights[scale],
00689                     pyr_widths[scale],
00690                     pyr_heights[scale-1],
00691                     pyr_widths[scale-1],
00692                     i);
00693         }
00694 
00695 
00696 #ifdef DEBUG
00697         sprintf(filename, "up_depth_after_filtering_scale%d.pgm", scale);
00698         // Now that we've performed the filtering, save the intermediate image.
00699         savePGM(depth_ms_h + pyr_offsets[scale-1], filename, pyr_heights[scale-1], pyr_widths[scale-1]);
00700 
00701         sprintf(filename, "up_valid_after_filtering_scale%d.pgm", scale);
00702         // Now that we've performed the filtering, save the intermediate image.
00703         savePGM(valid_ms_h + pyr_offsets[scale-1], filename, pyr_heights[scale-1], pyr_widths[scale-1]);
00704 #endif
00705     }
00706 
00707     // Copy the final result from the device.
00708     for (int nn = 0; nn < N; ++nn) {
00709         if (mask_ms_h[nn]) {
00710             result[nn] = static_cast<uint8_t>(result_ms_h[nn] * 255);
00711         } else {
00712             result[nn] = depth[nn];
00713         }
00714     }
00715 
00716     free(depth_ms_h);
00717     free(intensity_ms_h);
00718     free(mask_ms_h);
00719     free(result_ms_h);
00720     free(valid_ms_h);
00721     free(abs_inds_to_filter_h);
00722 
00723     toc("Entire Function", start_func);
00724 }
00725 
00726 cv::Mat fill_depth_cbf(cv::Mat imgRgb, cv::Mat imgDepthAbs, double* spaceSigmas, double* rangeSigmas)
00727 {
00728     double spaceSigmas_default[3];
00729     spaceSigmas_default[0] = 12;
00730     spaceSigmas_default[1] = 5;
00731     spaceSigmas_default[2] = 8;
00732 
00733     double rangeSigmas_default[3];
00734     rangeSigmas_default[0] = 0.2;
00735     rangeSigmas_default[1] = 0.08;
00736     rangeSigmas_default[2] = 0.02;
00737 
00738     // Create the 'noise' image and get the maximum observed depth.
00739     cv::Mat imgIsNoise = imgDepthAbs != imgDepthAbs;
00740     cv::Mat imgIsNotNoise = imgDepthAbs == imgDepthAbs;
00741 
00742     double min, max;
00743     cv::minMaxLoc(imgDepthAbs, &min, &max, 0, 0, imgIsNotNoise);
00744 
00745     // Convert the depth image to uint8.
00746     cv::Mat imgDepth = (255/max) * imgDepthAbs;
00747     imgDepth.setTo(255, imgDepth >255);
00748 
00749     cv::Mat img_depth_8u;
00750     imgDepth.convertTo(img_depth_8u, CV_8U);
00751 
00752     cv::Mat result_8u;
00753     img_depth_8u.copyTo(result_8u);
00754 
00755     bool* isnoise = (bool*) malloc(IMG_WIDTH*IMG_HEIGHT * sizeof(bool));
00756 
00757     for(int k=0; k<imgIsNoise.cols; k++)
00758     {
00759         for(int j=0; j<imgIsNoise.rows; j++)
00760         {
00761             if(imgIsNoise.at<uchar>(j,k) == 0)
00762             {
00763                 isnoise[j*imgIsNoise.cols + k] = false;
00764             }else{
00765                 isnoise[j*imgIsNoise.cols + k] = true;
00766             }
00767         }
00768     }
00769 
00770     // Run the cross-bilateral filter.
00771     cbf(img_depth_8u.data, imgRgb.data, isnoise, result_8u.data, spaceSigmas_default, rangeSigmas_default);
00772 
00773     cv::Mat result_double;
00774     result_8u.convertTo(result_double, CV_32FC1);
00775     result_double = result_double*(max/255.0);
00776 
00777     return result_double;
00778 }
00779 
00780 }


shape_reconstruction
Author(s): Roberto Martín-Martín
autogenerated on Sat Jun 8 2019 18:36:32