Uses 108K of libraries. Click here for Pure Java version (10828L/76K).
// complexity is number of assumed heights * number of widths sclass MultiLevelRecognizer2 { // how big do we think the prototype is in the whole image // (percentage by height) transient L<Double> assumedPrototypeHeightPercentages = ll(70.0, 70.0/sqrt(2), 35.0, 35.0/sqrt(2), 17.0); // widths to scale camera image to transient L<Int> widths = ll(32, 64, 128); transient JTabbedPane tabs; // initialize if you want visualization transient ImageSurface bestImageSurface; transient JLabel bestLabel; transient BWIntegralImage baseImage; transient new L<BWIntegralImage> prototypeImages; transient new Map<Int, IBWIntegralImage> integralImages; // key = width transient new L<Chain> chains; // one per assumed height & prototype // chain of recognizers for one assumed height class Chain { BWIntegralImage prototypeImage; double assumedHeightPercentage; new L<OneLevel> levels; // recognizers for each granularity new Map<Int, BWImage> scaledPrototypeImages; // key = height *(double *assumedHeightPercentage, BWIntegralImage *prototypeImage) { make(); } void make { for (int w : widths) { IBWIntegralImage ii = mapGetOrCreate(integralImages, w, () -> scaledIBWIntegralImage(baseImage, w)); OneLevel lvl = new(this, last(levels), ii); levels.add(lvl); if (tabs != null && eq(w, last(widths))) { lvl.is = jPixelatedZoomedImageSurface( doubleRatio(baseImage.getWidth(), w), iBWIntegralImageToBWImage(ii)); addTab(tabs, iround(assumedHeightPercentage) + ":" + w, northAndCenterWithMargins( lvl.infoLabel = jcenteredlabel(), jFullCenterScroll(lvl.is))); } } } void reset { for (OneLevel l : levels) l.reset(); } Steppable makeSteppable() { ret iteratorToSteppable(roundRobinCombinedIterator(lambdaMap steppableToIterator(levels))); } Scored<Rect> bestResult() { ret last(levels).scoredBestRescaled(); } } class OneLevel extends SteppableAndBest<Rect> { Chain chain; OneLevel previous, next; IBWIntegralImage ii; // scaled integral image BWImage image; // scaled image BWImage prototype; // scaled prototype float minSimilarity = 0.5f; ImageSurface is; JLabel infoLabel; // candidates are top-left corner of rect to try in our coordinates L<Pt> candidatesQueue = syncLinkedList(); new Set<Pt> candidatesTried; Iterator<Pt> candidatesStream; *(Chain *chain, OneLevel *previous, IBWIntegralImage *ii) { if (previous != null) previous.next = this; image = iBWIntegralImageToBWImage(ii); // get assumed height of prototype in scaled-down image int ph = iround(ii.getHeight()*chain.assumedHeightPercentage/100.0); // resize prototype prototype = mapGetOrCreate(chain.scaledPrototypeImages, ph, () -> scaleDownUsingIntegralImageBW(chain.prototypeImage, ph); /*addTab(tabs, "proto " + ii.getWidth(), jFullCenterScroll(jPixelatedZoomedImageSurface(4.0, prototype))); */ reset(); } void reset { candidatesTried.clear(); candidatesStream = fullStream(); } // all candidates Iterator<Pt> fullStream() { ret allSubRectsOfSizeIterator_topLeftCorners(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) best.put(new Rect(x, y, wp, hp), 1-diff/(wp*hp)); } void showBest() { setImageSurfaceSelection(is, best!); setText(infoLabel, best); } // best rect in original image coordinates Rect bestRescaled() { ret rescaleRect(best!, ii.getWidth(), ii.getHeight(), baseImage.getWidth(), baseImage.getHeight()); } Scored<Rect> scoredBestRescaled() { ret scored(bestRescaled(), best.score); } } *() {} *(File imgFile) { baseImage = loadBWIntegralImage(imgFile); } void addPrototype(BufferedImage img) { prototypeImages.add(bwIntegralImage(img)); } void addPrototype(File imgFile) { addPrototype(loadImage2(imgFile)); } void addPrototypes(Iterable<BufferedImage> l) { fOr (BufferedImage img : l) addPrototype(img); } Scored<Rect> go() { if (empty(chains)) { assertNotNull(+baseImage); assertNempty(+prototypeImages); if (tabs != null) addTab(tabs, "Best", northAndCenterWithMargins( bestLabel = jcenteredlabel(), jFullCenterScroll(bestImageSurface = jImageSurface(bwIntegralImageToBWImage(baseImage))))); makeChains(); } else reset(); time "Process" { print("Steps: " + stepAll_roundRobin(map(chains, c -> c.makeSteppable()))); } showBest(); ret bestResult(); } void showBest { for (Chain c : chains) for (OneLevel l : c.levels) l.showBest(); setText(bestLabel, bestResult()); setImageSurfaceSelection(bestImageSurface, bestResult()!); } void makeChains { chains.clear(); for (double ah : assumedPrototypeHeightPercentages) for (BWIntegralImage proto : prototypeImages) chains.add(new Chain(ah, proto)); } Scored<Rect> bestResult() { ret bestScored(map(methodLambda0 bestResult, chains)); } void reset { for (Chain c : chains) c.reset(); } }
download show line numbers debug dex old transpilations
Travelled to 7 computer(s): bhatertpkbcr, mqqgnosmbjvj, pyentgdyhuwx, pzhvpgtvlbxg, tvejysmllsmz, vouqrxazstgt, xrpafgyirdlv
No comments. add comment
Snippet ID: | #1027247 |
Snippet name: | MultiLevelRecognizer2 - finds multiple prototype images |
Eternal ID of this version: | #1027247/21 |
Text MD5: | 62585171456f4f4485b719caf910587a |
Transpilation MD5: | d796895d36c2cd115c37b580cbd9a70b |
Author: | stefan |
Category: | |
Type: | JavaX fragment (include) |
Public (visible to everyone): | Yes |
Archived (hidden from active list): | No |
Created/modified: | 2020-02-28 15:55:31 |
Source code size: | 6141 bytes / 197 lines |
Pitched / IR pitched: | No / No |
Views / Downloads: | 254 / 666 |
Version history: | 20 change(s) |
Referenced in: | #1034167 - Standard Classes + Interfaces (LIVE, continuation of #1003674) |