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 #ifndef PSYCHO_CLASSICSEARCHITEM_C_DEFINED
00039 #define PSYCHO_CLASSICSEARCHITEM_C_DEFINED
00040
00041 #include "Psycho/ClassicSearchItem.H"
00042
00043 #include "Image/Image.H"
00044 #include "Image/ShapeOps.H"
00045
00046 #include <cmath>
00047
00048 namespace
00049 {
00050 Image<double> makeC(int sz, const double angle)
00051 {
00052 Image<double> result(sz, sz, NO_INIT);
00053
00054 Image<double>::iterator ptr = result.beginw();
00055
00056 const double ro2 = (0.25 * sz) * (0.25 * sz);
00057 const double ri2 = (0.2 * sz) * (0.2 * sz);
00058 const double xc = 0.5 * sz - 0.5;
00059 const double yc = 0.5 * sz - 0.5;
00060
00061 for (int y = 0; y < sz; ++y)
00062 {
00063 const double y2 = (y-yc)*(y-yc);
00064
00065 for (int x = 0; x < sz; ++x)
00066 {
00067 const double r2 = (x-xc)*(x-xc) + y2;
00068
00069 const double theta = atan2(yc-y, x-xc);
00070
00071 const double diff = geom::rad_npi_pi(geom::rad_npi_pi(angle) - theta);
00072
00073 if (fabs(diff) > M_PI/8.0 &&
00074 r2 > ri2 && r2 <= ro2)
00075 *ptr++ = -1.0;
00076 else
00077 *ptr++ = 0.0;
00078 }
00079 }
00080
00081 return result;
00082 }
00083
00084 Image<double> makeO(int sz)
00085 {
00086 Image<double> result(sz, sz, NO_INIT);
00087
00088 Image<double>::iterator ptr = result.beginw();
00089
00090 const double ro2 = (0.25 * sz) * (0.25 * sz);
00091 const double ri2 = (0.2 * sz) * (0.2 * sz);
00092 const double xc = 0.5 * sz - 0.5;
00093 const double yc = 0.5 * sz - 0.5;
00094
00095 for (int y = 0; y < sz; ++y)
00096 {
00097 const double y2 = (y-yc)*(y-yc);
00098
00099 for (int x = 0; x < sz; ++x)
00100 {
00101 const double r2 = (x-xc)*(x-xc) + y2;
00102
00103 if (r2 > ri2 && r2 <= ro2)
00104 *ptr++ = -1.0;
00105 else
00106 *ptr++ = 0.0;
00107 }
00108 }
00109
00110 return result;
00111 }
00112
00113 Image<double> makeQ(int sz, const double angle)
00114 {
00115 Image<double> result(sz, sz, NO_INIT);
00116
00117 Image<double>::iterator ptr = result.beginw();
00118
00119 const double cosa = cos(-angle);
00120 const double sina = sin(-angle);
00121 const double ro2 = (0.25 * sz) * (0.25 * sz);
00122 const double ri2 = (0.2 * sz) * (0.2 * sz);
00123 const double xc = 0.5 * sz - 0.5;
00124 const double yc = 0.5 * sz - 0.5;
00125
00126 const double dh = 0.025 * sz;
00127
00128 for (int y = 0; y < sz; ++y)
00129 {
00130 const double y2 = (y-yc)*(y-yc);
00131
00132 for (int x = 0; x < sz; ++x)
00133 {
00134 const double r2 = (x-xc)*(x-xc) + y2;
00135
00136 const double u = (x-xc) * cosa - (yc-y) * sina;
00137 const double v = (x-xc) * sina + (yc-y) * cosa;
00138
00139 if ((r2 > ri2 && r2 <= ro2)
00140 ||
00141 (fabs(v) <= dh && fabs(u-0.225*sz) < 0.1*sz))
00142 *ptr++ = -1.0;
00143 else
00144 *ptr++ = 0.0;
00145 }
00146 }
00147
00148 return result;
00149 }
00150
00151 Image<double> makePlus(int sz, const double angle)
00152 {
00153 Image<double> result(sz, sz, NO_INIT);
00154
00155 Image<double>::iterator ptr = result.beginw();
00156
00157 const double cosa = cos(-angle);
00158 const double sina = sin(-angle);
00159 const double xc = 0.5 * sz - 0.5;
00160 const double yc = 0.5 * sz - 0.5;
00161
00162 const double dh = 0.025 * sz;
00163 const double dw = 0.25 * sz;
00164
00165 for (int y = 0; y < sz; ++y)
00166 for (int x = 0; x < sz; ++x)
00167 {
00168 const double u = (x-xc) * cosa - (yc-y) * sina;
00169 const double v = (x-xc) * sina + (yc-y) * cosa;
00170
00171 if ((fabs(u) <= dw && fabs(v) <= dh)
00172 ||
00173 (fabs(v) <= dw && fabs(u) <= dh))
00174 *ptr++ = -1.0;
00175 else
00176 *ptr++ = 0.0;
00177 }
00178
00179 return result;
00180 }
00181
00182 Image<double> makeL(int sz, const double angle)
00183 {
00184 Image<double> result(sz, sz, NO_INIT);
00185
00186 Image<double>::iterator ptr = result.beginw();
00187
00188 const double cosa = cos(-angle);
00189 const double sina = sin(-angle);
00190 const double xc = 0.5 * sz - 0.5;
00191 const double yc = 0.5 * sz - 0.5;
00192
00193 const double dh = 0.025 * sz;
00194 const double dw = 0.25 * sz;
00195
00196 for (int y = 0; y < sz; ++y)
00197 for (int x = 0; x < sz; ++x)
00198 {
00199 const double u = (x-xc) * cosa - (yc-y) * sina;
00200 const double v = (x-xc) * sina + (yc-y) * cosa;
00201
00202 if ((fabs(u+0.225*sz) <= dh && fabs(v) <= dw)
00203 ||
00204 (fabs(v+0.225*sz) <= dh && fabs(u) <= dw))
00205 *ptr++ = -1.0;
00206 else
00207 *ptr++ = 0.0;
00208 }
00209
00210 return result;
00211 }
00212
00213 Image<double> makeT(int sz, const double angle)
00214 {
00215 Image<double> result(sz, sz, NO_INIT);
00216
00217 Image<double>::iterator ptr = result.beginw();
00218
00219 const double cosa = cos(-angle);
00220 const double sina = sin(-angle);
00221 const double xc = 0.5 * sz - 0.5;
00222 const double yc = 0.5 * sz - 0.5;
00223
00224 const double dh = 0.025 * sz;
00225 const double dw = 0.25 * sz;
00226
00227 for (int y = 0; y < sz; ++y)
00228 for (int x = 0; x < sz; ++x)
00229 {
00230 const double u = (x-xc) * cosa - (yc-y) * sina;
00231 const double v = (x-xc) * sina + (yc-y) * cosa;
00232
00233 if ((fabs(u) <= dh && fabs(v) <= dw)
00234 ||
00235 (fabs(v-0.225*sz) <= dh && fabs(u) <= dw))
00236 *ptr++ = -1.0;
00237 else
00238 *ptr++ = 0.0;
00239 }
00240
00241 return result;
00242 }
00243
00244 Image<double> makeDash(int sz, const double angle)
00245 {
00246 Image<double> result(sz, sz, NO_INIT);
00247
00248 Image<double>::iterator ptr = result.beginw();
00249
00250 const double cosa = cos(-angle);
00251 const double sina = sin(-angle);
00252 const double xc = 0.5 * sz - 0.5;
00253 const double yc = 0.5 * sz - 0.5;
00254
00255 const double dh = 0.025 * sz;
00256 const double dw = 0.25 * sz;
00257
00258 for (int y = 0; y < sz; ++y)
00259 for (int x = 0; x < sz; ++x)
00260 {
00261 const double u = (x-xc) * cosa - (yc-y) * sina;
00262 const double v = (x-xc) * sina + (yc-y) * cosa;
00263
00264 if (fabs(u) <= dw && fabs(v) <= dh)
00265 *ptr++ = -1.0;
00266 else
00267 *ptr++ = 0.0;
00268 }
00269
00270 return result;
00271 }
00272
00273 Image<double> shrink(const Image<double>& img, int noctaves)
00274 {
00275 Image<double> result = img;
00276 for (int i = 0; i < noctaves; ++i)
00277 result = quickLocalAvg2x2(result);
00278 return result;
00279 }
00280 }
00281
00282
00283 ClassicSearchItem::ClassicSearchItem(Type t, int sz, double angle,
00284 int antialiasOctaves)
00285 :
00286 itsType(t),
00287 itsSize(sz),
00288 itsAngle(angle),
00289 itsAntialiasOctaves(antialiasOctaves)
00290 {}
00291
00292
00293 ClassicSearchItem::~ClassicSearchItem()
00294 {}
00295
00296
00297 Image<double> ClassicSearchItem::getPatch() const
00298 {
00299 const int zoom = (1 << itsAntialiasOctaves);
00300
00301 switch (itsType)
00302 {
00303 case ITEM_C: return shrink(makeC(itsSize*zoom, itsAngle), itsAntialiasOctaves);
00304 case ITEM_O: return shrink(makeO(itsSize*zoom), itsAntialiasOctaves);
00305 case ITEM_Q: return shrink(makeQ(itsSize*zoom, itsAngle), itsAntialiasOctaves);
00306 case ITEM_PLUS: return shrink(makePlus(itsSize*zoom, itsAngle), itsAntialiasOctaves);
00307 case ITEM_L: return shrink(makeL(itsSize*zoom, itsAngle), itsAntialiasOctaves);
00308 case ITEM_T: return shrink(makeT(itsSize*zoom, itsAngle), itsAntialiasOctaves);
00309 case ITEM_DASH: return shrink(makeDash(itsSize*zoom, itsAngle), itsAntialiasOctaves);
00310 default:
00311 break;
00312 }
00313
00314 LFATAL("unsupported item type");
00315 return Image<double>();
00316 }
00317
00318
00319 ClassicSearchItem::Type ClassicSearchItem::typeFromChar(char c)
00320 {
00321 switch (toupper(c))
00322 {
00323 case 'C': return ITEM_C;
00324 case 'O': return ITEM_O;
00325 case 'Q': return ITEM_Q;
00326 case '+': return ITEM_PLUS;
00327 case 'L': return ITEM_L;
00328 case 'T': return ITEM_T;
00329 case '-': return ITEM_DASH;
00330 }
00331
00332 LFATAL("invalid search item type '%c'", c);
00333 return Type(-1);
00334 }
00335
00336
00337 ClassicSearchItemFactory::ClassicSearchItemFactory(SearchItem::Type c,
00338 const std::string& types,
00339 int sz,
00340 const Range<double>& angleRange,
00341 int antialiasOctaves,
00342 int angleSeed,
00343 int typeSeed)
00344 :
00345 itsLayer(c),
00346 itsTypeList(types),
00347 itsSize(sz),
00348 itsAngleRange(angleRange),
00349 itsAntialiasOctaves(antialiasOctaves),
00350 itsAngles(angleSeed),
00351 itsTypes(typeSeed)
00352 {
00353 if (itsTypeList.size() == 0)
00354 LFATAL("search item typelist must include at least one type");
00355 }
00356
00357
00358 ClassicSearchItemFactory::~ClassicSearchItemFactory()
00359 {}
00360
00361
00362 rutz::shared_ptr<SearchItem> ClassicSearchItemFactory::make(const geom::vec2d& pos)
00363 {
00364 ClassicSearchItem::Type t =
00365 ClassicSearchItem::typeFromChar(itsTypeList[itsTypes.idraw(itsTypeList.size())]);
00366
00367 rutz::shared_ptr<ClassicSearchItem> el
00368 (new ClassicSearchItem(t, itsSize,
00369 itsAngles.fdraw_range(itsAngleRange.min(), itsAngleRange.max()),
00370 itsAntialiasOctaves));
00371
00372 el->type = itsLayer;
00373 el->pos = pos;
00374
00375 return el;
00376 }
00377
00378
00379
00380
00381
00382
00383
00384
00385 #endif // PSYCHO_CLASSICSEARCHITEM_C_DEFINED