1
+
2
+ import numpy
3
+ import scipy .ndimage
4
+
5
+ def correlate_fftns (fft1 , fft2 ):
6
+ prod = fft1 * fft2 .conj ()
7
+ res = numpy .fft .ifftn (prod )
8
+
9
+ corr = numpy .fft .fftshift (res ).real
10
+ return corr
11
+
12
+
13
+ def ccorr_fftn (img1 , img2 ):
14
+ # TODO do we want to pad this?
15
+ fft1 = numpy .fft .fftn (img1 )
16
+ fft2 = numpy .fft .fftn (img2 )
17
+
18
+ return correlate_fftns (fft1 , fft2 )
19
+
20
+
21
+ def autocorr_fftn (img ):
22
+ fft = numpy .fft .fftn (img )
23
+ return correlate_fftns (fft , fft )
24
+
25
+
26
+ def ccorr_and_autocorr_fftn (img1 , img2 ):
27
+ # TODO do we want to pad this?
28
+ fft1 = numpy .fft .fftn (img1 )
29
+ fft2 = numpy .fft .fftn (img2 )
30
+ ccorr = correlate_fftns (fft1 , fft2 )
31
+ acorr1 = correlate_fftns (fft1 , fft1 )
32
+ acorr2 = correlate_fftns (fft2 , fft2 )
33
+ return ccorr , acorr1 , acorr2
34
+
35
+
36
+ def subpixel_maximum (arr ):
37
+ max_loc = numpy .unravel_index (numpy .argmax (arr ), arr .shape )
38
+
39
+ sub_arr = arr [
40
+ tuple (slice (ml - 1 , ml + 2 ) for ml in max_loc )
41
+ ]
42
+
43
+ # get center of mass of sub_arr
44
+ subpixel_max_loc = numpy .array (scipy .ndimage .center_of_mass (sub_arr )) - 1
45
+ return subpixel_max_loc + max_loc
46
+
47
+
48
+ def ccorr_disp (img1 , img2 , autocorrelation_threshold = None , padarray = False , value_threshold = 0 ):
49
+ if padarray :
50
+ d = numpy .ceil (numpy .array (img1 .shape ) / 2 )
51
+ pw = numpy .asarray ([(di ,di ) for di in d ],dtype = int )
52
+ img1 = numpy .pad (img1 ,pw )
53
+ img2 = numpy .pad (img2 ,pw )
54
+ if value_threshold :
55
+ img1 [img1 < value_threshold ] = 0
56
+ img2 [img2 < value_threshold ] = 0
57
+ if autocorrelation_threshold is not None :
58
+ cc , ac1 , ac2 = ccorr_and_autocorr_fftn (img1 , img2 )
59
+ ac1max = ac1 .max ()
60
+ ac2max = ac2 .max ()
61
+ if (not numpy .isnan (ac1max ) and ac1max > 0 ) and (not numpy .isnan (ac2max ) and ac2max > 0 ):
62
+ autocorrelation_ratio = cc .max () / (numpy .sqrt (ac1max * ac2max ))
63
+ if autocorrelation_ratio < autocorrelation_threshold :
64
+ # what to do here?
65
+ print ("ratio below threshold: " + str (autocorrelation_ratio ))
66
+ return None
67
+ else :
68
+ return None
69
+ else :
70
+ cc = ccorr_fftn (img1 , img2 )
71
+ max_loc = subpixel_maximum (cc )
72
+ mid_point = numpy .array (img1 .shape ) // 2
73
+ return max_loc - mid_point
74
+
75
+
76
+ def get_point_correspondence (src_pt , dst_pt , src_patch , dst_patch , autocorrelation_threshold = 0.8 ,padarray = False ,value_threshold = 0 ):
77
+ disp = ccorr_disp (src_patch , dst_patch , autocorrelation_threshold , padarray ,value_threshold )
78
+ if disp is not None :
79
+ return src_pt , dst_pt - disp
80
+ return None ,None
0 commit comments