-
Notifications
You must be signed in to change notification settings - Fork 2
/
fourier_descriptors.py
74 lines (52 loc) · 2.27 KB
/
fourier_descriptors.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
# -*- coding: utf-8 -*-
"""
Created on Tue Jan 13 13:03:59 2015
@author: tomish
"""
import numpy as np
def find_descriptors(contours, remove_dc=False):
"""Find the Fourier Descriptors for an image"""
contour_complex = np.empty(contours.shape[0], dtype=complex)
contour_complex.real = contours[:, 0]
contour_complex.imag = contours[:, 1]
#We can optionally remove the DC component (perhaps not the right place here)
if remove_dc:
contour_complex -= np.mean(contour_complex)
# Do we need to re-sample here so we can compare shapes
# with different sized contours?
descriptors = np.fft.fft(contour_complex)
return descriptors
def truncate_descriptor(descriptors, degree):
"""this function truncates an unshifted fourier descriptor array
and returns one also unshifted"""
descriptors = np.fft.fftshift(descriptors)
center_index = len(descriptors) / 2
descriptors = descriptors[
center_index - degree / 2:center_index + degree / 2]
descriptors = np.fft.ifftshift(descriptors)
return descriptors
def normalise_descriptors(descriptors):
# Scale
# descriptors / np.linalg.norm(descriptors) # or use first descriptor??
# Translation
# Rotation (phase)
pass
def pad_descriptors(descriptors, length):
"""Adds zeros to an unshifted fourier descriptor array
and returns one also unshifted"""
padded = np.zeros(length, dtype='complex')
degree = len(descriptors)
descriptors = np.fft.fftshift(descriptors)
center_index = length / 2
left_index = center_index - degree / 2 # Left index always round down
right_index = int(round(center_index + degree / 2.0)) # Right index rounded up
padded[left_index:right_index] = descriptors
padded = np.fft.ifftshift(padded)
return padded
def reconstruct(descriptors, length):
"""Reconstructs a list of contour coordinates from the fourier descriptors
Takes the length of the original contours to know how much to pad."""
padded = pad_descriptors(descriptors, length) # Pad descriptors
inversed = np.fft.ifft(padded) # Inverse Fourier transform
reconstructed = np.rint(np.column_stack((inversed.real, inversed.imag))).astype('int') # Convert to coordinates
return reconstructed