00001
00024
00025
00026
00027
00028 #include <defines.h>
00029
00030 #ifdef WITH_ROBOT_DETECTION
00031
00032
00033
00034
00035
00036
00037 #include <iostream>
00038 #include <fstream>
00039 #include <math.h>
00040 #include <time.h>
00041 #include <sstream>
00042
00043
00044
00045
00046
00047 #include <controllers/sensorFusion/detectRobotVisually.h>
00048 #include <controllers/positionControllers/defaultWheelController.h>
00049
00050
00051
00052
00053
00054 using namespace srCore;
00055 using namespace std;
00056 using namespace almendeSensorFusion;
00057
00058
00059
00060
00061
00062 using namespace srAlmende;
00063
00064 #define NO_LOCATION DefaultWheelController::NO_LOCATION
00065
00073 DetectRobotVisually::DetectRobotVisually(const std::string &name,
00074 RobotActorBase *robotActor): SubController(name, robotActor),
00075
00076 useAttention(true),
00077 useFusion(true),
00078
00079 saliencyD("Camera"),
00080 imageLocHist(3, NO_LOCATION),
00081 energyClassHistImage(2, NO_LOCATION),
00082 energyClassHistAI(2, NO_LOCATION),
00083
00084 localCounter(0),
00085 imageScale(2),
00086 trackingGoal(false),
00087 experiment("sound-image-experiment") {
00088
00089 LOG_INFO("Create visual robot detector");
00090
00091 fusionInput.audio = NULL;
00092
00093
00094 initSaliencyDetector();
00095
00096
00097 saveTimer = time(NULL);
00098 trackTimer = time(NULL);
00099
00100 lastImage = NULL;
00101
00102 counter = 0;
00103 }
00104
00112 void DetectRobotVisually::initSaliencyDetector() {
00113 std::vector<int> rFSizes = std::vector<int>(0);
00114 std::vector<ImageFilter*>* iFilters = new std::vector<ImageFilter*>(0);
00115
00116 rFSizes.push_back(2);
00117 rFSizes.push_back(4);
00118 rFSizes.push_back(6);
00119 rFSizes.push_back(8);
00120 rFSizes.push_back(12);
00121 rFSizes.push_back(16);
00122 rFSizes.push_back(20);
00123 rFSizes.push_back(26);
00124 rFSizes.push_back(32);
00125
00126 iFilters->push_back(new IntensityFilter(rFSizes, 1, true, 0.1));
00127 iFilters->push_back(new ColorFilter(rFSizes, 1,true, 1, ON_RED_OFF_GREEN));
00128
00129 iFilters->push_back(new OrientationFilter(rFSizes, 1,true, 1, DEGREES_0));
00130
00131
00132 saliencyD.setreceptiveFieldSize(rFSizes);
00133 saliencyD.setFilters(iFilters);
00134 saliencyD.setGaussianSmoothVariance(1);
00135 }
00136
00140 DetectRobotVisually::~DetectRobotVisually() { }
00141
00142
00147 bool DetectRobotVisually::salientImage(osg::ref_ptr<osg::Image> camImage, float* location) {
00148
00149
00150
00151 if(camImage->getTotalSizeInBytes() > 0) {
00152
00153 int x, y, xMax, yMax;
00154 float value;
00155 bool salientImg = true;
00156
00157 if(lastImage == NULL) {
00158 LOG_INFO("Initialise the audio-visual fusion class...");
00159 AVFusion.initVisual(camImage->s(), camImage->t(), 3, 2, 0.93);
00160 } else {
00161 for (int x = 0; x < fusionInput.imageWidth; ++x) {
00162 delete [] lastImage[x];
00163 }
00164 delete [] lastImage;
00165 }
00166
00167 lastImage = saliencyD.convertImage(camImage);
00168
00169 fusionInput.image = lastImage;
00170 fusionInput.imageHeight = camImage->t();
00171 fusionInput.imageWidth = camImage->s();
00172
00173 if(useAttention) {
00174
00175
00176 saliencyD.setImage(camImage,imageScale);
00177 salientImg = saliencyD.detect(&x, &y, &xMax, &yMax, &value);
00178
00179 fusionInput.imgRegionWidth = fusionInput.imageWidth/3;
00180 fusionInput.imgRegionHeight = fusionInput.imageHeight/3;
00181 fusionInput.imgRegionX = (x*imageScale)-(fusionInput.imgRegionWidth/2);
00182 fusionInput.imgRegionY = (x*imageScale)-(fusionInput.imgRegionHeight/2);
00183 if(fusionInput.imgRegionX < 0)
00184 fusionInput.imgRegionX = 0;
00185 if(fusionInput.imgRegionY < 0)
00186 fusionInput.imgRegionY = 0;
00187 if(fusionInput.imgRegionWidth+fusionInput.imgRegionX > fusionInput.imageWidth)
00188 fusionInput.imgRegionWidth = (fusionInput.imageWidth - fusionInput.imgRegionX)-1;
00189 if(fusionInput.imgRegionHeight+fusionInput.imgRegionY > fusionInput.imageHeight)
00190 fusionInput.imgRegionHeight = (fusionInput.imageHeight - fusionInput.imgRegionY)-1;
00191
00192 if ((fusionInput.imgRegionWidth*fusionInput.imgRegionHeight) < ((xMax - x)*imageScale)*((yMax - y)*imageScale))
00193 {
00194 fusionInput.imgRegionX = x*imageScale;
00195 fusionInput.imgRegionY = y*imageScale;
00196 fusionInput.imgRegionWidth = (xMax - x)*imageScale;
00197 fusionInput.imgRegionHeight = (yMax - y)*imageScale;
00198
00199 }
00200
00201 if(fusionInput.imgRegionY < float(fusionInput.imageHeight)*float(3/4))
00202 salientImg = false;
00203
00204
00205
00206 if(value < 10 || (fusionInput.imgRegionWidth < 2 && fusionInput.imgRegionHeight < 2 ))
00207 salientImg = false;
00208 if (salientImg)
00209 {
00210 int width = saliencyD.getWidth();
00211
00212
00213
00214 x += (int) (float(xMax-x)/2.0);
00215 *location = (float(x)*(120.0/float(width))) - 60.0;
00216 }
00217 }
00218 else
00219 {
00220 fusionInput.imgRegionX = 0;
00221 fusionInput.imgRegionY = 0;
00222 fusionInput.imgRegionWidth = fusionInput.imageWidth-1;
00223 fusionInput.imgRegionHeight = fusionInput.imageHeight-1;
00224
00225 *location = 0;
00226 }
00227 return salientImg;
00228 }
00229 else
00230 return false;
00231 }
00232
00233 #ifdef WITH_UNITTESTING
00234
00239 int DetectRobotVisually::extractClassId() {
00240 const std::string name = camImage->getFileName();
00241 std::string extract; size_t pos;
00242 pos = name.find("norobot");
00243
00244 if (pos == string::npos) return 0;
00245 return 1;
00246 }
00247 #endif
00248
00252 int DetectRobotVisually::classifyObject(bool learning)
00253 {
00254 if(!learning) {
00255 LOG_INFO("Start classification with previously learned data.");
00256 fusionInput.classId = -1;
00257 } else {
00258 #ifdef WITH_UNITTESTING
00259 fusionInput.classId = extractClassId();
00260 ostringstream msg; msg.clear(); msg.str("");
00261 msg << "Learn to classify this image as class id " << fusionInput.classId;
00262 LOG_INFO(msg.str());
00263 #else
00264 LOG_WARNING("How do you want to do supervised learning in a non-unit test mode?");
00265
00266
00267 #endif
00268 }
00269
00270 int classId = -1;
00271
00272 if(learning) {
00273 fusionInput.imgRegionX = 0;
00274 fusionInput.imgRegionY = 0;
00275 fusionInput.imgRegionWidth = fusionInput.imageWidth-1;
00276 fusionInput.imgRegionHeight = fusionInput.imageHeight-1;
00277 LOG_DEBUG("In the learning phase");
00278 }
00279 vector<vector<ART_TYPE>*>* classes = AVFusion.classify(&fusionInput, !learning);
00280
00281 for (unsigned int x = 0; x < classes->size(); ++x) {
00283 if((*classes)[x] != NULL)
00284 {
00285 vector<ART_TYPE>* output = (*classes)[x];
00286 for (unsigned int y = 0; y < output->size(); ++y)
00287 {
00288 if(x == 0 && learning)
00289 LOG_ERROR("Audio class as one of the ART maps, why!?");
00290 if(x == 1 && learning) {
00291
00292
00293
00294
00295 }
00296 if(x == 2) {
00297
00298 if((*output)[y] > -1) {
00299 classId = (int)(AVFusion.d_artEnergy.getF2()->at((*output)[y])->at(0));
00300
00301 }
00302 }
00303 }
00304 delete (*classes)[x];
00305 }
00306 }
00307
00308 if(classes != NULL)
00309 delete classes;
00310
00311
00312
00313
00314
00315
00316
00317
00318
00319
00320 return classId;
00321 }
00322
00323
00324
00325
00326
00327
00328
00329
00336 CtrlMsg* DetectRobotVisually::Act(CtrlMsg *message) {
00337
00338 LOG_INFO("Visual robot detector gets a message...");
00339
00340 if (message->type != CAMERA_IMAGE) {
00341 LOG_ERROR("Received the wrong message type as input! This class does not know\
00342 how to handle this type");
00343 outgoingMsg.type = INVALID;
00344 return &outgoingMsg;
00345 }
00346
00347 camImage = *(osg::ref_ptr<osg::Image>*)message->value;
00348
00349
00350 salientImage(camImage, &location);
00351
00352
00353
00354
00355
00356 outgoingMsg.type = LOCATION_IN_VIEW;
00357 outgoingMsg.value = &location;
00358
00359 #ifndef WITH_UNITTESTING
00360 if (counter < 64) {
00361
00362 classifyObject(true);
00363 }
00364 else {
00365
00366 classifyObject(false);
00367 }
00368
00369 if (counter == 64) {
00370 AVFusion.saveMemory("output/robotDetection");
00371 }
00372 counter++;
00373 #else
00374 if (counter == 0) {
00375 AVFusion.loadMemory("output/robotDetection");
00376 }
00377
00378 int classId = classifyObject(false);
00379 if (classId == 0) {
00380 LOG_ALWAYS("Robot detected!");
00381 } else if (classId == 1) {
00382 LOG_ALWAYS("Background...");
00383 } else {
00384 LOG_ALWAYS("Huh?");
00385 }
00386 counter++;
00387
00388
00389 if (classId != 0) {
00390 outgoingMsg.type = NO_LOCATION;
00391 }
00392 #endif
00393
00394
00395 return &outgoingMsg;
00396 }
00397
00398 #endif