4
4
5
5
@author: andrewcorbato
6
6
"""
7
- def icp (model ,data ,* args ):
7
+ def icp (model ,data ,* arg ):
8
8
# ICP Iterative Closest Point Algorithm. Takes use of
9
9
# Delaunay tesselation of points in model.
10
10
#
@@ -110,66 +110,83 @@ def icp(model,data,*args):
110
110
# To clear old global tesselation variables run: "clear global Tes ir jc" (tes_flag=1)
111
111
# or run: "clear global Tes Tesind Tesver" (tes_flag=2) in Command Window.
112
112
#
113
- # m-file can be downloaded for free at
113
+ # based on an m-file can be downloaded for free at
114
114
# http://www.mathworks.com/matlabcentral/fileexchange/loadFile.do?objectId=12627&objectType=FILE
115
115
#
116
- # icp version 1.4
117
116
#
118
- # written by Per Bergstrm 2007-03-07
119
117
120
118
import numpy as np
121
119
import scipy as sp
122
120
from numpy import matlib as ml
123
121
from numpy import matrix as mx
122
+ import sys
124
123
125
- if model == False and data == False :
126
- import sys
127
- sys .exit ('ERROR: Only one input. There must be at least two inputs.' )
128
- elif model == False :
129
- import sys
130
- sys .exit ('ERROR: Model cannot be an empty matrix.' )
124
+ if model .any () == False and data .any () == False :
125
+ raise ValueError ('ERROR: Only one input. There must be at least two inputs.' )
126
+ elif model .any () == False :
127
+ raise ValueError ('ERROR: Model cannot be an empty matrix.' )
131
128
global MODEL , DATA , TR , TT , TS
132
129
133
130
dims_model = np .shape (model )
134
131
if dims_model [1 ]< dims_model [0 ]:
135
- global MODEL
136
132
MODEL = np .transpose (model )
137
133
else :
138
- global MODEL
139
134
MODEL = model
140
135
141
136
dims_data = np .shape (data )
142
137
if dims_data [1 ]< dims_data [0 ]:
143
138
data = np .transpose (data )
144
139
dims_data = np .shape (data )
145
- global DATA
146
140
DATA = data
147
141
else :
148
- global DATA
149
142
DATA = data
150
143
151
144
if dims_data [0 ] is not dims_model [0 ]:
152
- import sys
153
- sys .exit ('ERROR: DATA and MODEL cannot have different dimensions.' )
154
- # default options
155
- if len (args ) == 0 :
156
- options = {'max_iter' : 104 , 'min_iter' : 4 ,'fitting' : 2 ,'thres' : 1e-05 , \
145
+ raise ValueError ('ERROR: DATA and MODEL cannot have different dimensions.' )
146
+ # default options
147
+ if not len (arg )== 0 :
148
+ opt = arg [0 ]
149
+ else :
150
+ opt = {'max_iter' : 104 , 'min_iter' : 4 ,'fitting' : [2 ],'thres' : 1e-05 , \
157
151
'init_flag' : 1 ,'tes_flag' : 1 , 'delta' : 10 ,'mode' : 'rigid' , \
158
152
'refpnt' : np .array ([]),}
159
- elif len (args ) != 9 :
160
- import sys
161
- sys .exit ('ERROR: Options dictionary must have 9 entries.' )
153
+
154
+ print (opt )
155
+
156
+ if not isinstance (opt , dict ):
157
+ raise ValueError ("opt must be dictionary of options" )
158
+ if not 'max_iter' in opt :
159
+ opt ['max_iter' ] = 104 ;
160
+ if not 'min_iter' in opt :
161
+ opt ['min_iter' ] = 4 ;
162
+ if not 'fitting' in opt :
163
+ opt ['fitting' ] = [2 ];
164
+ if not 'thres' in opt :
165
+ opt ['thres' ] = 1e-5 ;
166
+ if not 'delta' in opt :
167
+ opt ['delta' ] = 10 ;
168
+ if not 'mode' in opt :
169
+ opt ['mode' ] = 'rigid' ;
170
+ if not 'refpnt' in opt :
171
+ opt ['refpnt' ] = np .array ([]);
172
+ if not 'init_flag' in opt :
173
+ opt ['init_flag' ] = 1 ;
174
+ if not 'tes_flag' in opt :
175
+ opt ['tes_flag' ] = 1 ;
176
+
177
+
178
+
162
179
163
180
# move options out of dictionary for ease of use
164
- max_iter = args ['max_iter' ]
165
- min_iter = args ['min_iter' ]
166
- fitting = args ['fitting' ]
167
- thres = args ['thres' ]
168
- init_flag = args ['init_flag' ]
169
- tes_flag = args ['tes_flag' ]
170
- delta = args ['delta' ]
171
- mode = args ['mode' ]
172
- refpnt = args ['refpnt' ]
181
+ max_iter = opt ['max_iter' ]
182
+ min_iter = opt ['min_iter' ]
183
+ fitting = opt ['fitting' ]
184
+ thres = opt ['thres' ]
185
+ init_flag = opt ['init_flag' ]
186
+ tes_flag = opt ['tes_flag' ]
187
+ delta = opt ['delta' ]
188
+ mode = opt ['mode' ]
189
+ refpnt = opt ['refpnt' ]
173
190
174
191
# input error checks
175
192
if (tes_flag != 0 and tes_flag != 1 and tes_flag != 2 and tes_flag != 3 ):
@@ -178,7 +195,7 @@ def icp(model,data,*args):
178
195
must be 0-3.' )
179
196
if dims_model [1 ] == dims_model [0 ] and tes_flag is not 0 :
180
197
import sys
181
- sys . exit ('ERROR: This icp method requires the number of model points \
198
+ raise ValueError ('ERROR: This icp method requires the number of model points \
182
199
to be greater than the dimension' )
183
200
if max_iter < min_iter :
184
201
max_iter = min_iter
@@ -309,9 +326,10 @@ def icp_init(init_flag,fitting):
309
326
DATA = DATA + ml .repmat (TT ,1 ,N ) # apply transformation
310
327
else :
311
328
import sys
312
- sys . exit ('ERROR: Wrong init_flag' )
329
+ raise ValueError ('ERROR: Wrong init_flag' )
313
330
###############################################################################
314
331
def icp_struct (tes_flag ):
332
+ global Tes , ir , jc , Tesind , Tesver
315
333
if tes_flag != 3 :
316
334
if tes_flag == 0 :
317
335
global ir
@@ -321,15 +339,15 @@ def icp_struct(tes_flag):
321
339
dims_Tesind = np .shape (Tesind )
322
340
if dims_Tesind [0 ] == 0 :
323
341
import sys
324
- sys . exit ('ERROR: No tesselation system exists' )
342
+ raise ValueError ('ERROR: No tesselation system exists' )
325
343
else :
326
344
tes_flag = 2
327
345
else :
328
346
tes_flag = 1
329
347
elif tes_flag == 3 :
330
348
return tes_flag
331
349
else :
332
- global MODEL , Tes
350
+
333
351
[m ,n ] = np .shape (MODEL )
334
352
if m == 1 :
335
353
ind1 = np .argsort (MODEL )
@@ -364,7 +382,6 @@ def icp_struct(tes_flag):
364
382
Tes = np .sort (np .sort (Tes ,axis = 1 ),axis = 1 )
365
383
[mT ,nT ] = np .shape (Tes )
366
384
if tes_flag == 1 :
367
- global ir , jc
368
385
num = np .zeros ((1 ,n ))
369
386
for jj in range (0 ,mT ,1 ):
370
387
for kk in range (0 ,nT ,1 ):
@@ -381,7 +398,6 @@ def icp_struct(tes_flag):
381
398
ir [ind [Tes [i ,j ]]] = i
382
399
ind [Tes [i ,j ]] = ind [Tes [i ,j ]]+ 1
383
400
else : # tes_flag ==2
384
- global Tesind , Tesver
385
401
Tesind = np .zeros (mT ,nT )
386
402
Tesver = np .zeros (mT ,nT )
387
403
couvec = np .zeros (mT ,1 )
@@ -458,8 +474,8 @@ def icp_closest_start(tes_flag,fitting):
458
474
# ICP_CLOSEST_START finds indexes of closest MODEL points for each point in DATA.
459
475
# The _start version allocates memory for iclosest and finds the closest MODEL points
460
476
# to the DATA points
477
+ global MODEL , DATA , Tes , ir , jc , iclosest
461
478
if tes_flag == 3 :
462
- global MODEL , DATA , iclosest
463
479
dims_MODEL = np .shape (MODEL )
464
480
dims_DATA = np .shape (DATA )
465
481
mm = dims_MODEL [1 ]
@@ -477,25 +493,24 @@ def icp_closest_start(tes_flag,fitting):
477
493
ERROR += err (dist ,fitting ,ID )
478
494
479
495
elif tes_flag == 1 :
480
- global MODEL , DATA , Tes , ir , jc , iclosest
481
496
dims_DATA = np .shape (DATA )
482
497
md = dims_DATA [1 ]
483
498
dims_MODEL = np .shape (MODEL )
484
499
iclosest = np .zeros ((1 ,md ))
485
500
mid = np .round (md / 2 )
486
- iclosest ( mid ) = np .round ((dims_MODEL [1 ]/ 2 ))
501
+ iclosest [ mid ] = np .round ((dims_MODEL [1 ]/ 2 ))
487
502
bol = 1
488
503
while bol :
489
504
bol = np .logical_not (bol )
490
- distc = np .linalg .norm ((DATA [:,mid ]- MODEL [:,iclosest ( mid ) ]))
505
+ distc = np .linalg .norm ((DATA [:,mid ]- MODEL [:,iclosest [ mid ] ]))
491
506
distcc = 2 * distc
492
507
for i in range (ir [jc [iclosest [mid ]]],ir [jc [iclosest [mid ]+ 1 ]- 1 ],1 ):
493
508
for ind in Tes [i ,:]:
494
509
distcc = np .linalg .norm ((DATA [:,mid ]- MODEL [:,ind ]))
495
510
if distcc < distc :
496
511
distc = distcc
497
512
bol = np .logical_not (bol )
498
- iclosest ( mid ) = ind
513
+ iclosest [ mid ] = ind
499
514
break
500
515
if bol :
501
516
break
@@ -514,7 +529,7 @@ def icp_closest_start(tes_flag,fitting):
514
529
if distcc < distc :
515
530
distc = distcc
516
531
bol = np .logical_not (bol )
517
- iclosest ( mid ) = ind
532
+ iclosest [ mid ] = ind
518
533
break
519
534
if bol :
520
535
break
@@ -533,10 +548,9 @@ def icp_closest_start(tes_flag,fitting):
533
548
if distcc < distc :
534
549
distc = distcc
535
550
bol = np .logical_not (bol )
536
- iclosest ( mid ) = ind
551
+ iclosest [ mid ] = ind
537
552
break
538
553
else : # tes_flag == 2
539
- global MODEL , DATA , Tes , Tesind , Tesver , icTesind , iclosest
540
554
dims_DATA = np .shape (DATA )
541
555
md = dims_DATA [1 ]
542
556
iclosest = np .zeros ((1 ,md ))
@@ -691,8 +705,8 @@ def icp_transformation(fitting,refpnt,delta,optmode):
691
705
b = np .concatenate (0 ,DATA [0 ,n ],0 ,0 ,DATA [1 ,n ],0 ,0 ,DATA [2 ,n ],0 ,0 ,1 ,0 , axis = 1 )
692
706
c = np .concatenate (0 ,0 ,DATA [0 ,n ],0 ,0 ,DATA [1 ,n ],0 ,0 ,DATA [2 ,n ],0 ,0 ,1 , axis = 1 )
693
707
P [ind ,:] = np .concatenate (a ,b ,c , axis = 0 )
694
- q [ind ] = MODEL [0 :2 ,iclosest [p_ind [n ]]
695
- ind + = 3
708
+ q [ind ] = MODEL [0 :2 ,iclosest [p_ind [n ]]]
709
+ ind = 3
696
710
if mode == 'affine' :
697
711
theta = q / P
698
712
a_r = np .concatenate (theta [0 ],theta [3 ],theta [6 ],axis = 0 )
@@ -734,7 +748,7 @@ def err(dist,fitting,ind):
734
748
ERR = dist ** 2
735
749
else :
736
750
ERR = 0
737
- print (WARNING : Unknown fitting value .)
751
+ print (' WARNING: Unknown fitting value.' )
738
752
return ERR
739
753
###############################################################################
740
754
def weightfcn (distances ):
@@ -745,4 +759,4 @@ def weightfcn(distances):
745
759
else :
746
760
weights = max_distances + min_distances - distances
747
761
weights = weights / np .sum (weights )
748
- return weights
762
+ return weights
0 commit comments