MotionShot Banner

MotionShot

High-Performance Stroboscopic Action Sequence Camera for Android

Status Platform Language UI License

Engineered and maintained by Ahmad Hassan (B-Ted)


## Overview & Vision Human movement is inherently transient. Whether an athlete sprinting, a dancer executing a spin, a gymnast mid-air, or a child jumping, fleeting physical motion unfolds and vanishes within fractions of a second. **MotionShot** bridges high-speed mobile computer vision with human kinetic expression. Inspired by Sony's legacy Motion Shot technology, MotionShot captures dynamic action bursts and synthesizes a single, multi-pose stroboscopic composite image directly on-device in real time. Operating entirely offline with zero cloud latency and zero reliance on heavy AI neural networks, MotionShot renders motion as an aligned visual trajectory: sharp, stabilized, and captured in full sensor resolution.
## Visual Showcase
| Camera Viewfinder | Hardware Sliders | Step 1 Raw Gallery | Composite Result | | :---: | :---: | :---: | :---: | | Viewfinder | Sliders | Raw Gallery | Composite Result |

## Technical Specifications | Parameter | Specification & Range | Engineering Function | | :--- | :--- | :--- | | **Timer Window** | `1s`, `2s`, `5s`, `Custom (1–60s)` | Dynamic sequence capture deadline | | **Frame Count** | `5`, `15`, `25`, `Custom (2–50)` | Trajectory density sampling points | | **Shutter Speed** | `Auto`, `1/30s` to `1/8000s` | Logarithmic hardware motion-freeze slider | | **ISO Sensitivity** | `Auto`, `ISO 50` to `ISO 102,400` | Continuous sensor gain boost | | **Stabilization** | $\pm 16\text{px}$ 2D translation search | Sub-5ms background micro-jitter alignment | | **Blending Engine** | `PorterDuff.Mode.SRC_OVER` | Sequential alpha layer compositing | | **Persistence** | `SharedPreferences` | Automatic parameter restoration across sessions |
## Key Features - **Pixel-to-Pixel Handheld Image Stabilization**: The 2D translation alignment engine (`ImageStabilizer`) correlates background grid pixels across frames, locking static elements in place to eliminate camera shake. - **Normalized Chromaticity Motion Differencing**: Evaluates $r, g$ color space ratios alongside BT.601 luminance separation, making motion detection 100% immune to camera exposure shifts and shadows. - **High Shutter Speed Freeze-Frame Control**: Manual shutter speed control down to `1/8000s` ($125\,\mu\text{s}$ exposure) freezes ultra-fast movement without motion blur. - **Extended ISO Gain Boost**: Manual ISO control scaling up to **ISO 102,400** maintains crisp image brightness even under high shutter speeds in low light. - **Fast Motion Slide & Auto-Play Flipbook Preview**: Interactive touch-drag preview and a `▶ Play` button (15 FPS flipbook) allow instant sequence verification before finalizing. - **Pluggable Engine Architecture**: Decoupled `MotionEngine` interface and `MotionEngineFactory` allow instant engine swapping without modifying UI state logic.
## Architecture Overview MotionShot follows a strict **Contract-Based Clean Architecture**, decoupling UI presentation, state orchestration, image processing algorithms, and Camera2 hardware controls. ```mermaid graph TD subgraph Presentation["Presentation Layer (Jetpack Compose)"] MA[MainActivity] --> CS[CameraScreen] CS --> CP[CameraPreview Viewfinder] CS --> CC[CaptureControls Sheet & Sliders] CS --> RV[Step1ResultView Flipbook Gallery] end subgraph Domain["Domain Contracts & Storage"] VM[MotionShotViewModel] --> |Preferences| PR[PreferencesRepository] VM --> |Pluggable Contract| ME[MotionEngine Interface] end subgraph Engine["Image Processing Realizations"] ME --> FDEM[FastDifferenceMotionEngine] FDEM --> STAB[ImageStabilizer Engine] FDEM --> DIFF[FrameDifferencer Engine] FDEM --> MORPH[MorphologyOps Engine] FDEM --> CCMP[CanvasCompositor Engine] end subgraph Hardware["Hardware Capture Layer (CameraX / Camera2)"] VM --> FA[FrameAnalyzer] FA --> YR[Native C++ YuvToRgb] VM --> C2[Camera2Interop Control] C2 --> CP end ```
## Technical Processing Pipeline Each captured frame sequence moves through a zero-allocation processing pipeline: ```mermaid flowchart TD A["Raw Frame Burst (N Frames)"] --> B["1. 2D Translation Alignment (ImageStabilizer)"] B --> C["2. Normalized Chromaticity Differencing (FrameDifferencer)"] C --> D["3. 3x3 Morphological Opening (MorphologyOps)"] D --> E["4. Soft Contour Edge Feathering"] E --> F["5. Sequence Alpha Decay (CanvasCompositor)"] F --> G["Final Stroboscopic Composite Image"] ```
## Request Lifecycle & Frame Acquisition ```mermaid sequenceDiagram autonumber actor User participant UI as CameraScreen / Controls participant VM as MotionShotViewModel participant Analyzer as FrameAnalyzer participant Engine as MotionEngine User->>UI: Tap Capture Button UI->>VM: onCaptureToggle() VM->>VM: Lock Start Time & Set Hard Deadline (T seconds) loop Dynamic Time Window (T / N-1) VM->>Analyzer: shouldCapture.set(true) Analyzer-->>VM: frameChannel.receive() [Time-Bounded Timeout Guard] end VM->>Engine: process(capturedFrames) Engine->>Engine: 2D Translation Alignment Engine->>Engine: Normalized Chromaticity Masking Engine->>Engine: 3x3 Morphological Noise Removal Engine->>Engine: Native Canvas PorterDuff Stamping Engine-->>VM: Return Composite Bitmap VM->>UI: Phase = Done (Show Result & Interactive Flipbook) ```
## Technical Deep-Dives
1. Handheld 2D Translation Alignment Mathematics
Camera micro-jitter causes static background edges to shift between frames. MotionShot computes an optimal $(\Delta x, \Delta y)$ alignment vector over a $\pm 16\text{px}$ search window using a 4x grid subsampling strategy: $$\Delta x, \Delta y = \arg\min_{dx, dy} \sum_{y, x} \left| \text{Base}(x, y) - \text{Curr}(x + dx, y + dy) \right|$$ Target frame pixels are shifted by $(\Delta x, \Delta y)$ prior to motion differencing, locking static background elements 100% in place.
2. Normalized Chromaticity Color Space (r, g)
Camera auto-exposure shifts brightness across frames. Simple RGB subtraction fails under exposure drift. MotionShot converts pixels to **Normalized Chromaticity**: $$r = \frac{R}{R + G + B + 1}, \quad g = \frac{G}{R + G + B + 1}$$ Combining chromaticity distance $\Delta_{\text{chroma}} = |r_1 - r_0| + |g_1 - g_0|$ with BT.601 luminance separation ($\Delta_Y = |Y_1 - Y_0|$) ensures lighting fluctuations and shadows are 100% ignored.
3. Camera2 Hardware Exposure & ISO Interop
High shutter speeds (1/500s to 1/8000s) eliminate subject motion blur. CameraX parameters are applied directly to the Camera2 HAL via `Camera2CameraControl`: - `CaptureRequest.CONTROL_AE_MODE`: Set to `OFF` for manual exposure control. - `CaptureRequest.SENSOR_EXPOSURE_TIME`: Configured in nanoseconds via logarithmic slider. - `CaptureRequest.SENSOR_SENSITIVITY`: Configured up to ISO 102,400 for low-light gain compensation.

