A small, focused panorama stitcher for three horizontally-overlapping images (left, center, right).
- Left or right images being cut off after warping: the canvas size is computed from the transformed corners of all images so no content is clipped.
- Stitched results ending up in the top-left with large black areas: images are translated into a single positive-coordinate canvas so content appears centered rather than stuck to (0,0).
- Poor blending that only affected one side or left seams visible: blending uses distance-transform weighted blending (feathering) so seams from left/center/right are smooth and the center image is naturally prioritized.
- Smoothing did not affect matching: smoothing is applied only to the copies used for feature detection, so
--smoothimproves matching robustness without blurring the final output.
- Detect features using SIFT on optionally-smoothed copies of the input images.
- Match features (Lowe ratio test) and compute homographies mapping left→center and right→center.
- Compute bounding box of all warped corners to create a canvas large enough to hold everything.
- Warp the original (non-blurred) images into that canvas and composite:
- With blending (default): use distance-transform weights and light Gaussian blur to compute normalized per-pixel weights, then blend left, center, right.
- With
--no_blend: compositing order is center → left → right (later images overwrite earlier pixels where present).
- Python 3.8+
- numpy
- OpenCV with SIFT support (install
opencv-contrib-python):
pip install numpy opencv-contrib-pythonIf you get ModuleNotFoundError: No module named 'cv2', install the packages above.
From the repository root run:
cd src\test_images
python ..\main.py left.jpg center.jpg right.jpg # blend (default)
python ..\main.py left.jpg center.jpg right.jpg --smooth # smooth for matching
python ..\main.py left.jpg center.jpg right.jpg --no_blend # no blending, overwrite order- Output:
panorama_result.jpgwritten to the repository root. - Flags:
--smooth— apply Gaussian blur to images used for feature detection (improves matches on noisy images). Final output uses original images.--no_blend— disable feathered blending; images are composited center → left → right with overwrites.
src/main.py— the stitcher implementation and CLI entrypoint.src/test_images/left.jpg,src/test_images/center.jpg,src/test_images/right.jpg— sample inputs included for testing.
Input images (left, center, right) shown side-by-side:
![]() |
![]() |
![]() |
| Left | Center | Right |
Stitched panorama result:
If the panorama doesn't look right (alignment or seam issues), try:
- Running with
--smoothto improve feature matching. - Ensuring there's sufficient overlap(~30-40%) between images (SIFT needs common visual features).
- Inspecting the console output to confirm homographies were found (the script falls back to pairwise stitching if matches are insufficient).
- The code favors preserving final-image sharpness by only smoothing for detection.
- SIFT requires
opencv-contrib-pythonon most installations — use that if SIFT is unavailable.
contributions and suggestions are welcome! This is a personal project to explore panorama stitching concepts, so it's not production.



