Browse Source

minor improvement regarding the config file

Helge Wrede 9 years ago
parent
commit
4ab69b7493
14 changed files with 288 additions and 94 deletions
  1. 1 1
      CMakeLists.txt
  2. 23 15
      algo/Berclaz.cpp
  3. 5 4
      algo/Berclaz.h
  4. 0 2
      core/ObjectData.h
  5. 9 11
      core/ObjectDataBox.cpp
  6. 3 4
      core/ObjectDataBox.h
  7. 35 26
      main/main.cpp
  8. 2 2
      util/FileIO.cpp
  9. 1 1
      util/FileIO.h
  10. 99 0
      util/Filter2D.cpp
  11. 53 0
      util/Filter2D.h
  12. 46 3
      util/Grid.cpp
  13. 10 4
      util/Grid.h
  14. 1 21
      util/Parser.cpp

+ 1 - 1
CMakeLists.txt

@@ -23,7 +23,7 @@ set(SOURCE_FILES
         algo/Berclaz.cpp algo/Berclaz.h
         util/Grid.cpp util/Grid.h
         core/ObjectDataBox.cpp core/ObjectDataBox.h
-        algo/KShortestPaths.cpp algo/KShortestPaths.h)
+        algo/KShortestPaths.cpp algo/KShortestPaths.h util/Filter2D.cpp util/Filter2D.h)
 
 find_package(Doxygen)
 

+ 23 - 15
algo/Berclaz.cpp

@@ -36,8 +36,6 @@ namespace algo
         source = boost::add_vertex(core::ObjectDataPtr(new core::ObjectData()), graph);
         sink = boost::add_vertex(core::ObjectDataPtr(new core::ObjectData()), graph);
 
-//        util::Logger::LogDebug("source index: " + std::to_string(source));
-//        util::Logger::LogDebug("sink index: " + std::to_string(sink));
         util::Logger::LogDebug("add edges");
 
         // Iterate all vertices but source and sink
@@ -102,19 +100,7 @@ namespace algo
         }
 
         util::Logger::LogDebug("vertex count " + std::to_string(boost::num_vertices(graph)));
-//        util::Logger::LogDebug("calculated vertex count " + std::to_string(
-//           grid.GetWidthCount() * grid.GetHeightCount() * grid.GetDepthCount() + 2
-//        ));
         util::Logger::LogDebug("edge count " + std::to_string(boost::num_edges(graph)));
-//        util::Logger::LogDebug("width count " + std::to_string(grid.GetWidthCount()));
-//        util::Logger::LogDebug("height count " + std::to_string(grid.GetHeightCount()));
-//        util::Logger::LogDebug("depth count " + std::to_string(grid.GetDepthCount()));
-//        util::Logger::LogDebug("calculated edge count " + std::to_string(
-//           grid.GetWidthCount() * grid.GetHeightCount() * (grid.GetDepthCount() - 1) * 11 +
-//           grid.GetWidthCount() * grid.GetHeightCount() * 2 -
-//           (grid.GetWidthCount() + grid.GetHeightCount()) * 2 * 3 * (grid.GetDepthCount() - 1) +
-//           4 * (grid.GetDepthCount() - 1)
-//        ));
     }
 
     void Berclaz::ExtractTracks(DirectedGraph& graph, MultiPredecessorMap& map, Vertex origin,
@@ -141,7 +127,7 @@ namespace algo
 
     void Berclaz::Run(core::DetectionSequence& sequence,
                       size_t batch_size, size_t max_track_count,
-                      std::vector<core::TrackletPtr>& tracks)
+                      std::vector<core::TrackletPtr> & tracks, util::Filter2D & filter)
     {
         for (size_t i = 0; i < sequence.GetFrameCount(); i += batch_size)
         {
@@ -150,6 +136,28 @@ namespace algo
             util::Grid grid = util::Parser::ParseGrid(sequence, i, i + batch_size,
                                                       0.0, 1.0, h_res_, 0.0, 1.0, v_res_);
 
+            // Convolve with linear filter
+//            int vicinity = 1;
+//            double multiplier = 0.25;
+//            double* linear_filter = new double[9] {
+//                    0.25, 0.50, 0.25,
+//                    0.50, 1.00, 0.50,
+//                    0.25, 0.50, 0.25
+//            };
+//            grid.Convolve2D(vicinity, linear_filter, multiplier);
+//            delete[] linear_filter;
+
+            // Convolve with gaussian filter
+//            int vicinity = 1;
+//            double* gaussian_filter = new double[9] {
+//                    0.002284, 0.043222, 0.002284,
+//                    0.043222, 0.817976, 0.043222,
+//                    0.002284, 0.043222, 0.002284
+//            };
+//            grid.Convolve2D(vicinity, gaussian_filter, 1.0);
+//            delete[] gaussian_filter;
+            grid.Convolve2D(filter);
+
             util::Logger::LogDebug("create graph");
             DirectedGraph graph;
             Vertex source, sink;

+ 5 - 4
algo/Berclaz.h

@@ -59,10 +59,10 @@ namespace algo
          */
         void ExtractTracks(DirectedGraph& graph,
                            MultiPredecessorMap& map, Vertex origin,
-                           std::vector<core::TrackletPtr>& tracks);
+                           std::vector<core::TrackletPtr> & tracks);
 
         //TODO comment
-        void ConnectTracks(std::vector<core::TrackletPtr>& tracks);
+        void ConnectTracks(std::vector<core::TrackletPtr> & tracks);
     public:
         /**
          * Instantiate with the given parameters.
@@ -83,8 +83,9 @@ namespace algo
          * @param max_track_count The maximum number of tracks to extract
          * @param tracks The vector to store the found tracks into
          */
-        void Run(core::DetectionSequence& sequence, size_t batch_size,
-                 size_t max_track_count, std::vector<core::TrackletPtr>& tracks);
+        void Run(core::DetectionSequence & sequence, size_t batch_size,
+                 size_t max_track_count, std::vector<core::TrackletPtr> & tracks,
+                 util::Filter2D & filter);
     };
 }
 