## Repository Structure ```text bted.app.motionshot/ ├── capture/ │ ├── FrameAnalyzer.kt # CameraX ImageAnalysis analyzer │ └── YuvToRgb.kt # Native C++ accelerated ImageProxy to Bitmap ├── data/ │ └── PreferencesRepository.kt # SharedPreferences persistence (Timer, Count, Shutter, ISO) ├── engine/ │ ├── MotionEngine.kt # Pluggable engine interface contract │ ├── FastDifferenceMotionEngine.kt # Math & Differencing engine │ ├── MotionEngineFactory.kt # Engine registry & factory │ └── DebugPipelineConfig.kt # Step-by-step pipeline config ├── processing/ │ ├── FrameDifferencer.kt # Normalized chromaticity & luminance differencer │ ├── ImageStabilizer.kt # Pixel-to-pixel 2D handheld stabilizer │ ├── MorphologyOps.kt # 3x3 Erode, Dilate, and Morphological Opening │ └── CanvasCompositor.kt # Native Canvas PorterDuff compositing ├── ui/ │ ├── components/ │ │ ├── CaptureControls.kt # Sliders, custom input, tap-to-record button │ │ └── LoadingOverlay.kt # Pulsing progress overlay │ ├── state/ │ │ ├── MotionShotUiState.kt # UI state holder & CameraParameterUtils │ │ └── CapturePhase.kt # Capture phase lifecycle │ ├── theme/ # Dark aesthetic color, typography, theme │ ├── CameraPreview.kt # CameraX preview + Camera2Interop hardware controls │ └── CameraScreen.kt # Root camera & result flipbook gallery screen └── viewmodel/ └── MotionShotViewModel.kt # StateFlow, preferences, capture loop, engine dispatcher ```
## Building & Requirements ### System Requirements - **Android Studio**: Ladybug / Jellyfish or newer - **Android SDK**: Compile SDK 37 (Min SDK 24) - **Kotlin**: 2.2.10 - **Gradle**: 8.13+ ### Local Build Commands ```bash # Clone the repository git clone https://github.com/AhmadHassan-BTed/MotionShot.git cd MotionShot # Execute unit tests ./gradlew test # Build Debug APK ./gradlew assembleDebug ```

Engineered and maintained by Ahmad Hassan (B-Ted)