main
Spagnolo Gasper 2022-11-26 18:02:39 +01:00
parent 1922be45e2
commit e255c1c4ff
2 changed files with 177 additions and 40 deletions

View File

@ -28,7 +28,7 @@ def one_a() -> None:
axs[0, i].set_title(f"Sigma: {sigma}")
# Plot grayscale image
axs[1, i].imshow(img, cmap="gray")
# Plot scatter hessian points
# Plot scatter hessian points (x, y)
axs[1, i].scatter(hessian_points[:, 1], hessian_points[:, 0], s=20, c="r", marker="x")
plt.show()
@ -52,12 +52,56 @@ def one_b() -> None:
plt.show()
def ex2():
two_a()
def two_a() -> None:
"""
Hello
"""
graph_a_small = uz_image.imread_gray("data/graf/graf_a_small.jpg", uz_image.ImageType.float64)
graph_b_small = uz_image.imread_gray("data/graf/graf_b_small.jpg", uz_image.ImageType.float64)
# Get the keypoints
_, graph_a_keypoints = uz_image.harris_detector(graph_a_small, 3, treshold=1e-6)
_, graph_b_keypoints = uz_image.harris_detector(graph_b_small, 3, treshold=1e-6)
# Get the descriptors
graph_a_descriptors = uz_image.simple_descriptors(graph_a_small, graph_a_keypoints[:,0], graph_a_keypoints[:,1])
graph_b_descriptors = uz_image.simple_descriptors(graph_b_small, graph_b_keypoints[:,0], graph_b_keypoints[:,1])
# Find the correspondences
matches_a = uz_image.find_correspondences(graph_a_descriptors, graph_b_descriptors)
matches_b = uz_image.find_correspondences(graph_b_descriptors, graph_a_descriptors)
matches_a_coordinates = []
matche_b_coordinates = []
for i, match in enumerate(matches_a):
if i % 2 == 0: # plot every second one
if np.flip(match) in matches_b: # Check if the match is reciprocal
matches_a_coordinates.append(np.flip(graph_a_keypoints[match[0]]))
matche_b_coordinates.append(np.flip(graph_b_keypoints[match[1]]))
else:
print("Not reciprocal")
# Plot the matches
uz_image.display_matches(graph_a_small, matches_a_coordinates, graph_b_small, matche_b_coordinates)
def two_b() -> None:
"""
jjjjj
"""
# ######## #
# SOLUTION #
# ######## #
def main():
ex1()
#ex1()
ex2()
if __name__ == '__main__':
main()

View File

