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 NEURO_ENVSEGMENTERCOLORREGION_C_DEFINED
00039 #define NEURO_ENVSEGMENTERCOLORREGION_C_DEFINED
00040
00041 #include "Neuro/EnvSegmenterColorRegion.H"
00042
00043 #include "Component/ModelOptionDef.H"
00044 #include "Image/ColorOps.H"
00045 #include "Image/Image.H"
00046 #include "Image/ImageSet.H"
00047 #include "Image/LowPass.H"
00048 #include "Image/MathOps.H"
00049 #include "Image/Normalize.H"
00050 #include "Image/Pixels.H"
00051 #include "Image/PyramidOps.H"
00052 #include "Neuro/NeuroOpts.H"
00053 #include "Util/MathFunctions.H"
00054
00055 static const ModelOptionDef OPT_EseDynamicFoa =
00056 { MODOPT_FLAG, "EseDynamicFoa", &MOC_ITC, OPTEXP_CORE,
00057 "Whether to use a dynamically-sized FOA obtained from color-based "
00058 "segmentation",
00059 "ese-dynamic-foa", '\0', "", "true" };
00060
00061 static const ModelOptionDef OPT_EseFoaSize =
00062 { MODOPT_ARG(int), "EseFoaSize", &MOC_ITC, OPTEXP_CORE,
00063 "Size, in pixels, of the FOA box for non-dynamically-sized FOAs",
00064 "ese-foa-size", '\0', "int", "180" };
00065
00066 static const ModelOptionDef OPT_EseDynamicFoaMinSize =
00067 { MODOPT_ARG(int), "EseFoaMinSize", &MOC_ITC, OPTEXP_CORE,
00068 "Minimum size, in pixels, of the FOA box for dynamically-sized FOAs",
00069 "ese-foa-min-size", '\0', "int", "32" };
00070
00071 static const ModelOptionDef OPT_EseDynamicFoaMaxSize =
00072 { MODOPT_ARG(int), "EseFoaMaxSize", &MOC_ITC, OPTEXP_CORE,
00073 "Maximum size, in pixels, of the FOA box for dynamically-sized FOAs",
00074 "ese-foa-max-size", '\0', "int", "360" };
00075
00076 static const ModelOptionDef OPT_EseSegmentationThresh =
00077 { MODOPT_ARG(double), "EseSegmentationThresh", &MOC_ITC, OPTEXP_CORE,
00078 "Pixel-similarity threshold for object segmentation (0.0 .. 1.0)",
00079 "ese-segmentation-thresh", '\0', "double", "0.5" };
00080
00081 static const ModelOptionDef OPT_EseSegmentationScale =
00082 { MODOPT_ARG(size_t), "EseSegmentationScale", &MOC_ITC, OPTEXP_CORE,
00083 "Pyramid scale at which to compute object segmentation",
00084 "ese-segmentation-scale", '\0', "uint", "4" };
00085
00086 namespace
00087 {
00088 Rectangle segmentColor(const Image<PixRGB<byte> >& rgbin,
00089 const Point2D<int>& foacenter,
00090 const size_t segmentationScale,
00091 const float segmentationThresh,
00092 const int foaminsize,
00093 const int foamaxsize,
00094 Image<float>& distmap,
00095 Image<byte>& mask)
00096 {
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116 const ImageSet<PixRGB<byte> > pyr =
00117 buildPyrLocalAvg2x2(rgbin, segmentationScale+1);
00118
00119 Image<PixH2SV1<float> > h2sv1(pyr[segmentationScale]);
00120 Image<float> h1 = lowPass9(getPixelComponentImage(h2sv1, 0));
00121 Image<float> h2 = lowPass9(getPixelComponentImage(h2sv1, 1));
00122 Image<float> s = lowPass9(getPixelComponentImage(h2sv1, 2));
00123 Image<float> v = lowPass9(getPixelComponentImage(h2sv1, 3));
00124
00125 const PixH2SV1<float> target(h1.getVal(foacenter),
00126 h2.getVal(foacenter),
00127 s.getVal(foacenter),
00128 v.getVal(foacenter));
00129 distmap = Image<float>(h2sv1.getDims(), NO_INIT);
00130
00131 Image<PixH2SV1<float> >::const_iterator ptr = h2sv1.begin();
00132 Image<float>::iterator bptr = distmap.beginw();
00133
00134 Point2D<int> p;
00135 for (p.j = 0; p.j < distmap.getHeight(); ++p.j)
00136 for (p.i = 0; p.i < distmap.getWidth(); ++p.i)
00137 {
00138 const float dist = p.distance(foacenter) / 15.0;
00139 *bptr =
00140 0.2 * exp(-dist*dist)
00141 +
00142 0.8 * exp(-sqrt(0.3 * squareOf(ptr->p[0] - target.p[0])
00143 +
00144 0.3 * squareOf(ptr->p[1] - target.p[1])
00145 +
00146 0.3 * squareOf(ptr->p[2] - target.p[2])
00147 +
00148 0.1 * squareOf(ptr->p[3] - target.p[3])
00149 ));
00150
00151 ++bptr;
00152 ++ptr;
00153 }
00154
00155 distmap = lowPass9(distmap);
00156
00157 float mi, ma, avg; getMinMaxAvg(distmap, mi, ma, avg);
00158
00159 const float thresh = avg + segmentationThresh * (ma - avg);
00160
00161 mask = Image<byte>(distmap.getDims(), ZEROS);
00162
00163 std::vector<Point2D<int> > pts;
00164 pts.push_back(foacenter);
00165 mask[foacenter] = 255;
00166
00167 #if 0
00168 const Point2D<int> offsets[8] =
00169 {
00170 Point2D<int>(-1, -1), Point2D<int>(0, -1), Point2D<int>(1, -1),
00171 Point2D<int>(-1, 0), Point2D<int>(1, 0),
00172 Point2D<int>(-1, 1), Point2D<int>(0, 1), Point2D<int>(1, 1)
00173 };
00174 #endif
00175
00176 const Point2D<int> offsets[4] =
00177 {
00178 Point2D<int>(0, -1),
00179 Point2D<int>(-1, 0), Point2D<int>(1, 0),
00180 Point2D<int>(0, 1),
00181 };
00182
00183 int left = foacenter.i, top = foacenter.j, right = foacenter.i, bottom = foacenter.j;
00184
00185 while (pts.size() > 0)
00186 {
00187 const Point2D<int> p = pts.back();
00188 pts.pop_back();
00189
00190 if (p.i < left) left = p.i;
00191 else if (p.i > right) right = p.i;
00192 if (p.j < top) top = p.j;
00193 else if (p.j > bottom) bottom = p.j;
00194
00195 for (size_t i = 0; i < sizeof(offsets) / sizeof(offsets[0]); ++i)
00196 if (distmap.coordsOk(p+offsets[i]) &&
00197 distmap[p+offsets[i]] >= thresh &&
00198 mask[p+offsets[i]] == 0)
00199 {
00200 pts.push_back(p+offsets[i]);
00201 mask[p+offsets[i]] = 255;
00202 }
00203 }
00204
00205 ASSERT(left >= 0);
00206 ASSERT(right < mask.getWidth());
00207 ASSERT(top >= 0);
00208 ASSERT(bottom < mask.getHeight());
00209
00210 const Rectangle rawfoa =
00211 Rectangle::tlbrO(top << segmentationScale,
00212 left << segmentationScale,
00213 (bottom + 1) << segmentationScale,
00214 (right + 1) << segmentationScale);
00215
00216 return constrainRect(rawfoa, rgbin.getBounds(),
00217 foaminsize, foamaxsize);
00218 }
00219 }
00220
00221
00222 EnvSegmenterColorRegion::EnvSegmenterColorRegion(OptionManager& mgr)
00223 :
00224 EnvSegmenter(mgr, "Embeddable Color-Region FOA Segmenter", "EnvSegmenterColorRegion"),
00225 itsDynamicFoa(&OPT_EseDynamicFoa, this, ALLOW_ONLINE_CHANGES),
00226 itsFoaSize(&OPT_EseFoaSize, this, ALLOW_ONLINE_CHANGES),
00227 itsFoaMinSize(&OPT_EseDynamicFoaMinSize, this, ALLOW_ONLINE_CHANGES),
00228 itsFoaMaxSize(&OPT_EseDynamicFoaMaxSize, this, ALLOW_ONLINE_CHANGES),
00229 itsSegmentationThresh(&OPT_EseSegmentationThresh, this, ALLOW_ONLINE_CHANGES),
00230 itsSegmentationScale(&OPT_EseSegmentationScale, this, ALLOW_ONLINE_CHANGES)
00231 {}
00232
00233
00234 EnvSegmenterColorRegion::~EnvSegmenterColorRegion()
00235 {}
00236
00237
00238 void EnvSegmenterColorRegion::paramChanged(ModelParamBase* const param,
00239 const bool valueChanged,
00240 ParamClient::ChangeStatus* status)
00241 {
00242 EnvSegmenter::paramChanged(param, valueChanged, status);
00243
00244 if (param == &itsDynamicFoa)
00245 {
00246 const bool dyn = itsDynamicFoa.getVal();
00247
00248 itsFoaSize.setInactive(dyn);
00249 itsFoaMinSize.setInactive(!dyn);
00250 itsFoaMaxSize.setInactive(!dyn);
00251 itsSegmentationThresh.setInactive(!dyn);
00252 }
00253 else if (param == &itsFoaSize)
00254 {
00255 if (itsFoaSize.getVal() < 16)
00256 *status = ParamClient::CHANGE_REJECTED;
00257 }
00258 else if (param == &itsFoaMinSize)
00259 {
00260 if (itsFoaMinSize.getVal() < 16)
00261 *status = ParamClient::CHANGE_REJECTED;
00262 }
00263 else if (param == &itsFoaMaxSize)
00264 {
00265 if (itsFoaMaxSize.getVal() < itsFoaMinSize.getVal())
00266 *status = ParamClient::CHANGE_REJECTED;
00267 }
00268 else if (param == &itsSegmentationScale)
00269 {
00270 if (itsSegmentationScale.getVal() > 8)
00271 *status = ParamClient::CHANGE_REJECTED;
00272 }
00273 }
00274
00275
00276 Rectangle EnvSegmenterColorRegion::getFoa(const Image<PixRGB<byte> >& rgbin,
00277 const Point2D<int>& center,
00278 Image<byte>* foamask,
00279 Image<PixRGB<byte> >* segmentdisp) const
00280 {
00281 *foamask = Image<byte>();
00282 *segmentdisp = Image<PixRGB<byte> >();
00283
00284 if (itsDynamicFoa.getVal())
00285 {
00286 const int seg_zoom = (1 << itsSegmentationScale.getVal());
00287
00288 const Point2D<int> seg_scaled_maxpos = center / seg_zoom;
00289
00290 Image<float> distmap;
00291 const Rectangle foa =
00292 segmentColor(rgbin, seg_scaled_maxpos,
00293 itsSegmentationScale.getVal(),
00294 itsSegmentationThresh.getVal(),
00295 itsFoaMinSize.getVal(),
00296 itsFoaMaxSize.getVal(),
00297 distmap, *foamask);
00298
00299 *segmentdisp = normalizeFloat(distmap, FLOAT_NORM_0_255);
00300
00301 return foa;
00302 }
00303 else
00304 {
00305 Point2D<int> foatopleft = center - itsFoaSize.getVal()/2;
00306 foatopleft.clampToDims(rgbin.getDims());
00307
00308 const Rectangle foa =
00309 Rectangle(foatopleft, Dims(itsFoaSize.getVal(), itsFoaSize.getVal()))
00310 .getOverlap(rgbin.getBounds());
00311
00312 return foa;
00313 }
00314 }
00315
00316
00317
00318
00319
00320
00321
00322
00323 #endif // NEURO_ENVSEGMENTERCOLORREGION_C_DEFINED