00001 /*!@file Neuro/EnvInferoTemporal.C */ 00002 00003 // //////////////////////////////////////////////////////////////////// // 00004 // The iLab Neuromorphic Vision C++ Toolkit - Copyright (C) 2000-2005 // 00005 // by the 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: Rob Peters <rjpeters at usc dot edu> 00034 // $HeadURL: svn://isvn.usc.edu/software/invt/trunk/saliency/src/Neuro/EnvInferoTemporal.C $ 00035 // $Id: EnvInferoTemporal.C 14280 2010-12-01 05:35:16Z itti $ 00036 // 00037 00038 #ifndef NEURO_ENVINFEROTEMPORAL_C_DEFINED 00039 #define NEURO_ENVINFEROTEMPORAL_C_DEFINED 00040 00041 #include "Neuro/EnvInferoTemporal.H" 00042 00043 #include "Component/ModelOptionDef.H" 00044 #include "Image/CutPaste.H" 00045 #include "Util/StringUtil.H" 00046 #include "rutz/mutex.h" 00047 00048 static const ModelOptionCateg MOC_EIT = { 00049 MOC_SORTPRI_3, "EnvInferoTemporal-related Options" }; 00050 00051 static const ModelOptionDef OPT_ConfidenceThresh = 00052 { MODOPT_ARG(double), "ConfidenceThresh", &MOC_EIT, OPTEXP_CORE, 00053 "Threshold for object label confidence (between 0 and 1, inclusive), " 00054 "above which attention is switched to a new object", 00055 "confidence-thresh", '\0', "<double>", "0.0" }; 00056 00057 static const ModelOptionDef OPT_EitAddPatchReader = 00058 { MODOPT_ARG_STRING, "EitAddPatchReader", &MOC_EIT, OPTEXP_CORE, 00059 "IP address and port on which to communicate with a " 00060 "patch-reader/label-server.", 00061 "patch-reader", '\0', "<ipaddr:port>", "" }; 00062 00063 namespace 00064 { 00065 const PixRGB<byte> colors[4] = 00066 { 00067 PixRGB<byte>(128,255,0), 00068 PixRGB<byte>(0,255,128), 00069 PixRGB<byte>(0,0,255), 00070 PixRGB<byte>(255,0,255) 00071 }; 00072 } 00073 00074 // ###################################################################### 00075 EnvInferoTemporal::EnvInferoTemporal(OptionManager& mgr) 00076 : 00077 ModelComponent(mgr, "Embeddable Infero-Temporal Cortex", 00078 "EnvInferoTemporal"), 00079 itsConfidenceThresh(&OPT_ConfidenceThresh, this, ALLOW_ONLINE_CHANGES), 00080 itsIgnoreNomatch("EitIgnoreNomatch", this, false, ALLOW_ONLINE_CHANGES), 00081 itsAddPatchReader(&OPT_EitAddPatchReader, this), 00082 itsOnlineAddPatchReader("EitNewPatchReader", this, std::string(), 00083 ALLOW_ONLINE_CHANGES) 00084 { 00085 if (0 != pthread_mutex_init(&itsReadersLock, NULL)) 00086 PLFATAL("pthread_mutex_init() failed"); 00087 } 00088 00089 // ###################################################################### 00090 EnvInferoTemporal::~EnvInferoTemporal() 00091 { 00092 if (0 != pthread_mutex_destroy(&itsReadersLock)) 00093 PLERROR("pthread_mutex_destroy() failed"); 00094 } 00095 00096 // ###################################################################### 00097 void EnvInferoTemporal::paramChanged(ModelParamBase* const param, 00098 const bool valueChanged, 00099 ParamClient::ChangeStatus* status) 00100 { 00101 // We have two model params for adding new patch readers; one is 00102 // intended for command-line use (itsAddPatchReader) but not live 00103 // modification, and the other is intended for live/online 00104 // modifications (itsOnlineAddPatchReader). The difference is that 00105 // in the online case we want to "reject" the change so that the 00106 // GUI-displayed value always returns to an empty string, while in 00107 // the command-line case we must not reject the change, or else 00108 // command-line parsing will fail. 00109 if (param == &itsAddPatchReader) 00110 { 00111 this->addNewPatchReader(itsAddPatchReader.getVal()); 00112 } 00113 else if (param == &itsOnlineAddPatchReader) 00114 { 00115 const std::string addr = itsOnlineAddPatchReader.getVal(); 00116 if (addr.length() > 0) 00117 { 00118 // "reject" all changes so that our value always returns 00119 // back to the empty string 00120 *status = ParamClient::CHANGE_REJECTED; 00121 00122 this->addNewPatchReader(addr); 00123 } 00124 } 00125 } 00126 00127 // ###################################################################### 00128 void EnvInferoTemporal::initReaders(const std::string& addrlist) 00129 { 00130 if (addrlist.empty()) 00131 return; 00132 00133 GVX_MUTEX_LOCK(&itsReadersLock); 00134 00135 std::vector<std::string> addrs; 00136 split(addrlist, ",", std::back_inserter(addrs)); 00137 00138 for (size_t i = 0; i < addrs.size(); ++i) 00139 { 00140 itsReaders.push_back 00141 (rutz::make_shared 00142 (new Nv2LabelReader(colors[i%4], 00143 NV2_LABEL_READER_PORT+2*i, 00144 addrs[i]))); 00145 } 00146 } 00147 00148 // ###################################################################### 00149 void EnvInferoTemporal::sendPatch(const uint32_t id, 00150 const Image<PixRGB<byte> >& fullimg, 00151 const Rectangle& foa, 00152 const rutz::time& qtime, 00153 bool is_training_image, 00154 const std::string& training_label, 00155 const std::string& remote_command, 00156 Point2D<int> fixLoc) 00157 { 00158 GVX_MUTEX_LOCK(&itsReadersLock); 00159 00160 if (itsReaders.size() == 0) 00161 return; 00162 00163 Image<PixRGB<byte> > foapatch; 00164 00165 if (foa.isValid() 00166 && fullimg.rectangleOk(foa)) 00167 foapatch = crop(fullimg, foa); 00168 else 00169 foapatch = Image<PixRGB<byte> >(1,1,ZEROS); 00170 00171 for (size_t i = 0; i < itsReaders.size(); ++i) 00172 itsReaders[i]->sendPatch 00173 (id, fullimg, foa, foapatch, 00174 qtime, 00175 training_label.length() > 0, 00176 training_label, 00177 remote_command, 00178 fixLoc); 00179 00180 if (training_label.length() > 0) 00181 LINFO("committing training image with label '%s'", 00182 training_label.c_str()); 00183 } 00184 00185 // ###################################################################### 00186 std::vector<Nv2LabelReader::LabeledImage> 00187 EnvInferoTemporal::getLabeledImages(const size_t text_length) 00188 { 00189 GVX_MUTEX_LOCK(&itsReadersLock); 00190 00191 std::vector<Nv2LabelReader::LabeledImage> result; 00192 00193 for (size_t i = 0; i < itsReaders.size(); ++i) 00194 { 00195 const Nv2LabelReader::LabeledImage p = 00196 itsReaders[i]->getNextLabeledImage(itsIgnoreNomatch.getVal(), 00197 text_length, 0); 00198 00199 if (p.img.initialized()) 00200 result.push_back(p); 00201 } 00202 00203 return result; 00204 } 00205 00206 // ###################################################################### 00207 bool EnvInferoTemporal::belowConfidenceThresh() const 00208 { 00209 GVX_MUTEX_LOCK(&itsReadersLock); 00210 00211 const double thresh = itsConfidenceThresh.getVal(); 00212 00213 for (size_t i = 0; i < itsReaders.size(); ++i) 00214 if (itsReaders[i]->getLastConfidence() > thresh) 00215 return false; 00216 00217 return true; 00218 } 00219 00220 // ###################################################################### 00221 double EnvInferoTemporal::getMaxConfidence() const 00222 { 00223 GVX_MUTEX_LOCK(&itsReadersLock); 00224 00225 double c = 0.0; 00226 for (size_t i = 0; i < itsReaders.size(); ++i) 00227 if (itsReaders[i]->getLastConfidence() > c) 00228 c = itsReaders[i]->getLastConfidence(); 00229 00230 return c; 00231 } 00232 00233 // ###################################################################### 00234 void EnvInferoTemporal::addNewPatchReader(const std::string& addr) 00235 { 00236 if (addr.length() == 0) 00237 return; 00238 00239 GVX_MUTEX_LOCK(&itsReadersLock); 00240 const size_t i = itsReaders.size(); 00241 00242 LINFO("addr=%s, #readers = %"ZU, addr.c_str(), itsReaders.size()); 00243 00244 itsReaders.push_back 00245 (rutz::make_shared 00246 (new Nv2LabelReader(colors[i%4], 00247 NV2_LABEL_READER_PORT+2*i, 00248 addr))); 00249 00250 LINFO("#readers = %"ZU, itsReaders.size()); 00251 } 00252 00253 // ###################################################################### 00254 /* So things look consistent in everyone's emacs... */ 00255 /* Local Variables: */ 00256 /* mode: c++ */ 00257 /* indent-tabs-mode: nil */ 00258 /* End: */ 00259 00260 #endif // NEURO_ENVINFEROTEMPORAL_C_DEFINED