helpers.py
Go to the documentation of this file.
1 import matplotlib.pyplot as plt
2 import numpy as np
3 from scipy.ndimage.interpolation import geometric_transform
4 from scipy.signal import fftconvolve
5 from skimage.draw import polygon
6 import math
7 import sys
8 from shapely.geometry import LineString
9 
10 
11 def is_between(a, b, c):
12  crossproduct = (c[1] - a[1]) * (b[0] - a[0]) - (c[0] - a[0]) * (b[1] - a[1])
13  # compare versus epsilon for floating point values, or != 0 if using integers
14  if abs(crossproduct) > sys.float_info.epsilon * 100:
15  return False
16  dotproduct = (c[0] - a[0]) * (b[0] - a[0]) + (c[1] - a[1]) * (b[1] - a[1])
17  if dotproduct < 0:
18  return False
19  squaredlengthba = (b[0] - a[0]) * (b[0] - a[0]) + (b[1] - a[1]) * (b[1] - a[1])
20  if dotproduct > squaredlengthba:
21  return False
22  return True
23 
24 
25 def cart2pol(x, y):
26  rho = np.sqrt(x ** 2 + y ** 2)
27  phi = np.arctan2(y, x)
28  return (rho, phi)
29 
30 
31 def pol2cart(rho, phi):
32  x = rho * np.cos(phi)
33  y = rho * np.sin(phi)
34  return (x, y)
35 
36 
37 def normxcorr2(template, image, mode="full"):
38 
47 
48  """
49  Input arrays should be floating point numbers.
50  :param template: N-D array, of template or filter you are using for cross-correlation.
51  Must be less or equal dimensions to image.
52  Length of each dimension must be less than length of image.
53  :param image: N-D array
54  :param mode: Options, "full", "valid", "same"
55  full (Default): The output of fftconvolve is the full discrete linear convolution of the inputs.
56  Output size will be image size + 1/2 template size in each dimension.
57  valid: The output consists only of those elements that do not rely on the zero-padding.
58  same: The output is the same size as image, centered with respect to the 'full' output.
59  :return: N-D array of same dimensions as image. Size depends on mode parameter.
60  """
61 
62  # If this happens, it is probably a mistake
63  if np.ndim(template) > np.ndim(image) or \
64  len([i for i in range(np.ndim(template)) if template.shape[i] > image.shape[i]]) > 0:
65  print("normxcorr2: TEMPLATE larger than IMG. Arguments may be swapped.")
66 
67  template = template - np.mean(template)
68  image = image - np.mean(image)
69 
70  a1 = np.ones(template.shape)
71  # Faster to flip up down and left right then use fftconvolve instead of scipy's correlate
72  ar = np.flipud(np.fliplr(template))
73  out = fftconvolve(image, ar.conj(), mode=mode)
74 
75  image = fftconvolve(np.square(image), a1, mode=mode) - \
76  np.square(fftconvolve(image, a1, mode=mode)) / (np.prod(template.shape))
77 
78  # Remove small machine precision errors after subtraction
79  image[np.where(image < 0)] = 0
80 
81  template = np.sum(np.square(template))
82  out = out / np.sqrt(image * template)
83 
84  # Remove any divisions by 0 or very close to 0
85  out[np.where(np.logical_not(np.isfinite(out)))] = 0
86 
87  return out
88 
89 
90 def fft_structure(binary_map, tr):
91  ftimage = np.fft.fft2(binary_map * 255)
92  ftimage = np.fft.fftshift(ftimage)
93 
94  flat_ftimage = np.abs(ftimage.flatten())
95 
96  flat_ftimage = np.sort(flat_ftimage)
97  flat_ftimage = np.flip(flat_ftimage)
98 
99  tr_id = int(len(flat_ftimage) * tr)
100  tr = flat_ftimage[tr_id]
101  ftimage[np.abs(ftimage) < tr] = 0.0
102 
103  fig, ax = plt.subplots(nrows=1, ncols=1, sharex=True, sharey=True)
104  ax.plot(flat_ftimage, range(len(flat_ftimage)), '.')
105  ax.axvline(x=tr_id)
106  plt.show()
107  return ftimage
108 
109 
110 def structure_map(fft, binary_map, per):
111  iftimage = np.fft.ifft2(fft)
112  domin = abs(iftimage) / np.max(abs(iftimage))
113  fft_map = np.zeros(binary_map.shape)
114  fft_map[binary_map] = domin[binary_map]
115  ft_v = fft_map.flatten()
116  ft_v = ft_v[ft_v > 0]
117  tr = np.percentile(ft_v, per)
118  tr_fft_map = np.zeros(fft_map.shape)
119  tr_fft_map[fft_map > tr] = 1
120  return fft_map, tr_fft_map
121 
122 
123 def topolar(img, order=1):
124  """
125  Transform img to its polar coordinate representation.
126 
127  order: int, default 1
128  Specify the spline interpolation order.
129  High orders may be slow for large images.
130  """
131  # max_radius is the length of the diagonal
132  # from a corner to the mid-point of img.
133  max_radius = 0.5 * np.linalg.norm(img.shape)
134 
135  def transform(coords):
136  # Put coord[1] in the interval, [-pi, pi]
137  theta = 2 * np.pi * coords[1] / (img.shape[1] - 1.)
138 
139  # Then map it to the interval [0, max_radius].
140  # radius = float(img.shape[0]-coords[0]) / img.shape[0] * max_radius
141  radius = max_radius * coords[0] / img.shape[0]
142 
143  i = 0.5 * img.shape[0] - radius * np.sin(theta)
144  j = radius * np.cos(theta) + 0.5 * img.shape[1]
145  return i, j
146 
147  polar = geometric_transform(img, transform, order=order)
148 
149  rads = max_radius * np.linspace(0, 1, img.shape[0])
150  angs = np.linspace(0, 2 * np.pi, img.shape[1])
151 
152  return polar, (rads, angs)
153 
154 
155 def ang_dist(a, b):
156  phi = np.abs(a - b) % (2 * np.pi)
157  dist = (2 * np.pi - phi) if phi > np.pi else phi
158  return dist
159 
160 
161 def line_intersection(line1, line2):
162  xdiff = (line1[0][0] - line1[1][0], line2[0][0] - line2[1][0])
163  ydiff = (line1[0][1] - line1[1][1], line2[0][1] - line2[1][1])
164 
165  def det(a, b):
166  return a[0] * b[1] - a[1] * b[0]
167 
168  div = det(xdiff, ydiff)
169  if div == 0:
170  return np.nan, np.nan
171 
172  d = (det(*line1), det(*line2))
173  x = det(d, xdiff) / div
174  y = det(d, ydiff) / div
175  return x, y
176 
177 
178 def find_nearest(array, value):
179  array = np.asarray(array)
180  idx = (np.abs(array - value)).argmin()
181  return array[idx], idx
182 
183 
184 def generate_mask(r, c, s):
185  rr, cc = polygon(r, c)
186  rm_rr_1 = rr < s[0]
187  rm_rr_2 = rr >= 0
188  rm_rr = np.logical_and(rm_rr_1, rm_rr_2)
189  rr = rr[rm_rr]
190  cc = cc[rm_rr]
191  rm_cc_1 = cc < s[1]
192  rm_cc_2 = cc >= 0
193  rm_cc = np.logical_and(rm_cc_1, rm_cc_2)
194  rr = rr[rm_cc]
195  cc = cc[rm_cc]
196  return rr, cc
197 
198 
200  return {x for x in range(1, (n + 1) // 2 + 1) if n % x == 0 and n != x}
201 
202 
203 def dot(v, w):
204  x, y = v
205  X, Y = w
206  return x * X + y * Y
207 
208 
209 def length(v):
210  x, y = v
211  return math.sqrt(x * x + y * y)
212 
213 
214 def vector(b, e):
215  x, y = b
216  X, Y = e
217  return X - x, Y - y
218 
219 
220 def unit(v):
221  x, y = v
222  mag = length(v)
223  return (x / mag, y / mag)
224 
225 
226 def distance(p0, p1):
227  return length(vector(p0, p1))
228 
229 
230 def scale(v, sc):
231  x, y = v
232  return (x * sc, y * sc)
233 
234 
235 def add(v, w):
236  x, y = v
237  X, Y = w
238  return (x + X, y + Y,)
239 
240 
241 # Given a line with coordinates 'start' and 'end' and the
242 # coordinates of a point 'pnt' the proc returns the shortest
243 # distance from pnt to the line and the coordinates of the
244 # nearest point on the line.
245 #
246 # 1 Convert the line segment to a vector ('line_vec').
247 # 2 Create a vector connecting start to pnt ('pnt_vec').
248 # 3 Find the length of the line vector ('line_len').
249 # 4 Convert line_vec to a unit vector ('line_unitvec').
250 # 5 Scale pnt_vec by line_len ('pnt_vec_scaled').
251 # 6 Get the dot product of line_unitvec and pnt_vec_scaled ('t').
252 # 7 Ensure t is in the range 0 to 1.
253 # 8 Use t to get the nearest location on the line to the end
254 # of vector pnt_vec_scaled ('nearest').
255 # 9 Calculate the distance from nearest to pnt_vec_scaled.
256 # 10 Translate nearest back to the start/end line.
257 # Malcolm Kesson 16 Dec 2012
258 
259 def closest_point_on_line(start, end, pnt):
260  line_vec = vector(start, end)
261  pnt_vec = vector(start, pnt)
262  line_len = length(line_vec)
263  line_unitvec = unit(line_vec)
264  pnt_vec_scaled = scale(pnt_vec, 1.0 / line_len)
265  t = dot(line_unitvec, pnt_vec_scaled)
266  if t < 0.0:
267  t = 0.0
268  elif t > 1.0:
269  t = 1.0
270  nearest = scale(line_vec, t)
271  dist = distance(nearest, pnt_vec)
272  nearest = add(nearest, start)
273  return dist, nearest
274 
275 
276 def segment_interesction(segment1, segment2):
277  x, y = line_intersection(segment1, segment2)
278  if is_between([segment1[0][0], segment1[0][1]], [segment1[1][0], segment1[1][1]], [x, y]):
279  return x, y
280  else:
281  return np.nan, np.nan
282 
283 
285  x, y = segment_interesction([[s1[0], s1[1]], [s1[2], s1[3]]], [[s2[0], s2[1]], [s2[2], s2[3]]])
286  dist = np.inf
287 
288  if x is np.nan and y is np.nan:
289  dist_n, _ = closest_point_on_line([s1[0], s1[1]], [s1[2], s1[3]], [s2[0], s2[1]])
290  if dist_n < dist:
291  dist = dist_n
292  dist_n, _ = closest_point_on_line([s1[0], s1[1]], [s1[2], s1[3]], [s2[2], s2[3]])
293  if dist_n < dist:
294  dist = dist_n
295  dist_n, _ = closest_point_on_line([s2[0], s2[1]], [s2[2], s2[3]], [s1[0], s1[1]])
296  if dist_n < dist:
297  dist = dist_n
298  dist_n, _ = closest_point_on_line([s2[0], s2[1]], [s2[2], s2[3]], [s1[2], s1[3]])
299  if dist_n < dist:
300  dist = dist_n
301 
302  else:
303  dist = 0
304  return dist
305 
306 
307 def cetral_line(points):
308  edges_1 = [LineString([points[0], points[1]]), LineString([points[2], points[3]])]
309  edges_2 = [LineString([points[1], points[2]]), LineString([points[3], points[4]])]
310  if edges_1[0].length<edges_2[0].length:
311  return (edges_1[0].interpolate(0.5, normalized=True), edges_1[1].interpolate(0.5, normalized=True))
312  else:
313  return (edges_2[0].interpolate(0.5, normalized=True), edges_2[1].interpolate(0.5, normalized=True))
helpers.fft_structure
def fft_structure(binary_map, tr)
Definition: helpers.py:90
helpers.unit
def unit(v)
Definition: helpers.py:220
helpers.dot
def dot(v, w)
Definition: helpers.py:203
helpers.line_intersection
def line_intersection(line1, line2)
Definition: helpers.py:161
helpers.add
def add(v, w)
Definition: helpers.py:235
helpers.distance
def distance(p0, p1)
Definition: helpers.py:226
helpers.closest_point_on_line
def closest_point_on_line(start, end, pnt)
Definition: helpers.py:259
helpers.find_nearest
def find_nearest(array, value)
Definition: helpers.py:178
helpers.generate_mask
def generate_mask(r, c, s)
Definition: helpers.py:184
helpers.topolar
def topolar(img, order=1)
Definition: helpers.py:123
helpers.segment_interesction
def segment_interesction(segment1, segment2)
Definition: helpers.py:276
helpers.normxcorr2
def normxcorr2(template, image, mode="full")
Definition: helpers.py:37
helpers.length
def length(v)
Definition: helpers.py:209
helpers.is_between
def is_between(a, b, c)
Definition: helpers.py:11
helpers.cetral_line
def cetral_line(points)
Definition: helpers.py:307
helpers.structure_map
def structure_map(fft, binary_map, per)
Definition: helpers.py:110
helpers.ang_dist
def ang_dist(a, b)
Definition: helpers.py:155
helpers.cart2pol
def cart2pol(x, y)
Definition: helpers.py:25
helpers.vector
def vector(b, e)
Definition: helpers.py:214
helpers.proper_divs2
def proper_divs2(n)
Definition: helpers.py:199
helpers.pol2cart
def pol2cart(rho, phi)
Definition: helpers.py:31
helpers.shortest_distance_between_segements
def shortest_distance_between_segements(s1, s2)
Definition: helpers.py:284
helpers.scale
def scale(v, sc)
Definition: helpers.py:230


rose2
Author(s): Gabriele Somaschini, Matteo Luperto
autogenerated on Wed Jun 28 2023 02:21:53