!7 cmodule WebCamFaceFinder > DynImageSurfaceAndEnabled { transient BufferedImage lastImage; FaceFinderByPictures1 finder; switchable bool overlay; switchable bool useFullFinder; switchable bool withNoFace = true; transient ReliableSingleThread rstUpdateImage = dm_rst(this, r updateImage); transient long duration = -1; // ms per recognition transient JLabel lblInfo; start-thread { dm_onFieldChange useFullFinder(r makeFinder); dm_onFieldChange withNoFace(r makeFinder); dm_runInQAndWait(r makeFinder); doEvery(100, rstUpdateImage); } void makeFinder { FaceFinderByPictures1 finder; File f = newFile(withNoFace ? ai_faceFinderDir("with-no-face") : ai_faceFinderDir(), useFullFinder ? "full-finder.struct" : "smallest-finder-over-95.struct"); finder = (FaceFinderByPictures1) unstructFileOpt(f); if (finder != null) print("Made finder: " + f); else { finder = defaultFaceFinderByPictures(); print("Using default finder"); } setField(+finder); } afterVisualize { imageSurface_pixelated(imageSurface); containerAddFirst(buttons, lblInfo = jlabel(), dm_checkBox('overlay), dm_checkBox('useFullFinder), dm_checkBox('withNoFace)); } void updateImage enter { if (imageSurface == null || !enabled) ret; final BufferedImage img = dm_webCamImage(); temp tempAfterwards(r { lastImage = img }); if (img == null || img == lastImage) ret; RGBImage rgb = RGBImage(img); long time = sysNow(); FoundImgPlus found = finder.getPlus(rgb); setField(duration := sysNow()-time); setText(lblInfo, duration + " ms. Score: " + formatIntPercent_99(toIntPercent(foundImgScore(found)))); 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); } }