DogDetector is an iOS SwiftUI app that fetches dog images, runs pose detection, and renders highlighted detections with keypoints. Demo Video here: https://www.youtube.com/shorts/zKRpOKIQS7Q
- iOS 18+
- Uses a YOLO pose estimation model trained for dogs (
dog_pose_model.mlmodel). - Dog-pose setup follows the Ultralytics Dog-Pose dataset conventions (24 keypoints, dog class).
- Reference: https://docs.ultralytics.com/datasets/pose/dog-pose/#introduction
- SwiftUI for UI
- Apple Vision (
CoreMLRequest) for model inference - CoreML for running the YOLO pose model
- CoreImage/CoreGraphics (
CGImage) for rendering overlays and effects
- Image enters the system as a
CGImage. DogDetectionServiceruns Vision + CoreML with.scaleFit.- Model output is decoded from tensor shape
[1, 300, 78]:- per-detection box + score + keypoints
- Coordinates are mapped from model-input space back to original image space.
- Results are converted to normalized coordinates for drawing.
- Image transforms are done in
CGImagespace to reduce conversion overhead. - Rendering operations (
lensHighlightRegions, keypoint drawing) use CoreImage/CoreGraphics directly. - Shared
CIContextis reused for frame/image conversions. DogViewModelusesNSCache(count + memory cost limits) to avoid unbounded image memory growth.
- Fetches random dog images from Dog API.
- Toggle to enable/disable detection overlays.
- Lazy list paging to load more images as user scrolls.
- Full-screen camera preview for real-time model testing.
- Runs detection per frame through
DogDetectionService. - Applies a One Euro filter to smooth box/keypoint jitter frame-to-frame.
- Useful for validating model behavior under live framerate constraints.
The app uses a small service-oriented networking layer:
Endpointprotocol defines path/method/query/body contract.NetworkClientbuilds and executes typed async requests and decodes JSON generically.DogServiceowns Dog API-specific endpoint(s) and maps response payloads to app models.DogDetectionServiceis dedicated to inference and decode logic, separated from UI/view model code.
This separation keeps API access, ML inference, and UI state management independent and easier to maintain.
- Detection path uses throwing async flow.
- UI surfaces service/network failures through
DogViewModel.errorMessageand a SwiftUI alert.