Welcome to the fourth and final unit of our course! Throughout the previous units, we have built a solid foundation. You learned how to extract features, use RANSAC to calculate a homography matrix while filtering out bad matches, and warp images into a shared coordinate frame to stitch them together.
Up until now, whenever we matched features or ran RANSAC, we used fixed numbers for our settings — like a match ratio of 0.75 or a RANSAC threshold of 5.0. In programming, we often call these hardcoded values "magic numbers."
The problem with magic numbers is that the same image pair might align perfectly or fail completely depending on these settings. In the real world, you need to adjust them. In this lesson, we will build a parameter sweeper — a tool that automatically tests different combinations of these settings to help us find the perfect balance for our alignment.
Before we start tuning our settings, we need to load our images and extract their features. Since we already covered these steps in previous lessons, we will use our custom helper functions to handle this quickly.
As a quick reminder, detect_and_compute finds the interesting points (keypoints or kp) and describes what they look like (descriptors or des). We do this for both images so we can compare them. With our features ready, we can focus entirely on the tuning process.
When we try to align two images, there are two main parameters that control our success:
- Ratio: This controls how strict we are when matching descriptors between the two images. A lower
ratio(like0.65) means we are very strict and only keep matches we are highly confident about. A higherratio(like0.85) is more relaxed and will give us more matches, but many of them might be incorrect. - RANSAC Threshold: This controls how much geometric error we tolerate. It is measured in pixels. If we set it to
3.0, a matched point must land within3pixels of its expected location to be considered a good match (an "inlier"). If we set it to8.0, we allow up to8pixels of error.
Our goal is to find settings that produce a high percentage of inliers, not just the largest total number of matches. To do this, we need to test multiple combinations of both parameters.
To test multiple combinations, we can use nested for loops in Python. This means we will place one loop inside another.
First, let's set up a table header to make our results easy to read, and write our outer loop to test different ratio values.
In this code, we loop through five different ratio values. Notice that we call match_descriptors inside this loop. We do this here because the matching process only relies on the ratio, not the RANSAC threshold.
Next, we add our inner loop to test different RANSAC thresholds for each ratio.
With this nested structure, for every single ratio (like 0.65), Python will test all three ransac_threshold values (3.0, 5.0, and 8.0) before moving on to the next ratio.
When we estimate our homography matrix, RANSAC requires a minimum number of matches to work (usually at least 4). If our ratio is too strict, we might not get enough matches, and estimate_homography will crash by throwing a ValueError.
To prevent our entire script from crashing, we use a try...except block. This allows us to catch the error, print a "fail" message, and safely move on to the next combination.
Let's complete our code by adding the homography estimation, the try...except block, and the final print statements.
In the print statement for a success, we use a few formatting tricks. The :6.2f tells Python to use 6 spaces and 2 decimal places, keeping our columns perfectly aligned.
We also calculate two important numbers from our inliers list:
inliers.sum(): Sinceinliersare represented as1s and outliers as0s, adding them together gives us the total number of good matches.inliers.mean(): This calculates the average. In this case, it represents our inlier ratio — the percentage of total matches that actually turned out to be good.
If you run this code, the output will look something like this:
Excellent work! You have successfully built a diagnostic tool that sweeps through different parameters to find the best settings for image alignment.
When you look at the results of your sweep, remember that the highest total number of matches is not always the best choice. A better alignment usually comes from a setting that produces a reasonable number of total inliers alongside a high inlier ratio (meaning very few bad matches slipped through).
You have officially made it to the final lesson of this course! I am incredibly proud of how far you have come — from struggling to understand how a computer sees images, to building a robust pipeline that can analyze, tune, and stitch images together dynamically.
Up next are the final practice exercises on the CodeSignal IDE. You will write these nested loops, handle the exceptions, and run this sweep on real image pairs to analyze the results yourself. Let's finish strong!
