00001 #include <opencv2/highgui/highgui.hpp>
00002
00003 #include <costmap_converter/costmap_to_dynamic_obstacles/background_subtractor.h>
00004
00005 BackgroundSubtractor::BackgroundSubtractor(const Params ¶meters): 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
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
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
00030 transformToCurrentFrame(shift_relative_to_previous_pos_x_, shift_relative_to_previous_pos_y_);
00031
00032
00033
00034
00035 int size = 3;
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
00043
00044
00045
00046
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
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
00054
00055 cv::threshold(occupancy_grid_fast_, occupancy_grid_fast_, params_.min_occupancy_probability, 0 , cv::THRESH_TOZERO);
00056
00057
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
00061
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
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
00073
00074
00075
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
00087
00088
00089
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());
00093 cv::warpAffine(occupancy_grid_slow_, temp_slow, translation_mat, occupancy_grid_slow_.size());
00094
00095
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 ¶meters)
00113 {
00114 params_ = parameters;
00115 }