+ 0 - 2
core/ObjectData.h

@@ -17,7 +17,6 @@ namespace core
     class ObjectData;
     typedef std::shared_ptr<ObjectData> ObjectDataPtr;
 
-    //TODO RENAME ObjectDataBase / ObjectBase / DataBase / AObject / DetectionBase ...
     /**
      * Base class for all detected objects.
      * Stores the corresponding frame index.
@@ -88,7 +87,6 @@ namespace core
          */
         bool IsVirtual() const;
 
-        //TODO RENAME ObjectDataComparable / IComparable ...
         /**
          * Compares this object with the given object.
          * @param obj A pointer to the object to compare this object to

+ 9 - 11
core/ObjectDataBox.cpp

@@ -8,9 +8,9 @@
 
 namespace core
 {
-    ObjectDataBox::ObjectDataBox(size_t frame_index, cv::Point2d anchor,
+    ObjectDataBox::ObjectDataBox(size_t frame_index, cv::Point2d center,
                                  cv::Point2d size)
-            : ObjectData2D(frame_index, anchor),
+            : ObjectData2D(frame_index, center),
               size_(size)
     {
     }
@@ -33,8 +33,7 @@ namespace core
         cv::Point2d other_center = other->GetPosition() + other->size_ * 0.5;
 
         double d_temp = other->GetFrameIndex() - GetFrameIndex();
-        double d_spat = util::MyMath::EuclideanDistance(this_center,
-                                                        other_center);
+        double d_spat = util::MyMath::EuclideanDistance(this_center, other_center);
 
         return d_temp * GetTemporalWeight() + d_spat * GetSpatialWeight();
     }
@@ -47,10 +46,9 @@ namespace core
         size_t frame = (size_t) fabs(util::MyMath::Lerp(GetFrameIndex(),
                                                         other->GetFrameIndex(),
                                                         fraction));
-        double x = util::MyMath::Lerp(GetPosition().x, other->GetPosition().x,
-                                      fraction);
-        double y = util::MyMath::Lerp(GetPosition().y, other->GetPosition().y,
-                                      fraction);
+
+        double x = util::MyMath::Lerp(GetPosition().x, other->GetPosition().x, fraction);
+        double y = util::MyMath::Lerp(GetPosition().y, other->GetPosition().y, fraction);
         double w = util::MyMath::Lerp(size_.x, other->size_.x, fraction);
         double h = util::MyMath::Lerp(size_.y, other->size_.y, fraction);
 
@@ -62,11 +60,11 @@ namespace core
 
     void ObjectDataBox::Visualize(cv::Mat& image, cv::Scalar& color) const
     {
-        cv::Point2d position(GetPosition().x * image.cols,
-                             GetPosition().y * image.rows);
+        cv::Point2d center(GetPosition().x * image.cols, GetPosition().y * image.rows);
         cv::Point2d size(size_.x * image.cols, size_.y * image.rows);
+        cv::Point2d top_left = center - size * 0.5;
 
-        cv::rectangle(image, position, position + size, color);
+        cv::rectangle(image, top_left, top_left + size, color);
     }
 
     cv::Point2d ObjectDataBox::GetSize() const

+ 3 - 4
core/ObjectDataBox.h

@@ -29,10 +29,10 @@ namespace core
          * Creates a new detection with an bounding box of the given size.
          *
          * @param frame_index The frame index of the detection
-         * @param anchor The top left corner of the bounding box
+         * @param center The center of the bounding box
          * @param size The size of the bounding box
          */
