An intelligent, cross-platform .NET 10 desktop application designed to automatically detect, straighten, and extract multiple photos from a single scanner bed image. Built with Avalonia UI and Emgu.CV (OpenCV).
The solution consists of three main projects:
PhotoCropper(Core Library): Contains the core image-processing and detection logic, encapsulated inside the robustPhotoCropperEngineclass.PhotoCropperGui(Avalonia Desktop App): A high-performance GUI using a modern dark theme and custom-drawn interactive canvas widgets.PhotoCropper.Tests(xUnit Test Suite): Comprehensive unit tests checking algorithm correctness, boundary constraints, and edge cases.
- Direct Pointer-to-Bitmap Transfer: Replaced slow PNG/JPEG encoding and decoding with direct memory copies. By constructing Avalonia
Bitmapinstances using native pointers (IntPtr) and theBgra8888pixel format, the application renders high-DPI scanner scans instantly without UI lag. - Unified BGR Color Management: Standardized internally on OpenCV's native BGR layout. The UI performs a single
Bgr2Bgraconversion purely for display, avoiding redundant color conversions and correcting the "blue-tint" saving artifact perfectly.
- 8-Point Median Background Profiling: Rejects corner-photo anomalies by sampling HSV values at 8 distinct points around the scan perimeter (corners and edge centers) to compute median saturation, hue, and brightness.
- Resolution-Aware Morphology: Morphological opening and closing kernels dynamically scale according to the scan's resolution, ensuring identical edge-detection performance whether processing 150 DPI or 1200 DPI scans.
- Adaptive Shadow Tolerance: Brightness thresholds are scaled dynamically for light backgrounds, allowing the engine to absorb scanner lid gradients and shadows while preserving photo integrity.
- Convex Hull Overlap Verification: Rather than checking basic axis-aligned bounding rectangles, the engine uses OpenCV's convex hull polygon testing (
PointPolygonTest) to separate tilted adjacent photos. - Interactive Background Color Picker: Allows manual background sampling via a noise-resistant 5x5 average neighborhood in HSV space directly from any clicked zoom/pan pixel, giving the user control when scanner grain or irregular gradients confound the auto-detector.
- Interactive Refinement Mode: Shrink-wraps the crop box around physical photos using an adaptive border-trimming algorithm. It automatically detects and removes the scanner's white canvas borders.
- Local ROI Rotation: Instead of rotating the entire giant scan, only the region of interest is padded, extracted, rotated, and tightly cropped using Cubic interpolation, saving substantial memory and processing overhead.
- Global Key Event Tunneling: Uses Avalonia's tunneling event routing (
RoutingStrategies.Tunnel) for key-down events. This intercepts keyboard navigation events at the Window level before they can reach child controls. - Non-Focusable Controls: Sidebar controls, sliders, combo boxes, and buttons are explicitly configured as
Focusable="False". This prevents active UI controls from stealing focus, ensuring key-based navigation (like arrow keys) remains fully responsive at all times.
The codebase strictly enforces the highest standard of static analysis and memory hygiene:
- Warnings-as-Errors Policy: Enforced solution-wide via
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>and<AnalysisLevel>latest-All</AnalysisLevel>insideDirectory.Build.props. - Zero-Warning Success: Compiles with
0 Warningsand0 Errorsacross both Debug and Release configurations. - OpenCV Memory Safety (CA2000): Implements explicit
usingstatements, unmanaged resource trackers, and try-finally ownership transfer patterns to prevent native memory leaks during parallel contour processing. - Encapsulation & Security: Core internal helper elements are marked as
internal sealed, exposing APIs through read-only interfaces (IReadOnlyList,Collection<T>) to guarantee architectural robustness.
| Shortcut | Action |
|---|---|
Left / Right |
Navigate between cropped photos |
Up / Down / PageUp / PageDown |
Switch between original loaded scans |
R |
Rotate the current cropped photo 90° clockwise |
X / Delete |
Permanently delete the currently selected photo |
N / Ñ |
Enter Interactive Refinement Mode |
Enter / A |
Accept Refinement (while in Refinement Mode) |
Backspace / Esc / C |
Reject Refinement (while in Refinement Mode) |
Esc |
Close Help or Refinement overlays |
Ctrl + Mouse Wheel |
Zoom in/out on the original scan |
Ctrl + S |
Save all results |
To restore dependencies and build the entire solution:
dotnet buildTo run the desktop application:
dotnet run --project PhotoCropperGuiTo execute all 22 unit tests:
dotnet testThe application is fully cross-platform and supports Windows and Ubuntu/Linux.
To publish the application without manual configuration, run the provided PowerShell script:
./publish.ps1This will create a publish/ folder containing self-contained, single-file executables for both platforms. No .NET runtime installation is required on the target machines.
This project is licensed under the GNU General Public License v3.0 - see the LICENSE file for details.