@ -400,8 +400,8 @@ def sharpen_image(image: Union[npt.NDArray[np.float64], npt.NDArray[np.uint8]],
sharpened_image = image.copy()
KERNEL = np.array([[-1, -1, -1],
[-1, 17, -1],
[-1, -1,-1]]) * 1./9. * sharpen_factor
[-1, 17, -1],
[-1, -1,-1]]) * 1./9. * sharpen_factor
if image.dtype.type == np.float64:
sharpened_image = cv2.filter2D(sharpened_image, cv2.CV_64F, KERNEL)
@ -594,7 +594,7 @@ def derive_image_by_y(image: Union[npt.NDArray[np.float64], npt.NDArray[np.uint8
def derive_image_first_order(image: Union[npt.NDArray[np.float64], npt.NDArray[np.uint8]],
sigma: float) -> tuple[Union[npt.NDArray[np.float64], npt.NDArray[np.uint8]],
Union[npt.NDArray[np.float64], npt.NDArray[np.uint8]]]:
Union[npt.NDArray[np.float64], npt.NDArray[np.uint8]]]:
"""
Accepts: image
returns: image derived by x, image derived by y
@ -603,8 +603,8 @@ def derive_image_first_order(image: Union[npt.NDArray[np.float64], npt.NDArray[n
def derive_image_second_order(image: Union[npt.NDArray[np.float64], npt.NDArray[np.uint8]],
sigma: float) -> tuple[tuple[Union[npt.NDArray[np.float64], npt.NDArray[np.uint8]],
Union[npt.NDArray[np.float64], npt.NDArray[np.uint8]]], tuple[Union[npt.NDArray[np.float64],
npt.NDArray[np.uint8]], Union[npt.NDArray[np.float64], npt.NDArray[np.uint8]]]]:
Union[npt.NDArray[np.float64], npt.NDArray[np.uint8]]], tuple[Union[npt.NDArray[np.float64],
npt.NDArray[np.uint8]], Union[npt.NDArray[np.float64], npt.NDArray[np.uint8]]]]:
"""
Accepts: image
Returns: Ixx, Ixy, Iyx, Iyy
@ -616,7 +616,7 @@ def derive_image_second_order(image: Union[npt.NDArray[np.float64], npt.NDArray[
def gradient_magnitude(image: Union[npt.NDArray[np.float64], npt.NDArray[np.uint8]],
sigma: float) -> tuple[Union[npt.NDArray[np.float64], npt.NDArray[np.uint8]],
Union[npt.NDArray[np.float64], npt.NDArray[np.uint8]]]:
Union[npt.NDArray[np.float64], npt.NDArray[np.uint8]]]:
"""
Accepts: image
Returns: gradient magnitude of image and derivative angles
@ -705,7 +705,7 @@ def find_edges_canny(image: Union[npt.NDArray[np.float64], npt.NDArray[np.uint8]
idxs = np.where(image_nms[labels == i] > t_high)
if idxs != []:
new_image[labels == i] = 1
new_image[labels == i] = 1
return new_image
@ -792,8 +792,8 @@ def hough_find_lines(image: Union[npt.NDArray[np.float64], npt.NDArray[np.uint8]
return accumulator
def hough_find_lines_i(image_with_lines: Union[npt.NDArray[np.float64], npt.NDArray[np.uint8]], gradient_angles: npt.NDArray[np.float64],
gradient_magnitude: npt.NDArray[np.float64],
n_bins_theta: int, n_bins_rho: int, treshold: float) -> Union[npt.NDArray[np.uint64], npt.NDArray[np.float64]]:
gradient_magnitude: npt.NDArray[np.float64],
n_bins_theta: int, n_bins_rho: int, treshold: float) -> Union[npt.NDArray[np.uint64], npt.NDArray[np.float64]]:
""""
Accepts: bw image with lines, n_bins_theta, n_bins_rho, treshold
Returns: image points above treshold transformed into hough space
@ -968,3 +968,96 @@ def harris_detector(image: Union[npt.NDArray[np.float64],
return features.astype(np.float64), points.astype(np.float64)
def simple_descriptors(I, Y, X, n_bins = 16, radius = 40, sigma = 2):
"""
Computes descriptors for locations given in X and Y.
I: Image in grayscale.
Y: list of Y coordinates of locations. (Y: index of row from top to bottom)
X: list of X coordinates of locations. (X: index of column from left to right)
Returns: tensor of shape (len(X), n_bins^2), so for each point a feature of length n_bins^2.
"""
assert np.max(I) <= 1, "Image needs to be in range [0, 1]"
assert I.dtype == np.float64, "Image needs to be in np.float64"
# Additional assertions for dumb programmers as me
assert len(X) == len(Y), "X and Y need to have same length"
assert len(X) > 0, "X and Y need to have at least one element"
g = get_gaussian_kernel(sigma)
d = gaussdx(sigma)
Ix = convolve(I, g.T, d)
Iy = convolve(I, g, d.T)
Ixx = convolve(Ix, g.T, d)
Iyy = convolve(Iy, g, d.T)
mag = np.sqrt(Ix ** 2 + Iy ** 2)
mag = np.floor(mag * ((n_bins - 1) / np.max(mag)))
feat = Ixx + Iyy
feat += abs(np.min(feat))
feat = np.floor(feat * ((n_bins - 1) / np.max(feat)))
desc = []
for y, x in zip(Y, X):
miny = max(y - radius, 0)
maxy = min(y + radius, I.shape[0])
minx = max(x - radius, 0)
maxx = min(x + radius, I.shape[1])
miny, maxy, minx, maxx = int(miny), int(maxy), int(minx), int(maxx) # Convert to int for indexing
r1 = mag[miny:maxy, minx:maxx].reshape(-1)
r2 = feat[miny:maxy, minx:maxx].reshape(-1)
a = np.zeros((n_bins, n_bins))
for m, l in zip(r1, r2):
a[int(m), int(l)] += 1
a = a.reshape(-1)
a /= np.sum(a)
desc.append(a)
return np.array(desc)
def find_correspondences(img_a_descriptors: npt.NDArray[np.float64],
img_b_descriptors: npt.NDArray[np.float64]):
correspondances = []
# Find img_a correspondences
for idx, descriptor_a in enumerate(img_a_descriptors):
dists = np.sqrt(0.5 * np.sum(np.square(np.sqrt(descriptor_a) - np.sqrt(img_b_descriptors)), axis=1))
min_dist_idx = np.argmin(dists)
correspondances.append((idx, min_dist_idx))
return np.array(correspondances)
def display_matches(I1, pts1, I2, pts2):
"""
Displays matches between images.
I1, I2: Image in grayscale.
pts1, pts2: Nx2 arrays of coordinates of feature points for each image (first column is x, second is y coordinates)
"""
assert I1.shape[0] == I2.shape[0] and I1.shape[1] == I2.shape[1], "Images need to be of the same size."
I = np.hstack((I1, I2))
w = I1.shape[1]
plt.imshow(I, cmap='gray')
for p1, p2 in zip(pts1, pts2):
x1 = p1[0]
y1 = p1[1]
x2 = p2[0]
y2 = p2[1]
plt.plot(x1, y1, 'bo', markersize=3)
plt.plot(x2 + w, y2, 'bo', markersize=3)
plt.plot([x1, x2 + w], [y1, y2], 'r', linewidth=.8)
plt.show()