iSpike  2.1
Spike conversion library for robotics
D:/Home/Programs/iSpike/src/Channel/InputChannel/VisualInputChannel.cpp
Go to the documentation of this file.
00001 //iSpike includes
00002 #include <iSpike/Channel/InputChannel/VisualInputChannel.hpp>
00003 #include <iSpike/ISpikeException.hpp>
00004 #include <iSpike/Log/Log.hpp>
00005 using namespace ispike;
00006 
00007 //Names of properties
00008 #define NEURON_WIDTH_NAME "Neuron Width"
00009 #define NEURON_HEIGHT_NAME "Neuron Height"
00010 #define FOVEA_RADIUS_NAME "Fovea Radius"
00011 #define POSITIVE_SIGMA_NAME "Positive Sigma"
00012 #define NEGATIVE_SIGMA_NAME "Negative Sigma"
00013 #define POSITIVE_FACTOR_NAME "Positive Factor"
00014 #define NEGATIVE_FACTOR_NAME "Negative Factor"
00015 #define OPPONENCY_MAP_NAME "Opponency Map"
00016 #define PARAM_A_NAME "Parameter A"
00017 #define PARAM_B_NAME "Parameter B"
00018 #define PARAM_C_NAME "Parameter C"
00019 #define PARAM_D_NAME "Parameter D"
00020 #define CURRENT_FACTOR_NAME "Current Factor"
00021 #define CONSTANT_CURRENT_NAME "Constant Current"
00022 
00023 
00025 VisualInputChannel::VisualInputChannel() {
00026         // Properties of log polar foveation
00027         addProperty(Property(Property::Integer, 50, NEURON_WIDTH_NAME, "Width of the neuron network", true));
00028         addProperty(Property(Property::Integer, 50, NEURON_HEIGHT_NAME, "Height of the neuron network", true));
00029         addProperty(Property(Property::Double, 20.0, FOVEA_RADIUS_NAME, "Radius of the central foveated area", true));
00030 
00031         //Properties of the difference of gaussians filter
00032         addProperty(Property(Property::Double, 2.0, POSITIVE_SIGMA_NAME, "Positive Gaussian Sigma", false));
00033         addProperty(Property(Property::Double, 4.0, NEGATIVE_SIGMA_NAME, "Negative Gaussian Sigma", false));
00034         addProperty(Property(Property::Double, 4.0, POSITIVE_FACTOR_NAME, "Multiplication ratio for positive image during subtraction", false));
00035         addProperty(Property(Property::Double, 2.0, NEGATIVE_FACTOR_NAME, "Multiplication ratio for negative image during subtraction", false));
00036         vector<string> tmpVector;
00037         tmpVector.push_back("R+G-");
00038         tmpVector.push_back("G+R-");
00039         tmpVector.push_back("B+Y-");
00040         tmpVector.push_back("B&W+B&W-");
00041         tmpVector.push_back("Motion sensitive");
00042         tmpVector.push_back("Motion sensitive with log");
00043         addProperty(Property("R+G-", tmpVector, OPPONENCY_MAP_NAME, "Which opponency map to use.", true));
00044 
00045         //Properties of the neural simulator
00046         addProperty(Property(Property::Double, 0.1, PARAM_A_NAME, "Parameter A of the Izhikevich Neuron Model", false));
00047         addProperty(Property(Property::Double, 0.2, PARAM_B_NAME,"Parameter B of the Izhikevich Neuron Model",false));
00048         addProperty(Property(Property::Double, -65, PARAM_C_NAME,"Parameter C of the Izhikevich Neuron Model",false));
00049         addProperty(Property(Property::Double, 2.0, PARAM_D_NAME, "Parameter D of the Izhikevich Neuron Model",false));
00050         addProperty(Property(Property::Double, 10.0, CURRENT_FACTOR_NAME, "Incoming current is multiplied by this value",false));
00051         addProperty(Property(Property::Double, 0.0, CONSTANT_CURRENT_NAME, "This value is added to the incoming current", false));
00052 
00053         //Create the description
00054         channelDescription = Description("Visual Input Channel", "This is a visual input channel", "Visual Reader");
00055 
00056         //Set up visual processing classes and neural simulator
00057         dataReducer = new LogPolarVisualDataReducer();
00058         dogFilter = new DOGVisualFilter(dataReducer);
00059 
00060         //Initialize variables
00061         reader = NULL;
00062         currentImageID = 0;
00063 }
00064 
00065 
00067 VisualInputChannel::~VisualInputChannel() {
00068         if(isInitialized()) {
00069                 delete reader;
00070                 delete dogFilter;
00071                 delete dataReducer;
00072         }
00073 }
00074 
00075 
00076 /*--------------------------------------------------------------------*/
00077 /*---------                 PUBLIC METHODS                     -------*/
00078 /*--------------------------------------------------------------------*/
00079 
00081 void VisualInputChannel::initialize(Reader* reader, map<string,Property>& properties) {
00082         //This class requires a visual reader, so reinterpret it and check
00083         this->reader = dynamic_cast<VisualReader*>(reader);
00084         if(this->reader == NULL)
00085                 throw ISpikeException("Cannot initialize VisualInputChannel with a null reader.");
00086 
00087         //Store properties in this and dependent classes
00088         updateProperties(properties);
00089 
00090         //Start the reader thread running
00091         this->reader->start();
00092 
00093         //Initialize neural simulator
00094         neuronSim.initialize(size());
00095 
00096         setInitialized(true);
00097 }
00098 
00099 
00101 void VisualInputChannel::setProperties(map<string,Property>& properties){
00102         updateProperties(properties);
00103 }
00104 
00105 
00106 //Inherited from Channel
00107 void VisualInputChannel::step() {
00108         //Check reader for errors
00109         if(reader->isError()){
00110                 LOG(LOG_CRITICAL)<<"AngleReader Error: "<<reader->getErrorMessage();
00111                 throw ISpikeException("Error in AngleReader");
00112         }
00113 
00114         //Update visual maps if necessary
00115         if(reader->getImageID() != currentImageID){
00116                 currentImageID = reader->getImageID();
00117                 dataReducer->setBitmap(reader->getBitmap());
00118                 dogFilter->update();
00119         }
00120 
00121         //Multiplication factor combines the current factor with the size of the value used to store the pixel
00122         double multFactor = currentFactor/ 255.0;
00123 
00124         //Load opponency data into neural simulator
00125         Bitmap& opponencyMap = dogFilter->getBitmap();
00126         if(!opponencyMap.isEmpty()) {
00127                 //Get reference to opponency map
00128                 int opponencyMapSize = opponencyMap.size();
00129                 unsigned char* opponencyMapContents = opponencyMap.getContents();
00130 
00131                 if(opponencyMapSize != size())
00132                         throw ISpikeException("VisualInputChannel: Incoming map size does not match size of visual channel");
00133 
00134                 //Convert pixels to currents in simulator
00135                 for(int i=0; i<opponencyMapSize; ++i){
00136                         //Set the input current to the neurons
00137                         //LOG(LOG_DEBUG)<<"INPUT CURRENT: "<<(multFactor * opponencyMapContents[i] + constantCurrent);
00138                         neuronSim.setInputCurrent(i, multFactor * opponencyMapContents[i] + constantCurrent);
00139                 }
00140         }
00141 
00142         //Step the simulator
00143         neuronSim.step();
00144 }
00145 
00146 
00147 /*--------------------------------------------------------------------*/
00148 /*---------              PROTECTED METHODS                     -------*/
00149 /*--------------------------------------------------------------------*/
00150 
00152 void VisualInputChannel::updateProperties(map<string, Property>& properties) {
00153         if(propertyMap.size() != properties.size())
00154                 throw ISpikeException("VisualInputChannel: Current properties do not match new properties.");
00155 
00156         //Update properties in the property map and the appropriate class
00157         updatePropertyCount = 0;
00158         for(map<string,Property>::iterator iter = properties.begin(); iter != properties.end(); ++iter) {
00159                 //When initialized, only update properties that are not read only
00160                 if( (isInitialized() && !iter->second.isReadOnly()) || !isInitialized()) {
00161                         string paramName = iter->second.getName();
00162                         switch (iter->second.getType()){
00163                                 case Property::Integer: {
00164                                         if (paramName == NEURON_WIDTH_NAME){
00165                                                 setWidth(updateIntegerProperty(iter->second));
00166                                                 dataReducer->setOutputWidth(getWidth());
00167                                         }
00168                                         else if (paramName == NEURON_HEIGHT_NAME){
00169                                                 setHeight(updateIntegerProperty(iter->second));
00170                                                 dataReducer->setOutputHeight(getHeight());
00171                                         }
00172                                         break;
00173                                 }
00174                                 case Property::Double: {
00175                                         if (paramName == PARAM_A_NAME)
00176                                                 neuronSim.setParameterA(updateDoubleProperty(iter->second));
00177                                         else if (paramName == PARAM_B_NAME)
00178                                                 neuronSim.setParameterB(updateDoubleProperty(iter->second));
00179                                         else if (paramName == PARAM_C_NAME)
00180                                                 neuronSim.setParameterC(updateDoubleProperty(iter->second));
00181                                         else if (paramName == PARAM_D_NAME)
00182                                                 neuronSim.setParameterD(updateDoubleProperty(iter->second));
00183                                         else if (paramName == CURRENT_FACTOR_NAME)
00184                                                 currentFactor = updateDoubleProperty(iter->second);
00185                                         else if (paramName == CONSTANT_CURRENT_NAME)
00186                                                 constantCurrent = updateDoubleProperty(iter->second);
00187                                         else if (paramName == POSITIVE_SIGMA_NAME)
00188                                                 dogFilter->setPositiveSigma(updateDoubleProperty(iter->second));
00189                                         else if (paramName == NEGATIVE_SIGMA_NAME)
00190                                                 dogFilter->setNegativeSigma(updateDoubleProperty(iter->second));
00191                                         else if (paramName == POSITIVE_FACTOR_NAME)
00192                                                 dogFilter->setPositiveFactor(updateDoubleProperty(iter->second));
00193                                         else if (paramName == NEGATIVE_FACTOR_NAME)
00194                                                 dogFilter->setNegativeFactor(updateDoubleProperty(iter->second));
00195                                         else if (paramName == FOVEA_RADIUS_NAME)
00196                                                 dataReducer->setFoveaRadius(updateDoubleProperty(iter->second));
00197                                         break;
00198                                 }       
00199                                 case Property::Combo:
00200                                         if(paramName == OPPONENCY_MAP_NAME){
00201                                                 string mapName = updateComboProperty(iter->second);
00202                                                 if(mapName == "R+G-")
00203                                                         dogFilter->setOpponencyTypeID(0);
00204                                                 else if(mapName == "G+R-")
00205                                                         dogFilter->setOpponencyTypeID(1);
00206                                                 else if(mapName == "B+Y-")
00207                                                         dogFilter->setOpponencyTypeID(2);
00208                                                 else if(mapName == "B&W+B&W-")
00209                                                         dogFilter->setOpponencyTypeID(3);
00210                                                 else if(mapName == "Motion sensitive")
00211                                                         dogFilter->setOpponencyTypeID(4);
00212                                                 else if(mapName == "Motion sensitive with log")
00213                                                         dogFilter->setOpponencyTypeID(5);
00214                                                 else
00215                                                         throw ISpikeException("VisualInputChannel: Opponency map type not recognized");
00216                                         }
00217                                 break;
00218                                 case Property::String:
00219                                 break;
00220                                 default:
00221                                         throw ISpikeException("Property type not recognized.");
00222                         }
00223                 }
00224         }
00225 
00226         //Check all properties were updated
00227         if(!isInitialized() && updatePropertyCount != propertyMap.size())
00228                 throw ISpikeException("Some or all of the properties were not updated: ", updatePropertyCount);
00229 }
00230 
 All Classes Namespaces Files Functions Variables Enumerations Enumerator Defines