Welcome to the second unit of our course. In the previous unit, you learned how to align images by calculating a homography matrix. You practiced extracting coordinates and using the RANSAC algorithm to find an accurate alignment while ignoring incorrect matches.
RANSAC does a fantastic job of filtering out bad matches, but as developers, we need to inspect what it accepted and what it rejected to ensure our alignment is actually sound. A homography might compute mathematically but practically represent a bad alignment.
In this lesson, we will learn how to extract the inliers (the good matches RANSAC kept) and the outliers (the bad matches it threw away) into separate lists. We will write a diagnostic tool to evaluate the alignment quality automatically, and then we will draw the results on the screen to visually confirm our math.
As a quick reminder, when we estimate a homography using RANSAC, the algorithm returns a matrix and a mask. This mask is essentially a list of 1s and 0s telling us exactly which matches fit the geometry (1) and which do not (0).
To make use of this mask, we need to split our original list of matches into two separate lists. We can achieve this cleanly in Python using the zip() function, which lets us loop through the matches and the mask at the same time.
Let's look at how we can use list comprehensions to separate our data:
In this code, zip(matches, inliers) pairs each match object m with its corresponding 1 or 0 value, which we call keep. If keep is 1 (which evaluates to True in Python), the match is added to our inlier_matches list.
We can apply the exact same logic to find the outliers by simply looking for the items we do not want to keep:
Output:
By separating them, we now have precise control over our data for both analysis and visualization.
Just looking at the number of inliers and outliers is not always enough. We want our program to automatically interpret the match data and warn us if something looks wrong. To do this, we can build a diagnose_alignment function.
First, we need to calculate some basic statistics from our inliers mask. Because our mask is a NumPy array, we can easily get the total number of inliers using .sum() and the ratio of inliers to total matches using .mean().
Now that we have our metrics, we can add a series of checks. Each scenario tells us something different about what is happening in the real world:
Let's break down these checks:
- Too few matches overall (
< 20): This indicates an issue with the initial feature matching step beforeRANSACeven runs. You might need to adjust your matching threshold. - Too few inliers (
< 10): Even if you have lots ofmatches, if fewer than10agree on the geometry, the images probably do not have enough reliable overlap to stitch together safely. - A low inlier ratio (
< 0.25): If you have1,000matches but only100inliers (a10%ratio), it often points to repeated patterns in the image (like a brick wall), moving objects, or a bad camera angle.
If we pass some mock data to our function, we get a clear, readable diagnosis:
Output:
Numbers and text are great, but seeing the results visually is the best way to understand how well RANSAC performed. We can use the OpenCV function cv2.drawMatches to draw lines connecting the matching features between our two images.
Let's start by drawing the "good" inlier matches in green.
There are two important practical tips to note here:
- Limiting the matches: Notice we sliced the list using
inlier_matches[:80]. Drawing hundreds of matches creates a chaotic web of lines that is impossible to read. Limiting it to the first80or so keeps the visualization clean. - Using flags: The
cv2.DrawMatchesFlags_NOT_DRAW_SINGLE_POINTSflag tellsOpenCVto only draw the features that actually have a connecting line. This prevents the image from being cluttered with unused dots.
Next, we can do the exact same thing for our outlier matches, but this time we will use red (0, 0, 255) to highlight the rejected matches.
By displaying these two images side-by-side using cv2.imshow(), you can instantly spot patterns. For example, you might notice all your red outlier lines are attaching to moving cars or the leaves of a tree blowing in the wind, which perfectly explains why RANSAC rejected them!
In this lesson, we explored the crucial step of evaluating our RANSAC output. Instead of blindly trusting the math, you learned how to:
- Split your feature
matchesinto separateinlierandoutlierlists using amask. - Interpret the geometric agreement of your images by building a
diagnose_alignmentfunction. - Render clear visual feedback using
cv2.drawMatchesto highlight successful and failed connections.
You now have a solid diagnostic layer for your image alignment pipeline. Coming up next, you will head into the CodeSignal IDE for hands-on practice. You will get to write the extraction logic, build the diagnostic function, and generate these visual reports yourself to see exactly how your images align.