-        ObjectDataBox(size_t frame_index, cv::Point2d anchor, cv::Point2d size);
+        ObjectDataBox(size_t frame_index, cv::Point2d center, cv::Point2d size);
 
         /**
          * Gets the size of the bounding box.
@@ -42,8 +42,7 @@ namespace core
         cv::Point2d GetSize() const;
 
         virtual double CompareTo(ObjectDataPtr obj) const override;
-        virtual ObjectDataPtr Interpolate(ObjectDataPtr obj,
-                                          double fraction) const override;
+        virtual ObjectDataPtr Interpolate(ObjectDataPtr obj, double fraction) const override;
         virtual void Visualize(cv::Mat& image, cv::Scalar& color) const override;
     };
 }

+ 35 - 26
main/main.cpp

@@ -100,6 +100,7 @@ struct
     int vicinity_size;
     size_t batch_size;
     size_t max_track_count;
+    util::Filter2D filter;
 } berclaz_params;
 
 void RunBerclaz(core::DetectionSequence& sequence, std::vector<core::TrackletPtr>& tracks)
@@ -110,8 +111,11 @@ void RunBerclaz(core::DetectionSequence& sequence, std::vector<core::TrackletPtr
     algo::Berclaz berclaz(berclaz_params.h_res,
                           berclaz_params.v_res,
                           berclaz_params.vicinity_size);
-    berclaz.Run(sequence, berclaz_params.batch_size,
-                berclaz_params.max_track_count, tracks);
+    berclaz.Run(sequence,
+                berclaz_params.batch_size,
+                berclaz_params.max_track_count,
+                tracks,
+                berclaz_params.filter);
 
     util::Logger::LogInfo("Interpolate tracks");
 
@@ -124,10 +128,11 @@ void RunBerclaz(core::DetectionSequence& sequence, std::vector<core::TrackletPtr
     util::Logger::LogInfo("Finished");
 }
 
-void Run(int argc, char** argv)
+void Run(int argc, char const * const * argv)
 {
     // Algorithm independent values
-    std::string input_file, output_path, images_folder, algorithm, config_path, header, input_format;
+    std::string input_file, output_path, images_folder, algorithm, config_path, header;
+    std::string input_format, berclaz_filter;
     bool info, debug, display, output, output_images;
     char input_delimiter, output_delimiter;
     double temporal_weight, spatial_weight, angular_weight, image_width, image_height;
@@ -196,59 +201,61 @@ void Run(int argc, char** argv)
             ("algorithm",
              boost::program_options::value<std::string>(&algorithm),
              "set the algorithm to use, current viable options: n-stage berclaz")
-            ("max-frame-skip",
+            ("n-stage.max-frame-skip",
              boost::program_options::value<std::string>(&n_stage_params.max_frame_skip)
                      ->default_value("1,1"),
-             "(n stage) set the maximum number of frames a track can skip between two detections,"
+             "(n-stage) set the maximum number of frames a track can skip between two detections,"
                      " if set to less or equal than zero all frames are linked")
-            ("max-tracklet-count",
+            ("n-stage.max-tracklet-count",
              boost::program_options::value<std::string>(&n_stage_params.max_tracklet_count)
                      ->default_value("-1,1"),
-             "(n stage) set the maximum number of tracklets to be extracted")
-            ("penalty-value",
+             "(n-stage) set the maximum number of tracklets to be extracted")
+            ("n-stage.penalty-value",
              boost::program_options::value<std::string>(&n_stage_params.penalty_value)
                      ->default_value("0,0"),
-             "(n stage) set the penalty value for edges from and to source and sink")
-            ("temporal-weight",
+             "(n-stage) set the penalty value for edges from and to source and sink")
+            ("n-stage.temporal-weight",
              boost::program_options::value<double>(&temporal_weight)
                      ->default_value(1.0),
-             "(n stage) temporal weight for difference calculations between two detections")
-            ("spatial-weight",
+             "(n-stage) temporal weight for difference calculations between two detections")
+            ("n-stage.spatial-weight",
              boost::program_options::value<double>(&spatial_weight)
                      ->default_value(1.0),
-             "(n stage) spatial weight for difference calculations between two detections")
-            ("angular-weight",
+             "(n-stage) spatial weight for difference calculations between two detections")
+            ("n-stage.angular-weight",
              boost::program_options::value<double>(&angular_weight)
                      ->default_value(1.0),
-             "(n stage) angular weight for difference calculations between two detections")
-            ("horizontal-resolution",
+             "(n-stage) angular weight for difference calculations between two detections")
+            ("berclaz.horizontal-resolution",
              boost::program_options::value<int>(&berclaz_params.h_res)
                      ->default_value(10),
              "(berclaz) the number of horizontal grid cells")
-            ("vertical-resolution",
+            ("berclaz.vertical-resolution",
              boost::program_options::value<int>(&berclaz_params.v_res)
                      ->default_value(10),
              "(berclaz) the number of vertical grid cells")
-            ("vicinity-size",
+            ("berclaz.vicinity-size",
              boost::program_options::value<int>(&berclaz_params.vicinity_size)
                      ->default_value(1),
              "(berclaz) the vicinity size, the number of cells a detection can travel between two frames")
-            ("max-track-count",
+            ("berclaz.max-track-count",
              boost::program_options::value<size_t>(&berclaz_params.max_track_count)
                      ->default_value(1),
              "(berclaz) the maximal number of tracks to extract")
-            ("batch-size",
+            ("berclaz.batch-size",
              boost::program_options::value<size_t>(&berclaz_params.batch_size)
                      ->default_value(100),
-             "(berclaz) the size of one processing batch");
+             "(berclaz) the size of one processing batch")
+            ("berclaz.filter",
+             boost::program_options::value<std::string>(&berclaz_filter)
+                     ->default_value(""),
+             "(berclaz) the filter used in the berclaz grid (comma separated),"
+                     " e.g. multiplier, m01, m02,...,mnn");
 
     boost::program_options::variables_map opt_var_map;
-#pragma clang diagnostic push
-#pragma clang diagnostic ignored "-Wincompatible-pointer-types-discards-qualifiers"
     boost::program_options::store(
             boost::program_options::parse_command_line(argc, argv, opts),
             opt_var_map);
-#pragma clang diagnostic pop
     boost::program_options::notify(opt_var_map);
 
     // Display help
@@ -369,6 +376,7 @@ void Run(int argc, char** argv)
     }
     else if (algorithm == "berclaz")
     {
+        berclaz_params.filter = util::Filter2D(berclaz_filter, ',');
         RunBerclaz(sequence, tracks);
     }
     else
@@ -916,9 +924,10 @@ void TestYAOKSP()
     }
 }
 
-int main(int argc, char** argv)
+int main(int argc, char const * const * argv)
 {
     //TODO load with frame offset
+    //TODO check visualizer for offset errors
 
     Run(argc, argv);
 

+ 2 - 2
util/FileIO.cpp

@@ -380,7 +380,7 @@ namespace util
 
             if (line.size() == 0) continue;
 
-            std::vector<std::string> parts = split(line, delimiter);
+            std::vector<std::string> parts = Split(line, delimiter);
 
             while (tracks.size() < (parts.size() / 2))
             {
@@ -404,7 +404,7 @@ namespace util
         in.close();
     }
 
-    std::vector<std::string> FileIO::split(const std::string& input, char delimiter)
+    std::vector<std::string> FileIO::Split(const std::string& input, char delimiter)
     {
         std::vector<std::string> output;
         std::stringstream ss(input);

+ 1 - 1
util/FileIO.h

@@ -132,7 +132,7 @@ namespace util
          * @param delimiter The delimiter used to split, the delimiter will not be stored
          * @return A vector of parts like (for string of length n: [0,d)...(d,d)...(d,n))
          */
