00001 /*!@file INVT/MPIopenvision.C MPI version of openvision.C */ 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: Laurent Itti <itti@usc.edu> 00034 // $HeadURL: svn://isvn.usc.edu/software/invt/trunk/saliency/src/INVT/MPIopenvision.C $ 00035 // $Id: MPIopenvision.C 10845 2009-02-13 08:49:12Z itti $ 00036 // 00037 00038 #include "Channels/RGBConvolveChannel.H" 00039 #include "Component/ModelManager.H" 00040 #include "Image/MathOps.H" 00041 #include "Image/MatrixOps.H" 00042 #include "Image/Pixels.H" 00043 #include "Image/Transforms.H" 00044 #include "Media/FrameSeries.H" 00045 #include "Neuro/NeuroOpts.H" 00046 #include "Channels/RawVisualCortex.H" 00047 #include "Raster/Raster.H" 00048 #include "Util/sformat.H" 00049 00050 #include <cmath> 00051 #include <fstream> 00052 #ifdef HAVE_MPI_H 00053 #include <mpi.h> 00054 #endif 00055 00056 #define ITMAX 200 00057 #define FTOL 0.00000001f 00058 #define NBCOEFFS 144 00059 #define MASTER 0 00060 #define MSG_DATA 1000 00061 #define MSG_RESULT 2000 00062 #define PATH "/tmphpc-01/itti/openvision" 00063 #define NB_PIC 14 00064 #define NB_FILTERS 3 00065 00066 #define NB_EVALS 1 00067 00068 #define NB_PROC (NBCOEFFS * NB_EVALS + 1) 00069 00070 00071 int main(int argc, char **argv) 00072 { 00073 #ifndef HAVE_MPI_H 00074 00075 LFATAL("<mpi.h> must be installed to use this program"); 00076 00077 #else 00078 00079 // Set verbosity: 00080 int loglev = LOG_ERR; 00081 MYLOGVERB = loglev; 00082 00083 // Number of coefficients: 00084 int n = 4; 00085 int m = n * n * NB_FILTERS * 3; 00086 00087 // Initialize the MPI system and get the number of processes: 00088 int myrank, size; 00089 MPI_Init(&argc, &argv); 00090 MPI_Comm_size(MPI_COMM_WORLD, &size); 00091 00092 // Check for proper number of processes: 00093 if(size < NB_PROC) 00094 { 00095 LERROR("*** Error: %d Processes needed. ***", NB_PROC); 00096 MPI_Finalize(); 00097 return 1; 00098 } 00099 00100 // Get the rank of the process: 00101 MPI_Comm_rank(MPI_COMM_WORLD, &myrank); 00102 00103 if (myrank == MASTER) 00104 { 00105 // ################ MASTER PROCESS ################ 00106 00107 // **************** INITIALIZATION **************** 00108 00109 MPI_Status status; 00110 00111 // Generate the starting point, directions and function value: 00112 float p[m]; 00113 float xi[m][m]; 00114 for(int i = 0; i < m; i++) 00115 { 00116 p[i] = 0.0f; 00117 for(int j = 0; j < m; j++) 00118 xi[j][i] = 0.0f; 00119 xi[i][i] = 1.0f; 00120 } 00121 p[0] = 0.1f; 00122 float fp = 10.0f; 00123 00124 // **************** OPTIMIZATION **************** 00125 00126 for (int iter = 0; ; iter++) 00127 { 00128 LERROR("### ITERATION %i ###", iter); 00129 int stop = 0; 00130 float del1 = 0.0f; 00131 float fp1 = fp; 00132 int ibig1 = 0; 00133 float p1[m]; 00134 for (int part = 0; part < 2; part++) 00135 { 00136 // Sent data to slave processes: 00137 for (int i = 0; i < m; i++) 00138 for (int mu = 1; mu <= NB_EVALS; mu++) 00139 { 00140 int proc = (i * NB_EVALS) + mu; 00141 float pt[m]; 00142 for (int j = 0; j < m; j++) 00143 if (part == 0) 00144 pt[j] = p[j] + (mu * 0.1f * xi[j][i]); 00145 else 00146 pt[j] = p[j] - (mu * 0.1f * xi[j][i]); 00147 MPI_Send(&stop, 1, MPI_INT, proc, 00148 4 * iter + part, 00149 MPI_COMM_WORLD); 00150 MPI_Send(pt, m, MPI_FLOAT, proc, 00151 MSG_DATA + 4 * iter + part, 00152 MPI_COMM_WORLD); 00153 } 00154 LERROR("*** PART %i : data sent to slaves.", 00155 part + 1); 00156 // Receive results and keep the best: 00157 for (int i = 0; i < m; i++) 00158 for (int mu = 1; mu <= NB_EVALS; mu++) 00159 { 00160 int proc = (i * NB_EVALS) + mu; 00161 float fpt; 00162 MPI_Recv(&fpt, 1, MPI_FLOAT, proc, 00163 MSG_RESULT + 4 * iter + part, 00164 MPI_COMM_WORLD, &status); 00165 if (fp - fpt > del1) 00166 { 00167 del1 = fp - fpt; 00168 ibig1 = i; 00169 for (int j = 0; j < m; j++) 00170 if (part == 0) 00171 p1[j] = p[j] + (mu * 0.1f * xi[j][i]); 00172 else 00173 p1[j] = p[j] - (mu * 0.1f * xi[j][i]); 00174 fp1 = fpt; 00175 } 00176 } 00177 LERROR("*** PART %i : result received from slaves.", 00178 part + 1); 00179 } 00180 float del2 = 0.0f; 00181 float fp2 = fp1; 00182 float p2[m]; 00183 int ibig2 = 0; 00184 for (int part = 0; part < 2; part++) 00185 { 00186 // Sent data to slave processes: 00187 for (int i = 0; i < m; i++) 00188 for (int mu = 1; mu <= NB_EVALS; mu++) 00189 { 00190 int proc = (i * NB_EVALS) + mu; 00191 float pt[m]; 00192 for (int j = 0; j < m; j++) 00193 if (part == 0) 00194 pt[j] = p1[j] + (mu * 0.1f * xi[j][i]); 00195 else 00196 pt[j] = p1[j] - (mu * 0.1f * xi[j][i]); 00197 MPI_Send(&stop, 1, MPI_INT, proc, 00198 4 * iter + 2 + part, 00199 MPI_COMM_WORLD); 00200 MPI_Send(pt, m, MPI_FLOAT, proc, 00201 MSG_DATA + 4 * iter + 2 + part, 00202 MPI_COMM_WORLD); 00203 } 00204 LERROR("*** PART %i : data sent to slaves", 00205 part + 3); 00206 // Receive results and keep the best: 00207 for (int i = 0; i < m; i++) 00208 for (int mu = 1; mu <= NB_EVALS; mu++) 00209 { 00210 int proc = (i * NB_EVALS) + mu; 00211 float fpt; 00212 MPI_Recv(&fpt, 1, MPI_FLOAT, proc, 00213 MSG_RESULT + 4 * iter + 2 + part, 00214 MPI_COMM_WORLD, &status); 00215 if (fp1 - fpt > del2) 00216 { 00217 del2 = fp1 - fpt; 00218 ibig2 = i; 00219 for (int j = 0; j < m; j++) 00220 if (part == 0) 00221 p2[j] = p1[j] + (mu * 0.1f * xi[j][i]); 00222 else 00223 p2[j] = p1[j] - (mu * 0.1f * xi[j][i]); 00224 fp2 = fpt; 00225 } 00226 } 00227 LERROR("*** PART %i : result received from slaves.", 00228 part + 3); 00229 } 00230 00231 LERROR("old value = %f *** new value = %f.", fp, fp2); 00232 00233 // Exit the loop if ITMAX is reach or if the decrease is too low: 00234 if (2.0 * fabs(fp - fp2) <= FTOL * (fabs(fp) + fabs(fp2))) 00235 { 00236 stop = 1; 00237 for (int i = 1; i < NB_PROC; i++) 00238 { 00239 MPI_Send(&stop, 1, MPI_INT, i, 00240 4 * iter + 4, MPI_COMM_WORLD); 00241 } 00242 LERROR("### Low decrease ! ###"); 00243 MPI_Finalize(); 00244 return 0; 00245 } 00246 if (iter == ITMAX) 00247 { 00248 stop = 1; 00249 for (int i = 1; i < NB_PROC; i++) 00250 { 00251 MPI_Send(&stop, 1, MPI_INT, i, 00252 4 * iter + 4, MPI_COMM_WORLD); 00253 } 00254 LERROR("### Maximum iterations exceeded ! ###"); 00255 MPI_Finalize(); 00256 return 0; 00257 } 00258 00259 // Update data: 00260 float xit[m]; 00261 float norm = 0; 00262 int ibig; 00263 if (del1 > del2) 00264 ibig = ibig1; 00265 else 00266 ibig = ibig2; 00267 for (int j = 0; j < m; j++) 00268 { 00269 xit[j] = p2[j] - p[j]; 00270 norm += xit[j] * xit[j]; 00271 p[j] = p2[j]; // Current position updated 00272 } 00273 00274 const std::string filename = 00275 sformat("%s/results/step%03i.txt", PATH, iter); 00276 std::ofstream resultfile (filename.c_str()); 00277 if (resultfile.is_open()) 00278 { 00279 for (int j = 0; j < m; j++) 00280 resultfile << p[j] << "\n"; 00281 resultfile.close(); 00282 } 00283 00284 norm = sqrt(norm); 00285 for (int j = 0; j < m; j++) 00286 { 00287 xi[j][ibig] = xit[j] / norm; // Current directions updated 00288 } 00289 fp = fp2; // Current value updated 00290 } 00291 } 00292 else 00293 { 00294 // ################ SLAVES PROCESS ################ 00295 00296 // **************** INITIALIZATION **************** 00297 00298 MPI_Status status; 00299 00300 // Generate the haar transform matrix: 00301 Image<float> hmat(n, n, NO_INIT); 00302 for(int i = 0; i < n; i++) 00303 { 00304 hmat.setVal(i, 0, 1.0f); 00305 } 00306 for(int i = 0; i < n / 2; i++) 00307 { 00308 hmat.setVal(i, 1, 1.0f); 00309 hmat.setVal(i + n / 2, 1, -1.0f); 00310 hmat.setVal(2 * i, i + n / 2, 1.0f); 00311 hmat.setVal(2 * i + 1, i + n / 2, -1.0f); 00312 } 00313 00314 // Load the input images and masks: 00315 ImageSet< PixRGB<byte> > input(NB_PIC); 00316 ImageSet<byte> mask(NB_PIC); 00317 for (int i = 0; i < NB_PIC; i++) 00318 { 00319 input[i] = 00320 Raster::ReadRGB(sformat("%s/pictures/PIC_%03i.PPM", PATH, i)); 00321 mask[i] = 00322 Raster::ReadGray(sformat("%s/pictures/PIC_%03i.PGM", PATH, i)); 00323 } 00324 00325 LERROR("### SLAVE %i INITIALIZED SUCCESFULLY ! ###", myrank); 00326 00327 // **************** OPTIMIZATION **************** 00328 00329 for (int iter = 0; ; ++iter) 00330 { 00331 // Receive the stop message: 00332 int stop; 00333 MPI_Recv(&stop, 1, MPI_INT, MASTER, 00334 iter, MPI_COMM_WORLD, &status); 00335 if (stop == 1) 00336 { 00337 MPI_Finalize(); 00338 return 0; 00339 } 00340 00341 // Receive data from master: 00342 float data[m]; 00343 MPI_Recv(data, m, MPI_FLOAT, MASTER, 00344 MSG_DATA + iter, MPI_COMM_WORLD, &status); 00345 00346 // Convert data into filters: 00347 ImageSet<float> trans(NB_FILTERS * 3); 00348 for (int i = 0; i < NB_FILTERS * 3; i++) 00349 trans[i] = Image<float>(data + (n * n * i), n, n); 00350 ImageSet<float> filter(NB_FILTERS * 3); 00351 Dims filterdim(8, 8); 00352 for (int i = 0; i < NB_FILTERS * 3; i++) 00353 filter[i] = scaleBlock(matrixMult(hmat, 00354 matrixMult(trans[i], 00355 transpose(hmat))), 00356 filterdim); 00357 00358 // Compute the dot product of the filters: 00359 Image<float> prod1(8, 8, ZEROS); 00360 Image<float> prod2(8, 8, ZEROS); 00361 Image<float> prod3(8, 8, ZEROS); 00362 for (int i = 0; i < NB_FILTERS; i++) 00363 { 00364 prod1 += filter[3 * i] * filter[3 * i + 1]; 00365 prod2 += filter[3 * i] * filter[3 * i + 2]; 00366 prod3 += filter[3 * i + 2] * filter[3 * i + 1]; 00367 } 00368 float dotprod = sum(prod1) + sum(prod2) + sum(prod3); 00369 00370 // Init resut: 00371 float result = 0.0f; 00372 00373 // Compute the error for each image: 00374 for (int p = 0; p < NB_PIC; p++) 00375 { 00376 // Instantiate a ModelManager: 00377 ModelManager manager("Open Attention Model"); 00378 00379 // Instantiate our various ModelComponents: 00380 nub::soft_ref<RawVisualCortex> vcx(new RawVisualCortex(manager)); 00381 manager.addSubComponent(vcx); 00382 00383 for (int i = 0; i < 1; i++) 00384 { 00385 // Create a channel attached to each filter: 00386 nub::soft_ref<RGBConvolveChannel> 00387 channel(new RGBConvolveChannel(manager)); 00388 channel->setDescriptiveName(sformat("RGBConvolve%d", i)); 00389 channel->setTagName(sformat("rgbconv%d", i)); 00390 00391 // Assign the 3 filters to the channel: 00392 channel->setFilters(filter[3 * i], filter[3 * i + 1], 00393 filter[3 * i + 2], 00394 CONV_BOUNDARY_ZERO); 00395 00396 // Attach the channel to our visual cortex: 00397 vcx->addSubChan(channel); 00398 } 00399 00400 // Let's get all our ModelComponent instances started: 00401 manager.exportOptions(MC_RECURSE); 00402 manager.setModelParamString("UsingFPE", "false"); 00403 manager.setModelParamString("TestMode", "true"); 00404 00405 // reduce amount of log messages: 00406 MYLOGVERB = loglev; 00407 00408 manager.start(); 00409 00410 // Process the image through the visual cortex: 00411 vcx->input(InputFrame::fromRgb(&input[p])); 00412 00413 // Get the resulting saliency map: 00414 Image<float> sm = vcx->getOutput(); 00415 00416 // Normalize the saliency map: 00417 inplaceNormalize(sm, 0.0f, 255.0f); 00418 Image<byte> smb = sm; 00419 00420 // Blur and resize the binary mask: 00421 Dims smbdim = smb.getDims(); 00422 Image<byte> blur_mask = binaryReverse(chamfer34(mask[p], 00423 (byte) 255), 00424 (byte) 255); 00425 inplaceLowThresh(blur_mask, (byte) 200); 00426 Image<byte> mask_in = scaleBlock(blur_mask, smbdim); 00427 Image<byte> mask_out = binaryReverse(mask_in, (byte) 255); 00428 00429 // Weight the saliency map using the in and out masks: 00430 Image<float> smb_in = (mask_in * (1.0f / 255.0f)) * smb; 00431 Image<float> smb_out = (mask_out * (1.0f / 255.0f)) * smb; 00432 00433 // Get the max_in and max_out values: 00434 float max_in, max_out, min; 00435 getMinMax(smb_in, min, max_in); 00436 getMinMax(smb_out, min, max_out); 00437 00438 // Compute the error: 00439 float detect_coeff = 1.0f - ((max_in - max_out) / 255.0f); 00440 result += detect_coeff * detect_coeff; 00441 00442 // Stop all our ModelComponents 00443 manager.stop(); 00444 } 00445 00446 // Send the result to the master : 00447 result /= NB_PIC; 00448 result += fabs(dotprod) * 0.001f; 00449 MPI_Send(&result, 1, MPI_FLOAT, MASTER, 00450 MSG_RESULT + iter, MPI_COMM_WORLD); 00451 } 00452 } 00453 00454 #endif // HAVE_MPI_H 00455 00456 } 00457 00458 // ###################################################################### 00459 /* So things look consistent in everyone's emacs... */ 00460 /* Local Variables: */ 00461 /* indent-tabs-mode: nil */ 00462 /* End: */