00001 /*************************************************************************** 00002 * Copyright (C) 2005-2011 LpzRobots development team * 00003 * Georg Martius <georg dot martius at web dot de> * 00004 * Frank Guettler <guettler at informatik dot uni-leipzig dot de * 00005 * Frank Hesse <frank at nld dot ds dot mpg dot de> * 00006 * Ralf Der <ralfder at mis dot mpg dot de> * 00007 * * 00008 * This program is free software; you can redistribute it and/or modify * 00009 * it under the terms of the GNU General Public License as published by * 00010 * the Free Software Foundation; either version 2 of the License, or * 00011 * (at your option) any later version. * 00012 * * 00013 * This program is distributed in the hope that it will be useful, * 00014 * but WITHOUT ANY WARRANTY; without even the implied warranty of * 00015 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 00016 * GNU General Public License for more details. * 00017 * * 00018 * You should have received a copy of the GNU General Public License * 00019 * along with this program; if not, write to the * 00020 * Free Software Foundation, Inc., * 00021 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * 00022 * * 00023 ***************************************************************************/ 00024 00025 #ifndef __OPTICALFLOW_H 00026 #define __OPTICALFLOW_H 00027 00028 #include "camerasensor.h" 00029 #include <selforg/controller_misc.h> 00030 00031 namespace lpzrobots { 00032 00033 /// configuration object for OpticalFlow 00034 struct OpticalFlowConf { 00035 /// dimensions to return the flow (X means horizonal, Y vertical) 00036 Sensor::Dimensions dims; 00037 /** points to measure optical flow in normalized coordinates [-1,1] 00038 however the points are placed sufficiently away from the border to have no 00039 boundary effects.*/ 00040 std::list<Pos> points; 00041 /** maximum fraction of the image dimension to consider for 00042 a possible flow. Larger values increase the computational demand and move the 00043 points more to the center (since we don't want edge effects)*/ 00044 double maxFlow; 00045 /** size (edge length) of the measurement field (block) in pixel 00046 (if 0 then 1/12th of width) */ 00047 int fieldSize; 00048 /** verbosity level 00049 (0: quite, 1: initialization values, 2: warnings, 3: info, 4: debug) */ 00050 int verbose; 00051 }; 00052 00053 /** This CameraSensor calculates the optical flow at few points of the image 00054 based on a box matching technique. 00055 This can be applied directly to the camera image. 00056 */ 00057 class OpticalFlow : public CameraSensor { 00058 public: 00059 00060 struct Vec2i { 00061 Vec2i() : x(0), y(0) {} 00062 Vec2i(int x, int y) : x(x), y(y) {} 00063 int x; 00064 int y; 00065 Vec2i operator + (const Vec2i& v) const; 00066 Vec2i operator * (int i) const; 00067 Vec2i operator / (int i) const; 00068 }; 00069 00070 typedef std::list< std::pair<Vec2i,int> > FlowDelList; 00071 00072 /** @see CameraSensor for further parameter explanation. 00073 */ 00074 OpticalFlow(OpticalFlowConf conf = getDefaultConf()); 00075 00076 virtual ~OpticalFlow(); 00077 00078 /** calculates default positions for optical flow detection. 00079 The points are in aranged horizontally in a line at the vertical center. 00080 For num 2 the points are at the border, 00081 3 points there is additioanlly one is the center and so on. 00082 */ 00083 static std::list<Pos> getDefaultPoints(int num); 00084 00085 /// the default config has 2 points in and calculates the flow in X and Y 00086 static OpticalFlowConf getDefaultConf(){ 00087 OpticalFlowConf c; 00088 c.dims = XY; 00089 c.points = getDefaultPoints(2); 00090 c.fieldSize = 24; 00091 c.maxFlow = 0.15; 00092 c.verbose = 1; 00093 return c; 00094 } 00095 00096 virtual void intern_init(); 00097 00098 /// Performs the calculations 00099 virtual bool sense(const GlobalData& globaldata); 00100 00101 virtual int getSensorNumber() const { 00102 return num; 00103 }; 00104 00105 virtual int get(sensor* sensors, int length) const; 00106 00107 00108 protected: 00109 /** 00110 compares a small part of two given images 00111 and returns the average absolute difference. 00112 Field center, size and shift have to be choosen, 00113 so that no clipping is required! 00114 \param field specifies position(center) of subimage to use for comparison 00115 \param size specifies the size of the field edged in pixels 00116 \param d_x shift in x direction 00117 \param d_y shift in y direction 00118 */ 00119 static double compareSubImg(const unsigned char* const I1, 00120 const unsigned char* const I2, 00121 const Vec2i& field, int size, int width, int height, 00122 int bytesPerPixel, int d_x,int d_y); 00123 00124 /** calculates the optimal transformation for one field in RGB 00125 * using all three color channels 00126 * @param minerror (is to return the minimum error achieved during the matching) 00127 */ 00128 Vec2i calcFieldTransRGB(const Vec2i& field, const osg::Image* current, 00129 const osg::Image* last, double& minerror) const; 00130 00131 protected: 00132 OpticalFlowConf conf; 00133 int num; 00134 std::list<Vec2i> fields; // fields in image coordinates 00135 sensor* data; 00136 osg::Image* lasts[4]; 00137 std::vector<Vec2i> oldFlows; 00138 int maxShiftX; 00139 int maxShiftY; 00140 int width; 00141 int height; 00142 int cnt; 00143 double avgerror; // average minimum matching error 00144 }; 00145 00146 00147 } 00148 00149 #endif