3636
3737from .rasterizer import polys
3838
39+
3940def _linear_transform (src , dst ):
4041 """ Parameters of a linear transform from range specifications """
4142 (s0 , s1 ), (d0 ,d1 ) = src , dst
@@ -44,13 +45,23 @@ def _linear_transform(src, dst):
4445 return w , b
4546
4647
47- def _check_points (x :np .ndarray ):
48+ def _validate_points (x :np .ndarray ):
4849 if not isinstance (x , np .ndarray ):
4950 raise TypeError ("Points must be numpy array" )
5051 if x .ndim != 2 or x .shape [1 ] != 2 :
5152 raise ValueError ("Points must be 2D array with 2 columns" )
5253
5354
55+ def _validate_bbox (bbox ):
56+ if not isinstance (bbox , (tuple , list , np .ndarray )):
57+ raise TypeError ("bbox must be tuple, list or numpy array" )
58+ if len (bbox ) != 4 :
59+ raise ValueError ("bbox must contain 4 elements" )
60+ x ,y ,w ,h = np .array (bbox ,"f" )
61+ if w <= 0 or h <= 0 :
62+ raise ValueError ("bbox width and heigh must be positive" )
63+
64+
5465class Normalizer :
5566 """
5667 Range mapping
@@ -76,23 +87,36 @@ class PCLines:
7687 Wrapper for PCLines accumulator of certain size
7788 """
7889 def __init__ (self , bbox , d = 256 ):
79- # TODO: check if bbox valid
90+ _validate_bbox (bbox )
91+ self .bbox = bbox
8092
8193 # Init accumulator
82- shape = ( d , 2 * d - 1 )
94+ shape = d , 2 * d - 1
8395 self .A = np .zeros (shape , "f" )
8496 self .d = d
8597
86- x ,y ,w ,h = bbox
87- bb_size = (w ,h )
88- ranges = d * np .array (bb_size )/ max (bb_size )
98+ ranges = d * np .array (self .input_shape )/ self .scale
8999 ofs = (d - ranges ) / 2
90100 (x0 ,y0 ),(x1 ,y1 ) = ofs , (ranges - 1 )+ ofs
91101
102+ x ,y = self .origin
103+ w ,h = self .input_shape
92104 self .norm_u = Normalizer ((y ,y + h + 1 ), (y1 , y0 ))
93105 self .norm_v = Normalizer ((x ,x + w + 1 ), (x0 , x1 ))
94106 self .norm_w = Normalizer ((y ,y + h + 1 ), (y0 , y1 ))
95107
108+ @property
109+ def origin (self ):
110+ return self .bbox [:2 ]
111+
112+ @property
113+ def input_shape (self ):
114+ return self .bbox [2 :]
115+
116+ @property
117+ def scale (self ):
118+ return max (self .input_shape )
119+
96120 def clear (self ):
97121 self .A [:] = 0
98122
@@ -110,7 +134,7 @@ def transform(self, x):
110134 p : ndarray
111135 Nx3 array with polyline coordinates for u, v, w parallel axes
112136 """
113- _check_points (x )
137+ _validate_points (x )
114138 x0 ,x1 = np .split (x ,2 ,axis = 1 )
115139 return np .concatenate ([self .norm_u (x1 ), self .norm_v (x0 ), self .norm_w (x1 )], axis = 1 ).astype ("f" )
116140
@@ -119,19 +143,20 @@ def inverse(self, l):
119143 Transform a point from PCLines to homogeneous parameters of line
120144 """
121145 d = self .d
122- x ,y ,w ,h = self .bbox
123- m = max (w , h ) - 1
146+ m = self .scale - 1
124147 norm_v = Normalizer ((0 ,d - 1 ),(- m / 2 , m / 2 ))
125148
126149 u ,v = l [:,1 ], l [:,0 ]
127150 u = u - (d - 1 )
128151 v = norm_v (v )
129152
130153 f = u < 0
131- h = np .array ([f * (d + u )+ (1 - f )* (d - u ), u , - v * d ], "f" ).T # TODO: add reference to eq in paper
154+ lines = np .array ([f * (d + u )+ (1 - f )* (d - u ), u , - v * d ], "f" ).T # TODO: add reference to eq in paper
155+ x ,y = self .origin
156+ w ,h = self .input_shape
132157 tx ,ty = x + 0.5 * w , y + 0.5 * h
133- h [:,2 ] -= h [:,0 ]* tx + h [:,1 ]* ty
134- return h
158+ lines [:,2 ] -= lines [:,0 ]* tx + lines [:,1 ]* ty
159+ return lines
135160
136161 def valid_points (self , p ):
137162 return np .all (np .logical_and (p >= 0 , p < self .d ), axis = 1 )
0 commit comments