Repository navigation
Add the tiled setting to detectFaces (contracts 0.3) - #21
Open
06pratyush wants to merge 2 commits into
Open
06pratyush wants to merge 2 commits into
06pratyush wants to merge 2 commits into
Conversation
The eval page now runs part B's tiled setting (docs/contracts.md, section 1:
tiling { kind: 'tiles', longSide, overlap }). The photo is shrunk so its
long side is at most longSide, never enlarged; cut into 640 px tiles that
start every round(640 x (1 - overlap)) px, the last one moved back to end
at the edge; YuNet runs on each tile; and one NMS runs over the boxes of
all tiles, in the shrunk image's pixels, before the score filter, so the
runner can still filter its boxes at any threshold afterwards.
letterbox() is now resizeArea() plus tile(), which the tiled setting
shares; the single setting's input is unchanged, and its OpenCV test still
passes in all three browsers. tests/reference/opencv_yunet_tiles.py,
written from a description of the setting without this code, gives the
boxes the new eval-page test compares: all 38 match within 0.0011 px in
Chromium.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- The shrunk size is now tiledSize(), unit-tested for portrait and landscape photos, rounding and never enlarging; no test reached the never-enlarge rule before, and the portrait golden photo hid taking the height as the long side. An eval-page test checks that the photo drawn at 750 x 1000 gives the same boxes with longSide 1000 and 4000. - docs/contracts.md 0.3: section 1 says where the tiles lie, and that boxes from different tiles merge only when they overlap by more than nmsIoU, so a face no tile holds whole can come back as several boxes. The comment in detect.ts said such a face was "kept once"; a unit test now keeps a cut view at IoU 0.3. - Unknown tiling kinds and overlaps that put tiles under 1 px apart are refused before any work; the full-size pixels are no longer kept during the model runs; the shrunk planes are bytes. - resizeArea's comment and tests/README.md say where it differs from INTER_AREA: exact halves, which it rounds up. Unit tests now cover its rounding and portrait letterboxing; the eval-page tests type their options. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Stacked on #20 (the eval page): merge that first. With this,
eval/run_detect.py --tiles 1920,0.25runs instead of stopping atdetectFaces, so part B can compare the single and tiled settings for YuNet.What it does
detectFaceswithtiling: { kind: "tiles", longSide, overlap }:longSide(tiledSize()), by the same area averaging as the single setting, and never enlarges it;A 4000 × 3000 photo becomes 1920 × 1440 and 12 tiles. An Open Images copy of at most 1,024 px is not shrunk and gives at most 4.
letterbox()is nowresizeArea()plustile(), which the tiled setting shares. The single setting's input is bit for bit what it was.docs/contracts.mdgoes to 0.3: section 1 now says where the tiles lie and how their boxes merge. A contract change needs both of us, so approving this PR approves that too.Tests
tiledSize()for portrait, landscape, rounding and never enlarging;tile()'s padding, rounding inresizeArea(), and portrait letterboxing;tests/reference/opencv_yunet_tiles.pyruns OpenCV's FaceDetectorYN on each tile and merges the boxes with one NMS.longSide1000 and 4000. Most part-B images take this path, which the 4,000 px golden photo cannot reach.The full suite passes in Chromium, Firefox and WebKit.
Checked before opening
/code-review, then four more agents: one on conformance with the contract and protocol, one mutation-testing in its own worktree, one on memory and time, and a skeptic for each finding. Fixed in the second commit:tiledSize(), unit-tested on both shapes, and the eval-page test above covers never enlarging. One mistake no test catches: swapping the x and y scales in the final mapping. The test photo's two scales are both exactly 0.48. At 2048 × 1365 the swap would move boxes by under 0.4 px.nmsIoU. The comment and the contract now say so, and a unit test keeps a cut view of a face as a box of its own at IoU 0.3.resizeArea()matches OpenCV's INTER_AREA except where an average falls exactly halfway. It rounds those up, while OpenCV's float32 sums land on either side.tests/README.mdnow say this rather than implying an exact match.Left as they are: the resize's float intermediate (69 MB for a 12 MP photo in this setting) and a new tensor per tile. Both matter only if the app or the bench page runs this setting on phones.
For Shashwat
Tile layout in the protocol. Part B says the tiles "overlap by 25%" but not where they start. The contract now does. Part B and the paper could say "cut into 640 px tiles that start every 480 px, the last in each row and column moved back to end at the image's edge".
Faces larger than the overlap. With tiles alone, a face more than 160 px across at the 1,920 px scale (a twelfth of the long side) may lie whole in no tile, and one more than 640 px (a third) never does. The test photo shows what that does.
The face-size breakdown will show what this costs across the set. A setting that keeps the gain on small faces without this loss would be tiles plus the whole image, merged by the same NMS. That would be one more
Tilingkind, so a contract change.Speed. A 12 MP photo takes 12 model runs in this setting, against 1 in the single setting. Measured in Node on my desktop, that is about 0.7 s against 0.13 s per photo; part D will measure the browsers.
🤖 Generated with Claude Code