-        static std::vector<std::string> split(const std::string& input, char delimiter);
+        static std::vector<std::string> Split(const std::string& input, char delimiter);
     };
 }
 

+ 99 - 0
util/Filter2D.cpp

@@ -0,0 +1,99 @@
+//
+// Created by wrede on 11.07.16.
+//
+
+#include <cmath>
+#include "Filter2D.h"
+#include "FileIO.h"
+
+namespace util
+{
+    Filter2D::Filter2D()
+    {
+        multiplier_ = 1.0;
+        mask_.push_back(1.0);
+        dimension_ = 1;
+        vicinity_ = 0;
+    }
+
+    Filter2D::Filter2D(double multiplier, std::vector<double> mask)
+    {
+        multiplier_ = multiplier;
+        mask_ = mask;
+        dimension_ = Dimension(static_cast<int>(mask_.size()));
+        vicinity_ = Vicinity(static_cast<int>(mask_.size()));
+    }
+
+    Filter2D::Filter2D(std::string const & mask_string, char delimiter)
+    {
+        if (mask_string.empty())
+        {
+            multiplier_ = 1.0;
+            mask_.push_back(1.0);
+            dimension_ = 1;
+            vicinity_ = 0;
+        }
+        else
+        {
+            std::vector<std::string> parts = FileIO::Split(mask_string, delimiter);
+
+            multiplier_ = stof(parts[0]);
+
+            for (int i = 1; i < parts.size(); ++i)
+            {
+                mask_.push_back(stod(parts[i]));
+            }
+
+            dimension_ = Dimension(static_cast<int>(mask_.size()));
+            vicinity_ = Vicinity(static_cast<int>(mask_.size()));
+        }
+    }
+
+    int Filter2D::Index(int x, int y) const
+    {
+        return static_cast<int>(y * mask_.size() + x);
+    }
+
+    int Filter2D::Vicinity(int count) const
+    {
+        return static_cast<int>(std::sqrt(count) / 2);
+    }
+
+    int Filter2D::Dimension(int size) const
+    {
+        return static_cast<int>(std::sqrt(size));
+    }
+
+    double Filter2D::Get(int x, int y) const
+    {
+        return mask_[Index(x, y)];
+    }
+
+    double Filter2D::Get(int i) const
+    {
+        return mask_[i];
+    }
+
+    double Filter2D::GetMultiplier() const
+    {
+        return multiplier_;
+    }
+
+    int Filter2D::GetVicinity() const
+    {
+        return vicinity_;
+    }
+
+    int Filter2D::GetDimension() const
+    {
+        return dimension_;
+    }
+
+    void Filter2D::Normalize()
+    {
+        for (auto & value : mask_)
+            value *= multiplier_;
+
+        multiplier_ = 1.0;
+    }
+}

