13 KiB
13 KiB
None
<html>
<head>
</head>
</html>
Question 2 (20 marks)¶
In [1]:
import cv2
import numpy as np
In [2]:
n_clusters = 100
Read images
In [3]:
im_book = cv2.imread('data/books.jpg', cv2.IMREAD_GRAYSCALE)
im_mount = cv2.imread('data/mount_rushmore_1.jpg', cv2.IMREAD_GRAYSCALE)
im_notre = cv2.imread('data/notre_dame_1.jpg', cv2.IMREAD_GRAYSCALE)
Generate Clusters¶
In [4]:
def get_features(image):
image = image[:, :, np.newaxis]
# Initialize a SIFT detector
sift = cv2.SIFT_create()
# Detect keypoints and compute descriptors
keypoints, descriptors = sift.detectAndCompute(image, None)
return keypoints, descriptors
In [5]:
from sklearn.cluster import KMeans
def get_clusters(keypoints, descriptors, n_clusters=100):
# Perform k-means clustering
kmeans = KMeans(n_clusters=n_clusters, random_state=42, n_init=10)
kmeans.fit(descriptors)
# Assign descriptors to clusters
clusters = kmeans.predict(descriptors)
# Convert keypoints to locations (x, y coordinates)
locations = np.array([kp.pt for kp in keypoints], dtype=np.int64)
return clusters, locations
In [6]:
kpts_book, des_book = get_features(im_book)
kpts_mount, des_mount = get_features(im_mount)
kpts_notre, des_notre = get_features(im_notre)
In [7]:
clusters_book, locations_book = get_clusters(kpts_book, des_book, n_clusters=n_clusters)
clusters_mount, locations_mount = get_clusters(kpts_mount, des_mount, n_clusters=n_clusters)
clusters_notre, locations_notre = get_clusters(kpts_notre, des_notre, n_clusters=n_clusters)
Method 1 (Two FOR loops)¶
In [8]:
def m1_generate_bovw_spatial_histogram(im, locations, clusters, division):
"""
Create bag of visual words representation of an image based on the division information.
Parameters:
im (numpy.ndarray): Image array of data type uint8.
locations (numpy.ndarray): Array of shape (N, 2) with Cartesian coordinates (x, y).
clusters (numpy.ndarray): Array of shape (N,) with quantised cluster id.
division (list): List of integers of length 2 indicating division along Y and X axes.
Returns:
numpy.ndarray: 1-dimensional array representing the BoVW spatial histogram.
"""
# Determine the size of each division
div_height = im.shape[0] // division[0]
div_width = im.shape[1] // division[1]
# Initialize the histogram
num_clusters = np.unique(clusters).size
histogram = np.zeros((division[0] * division[1] * num_clusters,), dtype=np.int64)
# Two FOR loops
for div_y in range(division[0]):
for div_x in range(division[1]):
# Define the bounds of the current division
y_start = div_y * div_height
y_end = (div_y + 1) * div_height
x_start = div_x * div_width
x_end = (div_x + 1) * div_width
# Find features within the current division
div_mask = (locations[:, 1] >= y_start) & (locations[:, 1] < y_end) & \
(locations[:, 0] >= x_start) & (locations[:, 0] < x_end)
div_locations = locations[div_mask]
div_clusters = clusters[div_mask]
# Calculate the histogram for the current division
for i in range(num_clusters):
cluster_mask = (div_clusters == i)
histogram[div_y * division[1] * num_clusters + div_x * num_clusters + i] = np.sum(cluster_mask)
return histogram
Method 2 (One FOR loop)¶
In [9]:
def m2_generate_bovw_spatial_histogram(im, locations, clusters, division):
img_shape = np.shape(im)
height = img_shape[0]
width = img_shape[1]
## Possible Mistakes: Some students swapped x and y
div_x = division[1]
div_y = division[0]
x_size = width / div_x
y_size = height / div_y
num_divisions = division[0] * division[1]
num_clusters = np.max(clusters) + 1
histogram = np.zeros(num_clusters * num_divisions)
# One FOR loop
for i in range(len(locations)):
point = locations[i]
cluster = clusters[i]
x_div = np.ceil((point[0] + 1) / x_size).astype(np.int64) - 1
y_div = np.ceil((point[1] + 1) / y_size).astype(np.int64) - 1
# Possible Mistakes: Some students miscalculated the boundary condition
# x_div = np.ceil(point[0] / x_size).astype(np.int64) - 1
# y_div = np.ceil(point[1] / y_size).astype(np.int64) - 1
# Calculate the array position
div = x_div + (y_div * div_x)
array_pos = (div * num_clusters) + cluster
# Update the histogram
histogram[array_pos] = histogram[array_pos] + 1
return histogram.astype(int)
Put students' implementations here¶
In [10]:
# Be careful, some students used a different function name (e.g. bowv rather than bovw)
def generate_bovw_spatial_histogram(im, locations, clusters, division):
# Determine the number of clusters
num_clusters = np.unique(clusters).size
# Initialize histogram
spatial_histogram = np.zeros(num_clusters * np.prod(division), dtype=np.int64)
div_size_y = im.shape[0] // division[0]
div_size_x = im.shape[1] // division[1]
for div_y in range(division[0]):
for div_x in range(division[1]):
start_y = div_y * div_size_y
end_y = (div_y + 1) * div_size_y if div_y < division[0] - 1 else im.shape[0]
start_x = div_x * div_size_x
end_x = (div_x + 1) * div_size_x if div_x < division[1] - 1 else im.shape[1]
for loc, cluster_id in zip(locations, clusters):
x, y = loc
if start_y <= y < end_y and start_x <= x < end_x:
index = (div_y * division[1] + div_x) * num_clusters + cluster_id
spatial_histogram[index] += 1
return spatial_histogram
Test (Should output ALL PASS)¶
Restart and Run ALL for each submission
In [11]:
histograms = []
for division in [ [1, 1], [2, 2], [2, 3] ]:
print('Testing division:', division)
m1_histogram_book = m1_generate_bovw_spatial_histogram(im_book, locations_book, clusters_book, division)
m1_histogram_mount = m1_generate_bovw_spatial_histogram(im_mount, locations_mount, clusters_mount, division)
m1_histogram_notre = m1_generate_bovw_spatial_histogram(im_notre, locations_notre, clusters_notre, division)
m2_histogram_book = m2_generate_bovw_spatial_histogram(im_book, locations_book, clusters_book, division)
m2_histogram_mount = m2_generate_bovw_spatial_histogram(im_mount, locations_mount, clusters_mount, division)
m2_histogram_notre = m2_generate_bovw_spatial_histogram(im_notre, locations_notre, clusters_notre, division)
# Students' implementations
histogram_book = generate_bovw_spatial_histogram(im_book, locations_book, clusters_book, division)
histogram_mount = generate_bovw_spatial_histogram(im_mount, locations_mount, clusters_mount, division)
histogram_notre = generate_bovw_spatial_histogram(im_notre, locations_notre, clusters_notre, division)
assert np.allclose(m1_histogram_book, m2_histogram_book)
assert np.allclose(m1_histogram_book, histogram_book)
print("PASS: Book")
assert np.allclose(m1_histogram_mount, m2_histogram_mount)
assert np.allclose(m1_histogram_mount, histogram_mount)
print("PASS: Mount")
assert np.allclose(m1_histogram_notre, m2_histogram_notre)
assert np.allclose(m1_histogram_notre, histogram_notre)
print("PASS: Notre")
histograms.append( [m1_histogram_book, m1_histogram_mount, m1_histogram_notre] )
print("ALL PASS")
Save Output¶
In [12]:
np.save('data/question_3_histogram.npy', histograms)
In [ ]: