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 CHANNELS_INPUTFRAME_C_DEFINED
00039 #define CHANNELS_INPUTFRAME_C_DEFINED
00040
00041 #include "Channels/InputFrame.H"
00042
00043 #include "Image/ColorOps.H"
00044 #include "Util/Assert.H"
00045 #include "Util/JobWithSemaphore.H"
00046 #include "Util/MainJobServer.H"
00047
00048 #include <pthread.h>
00049 #include <vector>
00050
00051
00052 struct RgbByteToLuminanceJob : public JobWithSemaphore
00053 {
00054 RgbByteToLuminanceJob(const PixRGB<byte>* in_,
00055 const PixRGB<byte>* end_,
00056 float* lumout_)
00057 :
00058 in(in_), end(end_),
00059 lumout(lumout_)
00060 {}
00061
00062 virtual ~RgbByteToLuminanceJob()
00063 {}
00064
00065 virtual void run()
00066 {
00067 const PixRGB<byte>* in_ = in;
00068 const PixRGB<byte>* const end_ = end;
00069 float* lumout_ = lumout;
00070
00071 const float one_third = 1.0f / 3.0f;
00072
00073 while (in_ != end_)
00074 {
00075 *lumout_++ = one_third * (in_->p[0] + in_->p[1] + in_->p[2]);
00076 ++in_;
00077 }
00078
00079 this->markFinished();
00080 }
00081
00082 virtual const char* jobType() const { return "RgbByteToLuminanceJob"; }
00083
00084 const PixRGB<byte>* const in;
00085 const PixRGB<byte>* const end;
00086 float* const lumout;
00087 };
00088
00089
00090 struct RgbByteToFloatJob : public JobWithSemaphore
00091 {
00092 RgbByteToFloatJob(const PixRGB<byte>* in_,
00093 const PixRGB<byte>* end_,
00094 PixRGB<float>* rgbout_)
00095 :
00096 in(in_), end(end_),
00097 rgbout(rgbout_)
00098 {}
00099
00100 virtual ~RgbByteToFloatJob()
00101 {}
00102
00103 virtual void run()
00104 {
00105 const PixRGB<byte>* in_ = in;
00106 const PixRGB<byte>* const end_ = end;
00107 PixRGB<float>* rgbout_ = rgbout;
00108
00109 while (in_ != end_)
00110 *rgbout_++ = PixRGB<float>(*in_++);
00111
00112 this->markFinished();
00113 }
00114
00115 virtual const char* jobType() const { return "RgbByteToFloatJob"; }
00116
00117 const PixRGB<byte>* const in;
00118 const PixRGB<byte>* const end;
00119 PixRGB<float>* const rgbout;
00120 };
00121
00122
00123 InputFrame::InputFrame()
00124 {}
00125
00126
00127 InputFrame InputFrame::fromRgb(const Image<PixRGB<byte> >* in,
00128 SimTime t,
00129 const Image<byte>* clip,
00130 const rutz::shared_ptr<PyramidCache<float> >& cache,
00131 bool disableCache)
00132 {
00133 ASSERT(in != 0); ASSERT(in->initialized());
00134
00135 InputFrame result;
00136
00137 result.itsTime = t;
00138 result.itsDims = in->getDims();
00139 if (clip != 0)
00140 result.itsClipMask = *clip;
00141 else
00142 result.itsClipMask = Image<byte>();
00143 result.itsColorByte = *in;
00144
00145 result.itsColorFloat = Image<PixRGB<float> >();
00146 result.itsGrayFloat = Image<float>(in->getDims(), NO_INIT);
00147 result.itsPyrCache =
00148 disableCache
00149 ? rutz::shared_ptr<PyramidCache<float> >()
00150 : cache.get() != 0
00151 ? cache
00152 : rutz::shared_ptr<PyramidCache<float> >(new PyramidCache<float>);
00153
00154 result.itsPyrCacheRgb = rutz::shared_ptr<PyramidCache<PixRGB<float> > >();
00155
00156 const int sz = in->getSize();
00157
00158 JobServer& srv = getMainJobServer();
00159
00160 const unsigned int ntiles = srv.getParallelismHint();
00161
00162 LDEBUG("ntiles = %u", ntiles);
00163
00164 std::vector<rutz::shared_ptr<RgbByteToLuminanceJob > > jobs;
00165
00166 for (unsigned int i = 0; i < ntiles; ++i)
00167 {
00168 const int start = (i*sz)/ntiles;
00169 const int end = ((i+1)*sz)/ntiles;
00170
00171 jobs.push_back
00172 (rutz::make_shared(new RgbByteToLuminanceJob
00173 (in->getArrayPtr() + start,
00174 in->getArrayPtr() + end,
00175 result.itsGrayFloat.getArrayPtr() + start)));
00176
00177 srv.enqueueJob(jobs.back());
00178 }
00179
00180 for (size_t i = 0; i < jobs.size(); ++i)
00181 jobs[i]->wait();
00182
00183 return result;
00184 }
00185
00186
00187 InputFrame InputFrame::fromRgbFloat(const Image<PixRGB<float> >* col,
00188 SimTime t,
00189 const Image<byte>* clip,
00190 const rutz::shared_ptr<PyramidCache<float> >& cache,
00191 bool disableCache)
00192 {
00193 ASSERT(col != 0); ASSERT(col->initialized());
00194
00195 InputFrame result;
00196
00197 result.itsTime = t;
00198 result.itsDims = col->getDims();
00199 if (clip != 0)
00200 result.itsClipMask = *clip;
00201 else
00202 result.itsClipMask = Image<byte>();
00203 result.itsColorByte = Image<PixRGB<byte> >();
00204 result.itsColorFloat = *col;
00205 result.itsGrayFloat = luminance(result.itsColorFloat);
00206 result.itsPyrCache =
00207 disableCache
00208 ? rutz::shared_ptr<PyramidCache<float> >()
00209 : cache.get() != 0
00210 ? cache
00211 : rutz::shared_ptr<PyramidCache<float> >(new PyramidCache<float>);
00212
00213 result.itsPyrCacheRgb = rutz::shared_ptr<PyramidCache<PixRGB<float> > >();
00214
00215 return result;
00216 }
00217
00218
00219 InputFrame InputFrame::fromGrayFloat(const Image<float>* bw,
00220 SimTime t,
00221 const Image<byte>* clip,
00222 const rutz::shared_ptr<PyramidCache<float> >& cache,
00223 bool disableCache)
00224 {
00225 ASSERT(bw != 0); ASSERT(bw->initialized());
00226
00227 InputFrame result;
00228
00229 result.itsTime = t;
00230 result.itsDims = bw->getDims();
00231 if (clip != 0)
00232 result.itsClipMask = *clip;
00233 else
00234 result.itsClipMask = Image<byte>();
00235 result.itsColorByte = Image<PixRGB<byte> >();
00236 result.itsColorFloat = Image<PixRGB<float> >();
00237 result.itsGrayFloat = *bw;
00238 result.itsPyrCache =
00239 disableCache
00240 ? rutz::shared_ptr<PyramidCache<float> >()
00241 : cache.get() != 0
00242 ? cache
00243 : rutz::shared_ptr<PyramidCache<float> >(new PyramidCache<float>);
00244
00245 result.itsPyrCacheRgb = rutz::shared_ptr<PyramidCache<PixRGB<float> > >();
00246
00247 return result;
00248 }
00249
00250 InputFrame InputFrame::fromRgbAndGrayFloat(const Image<PixRGB<byte> >* rgbb,
00251 const Image<PixRGB<float> >* rgbf,
00252 const Image<float>* bw,
00253 SimTime t,
00254 const Image<byte>* clip,
00255 const rutz::shared_ptr<PyramidCache<float> >& cache,
00256 bool disableCache)
00257 {
00258 ASSERT(rgbb != 0); ASSERT(rgbb->initialized());
00259 ASSERT(rgbf != 0); ASSERT(rgbf->initialized());
00260 ASSERT(bw != 0); ASSERT(bw->initialized());
00261
00262 if (rgbb->getDims() != rgbf->getDims())
00263 LFATAL("Color-byte and color-float inputs must have the same dimensions "
00264 "(got %dx%d color-byte and %dx%d color-float)",
00265 rgbb->getWidth(), rgbb->getHeight(),
00266 rgbf->getWidth(), rgbf->getHeight());
00267
00268 if (rgbf->getDims() != bw->getDims())
00269 LFATAL("Color and grayscale inputs must have the same dimensions "
00270 "(got %dx%d color and %dx%d grayscale)",
00271 rgbf->getWidth(), rgbf->getHeight(),
00272 bw->getWidth(), bw->getHeight());
00273
00274 InputFrame result;
00275
00276 result.itsTime = t;
00277 result.itsDims = rgbb->getDims();
00278 if (clip != 0)
00279 result.itsClipMask = *clip;
00280 else
00281 result.itsClipMask = Image<byte>();
00282 result.itsColorByte = *rgbb;
00283 result.itsColorFloat = *rgbf;
00284 result.itsGrayFloat = *bw;
00285 result.itsPyrCache =
00286 disableCache
00287 ? rutz::shared_ptr<PyramidCache<float> >()
00288 : cache.get() != 0
00289 ? cache
00290 : rutz::shared_ptr<PyramidCache<float> >(new PyramidCache<float>);
00291
00292 result.itsPyrCacheRgb = rutz::shared_ptr<PyramidCache<PixRGB<float> > >();
00293
00294 return result;
00295 }
00296
00297 InputFrame InputFrame::fromRgbDepth(const Image<PixRGB<byte> >* in,
00298 const Image<uint16>* depth,
00299 SimTime t,
00300 const Image<byte>* clip,
00301 const rutz::shared_ptr<PyramidCache<float> >& cache,
00302 bool disableCache)
00303 {
00304 ASSERT(in != 0); ASSERT(in->initialized());
00305 ASSERT(depth != 0); ASSERT(depth->initialized());
00306
00307 InputFrame result;
00308
00309 result.itsTime = t;
00310 result.itsDims = in->getDims();
00311 if (clip != 0)
00312 result.itsClipMask = *clip;
00313 else
00314 result.itsClipMask = Image<byte>();
00315 result.itsColorByte = *in;
00316
00317 result.itsDepthImage = *depth;
00318
00319 result.itsColorFloat = Image<PixRGB<float> >();
00320 result.itsGrayFloat = Image<float>(in->getDims(), NO_INIT);
00321 result.itsPyrCache =
00322 disableCache
00323 ? rutz::shared_ptr<PyramidCache<float> >()
00324 : cache.get() != 0
00325 ? cache
00326 : rutz::shared_ptr<PyramidCache<float> >(new PyramidCache<float>);
00327
00328 result.itsPyrCacheRgb = rutz::shared_ptr<PyramidCache<PixRGB<float> > >();
00329
00330 const int sz = in->getSize();
00331
00332 JobServer& srv = getMainJobServer();
00333
00334 const unsigned int ntiles = srv.getParallelismHint();
00335
00336 LDEBUG("ntiles = %u", ntiles);
00337
00338 std::vector<rutz::shared_ptr<RgbByteToLuminanceJob > > jobs;
00339
00340 for (unsigned int i = 0; i < ntiles; ++i)
00341 {
00342 const int start = (i*sz)/ntiles;
00343 const int end = ((i+1)*sz)/ntiles;
00344
00345 jobs.push_back
00346 (rutz::make_shared(new RgbByteToLuminanceJob
00347 (in->getArrayPtr() + start,
00348 in->getArrayPtr() + end,
00349 result.itsGrayFloat.getArrayPtr() + start)));
00350
00351 srv.enqueueJob(jobs.back());
00352 }
00353
00354 for (size_t i = 0; i < jobs.size(); ++i)
00355 jobs[i]->wait();
00356
00357 return result;
00358 }
00359
00360
00361 const Image<PixRGB<float> >& InputFrame::colorFloat() const
00362 {
00363 if (!itsColorFloat.initialized() && itsColorByte.initialized())
00364 {
00365 itsColorFloat = Image<float>(itsColorByte.getDims(), NO_INIT);
00366
00367 const int sz = itsColorByte.getSize();
00368
00369 JobServer& srv = getMainJobServer();
00370
00371 const unsigned int ntiles = srv.getParallelismHint();
00372
00373 LDEBUG("ntiles = %u", ntiles);
00374
00375 std::vector<rutz::shared_ptr<RgbByteToFloatJob > > jobs;
00376
00377 for (unsigned int i = 0; i < ntiles; ++i)
00378 {
00379 const int start = (i*sz)/ntiles;
00380 const int end = ((i+1)*sz)/ntiles;
00381
00382 jobs.push_back
00383 (rutz::make_shared(new RgbByteToFloatJob
00384 (itsColorByte.getArrayPtr() + start,
00385 itsColorByte.getArrayPtr() + end,
00386 const_cast<PixRGB<float>*>
00387 (itsColorFloat.getArrayPtr() + start))));
00388
00389 srv.enqueueJob(jobs.back());
00390 }
00391
00392 for (size_t i = 0; i < jobs.size(); ++i)
00393 jobs[i]->wait();
00394 }
00395
00396 return itsColorFloat;
00397 }
00398
00399 const rutz::shared_ptr<PyramidCache<float> > InputFrame::emptyCache;
00400
00401
00402
00403
00404
00405
00406
00407 #endif // CHANNELS_INPUTFRAME_C_DEFINED