Find the points an algorithm can recognise again: corners, blobs and edges.
Feature: a distinctive pattern in an image that can be reliably detected.
Where edges intersect: a high gradient in several directions.
Regions that differ from their surroundings.
Boundaries between regions.
Why detect features? Object recognition · image matching · tracking · 3-D reconstruction · image stitching
Corner: a point where two edges meet: intensity changes in several directions.
Measures "corner-ness" from the gradients in a small window.
Gradient matrix (summed over the window):
$$M = \sum \begin{bmatrix} I_x^2 & I_x I_y \\ I_x I_y & I_y^2 \end{bmatrix}$$Corner response:
$$R = \det(M) - k \cdot \operatorname{trace}(M)^2$$R > threshold → corner detected.
\(\det(M) = \lambda_1 \lambda_2\) and \(\operatorname{trace}(M) = \lambda_1 + \lambda_2\), where \(\lambda_1, \lambda_2\) are the eigenvalues of \(M\): how strongly intensity changes along the two main directions.
import cv2
import numpy as np
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
gray = np.float32(gray)
# detect harris corners
corners = cv2.cornerHarris(gray, blockSize=2, ksize=3, k=0.04) # ans:
# blockSize: neighbourhood size
# ans: size of the window the gradients are summed over
# ksize: Sobel kernel size
# ans: for computing the gradients (3, 5, 7)
# k: Harris parameter
# ans: typically 0.04-0.06, a sensitivity parameter
# threshold to mark corners
corners = cv2.dilate(corners, None)
img[corners > 0.01 * corners.max()] = [0, 0, 255]
# ans: marks corners in red where the response > threshold
Shi-Tomasi: an improved Harris, better for tracking.
\(R = \min(\lambda_1, \lambda_2)\)
# detect good features to track
corners = cv2.goodFeaturesToTrack(gray, maxCorners=100,
qualityLevel=0.01, minDistance=10) # ans:
# maxCorners: maximum number to return
# ans: the 100 strongest corners
# qualityLevel: minimum quality (0-1)
# ans: 0.01 keeps corners > 1% of the best one
# minDistance: minimum pixel distance between corners
# ans: at least 10 pixels apart
# draw corners
for corner in corners: # ans:
x, y = corner.ravel() # ans:
cv2.circle(img, (int(x), int(y)), 3, (0, 255, 0), -1) # ans:
FAST: Features from Accelerated Segment Test.
Advantage: very fast, real-time capable.
# create a FAST detector
fast = cv2.FastFeatureDetector_create() # ans:
# detect keypoints
keypoints = fast.detect(gray, None) # ans:
# draw keypoints
img_kp = cv2.drawKeypoints(img, keypoints, None, color=(0, 255, 0)) # ans:
# adjust the threshold
fast.setThreshold(30)
# ans: higher threshold = fewer, stronger corners
# control non-max suppression
fast.setNonmaxSuppression(True)
# ans: removes adjacent weak corners
Blob: a region significantly different from its surroundings.
SimpleBlobDetector finds bright or dark roughly circular regions, filtered by colour, size (area), circularity, convexity and inertia.
Circularity = 4π · area / perimeter²: 1 for a circle, about 0.785 for a square.
# create a blob detector with default params
detector = cv2.SimpleBlobDetector_create() # ans:
# detect blobs
keypoints = detector.detect(gray) # ans:
# draw blobs
img_blobs = cv2.drawKeypoints(img, keypoints, None, (0, 0, 255),
cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS) # ans:
# custom parameters
params = cv2.SimpleBlobDetector_Params()
params.filterByArea = True
params.minArea = 100
params.maxArea = 5000
params.filterByCircularity = True
params.minCircularity = 0.8
detector = cv2.SimpleBlobDetector_create(params) # ans:
# ans: detects circular blobs of 100-5000 pixels, circularity > 0.8
Answer first, then press → to check.
What is a corner?
A point with a high gradient in several directions.
Why detect features?
Object recognition, matching, tracking, stitching.
What does Harris detect?
Corners, using the gradient matrix.
What is the difference between Harris and Shi-Tomasi?
Shi-Tomasi uses min(λ1, λ2), which is better for tracking.
What is FAST?
A fast corner detector that tests a circle of pixels.
What is a blob?
A region significantly different from its surroundings.
What is the k parameter in Harris?
The sensitivity, typically 0.04-0.06.
What is qualityLevel in goodFeaturesToTrack?
The minimum quality, as a fraction (0-1) of the best corner.
Why is FAST fast?
A simple comparison test; no gradient computation.
What does the minDistance parameter do?
It keeps corners at least N pixels apart.
# detect Harris corners
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
gray = np.float32(gray)
corners = cv2.cornerHarris(gray, 2, 3, 0.04) # ans:
# detect Shi-Tomasi corners
corners = cv2.goodFeaturesToTrack(gray, 100, 0.01, 10) # ans:
# create a FAST detector
fast = cv2.FastFeatureDetector_create() # ans:
keypoints = fast.detect(gray, None) # ans:
# detect blobs
detector = cv2.SimpleBlobDetector_create() # ans:
keypoints = detector.detect(gray) # ans:
# draw Harris corners
corners = cv2.cornerHarris(gray, 2, 3, 0.04)
corners = cv2.dilate(corners, None)
img[corners > 0.01 * corners.max()] = [0, 0, 255] # ans:
# draw Shi-Tomasi corners
corners = cv2.goodFeaturesToTrack(gray, 100, 0.01, 10)
for corner in corners: # ans:
x, y = corner.ravel() # ans:
cv2.circle(img, (int(x), int(y)), 3, (255, 0, 0), -1) # ans:
# adjust the FAST threshold
fast = cv2.FastFeatureDetector_create()
fast.setThreshold(50) # ans:
keypoints = fast.detect(gray, None) # ans:
# detect the top 50 Shi-Tomasi corners
corners = cv2.goodFeaturesToTrack(gray, 50, 0.01, 10) # ans:
# custom blob parameters
params = cv2.SimpleBlobDetector_Params()
params.filterByArea = True # ans:
params.minArea = 50 # ans:
params.maxArea = 1000 # ans:
detector = cv2.SimpleBlobDetector_create(params) # ans: