00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039 #include "Component/ModelManager.H"
00040 #include "Component/ModelOptionDef.H"
00041 #include "Image/ColorOps.H"
00042 #include "Image/CutPaste.H"
00043 #include "Image/DrawOps.H"
00044 #include "Image/Image.H"
00045 #include "Image/MathOps.H"
00046 #include "Image/LowPass.H"
00047 #include "Image/ShapeOps.H"
00048 #include "Image/Transforms.H"
00049 #include "Image/Layout.H"
00050 #include "Psycho/PsychoDisplay.H"
00051 #include "Psycho/EyeTrackerConfigurator.H"
00052 #include "Psycho/EyeTracker.H"
00053 #include "Psycho/PsychoOpts.H"
00054 #include "Image/geom.h"
00055 #include "Psycho/ClassicSearchItem.H"
00056 #include "Psycho/SearchArray.H"
00057 #include "Component/EventLog.H"
00058 #include "Component/ComponentOpts.H"
00059 #include "Raster/Raster.H"
00060 #include "rutz/shared_ptr.h"
00061 #include "Util/MathFunctions.H"
00062 #include "Util/StringUtil.H"
00063 #include "Util/StringConversions.H"
00064 #include "GUI/GUIOpts.H"
00065
00066 #include <sstream>
00067 #include <ctime>
00068 #include <ctype.h>
00069 #include <vector>
00070 #include <string>
00071 #include <fstream>
00072
00073 using namespace std;
00074
00075 static const ModelOptionCateg MOC_RANDGENIMAGE = {
00076 MOC_SORTPRI_2, "Options for random image generation" };
00077
00078 static const ModelOptionDef OPT_RandImageDims =
00079 { MODOPT_ARG(Dims), "GenImageDims", &MOC_RANDGENIMAGE, OPTEXP_CORE,
00080 "dimensions of the random image",
00081 "rand-image-dims", '\0', "<width>x<height>", "1280x720" };
00082
00083
00084 class fillTool {
00085 public:
00086 fillTool() {}
00087 virtual Image<byte> fill(const Dims d) const {return Image<byte>(d,NO_INIT);}
00088
00089 protected:
00090 };
00091
00092
00093 class fillTexture : public fillTool {
00094 public:
00095 Image<byte> fill(const Dims d) const;
00096
00097 void setSeed(const uint c) {seed = c;}
00098 uint getSeed() const {return seed;}
00099
00100 protected:
00101
00102 uint seed;
00103 };
00104
00105
00106 class fillColor : public fillTool {
00107 public:
00108 Image<byte> fill(const Dims d) const;
00109
00110 void setColor(const byte c) {bg = c;}
00111 byte getColor() const {return bg;}
00112
00113
00114 protected:
00115 byte bg;
00116 };
00117
00118
00119 class renderObject {
00120 public:
00121 renderObject() {}
00122 virtual void drawOn(Image<byte> &im) const = 0;
00123 virtual bool inBounds(const Dims &d) const = 0;
00124 Point2D<int> getLocation() {return loc;} const
00125 void setLocation(const Point2D<int> &P) {loc = P;}
00126
00127 int getSize() {return siz;} const
00128 void setSize(const int &s) {siz = s;}
00129
00130 float getDirection() {return dir;} const
00131 void setDirection(const float &t) {dir = t;}
00132
00133 protected:
00134 Point2D<int> loc;
00135 float dir;
00136 int siz;
00137 };
00138
00139 class renderDot : public renderObject {
00140 public:
00141 void drawOn(Image<byte> &im) const;
00142 bool inBounds(const Dims &d) const
00143 {return 0 <= loc.i - dir && 0 <= loc.j - dir && loc.i + dir < d.w() && loc.j + dir < d.h();}
00144
00145 void setFill(rutz::shared_ptr<fillTool> f) {filler = f;}
00146 rutz::shared_ptr<fillTool> getFill() const {return filler;}
00147 private:
00148 rutz::shared_ptr<fillTool> filler;
00149 };
00150
00151
00152 int randomInRange(const int x, const int y);
00153
00154
00155
00156 Point2D<int> randomPointIn(const Dims d);
00157
00158
00159 void drawRandomLine(Image<byte> & im, const byte val, const int thickness);
00160 void extrapolateLine(Dims d, Point2D<int> & X, Point2D<int> & Y);
00161
00162 template <class T>
00163 Image<byte> makeNary(const Image<T>& src, const std::vector<T> thresholds,
00164 const std::vector<byte> levels);
00165
00166
00167 Image<byte> texturizeImage(const Image<byte> im, const uint Nlevels);
00168 Image<byte> discretizeImage(const Image<byte> im, const int Nlevels);
00169 Image<byte> getBrodatzTexture(uint seed, const Dims dims);
00170 Image<byte> getStretchedTexture(const std::string filename, const Dims dims);
00171 Image<byte> getTiledTexture(const std::string filename, const Dims dims);
00172
00173
00174 static int submain(const int argc, char** argv)
00175 {
00176 MYLOGVERB = LOG_INFO;
00177
00178
00179 ModelManager manager("AppMedia: Flyover stimulus");
00180
00181
00182 if (manager.parseCommandLine(argc, argv,"<out_stem>", 1, 1) == false)
00183 return(1);
00184
00185
00186
00187 char filename[255], texfile[255], fillfile[255];
00188
00189 OModelParam<Dims> dims(&OPT_RandImageDims, &manager);
00190
00191
00192 sprintf(filename, "%s.png",manager.getExtraArg(0).c_str());
00193 sprintf(texfile, "%s-tex.png",manager.getExtraArg(0).c_str());
00194 sprintf(fillfile, "%s-fill.png",manager.getExtraArg(0).c_str());
00195
00196
00197 manager.start();
00198
00199
00200
00201
00202
00203
00204
00205 Image<byte> myBkgd = Image<byte>(dims.getVal(),ZEROS)+128;
00206 Image<byte> myMap = myBkgd;
00207 rutz::shared_ptr<fillTexture> style(new fillTexture);
00208 rutz::shared_ptr<fillColor> color(new fillColor);
00209
00210 rutz::shared_ptr<renderDot> dot(new renderDot);
00211 dot->setSize(50);
00212
00213 int rseed, rcol;
00214 for(int i = 0; i < 50; i++) {
00215 rseed = randomUpToIncluding(255);
00216 rcol = randomUpToIncluding(1);
00217 if(rcol==0) {
00218 style->setSeed(rseed);
00219 dot->setFill(style);
00220 }
00221 else {
00222 color->setColor(rseed);
00223 dot->setFill(color);
00224 }
00225 dot->setLocation(randomPointIn(dims.getVal()));
00226 dot->drawOn(myMap);
00227 }
00228
00229 LINFO("writing pattern image to %s", filename);
00230 Raster::WriteGray(myMap,filename);
00231
00232
00233 manager.stop();
00234
00235
00236 return 0;
00237 }
00238
00239
00240
00241 extern "C" int main(const int argc, char** argv)
00242 {
00243
00244
00245
00246
00247 try
00248 {
00249 return submain(argc, argv);
00250 }
00251 catch (...)
00252 {
00253 REPORT_CURRENT_EXCEPTION;
00254 }
00255
00256 return 1;
00257 }
00258
00259
00260
00261 Image<byte> fillTexture::fill(const Dims d) const {
00262 return getBrodatzTexture(seed, d);
00263 }
00264
00265
00266 Image<byte> fillColor::fill(const Dims d) const {
00267 return Image<byte>(d,ZEROS) + bg;
00268 }
00269
00270
00271 void renderDot::drawOn(Image<byte> & im) const
00272 {
00273 const byte mask_col = 255;
00274
00275 Image<byte> mask(im.getDims(), ZEROS);
00276 drawDisk(mask, loc, siz, mask_col);
00277
00278 Image<byte> myPrint = filler->fill(im.getDims());
00279 std::vector<Image<byte> > bgs;
00280 bgs.push_back(im); bgs.push_back(myPrint);
00281 byte bg_assigns[2] = {0, mask_col};
00282 im = mosaic(mask, &bgs[0], bg_assigns, 2);
00283 }
00284
00285
00286
00287 int randomInRange(const int x, const int y)
00288 {
00289 return randomUpToNotIncluding(y-x-1)+(x+1);
00290 }
00291
00292
00293
00294
00295 void drawRandomLine(Image<byte> & im, const byte val, const int thickness)
00296 {
00297 Point2D<int> P = randomPointIn(im.getDims());
00298 Point2D<int> Q = randomPointIn(im.getDims());
00299
00300 extrapolateLine(im.getDims(),P,Q);
00301 drawLine(im, P, Q, val, thickness);
00302 }
00303
00304
00305
00306
00307 void extrapolateLine(Dims d, Point2D<int> & X, Point2D<int> & Y)
00308 {
00309
00310 Image<byte> foo(d, NO_INIT);
00311 if(!(foo.coordsOk(X) && foo.coordsOk(Y)) || X == Y) return;
00312
00313 if (X.i == Y.i) {X.j = 0; Y.j = d.h(); return;}
00314 else if(X.j == Y.j) {X.i = 0; Y.j = d.w(); return;}
00315 else {float y_0 = (X.j*Y.i-X.i*Y.j)/(Y.i-X.i);
00316 float x_0 = (X.i*Y.j-X.j*Y.i)/(Y.j-X.j);
00317 float slope = (Y.j-X.j)/(Y.i-X.i);
00318
00319 std::vector<Point2D<int> > bounds;
00320 bounds.push_back(Point2D<int>(0,y_0));
00321 bounds.push_back(Point2D<int>(x_0,0));
00322 bounds.push_back(Point2D<int>(d.w()-1,y_0+(d.w()-1)*slope));
00323 bounds.push_back(Point2D<int>(x_0+(d.h()-1)/slope,d.h()-1));
00324
00325 bool Xdone = 0;
00326 for(int i = 0; i < 4; i++)
00327 if(foo.coordsOk(bounds[i])) {
00328 if(!Xdone) {
00329 X = bounds[i];
00330 Xdone = true;
00331 }
00332 else {
00333 Y = bounds[i];
00334 break;
00335 }
00336 }
00337 }
00338 }
00339
00340
00341
00342
00343 Point2D<int> randomPointIn(const Dims d)
00344 {
00345 return Point2D<int>(randomInRange(0,d.w()),
00346 randomInRange(0,d.h()));
00347 }
00348
00349
00350
00351
00352 template <class T>
00353 Image<byte> makeNary(const Image<T>& src, const std::vector<T> thresholds,
00354 const std::vector<byte> levels)
00355 {
00356 ASSERT(thresholds.size() == levels.size() - 1);
00357 Image<byte> acc(src.getDims(),ZEROS);
00358 byte floor;
00359 for(uint i = 0; i < thresholds.size(); i++)
00360 {
00361 if(i == 0)
00362 {
00363 floor = levels[0];
00364 }
00365 else
00366 {
00367 floor = 0;
00368 }
00369 acc += makeBinary(src, thresholds[i],floor,levels[1]);
00370 }
00371
00372 return acc;
00373 }
00374
00375
00376
00377 Image<byte> texturizeImage(const Image<byte> im, const uint Nlevels)
00378 {
00379 uint i, seed;
00380
00381 std::vector<Image<byte> > texBkgds;
00382 for(i = 0; i < Nlevels; i++)
00383 {
00384 seed = randomInRange(0,112);
00385 texBkgds.push_back(getBrodatzTexture(seed, im.getDims()));
00386 }
00387
00388 byte tiers[Nlevels];
00389 for(uint i = 0; i < Nlevels; i++)
00390 tiers[i] = i*(255/(Nlevels-1));
00391
00392 return mosaic(im, &texBkgds[0], tiers, Nlevels);
00393
00394 }
00395
00396
00397
00398 Image<byte> discretizeImage(const Image<byte> im, const int Nlevels)
00399 {
00400 byte imMin, imMax, i;
00401 getMinMax(im, imMin, imMax);
00402
00403 const byte Ncuts = Nlevels - 1;
00404
00405
00406 float coeffs[Ncuts];
00407 for(i = 0; i < Ncuts; i++)
00408 coeffs[i] = (i+1.0)/(Ncuts+1.0);
00409
00410
00411 std::vector<byte> cuts;
00412 for(i = 0; i < Ncuts; i++)
00413 cuts.push_back(imMax*coeffs[i]+imMin*(1-coeffs[i]));
00414
00415
00416 std::vector<byte> tiers;
00417 for(i = 0; i <= cuts.size(); i++)
00418 tiers.push_back(i*(255/cuts.size()));
00419
00420
00421 Image<byte> pattern = makeNary(im,cuts,tiers);
00422
00423
00424 drawRandomLine(pattern, tiers[2], 50);
00425
00426 return pattern;
00427
00428 }
00429
00430
00431 Image<byte> getBrodatzTexture(uint seed, const Dims dims)
00432 {
00433 char texPath[255];
00434
00435
00436 const uint Nimages = 111;
00437 seed = seed % (Nimages - 1) + 1;
00438
00439 sprintf(texPath, "/lab/jshen/projects/eye-cuing/stimuli/textures/brodatz/D%u.png",seed);
00440 return getStretchedTexture(texPath, dims);
00441 }
00442
00443
00444 Image<byte> getStretchedTexture(const std::string filename, const Dims dims)
00445 {
00446 Image<byte> pat = Raster::ReadGray(filename,RASFMT_PNG);
00447 return rescale(pat, dims);
00448 }
00449
00450
00451 Image<byte> getTiledTexture(const std::string filename, const Dims dims)
00452 {
00453
00454 Image<byte> pat = Raster::ReadGray(filename,RASFMT_PNG);
00455
00456 const size_t nX = dims.w()/pat.getWidth()+1;
00457 const size_t nY = dims.h()/pat.getHeight()+1;
00458
00459 std::vector<Image<byte> > tiles(nX,pat);
00460 Layout<byte> horiztile(&tiles[0],nX,Layout<byte>::H);
00461
00462 std::vector<Layout<byte> > rows(nY,horiztile);
00463 Layout<byte> whole(&rows[0],nY,Layout<byte>::V);
00464
00465 return crop(whole.render(),Point2D<int>(0,0),dims);
00466 }
00467
00468
00469
00470
00471
00472