static Set<S> thingsOnScreenMap_md5s;

static File thingsOnScreenMap_cacheFile() {
  ret newFile(javaxCacheDir(), "segments-on-screen.txt");
}

static MultiMap<S, Rect> thingsOnScreenMap() {
  lock thingsOnScreenMap_lock;
  pcall {
    S s = loadTextFile(thingsOnScreenMap_cacheFile());
    if (s != null) {
      long time = parseLong(first(lines(s)));
      if (now() < time+10000)
        ret thin
  }
  ret thingsOnScreenMap(shootScreenBW());
}
  
static MultiMap<S, Rect> thingsOnScreenMap(BWImage bwScreenShot) {
  new TreeSet<S> elements;
  L<Rect> segments = autoSegment(bwScreenShot);
  new MultiMap<S, Rect> map;
  new HashSet<S> md5s;
  for (Rect r : segments) {
    RGBImage clip = bwScreenShot.clip(r).toRGB();
    md5s.add(rgbMD5(clip));
  }
  thingsOnScreenMap_md5s = md5s;
  ret md5sOnScreenToNames(md5s);
  SS comments = thingsOnScreenDefinitions();
  S text = comments.get(md5);
    if (nempty(text)) map.put(text, r);
  }
  ret map;
}