!7 // uses only one prototype image // goes through different granularities at once cmodule ImageRecogSpike { switchable S prototypeImageID = #1102884; switchable S inputImageID = #1102883; switchable bool showResizedProtos; switchable int numberOfCandidatesToShow = 3; // how big do we think the prototype is in the whole image // (percentage by height) transient double assumedPrototypeHeightPercentage = 70; transient L widths = ll(1, 2, 4, 8, 16, 32, 64, 128); transient new L integralImages; transient BWIntegralImage baseImage; transient JTabbedPane tabs = jTabbedPane(); transient BWImage prototypeImage; transient new L levels; // recognizers for each granularity class OneLevel extends SteppableAndBest { IBWIntegralImage ii; // scaled integral image BWImage image; // scaled image BWImage prototype; // scaled prototype float minSimilarity = 0.5f; ImageSurface is; new Map allScores; // candidates are top-left corner of rect to try in our coordinates L candidatesQueue = syncLinkedList(); new Set candidatesTried; Iterator candidatesStream; *(IBWIntegralImage *ii) { image = iBWIntegralImageToBWImage(ii); // get assumed height of prototype in scaled-down image int ph = iround(ii.getHeight()*assumedPrototypeHeightPercentage/100.0); // resize prototype prototype = bwResizeToHeightSmooth(prototypeImage, ph); if (showResizedProtos) addTab(tabs, "proto " + ii.getWidth(), jFullCenterScroll(jPixelatedZoomedImageSurface(4.0, prototype))); candidatesStream = mapI rectTopLeftCorner(allSubRectsOfSizeIterator(prototype.getWidth(), prototype.getHeight(), imageRect(image))); } public bool step() { Pt p = nextCandidate(); if (p != null) ret true with tryCandidate(p); false; } Pt nextCandidate() { try object Pt p = popFirst(candidatesQueue); ret nextFromIterator(candidatesStream); } void tryCandidate(Pt p) { if (!candidatesTried.add(p)) ret; int x = p.x, y = p.y, wp = prototype.getWidth(), hp = prototype.getHeight(); float maxError = (1f-minSimilarity)*wp*hp; float diff = bwImageSectionsSimilarity(image, prototype, x, y, maxError); if (diff <= maxError) putInBestAndMap(best, allScores, new Rect(x, y, wp, hp), 1-diff/(wp*hp); } void showBest() { overlaySelectionsOnImageSurface(is, topTenKeysByValue(numberOfCandidatesToShow, allScores)); } } start-thread { dm_watchField numberOfCandidatesToShow(r showBest); if (baseImage == null) baseImage = BWIntegralImage(loadImage2(inputImageID)); if (prototypeImage == null) prototypeImage = loadBWImage(prototypeImageID); for (int w : widths) { IBWIntegralImage ii = scaledIBWIntegralImage(baseImage, w); integralImages.add(ii); ImageSurface is = jPixelatedZoomedImageSurface( doubleRatio(baseImage.getWidth(), w), iBWIntegralImageToBWImage(ii)); addTab(tabs, "w=" + w, jFullCenterScroll(is)); levels.add(setAll(new OneLevel(ii), +is)); } addTab(tabs, "Prototype", jFullCenterScroll(jPixelatedZoomedImageSurface(4, prototypeImage))); time "Process" { print("Steps: " + stepAll_roundRobin(levels)); } showBest(); } void showBest { for (OneLevel l : levels) l.showBest(); } visual withCenteredButtons(tabs, withLabel("# of candidates to show:", dm_fieldSpinner numberOfCandidatesToShow(1, 100))); }