background_subtractor.cpp
Go to the documentation of this file.
00001 #include <opencv2/highgui/highgui.hpp>
00002 //#include <opencv2/cvv/cvv.hpp>
00003 #include <costmap_converter/costmap_to_dynamic_obstacles/background_subtractor.h>
00004 
00005 BackgroundSubtractor::BackgroundSubtractor(const Params &parameters): params_(parameters)
00006 {
00007 }
00008 
00009 void BackgroundSubtractor::apply(const cv::Mat& image, cv::Mat& fg_mask, int shift_x, int shift_y)
00010 {
00011   current_frame_ = image;
00012 
00013   // occupancy grids are empty only once in the beginning -> initialize variables
00014   if (occupancy_grid_fast_.empty() && occupancy_grid_slow_.empty())
00015   {
00016     occupancy_grid_fast_ = current_frame_;
00017     occupancy_grid_slow_ = current_frame_;
00018     previous_shift_x_ = shift_x;
00019     previous_shift_y_ = shift_y;
00020     return;
00021   }
00022 
00023   // Shift previous occupancy grid to new location (match current_frame_)
00024   int shift_relative_to_previous_pos_x_ = shift_x - previous_shift_x_;
00025   int shift_relative_to_previous_pos_y_ = shift_y - previous_shift_y_;
00026   previous_shift_x_ = shift_x;
00027   previous_shift_y_ = shift_y;
00028 
00029   // if(shift_relative_to_previous_pos_x_ != 0 || shift_relative_to_previous_pos_y_ != 0)
00030   transformToCurrentFrame(shift_relative_to_previous_pos_x_, shift_relative_to_previous_pos_y_);
00031 
00032   // cvv::debugFilter(occupancy_grid_fast_, currentFrame_, CVVISUAL_LOCATION);
00033 
00034   // Calculate normalized sum (mean) of nearest neighbors
00035   int size = 3; // 3, 5, 7, ....
00036   cv::Mat nearest_neighbor_mean_fast(occupancy_grid_fast_.size(), CV_8UC1);
00037   cv::Mat nearest_neighbor_mean_slow(occupancy_grid_slow_.size(), CV_8UC1);
00038   cv::boxFilter(occupancy_grid_fast_, nearest_neighbor_mean_fast, -1, cv::Size(size, size), cv::Point(-1, -1), true,
00039                 cv::BORDER_REPLICATE);
00040   cv::boxFilter(occupancy_grid_slow_, nearest_neighbor_mean_slow, -1, cv::Size(size, size), cv::Point(-1, -1), true,
00041                 cv::BORDER_REPLICATE);
00042   //  cv::GaussianBlur(occupancy_grid_fast_, nearest_neighbor_mean_fast, cv::Size(size,size), 1, 1, cv::BORDER_REPLICATE);
00043   //  cv::GaussianBlur(occupancy_grid_fast_, nearest_neighbor_mean_fast, cv::Size(size,size), 1, 1, cv::BORDER_REPLICATE);
00044 
00045   // compute time mean value for each pixel according to learningrate alpha
00046   // occupancy_grid_fast_ = beta*(alpha_fast*current_frame_ + (1.0-alpha_fast)*occupancy_grid_fast_) + (1-beta)*nearest_neighbor_mean_fast;
00047   cv::addWeighted(current_frame_, params_.alpha_fast, occupancy_grid_fast_, (1 - params_.alpha_fast), 0, occupancy_grid_fast_);
00048   cv::addWeighted(occupancy_grid_fast_, params_.beta, nearest_neighbor_mean_fast, (1 - params_.beta), 0, occupancy_grid_fast_);
00049   // occupancy_grid_slow_ = beta*(alpha_slow*current_frame_ + (1.0-alpha_slow)*occupancy_grid_slow) + (1-beta)*nearest_neighbor_mean_slow;
00050   cv::addWeighted(current_frame_, params_.alpha_slow, occupancy_grid_slow_, (1 - params_.alpha_slow), 0, occupancy_grid_slow_);
00051   cv::addWeighted(occupancy_grid_slow_, params_.beta, nearest_neighbor_mean_slow, (1 - params_.beta), 0, occupancy_grid_slow_);
00052 
00053   // 1) Obstacles should be detected after a minimum response of the fast filter
00054   //    occupancy_grid_fast_ > min_occupancy_probability
00055   cv::threshold(occupancy_grid_fast_, occupancy_grid_fast_, params_.min_occupancy_probability, 0 /*unused*/, cv::THRESH_TOZERO);
00056   // 2) Moving obstacles have a minimum difference between the responses of the slow and fast filter
00057   //    occupancy_grid_fast_-occupancy_grid_slow_ > min_sep_between_fast_and_slow_filter
00058   cv::threshold(occupancy_grid_fast_ - occupancy_grid_slow_, fg_mask, params_.min_sep_between_fast_and_slow_filter, 255,
00059                 cv::THRESH_BINARY);
00060   // 3) Dismiss static obstacles
00061   //    nearest_neighbor_mean_slow < max_occupancy_neighbors
00062   cv::threshold(nearest_neighbor_mean_slow, nearest_neighbor_mean_slow, params_.max_occupancy_neighbors, 255, cv::THRESH_BINARY_INV);
00063   cv::bitwise_and(nearest_neighbor_mean_slow, fg_mask, fg_mask);
00064 
00065   //visualize("Current frame", currentFrame_);
00066   cv::Mat setBorderToZero = cv::Mat(current_frame_.size(), CV_8UC1, 0.0);
00067   int border = 5;
00068   setBorderToZero(cv::Rect(border, border, current_frame_.cols-2*border, current_frame_.rows-2*border)) = 255;
00069 
00070   cv::bitwise_and(setBorderToZero, fg_mask, fg_mask);
00071 
00072   // cv::imwrite("/home/albers/Desktop/currentFrame.png", currentFrame_);
00073   // visualize("Foreground mask", fgMask);
00074 
00075   // Closing Operation
00076   cv::Mat element = cv::getStructuringElement(cv::MORPH_ELLIPSE,
00077                                               cv::Size(2*params_.morph_size + 1, 2*params_.morph_size + 1),
00078                                               cv::Point(params_.morph_size, params_.morph_size));
00079   cv::dilate(fg_mask, fg_mask, element);
00080   cv::dilate(fg_mask, fg_mask, element);
00081   cv::erode(fg_mask, fg_mask, element);
00082 }
00083 
00084 void BackgroundSubtractor::transformToCurrentFrame(int shift_x, int shift_y)
00085 {
00086   // TODO: initialize with current_frame (first observed image) rather than zeros
00087 
00088   // Translate (shift) image in costmap coordinates
00089   // in cv::Mat: shift X -> to the left; shift y -> to the top
00090   cv::Mat temp_fast, temp_slow;
00091   cv::Mat translation_mat = (cv::Mat_<double>(2, 3, CV_64F) << 1, 0, -shift_x, 0, 1, -shift_y);
00092   cv::warpAffine(occupancy_grid_fast_, temp_fast, translation_mat, occupancy_grid_fast_.size()); // can't operate in-place
00093   cv::warpAffine(occupancy_grid_slow_, temp_slow, translation_mat, occupancy_grid_slow_.size()); // can't operate in-place
00094 
00095   // cvv::debugFilter(occupancy_grid_fast_, temp_fast);
00096 
00097   occupancy_grid_fast_ = temp_fast;
00098   occupancy_grid_slow_ = temp_slow;
00099 }
00100 
00101 void BackgroundSubtractor::visualize(const std::string& name, const cv::Mat& image)
00102 {
00103   if (!image.empty())
00104   {
00105     cv::Mat im = image.clone();
00106     cv::flip(im, im, 0);
00107     cv::imshow(name, im);
00108     cv::waitKey(1);
00109   }
00110 }
00111 
00112 void BackgroundSubtractor::updateParameters(const Params &parameters)
00113 {
00114   params_ = parameters;
00115 }


costmap_converter
Author(s): Christoph Rösmann , Franz Albers , Otniel Rinaldo
autogenerated on Wed Sep 20 2017 03:00:37