+ 53 - 0
util/Filter2D.h

@@ -0,0 +1,53 @@
+//
+// Created by wrede on 11.07.16.
+//
+
+#ifndef GBMOT_FILTER_H
+#define GBMOT_FILTER_H
+
+
+#include <vector>
+#include <string>
+
+namespace util
+{
+    class Filter2D
+    {
+    public:
+        Filter2D();
+
+        Filter2D(double multiplier, std::vector<double> mask);
+
+        // Example:
+        // mask_string = multiplier, m00, m01, m02, ..., m10, m11, m12, ..., mnn
+        // delimiter = ,
+        Filter2D(std::string const & mask_string, char delimiter);
+
+        double Get(int x, int y) const;
+
+        double Get(int i) const;
+
+        double GetMultiplier() const;
+
+        int GetVicinity() const;
+
+        int GetDimension() const;
+
+        void Normalize();
+
+    private:
+        int Index(int x, int y) const;
+
+        int Vicinity(int size) const;
+
+        int Dimension(int size) const;
+
+        std::vector<double> mask_;
+        double multiplier_;
+        int dimension_;
+        int vicinity_;
+    };
+}
+
+
+#endif //GBMOT_FILTER_H

+ 46 - 3
util/Grid.cpp

@@ -43,12 +43,12 @@ namespace util
     void Grid::PositionToIndex(double x, double y, double z,
                                int& xi, int& yi, int& zi) const
     {
-        xi = (int) (x / cell_width_);
-        yi = (int) (y / cell_height_);
+        xi = static_cast<int>(x / cell_width_);
+        yi = static_cast<int>(y / cell_height_);
 
         if (depth_count_ > 1)
         {
-            zi = (int) (z / cell_depth_);
+            zi = static_cast<int>(z / cell_depth_);
         }
         else
         {
@@ -206,4 +206,47 @@ namespace util
             }
         }
     }
