00001 /*!@file CUDA/cudacbcl-server.C Test TCP Label Server accepts patches and returns labels */ 00002 00003 // //////////////////////////////////////////////////////////////////// // 00004 // The iLab Neuromorphic Vision C++ Toolkit - Copyright (C) 2001 by the // 00005 // University of Southern California (USC) and the iLab at USC. // 00006 // See http://iLab.usc.edu for information about this project. // 00007 // //////////////////////////////////////////////////////////////////// // 00008 // Major portions of the iLab Neuromorphic Vision Toolkit are protected // 00009 // under the U.S. patent ``Computation of Intrinsic Perceptual Saliency // 00010 // in Visual Environments, and Applications'' by Christof Koch and // 00011 // Laurent Itti, California Institute of Technology, 2001 (patent // 00012 // pending; application number 09/912,225 filed July 23, 2001; see // 00013 // http://pair.uspto.gov/cgi-bin/final/home.pl for current status). // 00014 // //////////////////////////////////////////////////////////////////// // 00015 // This file is part of the iLab Neuromorphic Vision C++ Toolkit. // 00016 // // 00017 // The iLab Neuromorphic Vision C++ Toolkit is free software; you can // 00018 // redistribute it and/or modify it under the terms of the GNU General // 00019 // Public License as published by the Free Software Foundation; either // 00020 // version 2 of the License, or (at your option) any later version. // 00021 // // 00022 // The iLab Neuromorphic Vision C++ Toolkit is distributed in the hope // 00023 // that it will be useful, but WITHOUT ANY WARRANTY; without even the // 00024 // implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR // 00025 // PURPOSE. See the GNU General Public License for more details. // 00026 // // 00027 // You should have received a copy of the GNU General Public License // 00028 // along with the iLab Neuromorphic Vision C++ Toolkit; if not, write // 00029 // to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, // 00030 // Boston, MA 02111-1307 USA. // 00031 // //////////////////////////////////////////////////////////////////// // 00032 // 00033 // Primary maintainer for this file: Dan Parks <danielfp@usc.edu> 00034 // $HeadURL: svn://isvn.usc.edu/software/invt/trunk/saliency/src/CUDA/cudacbcl-server.C $ 00035 // $Id: cudacbcl-server.C 14154 2010-10-21 05:07:25Z dparks $ 00036 // 00037 00038 #include "Component/ModelManager.H" 00039 #include "Learn/Bayes.H" 00040 #include "GUI/DebugWin.H" 00041 #include "NeovisionII/nv2_common.h" 00042 #include "NeovisionII/nv2_label_server.h" 00043 00044 #include "GUI/XWindow.H" 00045 #include "CUDA/CudaHmaxCBCL.H" 00046 #include "Image/Image.H" 00047 #include "Image/ImageSet.H" 00048 #include "Image/ColorOps.H" 00049 #include "Image/ShapeOps.H" 00050 #include "Image/CutPaste.H" 00051 #include "Image/FilterOps.H" 00052 #include "Image/Rectangle.H" 00053 #include "Image/MathOps.H" 00054 #include "Image/DrawOps.H" 00055 #include "Image/MatrixOps.H" 00056 #include "Image/Transforms.H" 00057 #include "Image/Convolutions.H" 00058 #include "Learn/SVMClassifier.H" 00059 #include "Media/FrameSeries.H" 00060 #include "nub/ref.h" 00061 #include "Raster/GenericFrame.H" 00062 #include "Raster/Raster.H" 00063 #include "Util/Types.H" 00064 #include "Util/log.H" 00065 00066 #include <signal.h> 00067 00068 #include "rutz/fstring.h" 00069 #include "rutz/time.h" 00070 #include "rutz/timeformat.h" 00071 00072 #include <fstream> 00073 #include <map> 00074 #include <vector> 00075 #include <utility> 00076 #include <iostream> 00077 #include <iomanip> 00078 #include <string> 00079 #include <unistd.h> 00080 #include <cstdlib> 00081 00082 00083 const bool USECOLOR = false; 00084 00085 bool terminate = false; 00086 00087 void terminateProc(int s) 00088 { 00089 terminate = true; 00090 } 00091 00092 std::string getBestLabel(const std::deque<std::string>& labels, 00093 const size_t mincount) 00094 { 00095 if (labels.size() == 0) 00096 return std::string(); 00097 00098 std::map<std::string, size_t> counts; 00099 00100 size_t bestcount = 0; 00101 size_t bestpos = 0; 00102 00103 for (size_t i = 0; i < labels.size(); ++i) 00104 { 00105 const size_t c = ++(counts[labels[i]]); 00106 00107 if (c >= bestcount) 00108 { 00109 bestcount = c; 00110 bestpos = i; 00111 } 00112 } 00113 00114 if (bestcount >= mincount) 00115 return labels[bestpos]; 00116 00117 return std::string(); 00118 } 00119 00120 namespace 00121 { 00122 void fillRegion(Image<PixRGB<byte> >& img, PixRGB<byte> col, 00123 const int x0, const int x1, 00124 const int y0, const int y1) 00125 { 00126 for (int x = x0; x < x1; ++x) 00127 for (int y = y0; y < y1; ++y) 00128 img.setVal(x, y, col); 00129 } 00130 00131 Image<PixRGB<byte> > makeColorbars(const int w, const int h) 00132 { 00133 Image<PixRGB<byte> > result = Image<PixRGB<byte> >(w, h, ZEROS); 00134 00135 const PixRGB<byte> cols[] = 00136 { 00137 PixRGB<byte>(255, 255, 255), // white 00138 PixRGB<byte>(255, 255, 0), // yellow 00139 PixRGB<byte>(0, 255, 255), // cyan 00140 PixRGB<byte>(0, 255, 0), // green 00141 PixRGB<byte>(255, 0, 255), // magenta 00142 PixRGB<byte>(255, 0, 0), // red 00143 PixRGB<byte>(0, 0, 255) // blue 00144 }; 00145 00146 int x1 = 0; 00147 for (int i = 0; i < 7; ++i) 00148 { 00149 const int x0 = x1+1; 00150 x1 = int(double(w)*(i+1)/7.0 + 0.5); 00151 fillRegion(result, cols[i], 00152 x0, x1, 00153 0, int(h*2.0/3.0)); 00154 } 00155 00156 x1 = 0; 00157 for (int i = 0; i < 16; ++i) 00158 { 00159 const int x0 = x1; 00160 x1 = int(double(w)*(i+1)/16.0 + 0.5); 00161 const int gray = int(255.0*i/15.0 + 0.5); 00162 fillRegion(result, PixRGB<byte>(gray, gray, gray), 00163 x0, x1, 00164 int(h*2.0/3.0)+1, int(h*5.0/6.0)); 00165 } 00166 00167 fillRegion(result, PixRGB<byte>(255, 0, 0), 00168 0, w, 00169 int(h*5.0/6.0)+1, h); 00170 00171 writeText(result, Point2D<int>(1, int(h*5.0/6.0)+2), 00172 "iLab Neuromorphic Vision", 00173 PixRGB<byte>(0, 0, 0), PixRGB<byte>(255, 0, 0), 00174 SimpleFont::FIXED(10)); 00175 00176 return result; 00177 } 00178 00179 Image<PixRGB<byte> > addLabels(const Image<PixRGB<byte> >& templ, 00180 const int fnum) 00181 { 00182 Image<PixRGB<byte> > result = templ; 00183 00184 std::string fnumstr = sformat("%06d", fnum); 00185 writeText(result, Point2D<int>(1, 1), 00186 fnumstr.c_str(), 00187 PixRGB<byte>(0, 0, 0), PixRGB<byte>(255, 255, 255), 00188 SimpleFont::FIXED(10)); 00189 00190 rutz::time t = rutz::time::wall_clock_now(); 00191 00192 writeText(result, Point2D<int>(1, result.getHeight() - 14), 00193 rutz::format_time(t).c_str(), 00194 PixRGB<byte>(32, 32, 32), PixRGB<byte>(255, 0, 0), 00195 SimpleFont::FIXED(6)); 00196 00197 return result; 00198 } 00199 00200 int maxKey(std::map<int, std::string> m) 00201 { 00202 map<int, std::string>::iterator cur,end; 00203 cur = m.begin(); end = m.end(); 00204 int mKey=-1; 00205 while(cur!=end) 00206 { 00207 if(cur->first > mKey) 00208 mKey = cur->first; 00209 cur++; 00210 } 00211 return mKey; 00212 } 00213 00214 std::map<int, std::string> loadLabels(std::string labelFile) 00215 { 00216 std::map<int, std::string> labels; 00217 FILE *fp = fopen(labelFile.c_str(),"r"); 00218 int ret; 00219 if(fp==NULL) return labels; 00220 while(1) 00221 { 00222 int id; char clabel[80]; 00223 ret = fscanf(fp,"%d ",&id); 00224 if(ret != 1) 00225 { 00226 fprintf(stderr,"fscanf failed with %d\n",ret); 00227 break; 00228 } 00229 ret = fscanf(fp,"%80s",clabel); 00230 if(ret != 1) 00231 { 00232 fprintf(stderr,"fscanf failed with %d\n",ret); 00233 break; 00234 } 00235 printf("loaded label %d %s\n",id,clabel); 00236 std::string label = std::string(clabel); 00237 labels.insert(std::pair<int, std::string>(id,label)); 00238 } 00239 fclose(fp); 00240 return labels; 00241 } 00242 00243 void writeLabels(std::string labelFile, std::map<int, std::string> labels) 00244 { 00245 FILE *fp = fopen(labelFile.c_str(),"w"); 00246 if(fp==NULL) return; 00247 map<int, std::string>::iterator cur,end; 00248 cur = labels.begin(); end = labels.end(); 00249 while(cur!=end) 00250 { 00251 fprintf(fp,"%d %80s\n",cur->first, (cur->second).c_str()); 00252 cur++; 00253 } 00254 fclose(fp); 00255 } 00256 00257 int findLabel(std::string label, std::map<int, std::string> labels) 00258 { 00259 map<int, std::string>::iterator cur,end; 00260 cur = labels.begin(); end = labels.end(); 00261 while(cur!=end) 00262 { 00263 if(cur->second.compare(label)==0) 00264 return cur->first; 00265 cur++; 00266 } 00267 return -1; 00268 } 00269 00270 00271 int addLabel(std::string label, std::map<int, std::string> &labels) 00272 { 00273 int id = maxKey(labels)+1; 00274 labels.insert(std::pair<int, std::string>(id,label)); 00275 return id; 00276 } 00277 00278 bool idExists(int id, std::map<int, std::string> &labels) 00279 { 00280 if(labels.find(id) == labels.end()) 00281 return false; 00282 else 00283 return true; 00284 } 00285 00286 } 00287 00288 00289 int main(const int argc, const char **argv) 00290 { 00291 00292 MYLOGVERB = LOG_INFO; 00293 00294 ModelManager *mgr = new ModelManager("Cuda Hmax CBCL Model Server"); 00295 00296 00297 mgr->exportOptions(MC_RECURSE); 00298 00299 00300 if (mgr->parseCommandLine( 00301 (const int)argc, (const char**)argv, "<cudadev> <labelFile> <c0patches> <c1patches> <featuresFile> <localport> <server_ip> <serverport> <svmModelFile> <svmRangeFile> ", 8, 10) == false) 00302 return 1; 00303 00304 std::string devArg, serverIP,serverPortStr,localPortStr; 00305 std::string c0Patches; 00306 std::string c1Patches; 00307 std::string svmModelFileName, svmRangeFileName; 00308 std::string c2FileName; 00309 std::string labelFileName, featuresFileName; 00310 std::string trainPosName; // Directory where positive images are 00311 00312 // Load the SVM Classifier Model and Range in 00313 SVMClassifier svm; 00314 00315 // Whether we are in training mode 00316 bool train = false; 00317 00318 00319 // Now we run 00320 mgr->start(); 00321 00322 // catch signals and redirect them to terminate for clean exit: 00323 signal(SIGHUP, terminateProc); signal(SIGINT, terminateProc); 00324 signal(SIGQUIT, terminateProc); signal(SIGTERM, terminateProc); 00325 signal(SIGALRM, terminateProc); 00326 00327 00328 devArg = mgr->getExtraArg(0); 00329 labelFileName = mgr->getExtraArg(1); 00330 c0Patches = mgr->getExtraArg(2); 00331 c1Patches = mgr->getExtraArg(3); 00332 featuresFileName = mgr->getExtraArg(4); 00333 localPortStr = mgr->getExtraArg(5); 00334 serverIP = mgr->getExtraArg(6); 00335 serverPortStr = mgr->getExtraArg(7); 00336 // If we are given the SVM info, load it in 00337 if(mgr->numExtraArgs() > 8) 00338 { 00339 if(mgr->numExtraArgs() == 9) 00340 { 00341 LFATAL("USAGE: prog <cudadev> <labelFile> <c0patches> <c1patches> <featuresFile> <localport> <server_ip> <serverport> <svmModelFile> <svmRangeFile>\n"); 00342 } 00343 svmModelFileName = mgr->getExtraArg(8); 00344 svmRangeFileName = mgr->getExtraArg(9); 00345 svm.readModel(svmModelFileName); 00346 svm.readRange(svmRangeFileName); 00347 } 00348 else 00349 { 00350 // With no SVM data, we should be in training mode 00351 train = true; 00352 } 00353 std::map<int,std::string> labels = loadLabels(labelFileName); 00354 00355 int dev = strtol(devArg.c_str(),NULL,0); 00356 CudaDevices::setCurrentDevice(dev); 00357 00358 CudaHmaxCBCL hmax(c0Patches,c1Patches); 00359 00360 XWinManaged xwin(Dims(256,256), 00361 -1, -1, "ILab Robot Head Demo"); 00362 00363 int serverPort = strtol(serverPortStr.c_str(),NULL,0); 00364 int localPort = strtol(localPortStr.c_str(),NULL,0); 00365 struct nv2_label_server* labelServer = 00366 nv2_label_server_create(localPort, 00367 serverIP.c_str(), 00368 serverPort); 00369 00370 nv2_label_server_set_verbosity(labelServer,1); //allow warnings 00371 00372 00373 const size_t max_label_history = 1; 00374 std::deque<std::string> recent_labels; 00375 00376 Image<PixRGB<byte> > colorbars = makeColorbars(256, 256); 00377 bool clearFile=true; 00378 00379 while(!terminate) 00380 { 00381 Point2D<int> clickLoc = xwin.getLastMouseClick(); 00382 if (clickLoc.isValid()) 00383 train = !train; 00384 00385 struct nv2_image_patch p; 00386 const enum nv2_image_patch_result res = 00387 nv2_label_server_get_current_patch(labelServer, &p); 00388 00389 std::string objName; 00390 if (res == NV2_IMAGE_PATCH_END) 00391 { 00392 LINFO("ok, quitting"); 00393 break; 00394 } 00395 else if (res == NV2_IMAGE_PATCH_NONE) 00396 { 00397 usleep(10000); 00398 continue; 00399 } 00400 else if (res == NV2_IMAGE_PATCH_VALID) 00401 { 00402 if (p.type != NV2_PIXEL_TYPE_RGB24) 00403 { 00404 LINFO("got a non-rgb24 patch; ignoring %i", p.type); 00405 continue; 00406 } 00407 00408 if (p.width * p.height == 1) 00409 { 00410 xwin.drawImage(addLabels(colorbars, p.id)); 00411 continue; 00412 } 00413 00414 Image<PixRGB<byte> > img(p.width, p.height, NO_INIT); 00415 // Get the test image from the socket 00416 memcpy(img.getArrayPtr(), p.data, p.width*p.height*3); 00417 00418 Image<PixRGB<byte> > inputImg = rescale(img, 256, 256); 00419 00420 xwin.drawImage(inputImg); 00421 00422 Image<float> inputf = luminanceNTSC(inputImg); 00423 00424 // Get the C2 Layer Response 00425 hmax.getC2(inputf.getArrayPtr(),inputf.getWidth(),inputf.getHeight()); 00426 if(!train) 00427 { 00428 // Output the c2 responses into a libsvm 00429 double prob; 00430 float *feat = hmax.getC2Features(); 00431 int numFeat = hmax.numC2Features(); 00432 double pred = svm.predict(feat,numFeat,&prob); 00433 printf("Prediction is %f\n",pred); 00434 int predId = (int) pred; 00435 bool knowObject = idExists(predId,labels); 00436 if(knowObject) 00437 { 00438 printf("Known object %d, prob %f\n",predId,prob); 00439 objName = labels[predId]; 00440 } 00441 else 00442 { 00443 printf("Unknown object %d, prob %f\n",predId,prob); 00444 char tmp[200]; 00445 sprintf(tmp,"Unknown-%d",predId); 00446 objName = std::string(tmp); 00447 } 00448 recent_labels.push_back(objName); 00449 while (recent_labels.size() > max_label_history) 00450 recent_labels.pop_front(); 00451 00452 struct nv2_patch_label l; 00453 l.protocol_version = NV2_LABEL_PROTOCOL_VERSION; 00454 l.patch_id = p.id; 00455 l.confidence = (int)(prob*NV2_MAX_LABEL_CONFIDENCE); 00456 snprintf(l.source, sizeof(l.source), "%s", 00457 "HmaxFL"); 00458 snprintf(l.name, sizeof(l.name), "%s", 00459 objName.c_str()); 00460 snprintf(l.extra_info, sizeof(l.extra_info), 00461 "%ux%u #%u", 00462 (unsigned int) p.width, 00463 (unsigned int) p.height, 00464 (unsigned int) p.id); 00465 00466 nv2_label_server_send_label(labelServer, &l); 00467 LINFO("sent label '%s (%s)'\n", l.name, l.extra_info); 00468 } 00469 // Determine what the object is 00470 else 00471 { 00472 printf("Enter a label for this object:\n"); 00473 std::getline(std::cin, objName); 00474 printf("You typed '%s'\n", objName.c_str()); 00475 00476 if (objName == "exit") 00477 break; 00478 else if (objName != "") 00479 { 00480 int newId = findLabel(objName,labels); 00481 if(newId == -1) 00482 { 00483 newId = addLabel(objName,labels); 00484 printf("No existing label found, adding [%s]\n",objName.c_str()); 00485 } 00486 else 00487 { 00488 printf("Found existing label\n"); 00489 } 00490 hmax.writeOutFeatures(featuresFileName,newId,clearFile); 00491 clearFile=false; 00492 } 00493 } 00494 00495 nv2_image_patch_destroy(&p); 00496 } 00497 } 00498 00499 writeLabels(labelFileName,labels); 00500 00501 if (terminate) 00502 LINFO("Ending application because a signal was caught"); 00503 00504 //nv2_label_server_destroy(labelServer); 00505 LINFO("Got Here"); 00506 00507 return 0; 00508 } 00509 00510 00511 00512 00513 // ###################################################################### 00514 /* So things look consistent in everyone's emacs... */ 00515 /* Local Variables: */ 00516 /* indent-tabs-mode: nil */ 00517 /* End: */