fix: correct preprocessing scale semantics for MiewID and detector path#11
Merged
JasonWildMe merged 3 commits intowildlife-reidfrom Apr 24, 2026
Merged
Conversation
`scale` in DetectorConfig.normalize is documented as a multiplier (e.g. 1/255) per docs/EMBEDDING_PACK_FORMAT.md, but native code on both platforms divided by it instead, and the MiewID TS wrapper hardcoded scale=1.0 — so a spec-compliant pack would feed pixel*255 into normalization, and MiewID got 0-255 values fed into ImageNet mean/std that expects 0-1. - ImageTensorModule.kt + ImageTensorModule.swift: divide → multiply - preprocessing.ts: MiewID embedding wrapper passes 1/255 (was 1.0) - Updated existing native tests to encode the multiplier convention - Added a cross-platform golden parity fixture (1×1 pure-red pixel through ImageNet norm + scale=1/255) asserting identical numerical output (R≈2.249, G≈-2.036, B≈-1.804) in Kotlin and Swift - Pre-commit: skip iOS tests when xcodebuild is unavailable (mirrors the existing SwiftLint-missing pattern); macOS CI still runs them before merge Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The wildlife re-ID fork lives on the long-lived `wildlife-reid` integration branch, but CI only fired for main. PRs against wildlife-reid (including #11) showed no status checks, blocking the Gemini / Codecov / SonarCloud review loop defined in CLAUDE.md. Adding wildlife-reid alongside main in both trigger filters so the integration branch gets the same quality gates as main. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
JasonWildMe
added a commit
that referenced
this pull request
Apr 24, 2026
The wildlife re-ID fork lives on the long-lived `wildlife-reid` integration branch, but CI only fired for main. PRs against wildlife-reid (including #11) showed no status checks, blocking the Gemini / Codecov / SonarCloud review loop defined in CLAUDE.md. Adding wildlife-reid alongside main in both trigger filters so the integration branch gets the same quality gates as main. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Author
|
Reopening to re-trigger CI once wildlife-reid has the workflow branch filter. |
Follow-up to the Stage 0 scale semantics fix — codex 5.5 deep review and first CI run surfaced two remaining issues: 1. DEFAULT_DETECTOR_CONFIG fallback in useCaptureFlow still had the pre-fix `scale: 255` (divisor convention). With the now-corrected native multiplier math, the fallback would have produced pixel*255, identical to the bug we just fixed for MiewID. Updated to `1/255` in both the production default and the integration test fixture at pipelineFlow.test.ts. 2. src/screens/MatchReviewScreen.tsx was a 23-line stub superseded long ago by the MatchReviewScreen/ directory form, but the stub was never removed from git. Node module resolution prefers file-over-directory, so Jest in CI resolved the test's import to the stub and all 19 MatchReviewScreen tests failed (no testIDs on the stub). Works locally because the working tree had the file deleted-but-not-committed. Dropping the stub. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Author
|
/gemini review |
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.
Summary
DetectorConfig.normalize.scaleis documented as a multiplier (e.g.1/255) indocs/EMBEDDING_PACK_FORMAT.md, but the nativeImageTensorModuleon both platforms divided by it. A spec-compliant pack would have producedpixel × 255going into normalization — wildly out of range.scale = 1.0, so even if the native math had been right, MiewID got 0–255 values fed into ImageNetmean/stdthat expects 0–1. Embeddings were silently garbage.scale = 1/255) that asserts identical numerical output —R≈2.249, G≈-2.036, B≈-1.804— in both Kotlin and Swift. If either native module drifts, both fail loudly with matching messages.xcodebuildis unavailable on the host (mirroring the existing SwiftLint-missing pattern). macOS CI still runs them before merge.Type of Change
Why this matters
This is the foundational fix for the on-device MiewID re-ID pipeline. Without it, every embedding extracted on device would be unusable, every cosine match meaningless, and every downstream stage of the integration plan would be tuning on noise. Catching this before MiewID is wired (rather than after, while debugging zero-rank matches) saves significant downstream work.
Files Changed
src/services/onnxInferenceService/preprocessing.tsscale: 1.0→1.0/255.0__tests__/unit/services/onnxInferenceService.test.ts1.0/255.0android/.../imagetensor/ImageTensorModule.kt(pixel / scale - mean) / std→(pixel * scale - mean) / stdandroid/.../imagetensor/ImageTensorModuleTest.ktios/ImageTensorModule.swiftios/OffgridMobileTests/OffgridMobileTests.swift.husky/pre-commitxcodebuildis unavailable (with warning)Test plan
npx tsc --noEmitcleannpx jest— 410/410 tests pass./gradlew :app:testDebugUnitTest --tests ImageTensorModuleTest— 11/11 tests pass on Android