+
+    void Grid::Convolve2D(util::Filter2D & filter)
+    {
+        // [x,y,z]    position in grid
+        // [vx,vy,vz] position in vicinity
+        // [nx,ny,nz] position in grid
+        // [mx,my,mz] position in mask
+        // [mi]       index in mask
+
+        int vicinity = filter.GetVicinity();
+        for (int z = 0; z < depth_count_; ++z)
+        {
+            for (int y = 0; y < height_count_; ++y)
+            {
+                for (int x = 0; x < width_count_; ++x)
+                {
+                    double score = 0.0;
+
+                    for (int vy = -vicinity; vy <= vicinity; ++vy)
+                    {
+                        int ny = y + vy;
+
+                        if (ny < 0 || ny >= height_count_) continue;
+
+                        int my = vy + vicinity;
+
+                        for (int vx = -vicinity; vx <= vicinity; ++vx)
+                        {
+                            int nx = x + vx;
+
+                            if (nx < 0 || nx >= width_count_) continue;
+
+                            int mx = vx + vicinity;
+
+                            score += GetValue(nx, ny, z)->GetDetectionScore() * filter.Get(mx, my);
+                        }
+                    }
+
+                    GetValue(x, y, z)->SetDetectionScore(score * filter.GetMultiplier());
+                }
+            }
+        }
+    }
 }

+ 10 - 4
util/Grid.h

@@ -7,6 +7,7 @@
 
 #include <vector>
 #include "../core/ObjectData.h"
+#include "Filter2D.h"
 
 namespace util
 {
@@ -104,8 +105,7 @@ namespace util
          * @param y The y axis value
          * @param z The z axis value
          */
-        void SetValue(core::ObjectDataPtr value,
-                      double x, double y, double z = 0);
+        void SetValue(core::ObjectDataPtr value, double x, double y, double z = 0);
 
         /**
          * Gets the value in the grid cell with the given index.
@@ -170,8 +170,7 @@ namespace util
          * @param yi The y axis index
          * @param zi The z axis index
          */
-        void PositionToIndex(double x, double y, double z,
-                             int& xi, int& yi, int& zi) const;
+        void PositionToIndex(double x, double y, double z, int& xi, int& yi, int& zi) const;
 
         /**
          * Performs a 2D convolution.
@@ -182,6 +181,13 @@ namespace util
          */
         void Convolve2D(int vicinity, double* mask, double multiplier);
 
+        /**
+         * Performs a 2D convolution.
+         *
+         * @param filter The 2D filter to use
+         */
+        void Convolve2D(util::Filter2D & filter);
+
         /**
          * Performs a 3D convolution.
          *

+ 1 - 21
util/Parser.cpp

@@ -10,6 +10,7 @@
 
 namespace util
 {
+    //TODO rename if necessary
     const std::string Parser::KEY_FRAME = "frame";
     const std::string Parser::KEY_ID = "id";
     const std::string Parser::KEY_SCORE = "score";
@@ -249,27 +250,6 @@ namespace util
             }
         }
 
-        // Convolve with linear filter
-//        int vicinity = 1;
-//        double multiplier = 0.25;
-//        double* linear_filter = new double[9] {
-//                0.25, 0.50, 0.25,
-//                0.50, 1.00, 0.50,
-//                0.25, 0.50, 0.25
-//        };
-//        grid.Convolve2D(vicinity, linear_filter, multiplier);
-//        delete[] linear_filter;
-
-        // Convolve with gaussian filter
-        int vicinity = 1;
-        double* gaussian_filter = new double[9] {
-                0.002284, 0.043222, 0.002284,
-                0.043222, 0.817976, 0.043222,
-                0.002284, 0.043222, 0.002284
-        };
-        grid.Convolve2D(vicinity, gaussian_filter, 1.0);
-        delete[] gaussian_filter;
-
         return grid;
     }
 }