from pathlib import Path
import matplotlib.pyplot as plt
Automated tile grid stitching - how it works
You can find a lot of tutorials how to do simple image stitching using two photos and that is no problem. But what to do when I want to make a panorama from 4-6 images or more?
This question posted on stackoverflow, this article, make clear that robust automated stitching of multiple images presents a much harder problem. In case you are interested to learn how this works. Here follows a brief description of the consecutive steps of automated tile stitching algorithm implemented in gridstitcher
.
To get started you need to obtain a list of the tile image files. This is best done with the operating system independent standard package pathlib
. Let’s also already import matplotlib
here to inspect the result below.
= Path('/home/frank/Work/Werknummers/2024-811_Falnama/data/Weimar-IRR_1600nm/71803-02_IRR 1600 nm/')
tiles_dir = sorted(tiles_dir.glob('*.tif'))
im_files len(im_files)
36
To perform the consecutive steps of the automated registration of the image tiles we first need to import the Tilegrid
class.
from gridstitcher import Tilegrid
Tile registration is performed in three consecutive steps. In step 1 we instantiate a Tilegrid
object with a sorted list of image files, and specify the number of rows and columns for the grid.
= Tilegrid(im_files, nrows=6, ncols=6) # 1) load images tg
Initializing regular 6x6 tile grid...
In step 2 the SIFT-RANSAC algorithm is used to obtain pairs of points that match corresponding features on adjacent tiles. These point pairs are computed and plotted with the Tilegrid.get_ransac_pair_points()
method.
tg.get_ransac_pair_points()
Detecting corresponding SIFT RANSAC point pairs...
Could not detect corresponding feature points in tile pair [2, 3]
Could not detect corresponding feature points in tile pair [3, 4]
For this specific example warnings are given that in the tile overlap pairs [2, 3]
and [3, 4]
no corresponding feature points were detected. The absence of overlap pair is not a problem as long as each tile is connected at least with one other tile.
In step 3 the sum of distances for all RANSAC point pairs in the tile grid is minimized by shifting each individual tile left-right and up-down. Note that we do not rotate, scale or warp the images.
# 3) shift tiles to optimal overlap tg.register_tiles()
Registering tiles...
Sum of tile distances: 4536.0
/home/frank/anaconda3/lib/python3.11/site-packages/scipy/optimize/_minimize.py:705: OptimizeWarning: Desired error not necessarily achieved due to precision loss.
res = _minimize_bfgs(fun, x0, args, jac, callback, **options)
Current function value: 4536.434504
Iterations: 115
Function evaluations: 15487
Gradient evaluations: 212
In our example we observe that the registration of the individual tiles is successful. To make the composite image array use the method Tilegrid.make_stitched()
. If you specify the option save_to=
you can automatically save to an image file.
= tg.make_stitched(save_to='../downloads/stitched.png') stitched_im
Saving image to: ../downloads/stitched.png
Let’s inspect our stitched mosaic image.
= plt.subplots()
fig, ax ax.imshow(stitched_im)
Nicely registered!
FUNCTIONS
make_stitched
make_stitched (ims, extent_list, save_to=None)
*Create a stitched mosaic image from tile images ims
and tile positions extent_list
.
Returns: stitched_im*
remove_outliers
remove_outliers (rpp_list, oip_list, nrows, ncols, max_delta=20, verbose=True)
Remove vector outliers from rpp and oip lists based on max_delta
pixels shift.
crop
crop (ax, extent_list)
plot_vectors
plot_vectors (canvas_rpp_list, oip_list, ax)
Plot vectors from canvas_rpp_list
on active canvas ax
with overlapping image pair list oip_list
.
total_distance
total_distance (b_flat, rpp_list, oip_list)
Compute distances.
get_canvas_rpp_list
get_canvas_rpp_list (rpp_list, oip_list, b_flat)
Compute canvas positions of red and green points.
get_extent_list
get_extent_list (b_flat, tile_h, tile_w)
*Compute tile images extents on canvas.
extent : left, right, bottom, top*
get_x0_list
get_x0_list (nrows, ncols, tile_h, tile_w, margin=20)
Initial flat tile positions list.
add_ransac_markers
add_ransac_markers (axs, oips, ransac_points_pair_list)
Add red and green markers for corresponding points in all tiles.
get_ransac_pair_points
get_ransac_pair_points (oips, kpts_descr_list)
make_overlap_image_pairs
make_overlap_image_pairs (nrows, ncols)
Generate image pair indices for horizontal and vertical overlap pairs.
make_kpts_descr_list
make_kpts_descr_list (ims)
Create keypoints and descriptors list for al images ims
.
Tilegrid
Tilegrid (im_files, nrows, ncols, filenames=True, tile_borders=True)
Create a Tilegrid object.