@@ -298,22 +298,13 @@ def dense_lucaskanade(R, **kwargs):
298298 continue
299299
300300 # exclude outlier vectors
301- vel = np .sqrt (u ** 2 + v ** 2 ) # [px/timesteps]
302- q1 , q2 = np .percentile (vel , [25 , 75 ])
303- min_speed_thr = np .max ((0 , q1 - nr_IQR_outlier * (q2 - q1 )))
304- max_speed_thr = q2 + nr_IQR_outlier * (q2 - q1 )
305- keep = np .logical_and (vel < max_speed_thr , vel > min_speed_thr )
306-
307- u = u [keep ][:, None ]
308- v = v [keep ][:, None ]
309- y0 = y0 [keep ][:, None ]
310- x0 = x0 [keep ][:, None ]
311-
312- # stack vectors within time window
313- x0Stack .append (x0 )
314- y0Stack .append (y0 )
315- uStack .append (u )
316- vStack .append (v )
301+ x0 , y0 , u , v = _outlier_removal (x0 , y0 , u , v , nr_IQR_outlier )
302+
303+ # stack vectors within time window as column vectors
304+ x0Stack .append (x0 [:, None ])
305+ y0Stack .append (y0 [:, None ])
306+ uStack .append (u [:, None ])
307+ vStack .append (v [:, None ])
317308
318309 # return zero motion field is no sparse vectors are found
319310 if len (x0Stack ) == 0 :
@@ -330,7 +321,7 @@ def dense_lucaskanade(R, **kwargs):
330321 v = np .vstack (vStack )
331322
332323 if verbose :
333- print ("--- LK found %i sparse vectors ---" % x0 .size )
324+ print ("--- LK found %i sparse vectors ---" % x .size )
334325
335326 # return sparse vectors if required
336327 if not dense :
@@ -541,6 +532,38 @@ def _clean_image(R, n=3, thr=0):
541532 return R
542533
543534
535+ def _outlier_removal (x , y , u , v , thr ):
536+
537+ """Outlier removal.
538+
539+ Parameters
540+ ----------
541+ x : array_like
542+ X-coordinates of the origins of the velocity vectors.
543+ y : array_like
544+ Y-coordinates of the origins of the velocity vectors.
545+ u : array_like
546+ X-components of the velocities.
547+ v : array_like
548+ Y-components of the velocities.
549+ thr : float
550+ Threshold for outlier detection defined as measure of deviation from
551+ the mean/median of the velocity distribution.
552+
553+ Returns
554+ -------
555+ A four-element tuple (x,y,u,v) containing the x- and y-coordinates and
556+ velocity components of the motion vectors.
557+ """
558+ vel = np .sqrt (u ** 2 + v ** 2 ) # [px/timesteps]
559+ q1 , q2 = np .percentile (vel , [25 , 75 ])
560+ min_speed_thr = np .max ((0 , q1 - thr * (q2 - q1 )))
561+ max_speed_thr = q2 + thr * (q2 - q1 )
562+ keep = np .logical_and (vel < max_speed_thr , vel > min_speed_thr )
563+
564+ return x [keep ], y [keep ], u [keep ], v [keep ]
565+
566+
544567def _declustering (x , y , u , v , decl_grid , min_nr_samples ):
545568 """Filter out outliers in a sparse motion field and get more representative
546569 data points. The method assigns data points to a (RxR) declustering grid
0 commit comments