!7 cmodule WebCamFaceFinder > DynImageSurfaceAndEnabled { transient BufferedImage lastImage; FaceFinderByPictures1 finder; switchable bool overlay; switchable bool useFullFinder; transient ReliableSingleThread rstUpdateImage = dm_rst(this, r updateImage); transient long duration = -1; // ms per recognition transient JLabel lblDuration; start-thread { dm_onFieldChange useFullFinder(r { setField(finder := null); makeFinder() }); dm_onFieldChange duration(r { setText(lblDuration, duration + " ms") }); dm_runInQAndWait(r makeFinder); doEvery(100, rstUpdateImage); } void makeFinder { if (finder == null) setField(finder := unstructFileOpt(ai_faceFinderDir( useFullFinder ? "full-finder.struct" : "smallest-finder-over-95.struct" ))); if (finder == null) setField(finder := defaultFaceFinderByPictures()); } afterVisualize { imageSurface_pixelated(imageSurface); containerAddFirst(buttons, lblDuration = jlabel(), dm_checkBox('overlay), dm_checkBox('useFullFinder)); } void updateImage enter { if (imageSurface == null || !enabled) ret; final BufferedImage img = dm_webCamImage(); temp tempAfterwards(r { lastImage = img }); if (img == null || img == lastImage) ret; long time = sysNow(); FoundImgPlus found = finder.getPlus(RGBImage(img)); setField(duration := sysNow()-time); setSelection(foundImgToRect(found)); if (overlay) { BufferedImage img2 = cloneBufferedImage(img); if (found != null) //fillRect(img2, found.r, Color.white); drawScaledPixelatedImage(img2, toBufferedImage(found.data), found.r); setImage(img2); } else setImage(img); } }