17
17
18
18
import cv2
19
19
import numpy as np
20
+ from numba import njit
20
21
21
22
log = getLogger (__name__ )
22
23
@@ -378,7 +379,7 @@ def harmonize_rects(rect_a, rect_b):
378
379
harm_rect_a = form_rectangle (harm_hori_a , harm_vert_a )
379
380
return harm_rect_a , rect_b
380
381
381
-
382
+ @ njit
382
383
def angles_to_points (angle_centers , angles , distance = 22 ):
383
384
r"""Calculate point representations of angles.
384
385
@@ -413,13 +414,66 @@ def angles_to_points(angle_centers, angles, distance=22):
413
414
"""
414
415
assert len (angle_centers ) == len (angles )
415
416
points_repr = np .zeros ((len (angle_centers ), 2 ), dtype = np .float32 )
416
- for i , center in enumerate (angle_centers ):
417
+ for i in range (angle_centers .shape [0 ]):
418
+ center = angle_centers [i , :]
417
419
z_rotation = np .array (angles [i ])
418
420
# remove round
419
421
points_repr [i , 0 ] = center [0 ] + distance * np .cos (z_rotation )
420
422
points_repr [i , 1 ] = center [1 ] + distance * np .sin (z_rotation )
421
423
return points_repr
422
424
425
+ @njit
426
+ def _process_points_to_angles (angle_centers , points_repr ):
427
+ angles = np .zeros (len (angle_centers ), dtype = np .float32 )
428
+
429
+ for i in range (angle_centers .shape [0 ]):
430
+ angle_center = angle_centers [i , :]
431
+ point_repr = points_repr [i ]
432
+ angle_center_x , angle_center_y = angle_center
433
+ point_repr_x , point_repr_y = point_repr
434
+
435
+ # the 0-angle has to be a ray from the center, which is perpendicular to the right border
436
+ # we abstract this ray as a point ``ray_pt`` which always lies on the right side of the
437
+ # center, so ``ray_pt_dis`` has to be just greater 0, we take 80
438
+ ray_pt_dis = np .float64 (80. )
439
+ ray_pt = np .array ([angle_center_x + ray_pt_dis , angle_center_y ])
440
+
441
+ """
442
+ angle_center p ray_pt
443
+ *---------------*
444
+ \ | /
445
+ \ angle / /
446
+ r \ / / d
447
+ \ --´ /
448
+ \ /
449
+ \ /
450
+ \ /
451
+ point_repr *
452
+ """
453
+
454
+ d = np .linalg .norm (ray_pt - point_repr )
455
+ p = ray_pt_dis
456
+ r = np .linalg .norm (angle_center - point_repr )
457
+ if r == 0 :
458
+ return None
459
+ cos_angle = (p ** 2 + r ** 2 - d ** 2 ) / (2 * r * p )
460
+
461
+ # this is due to some arithmetic problems, where cos_angle is something like
462
+ # cos_angle = 1.000000000000008 which leads to an error.
463
+ if cos_angle > 1 and cos_angle < 1 + 1e-9 :
464
+ cos_angle = 1
465
+ elif cos_angle < - 1 and cos_angle > - 1 - 1e-9 :
466
+ cos_angle = - 1
467
+
468
+ angle = np .arccos (cos_angle )
469
+
470
+ if angle_center_y > point_repr_y :
471
+ angle = - angle
472
+
473
+ angles [i ] = angle
474
+
475
+ return angles
476
+
423
477
424
478
def points_to_angles (angle_centers , points_repr ):
425
479
"""Convert angle point representation back to normal angle.
@@ -439,63 +493,12 @@ def points_to_angles(angle_centers, points_repr):
439
493
"""Calculate angle between vertical line passing through angle_centers and line AB."""
440
494
# https://de.wikipedia.org/wiki/Roll-Nick-Gier-Winkel#/media/File:RPY_angles_of_spaceships_(local_frame).png
441
495
# TODO(zeor_angle) variablen Nullwinkel einbauen, momentan ist entspricht dieser der x-Achse
442
- import warnings
443
- warnings .filterwarnings ('error' )
444
- np .seterr (all = 'warn' )
445
-
446
496
assert len (angle_centers ) == len (points_repr )
447
497
448
- angles = np .zeros (len (angle_centers ), dtype = np .float32 )
449
- for i , angle_center in enumerate (angle_centers ):
450
- point_repr = points_repr [i ]
451
- angle_center_x , angle_center_y = angle_center
452
- point_repr_x , point_repr_y = point_repr
453
-
454
- # the 0-angle has to be a ray from the center, which is perpendicular to the right border
455
- # we abstract this ray as a point ``ray_pt`` which always lies on the right side of the
456
- # center, so ``ray_pt_dis`` has to be just greater 0, we take 80
457
- ray_pt_dis = np .float64 (80 )
458
- ray_pt = np .array ([angle_center_x + ray_pt_dis , angle_center_y ])
459
-
460
- """
461
- angle_center p ray_pt
462
- *---------------*
463
- \ | /
464
- \ angle / /
465
- r \ / / d
466
- \ --´ /
467
- \ /
468
- \ /
469
- \ /
470
- point_repr *
471
- """
472
-
473
- d = np .linalg .norm (ray_pt - point_repr )
474
- p = ray_pt_dis
475
- r = np .linalg .norm (np .float64 (angle_center ) - point_repr )
476
- if r == 0 :
477
- raise Exception ('Angle center point {} and angle point representation {}'
478
- ' seams to be the same.' .format (angle_center , point_repr ))
479
- cos_angle = (p ** 2 + r ** 2 - d ** 2 ) / (2 * r * p )
480
-
481
- # this is due to some arithmetic problems, where cos_angle is something like
482
- # cos_angle = 1.000000000000008 which leads to an error.
483
- if cos_angle > 1 and np .isclose (cos_angle , 1 , atol = 1e-10 , rtol = 1e-9 ):
484
- cos_angle = 1
485
- elif cos_angle < - 1 and np .isclose (cos_angle , - 1 , atol = 1e-10 , rtol = 1e-9 ):
486
- cos_angle = - 1
487
- try :
488
- angle = np .arccos (cos_angle )
489
- except Warning :
490
- print ('angle_centers = {angle_centers}, '
491
- 'points_repr = {points_repr}' .format (angle_centers = angle_centers ,
492
- points_repr = points_repr ))
493
- raise Exception ('arccos can not handle {cos_angle}' .format (cos_angle = cos_angle ))
494
-
495
- if angle_center_y > point_repr_y :
496
- angle = - angle
497
-
498
- angles [i ] = angle
498
+ angles = _process_points_to_angles (angle_centers , points_repr )
499
+ if angles is None :
500
+ raise Exception ('Angle center point {} and angle point representation {}'
501
+ ' seams to be the same.' .format (angle_centers , points_repr ))
499
502
500
503
return angles
501
504
0 commit comments