37 #define WEIGHT_SCALEBITS ((env_size_t) 8)
41 const struct env_image * JEVOIS_UNUSED_PARAM(center),
42 const struct env_image * JEVOIS_UNUSED_PARAM(surround),
void * vdata)
57 if (tagName[2] ==
'd') { offset = 0; bitshift = 6; }
58 else { offset = (std::atoi(tagName + 10) + 6) * onechan; bitshift = 4; }
60 case 'b': offset = onechan; bitshift = 6;
break;
61 case 'i': offset = 2 * onechan; bitshift = 7;
break;
62 case 's': offset = (std::atoi(tagName + 10) + 2) * onechan; bitshift = 0;
break;
63 case 'f': offset = 7 * onechan; bitshift = 5;
break;
64 default:
LFATAL(
"Unknown channel " << tagName);
72 if (offset + 16 > vd->
gist_size)
LFATAL(
"gist offset " << offset <<
" out of range");
82 jevois::Component(instance), gist_size(72 * 16), itsProfiler(
"Saliency", 100, LOG_DEBUG), itsInputDone(true)
88 env_img_init_empty(&prev_input);
102 itsVisitorData.
envp = &envp;
117 if (!env_img_initialized(chanOut))
return;
119 intg32*
const sptr = env_img_pixelsw(chanOut);
123 std::lock_guard<std::mutex> _(itsMtx);
125 if (!env_img_initialized(
result))
148 #define SALUPDATE(envval, param) \
149 prev = envp.envval; envp.envval = saliency::param::get(); if (envp.envval != prev) nuke = true;
152 void Saliency::processStart(
struct env_dims const &
dims,
bool do_gist)
156 std::unique_lock<std::mutex> ulck(itsRawImageMtx);
157 itsInputDone =
false;
160 bool nuke =
false;
size_t prev;
201 if (env_img_initialized(&prev_input) && (prev_input.
dims.
w !=
dims.
w || prev_input.
dims.
h !=
dims.
h)) nuke =
true;
219 std::unique_lock<std::mutex> ulck(itsRawImageMtx);
220 if (itsInputDone)
return;
221 itsRawImageCond.wait(ulck, [&]() {
return itsInputDone; } );
228 static void * statdata =
nullptr;
233 processStart(dims, do_gist);
262 std::future<void> colorfut;
274 itsInputDone =
true; itsRawImageCond.notify_all();
281 std::future<void> motfut;
284 env_mt_motion_channel_input(&motion_chan,
"motion", bwimg.
dims, &lowpass5, statfunc, statdata, &
motion);
288 std::future<void> orifut;
291 env_mt_chan_orientation(
"orientation", &bwimg, statfunc, statdata, &
ori);
295 std::future<void> flickfut;
326 if (statfunc) (*statfunc)(statdata,
"saliency", &
salmap);
344 static void * statdata =
nullptr;
349 processStart(dims, do_gist);
353 const intg32 lumthresh = (3*255) / 10;
358 int const nthreads = 4;
359 int hh =
dims.
h / nthreads;
360 std::vector<std::future<void> > rgbyfut;
361 unsigned char const * inpix = input.
pixels<
unsigned char>();
362 intg32 * rgpix = env_img_pixelsw(&rgimg);
363 intg32 * bypix = env_img_pixelsw(&byimg);
364 intg32 * bwpix = env_img_pixelsw(&bwimg);
365 for (
int i = 0; i < nthreads-1; ++i)
367 int offset = dims.w * hh * ii;
368 convertYUYVtoRGBYL(dims.w, hh, inpix + offset*2, rgpix + offset, bypix + offset, bwpix + offset,
369 lumthresh, imath.nbits);
373 int offset =
dims.
w * hh * (nthreads - 1);
375 bwpix + offset, lumthresh, imath.
nbits);
384 std::future<void> rgfut, byfut;
388 for (
auto & f : rgbyfut) f.get();
393 itsInputDone =
true; itsRawImageCond.notify_all();
422 std::future<void> motfut;
425 env_mt_motion_channel_input(&motion_chan,
"motion", bwimg.
dims, &lowpass5, statfunc, statdata, &
motion);
429 std::future<void> orifut;
432 env_mt_chan_orientation(
"orientation", &bwimg, statfunc, statdata, &
ori);
436 std::future<void> flickfut;
460 if (rgfut.valid()) rgfut.get();
468 const intg32 *
const byptr = env_img_pixels(&byOut);
471 for (
env_size_t i = 0; i < sz; ++i) dptr[i] = (dptr[i] + byptr[i]) >> 1;
475 if (statfunc) (*statfunc)(statdata,
"color", &
color);
483 if (orifut.valid()) orifut.get();
486 if (flickfut.valid()) flickfut.get();
489 if (motfut.valid()) motfut.get();
495 if (statfunc) (*statfunc)(statdata,
"saliency", &
salmap);
511 void Saliency::env_mt_chan_orientation(
const char* tagName,
const struct env_image* img,
524 's',
't',
'e',
'e',
'r',
'a',
'b',
'l',
'e',
526 '/',
'_',
'_',
')',
'\0'
534 std::vector<std::future<void> > fut;
538 struct env_image chanOut; env_img_init_empty(&chanOut);
540 char tagname[17]; memcpy(tagname, buf, 17);
541 tagname[10] =
'0' + ((ii+1) / 10);
542 tagname[11] =
'0' + ((ii+1) % 10);
549 status_func, status_userdata, &chanOut);
552 std::lock_guard<std::mutex> _(mtx);
553 if (!env_img_initialized(
result))
569 for (std::future<void> & f : fut) f.get();
573 if (env_img_initialized(
result))
576 if (status_func) (*status_func)(status_userdata, tagName,
result);
580 void Saliency::env_mt_motion_channel_input(
struct env_motion_channel* chan,
const char* tagName,
597 'r',
'e',
'i',
'c',
'h',
'a',
'r',
'd',
't',
599 '/',
'_',
'_',
')',
'\0'
608 std::vector<std::future<void> > fut;
612 struct env_image chanOut; env_img_init_empty(&chanOut);
614 char tagname[17]; memcpy(tagname, buf, 17);
615 tagname[10] =
'0' + ((d+1) / 10);
616 tagname[11] =
'0' + ((d+1) % 10);
637 &chan->
shifted_prev[d], &shiftedCur, status_func, status_userdata, &chanOut);
643 std::lock_guard<std::mutex> _(mtx);
644 if (env_img_initialized(&chanOut))
646 if (!env_img_initialized(
result))
663 for (std::future<void> & f : fut) f.get();
665 if (env_img_initialized(
result))
668 if (status_func) (*status_func)(status_userdata, tagName,
result);
674 if (env_img_initialized(&
salmap) ==
false)
LFATAL(
"Saliency map has not yet been computed");
680 for (
int j = 0; j < smh; ++j)
681 for (
int i = 0; i < smw; ++i)
682 if (*sm >
value) {
value = *sm++; x = i; y = j; }
else ++sm;
688 if (env_img_initialized(&
salmap) ==
false)
LFATAL(
"Saliency map has not yet been computed");
691 float const sigsq = sigma * sigma;
693 for (
int j = 0; j < smh; ++j)
694 for (
int i = 0; i < smw; ++i)
696 float const distsq = (i-x)*(i-x) + (j-y)*(j-y);
702 val *= 1.0F - expf( -0.5
F * (distsq - sigsq ) / sigsq);
703 *sm++ =
static_cast<intg32>(val + 0.4999F);
712 unsigned int const imgw = img.
width;
713 unsigned short * d = img.
pixelsw<
unsigned short>() + xoff + yoff * imgw;
720 unsigned short const * dd = d;
726 unsigned short const val = 0x8000 | v;
727 for (
env_size_t k = 0; k < scale; ++k) *d++ = val;
732 for (
env_size_t k = 1; k < scale; ++k) { memcpy(d, dd, ws * 2); d += imgw; }
741 unsigned int scale,
unsigned int bitshift)
743 unsigned int const imgw = img.
width;
744 unsigned short * d = img.
pixelsw<
unsigned short>() + xoff + yoff * imgw;
751 unsigned short const * dd = d;
756 intg32 v = (*s++) >> bitshift;
if (v > 255) v = 255;
757 unsigned short const val = 0x8000 | v;
758 for (
env_size_t k = 0; k < scale; ++k) *d++ = val;
763 for (
env_size_t k = 1; k < scale; ++k) { memcpy(d, dd, ws * 2); d += imgw; }
772 unsigned int yoff,
unsigned int width,
unsigned int scale)
774 unsigned int const height = gistsize / width;
775 unsigned int const imgw = img.
width;
776 unsigned short * d = img.
pixelsw<
unsigned short>() + xoff + yoff * imgw;
777 unsigned char const *
const dataend = gist + gistsize;
778 unsigned int const ws = width * scale;
782 unsigned short const * dd = d;
787 intg32 v = gist >= dataend ? 0 : *gist++;
788 unsigned short const val = 0x8000 | v;
789 for (
env_size_t k = 0; k < scale; ++k) *d++ = val;
794 for (
env_size_t k = 1; k < scale; ++k) { memcpy(d, dd, ws * 2); d += imgw; }