00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038 #ifndef MOTIONOPS_C_DEFINED
00039 #define MOTIONOPS_C_DEFINED
00040
00041 #define MAX_NUM_FEATURES 1000
00042
00043
00044 #include "Image/OpenCVUtil.H"
00045
00046 #include "Image/CutPaste.H"
00047 #include "Image/ColorOps.H"
00048 #include "Image/MathOps.H"
00049 #include "Image/DrawOps.H"
00050
00051 #include <cstdio>
00052
00053 #include "Robots/Beobot2/Navigation/FOE_Navigation/MotionOps.H"
00054
00055 inline static void allocateOnDemand
00056 ( IplImage **img, CvSize size, int depth, int channels)
00057 {
00058 if ( *img != NULL ) return;
00059 *img = cvCreateImage( size, depth, channels );
00060 }
00061
00062
00063 rutz::shared_ptr<OpticalFlow> getCleanOpticFlow(Image<byte> img)
00064 {
00065 uint width = img.getWidth();
00066 uint height = img.getHeight();
00067
00068
00069 float ratio = 133.33*1000.0;
00070
00071 float Tx = 0.0 * ratio;
00072 float Ty = 0.0 * ratio;
00073 float Tz = .5 * ratio;
00074
00075
00076 float Ox = 0.0;
00077 float Oy = 0.0;
00078 float Oz = 0.0;
00079
00080
00081 float f = 400.0;
00082
00083
00084 float startDepth = 11.0*ratio;
00085 float rangeDepth = 200.0*ratio;
00086
00087 std::vector<Point2D<float> > startPt(MAX_NUM_FEATURES);
00088 std::vector<Point2D<float> > endPt(MAX_NUM_FEATURES);
00089
00090 float w2 = width/2;
00091 float h2 = height/2;
00092
00093
00094 for(uint i = 0; i < MAX_NUM_FEATURES; i++)
00095 {
00096
00097
00098 float x = float(width * float(rand())/(RAND_MAX + 1.0F)) - w2;
00099 float y = float(height * float(rand())/(RAND_MAX + 1.0F)) - h2;
00100
00101 float z = rangeDepth * float(rand())/(RAND_MAX + 1.0F) + startDepth;
00102
00103 float dx = 1.0/z*(-f*Tx + x*Tz) + ( x*y/f *Ox - (f+x*x/f)*Oy + y*Oz);
00104 float dy = 1.0/z*(-f*Ty + y*Tz) + ((f+y*y/f)*Ox - (x*y/f) *Oy + x*Oz);
00105
00106 startPt[i] = Point2D<float>((x+w2) , (y+h2) );
00107 endPt [i] = Point2D<float>((x+w2)+dx, (y+h2)+dy);
00108
00109
00110
00111 }
00112
00113 std::vector<rutz::shared_ptr<FlowVector> > fv; fv.clear();
00114 for(int i = 0; i < MAX_NUM_FEATURES; i++)
00115 {
00116 rutz::shared_ptr<FlowVector> tflow
00117 (new FlowVector(startPt[i], endPt[i], 1.0));
00118 fv.push_back(tflow);
00119
00120 LDEBUG("[%3d] flow: 1[%13.4f %13.4f] 2[%13.4f %13.4f] "
00121 "ang: %13.4f mag: %13.4f val: %13.4f",
00122 i, tflow->p1.i, tflow->p1.j, tflow->p2.i, tflow->p2.j,
00123 tflow->angle, tflow->mag, tflow->val);
00124 }
00125
00126
00127
00128 rutz::shared_ptr<OpticalFlow> oflow(new OpticalFlow(fv, img.getDims()));
00129
00130 return oflow;
00131 }
00132
00133
00134 void saveCleanOpticFlow(Image<byte> img)
00135 {
00136 uint width = img.getWidth();
00137 uint height = img.getHeight();
00138
00139
00140 float ratio = 133.33*1000.0;
00141
00142 float Tx = 0.0 * ratio;
00143 float Ty = 0.0 * ratio;
00144 float Tz = .5 * ratio;
00145
00146
00147 float Ox = 0.0;
00148 float Oy = 0.0;
00149 float Oz = 0.0;
00150
00151
00152 float f = 400.0;
00153
00154
00155 float startDepth = 11.0*ratio;
00156 float rangeDepth = 200.0*ratio;
00157
00158 std::vector<Point2D<float> > startPt(MAX_NUM_FEATURES);
00159 std::vector<Point2D<float> > endPt(MAX_NUM_FEATURES);
00160
00161 float w2 = width/2;
00162 float h2 = height/2;
00163
00164 std::string resFName("results.txt");
00165 FILE *rFile = fopen(resFName.c_str(), "at");
00166
00167
00168
00169 for(uint i = 0; i < MAX_NUM_FEATURES; i++)
00170 {
00171
00172
00173 float x = float(width * float(rand())/(RAND_MAX + 1.0F)) - w2;
00174 float y = float(height * float(rand())/(RAND_MAX + 1.0F)) - h2;
00175
00176 float z = rangeDepth * float(rand())/(RAND_MAX + 1.0F) + startDepth;
00177
00178 float dx = 1.0/z*(-f*Tx + x*Tz) + ( x*y/f *Ox - (f+x*x/f)*Oy + y*Oz);
00179 float dy = 1.0/z*(-f*Ty + y*Tz) + ((f+y*y/f)*Ox - (x*y/f) *Oy + x*Oz);
00180
00181
00182
00183
00184 float ox = x+w2;
00185 float oy = y+h2;
00186 LINFO("%f %f", ox, oy);
00187 LINFO("%f %f", ox+dx/2, oy+dy/2);
00188 LINFO("%f %f", ox+dx, oy+dy);
00189
00190 LDEBUG("saving result to %s", resFName.c_str());
00191 std::string line1 = sformat("%f %f \n", ox, oy);
00192 std::string line2 = sformat("%f %f \n", ox+dx/2, oy+dy/2);
00193 std::string line3 = sformat("%f %f \n", ox+dx, oy+dy);
00194
00195 fputs(line1.c_str(), rFile);
00196 fputs(line2.c_str(), rFile);
00197 fputs(line3.c_str(), rFile);
00198 }
00199
00200 fclose (rFile);
00201
00202 Raster::waitForKey();
00203 }
00204
00205
00206 rutz::shared_ptr<OpticalFlow> getLucasKanadeOpticFlow
00207 (Image<byte> image1, Image<byte> image2)
00208 {
00209 IplImage* frame1_1C = img2ipl(image1);
00210 IplImage* frame2_1C = img2ipl(image2);
00211
00212 CvSize frame_size;
00213 frame_size.width = image1.getWidth();
00214 frame_size.height = image1.getHeight();
00215
00216 static IplImage
00217 *eig_image = NULL, *temp_image = NULL,
00218 *pyramid1 = NULL, *pyramid2 = NULL;
00219
00220
00221
00222
00223 allocateOnDemand( &eig_image, frame_size, IPL_DEPTH_32F, 1 );
00224 allocateOnDemand( &temp_image, frame_size, IPL_DEPTH_32F, 1 );
00225
00226
00227 CvPoint2D32f frame1_features[MAX_NUM_FEATURES];
00228 int number_of_features = MAX_NUM_FEATURES;
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241 cvGoodFeaturesToTrack(frame1_1C, eig_image, temp_image, frame1_features,
00242 & number_of_features, .01, .01, NULL);
00243
00244
00245
00246 CvPoint2D32f frame2_features[MAX_NUM_FEATURES];
00247 char optical_flow_found_feature[MAX_NUM_FEATURES];
00248 float optical_flow_feature_error[MAX_NUM_FEATURES];
00249
00250
00251 CvSize optical_flow_window = cvSize(3,3);
00252
00253
00254
00255
00256 CvTermCriteria optical_flow_termination_criteria =
00257 cvTermCriteria( CV_TERMCRIT_ITER | CV_TERMCRIT_EPS, 20, .3 );
00258
00259
00260
00261 allocateOnDemand( &pyramid1, frame_size, IPL_DEPTH_8U, 1 );
00262 allocateOnDemand( &pyramid2, frame_size, IPL_DEPTH_8U, 1 );
00263
00264 LINFO("number of features: %d", number_of_features);
00265
00266
00267
00268
00269
00270
00271 cvCalcOpticalFlowPyrLK
00272 (frame1_1C, frame2_1C, pyramid1, pyramid2,
00273 frame1_features, frame2_features, number_of_features,
00274 optical_flow_window, 5, optical_flow_found_feature,
00275 optical_flow_feature_error, optical_flow_termination_criteria, 0 );
00276
00277 std::vector<rutz::shared_ptr<FlowVector> > fv; fv.clear();
00278 for(int i = 0; i < number_of_features; i++)
00279 {
00280
00281 if ( optical_flow_found_feature[i] == 0 ) continue;
00282
00283 rutz::shared_ptr<FlowVector> tflow
00284 (new FlowVector
00285 (Point2D<float>((float)frame1_features[i].x,
00286 (float)frame1_features[i].y),
00287 Point2D<float>((float)frame2_features[i].x,
00288 (float)frame2_features[i].y),
00289 optical_flow_found_feature[i]));
00290
00291 fv.push_back(tflow);
00292
00293 LDEBUG("[%3d] flow: 1[%13.4f %13.4f] 2[%13.4f %13.4f] "
00294 "ang: %13.4f mag: %13.4f val: %13.4f",
00295 i, tflow->p1.i, tflow->p1.j, tflow->p2.i, tflow->p2.j,
00296 tflow->angle, tflow->mag, tflow->val);
00297 }
00298
00299
00300 rutz::shared_ptr<OpticalFlow> oflow
00301 (new OpticalFlow(fv, image1.getDims()));
00302
00303 return oflow;
00304 }
00305
00306
00307 Image<PixRGB<byte> > drawOpticFlow
00308 (Image<PixRGB<byte> > img, rutz::shared_ptr<OpticalFlow> oflow)
00309 {
00310 std::vector<rutz::shared_ptr<FlowVector> > flow =
00311 oflow->getFlowVectors();
00312
00313
00314 for(uint i = 0; i < flow.size(); i++)
00315 {
00316 Point2D<int> pt1((int)flow[i]->p1.i, (int)flow[i]->p1.j);
00317 Point2D<int> pt2((int)flow[i]->p2.i, (int)flow[i]->p2.j);
00318 drawLine(img, pt1, pt2, PixRGB<byte>(255,0,0), 1);
00319
00320
00321
00322
00323
00324
00325
00326
00327
00328
00329
00330
00331
00332
00333
00334
00335
00336
00337
00338
00339
00340
00341
00342
00343
00344 }
00345
00346 return img;
00347 }
00348
00349
00350
00351
00352
00353
00354
00355 #endif // !MOTIONOPS_C_DEFINED