signature:
def learn ( * , network , env , total_timesteps , timesteps_per_batch = 1024 , # what to train on
max_kl = 0.001 , cg_iters = 10 , gamma = 0.99 , lam = 1.0 , # advantage estimation
seed = None , ent_coef = 0.0 , cg_damping = 1e-2 , vf_stepsize = 3e-4 , vf_iters = 3 , max_episodes = 0 , max_iters = 0 , # time constraint
callback = None , load_path = None , ** network_kwargs ) :
    '''learn a policy function with TRPO algorithm
 Parameters :
 network neural network to learn . Can be either string ( ' mlp ' , ' cnn ' , ' lstm ' , ' lnlstm ' for basic types )
 or function that takes input placeholder and returns tuple ( output , None ) for feedforward nets
 or ( output , ( state _ placeholder , state _ output , mask _ placeholder ) ) for recurrent nets
 env environment ( one of the gym environments or wrapped via baselines . common . vec _ env . VecEnv - type class
 timesteps _ per _ batch timesteps per gradient estimation batch
 max _ kl max KL divergence between old policy and new policy ( KL ( pi _ old | | pi ) )
 ent _ coef coefficient of policy entropy term in the optimization objective
 cg _ iters number of iterations of conjugate gradient algorithm
 cg _ damping conjugate gradient damping
 vf _ stepsize learning rate for adam optimizer used to optimie value function loss
 vf _ iters number of iterations of value function optimization iterations per each policy optimization step
 total _ timesteps max number of timesteps
 max _ episodes max number of episodes
 max _ iters maximum number of policy optimization iterations
 callback function to be called with ( locals ( ) , globals ( ) ) each policy optimization step
 load _ path str , path to load the model from ( default : None , i . e . no model is loaded )
 * * network _ kwargs keyword arguments to the policy / network builder . See baselines . common / policies . py / build _ policy and arguments to a particular type of network
 Returns :
 learnt model'''

implementation:
if MPI is not None :
    nworkers = MPI . COMM_WORLD . Get_size ( )
    rank = MPI . COMM_WORLD . Get_rank ( )
else :
    nworkers = 1
    rank = 0
cpus_per_worker = 1
U . get_session ( config = tf . ConfigProto ( allow_soft_placement = True , inter_op_parallelism_threads = cpus_per_worker , intra_op_parallelism_threads = cpus_per_worker ) )
policy = build_policy ( env , network , value_network = 'copy' , ** network_kwargs )
set_global_seeds ( seed )
np . set_printoptions ( precision = 3 )
# Setup losses and stuff
ob_space = env . observation_space
ac_space = env . action_space
ob = observation_placeholder ( ob_space )
with tf . variable_scope ( "pi" ) :
    pi = policy ( observ_placeholder = ob )
with tf . variable_scope ( "oldpi" ) :
    oldpi = policy ( observ_placeholder = ob )
atarg = tf . placeholder ( dtype = tf . float32 , shape = [ None ] )
# Target advantage function ( if applicable )
ret = tf . placeholder ( dtype = tf . float32 , shape = [ None ] )
# Empirical return
ac = pi . pdtype . sample_placeholder ( [ None ] )
kloldnew = oldpi . pd . kl ( pi . pd )
ent = pi . pd . entropy ( )
meankl = tf . reduce_mean ( kloldnew )
meanent = tf . reduce_mean ( ent )
entbonus = ent_coef * meanent
vferr = tf . reduce_mean ( tf . square ( pi . vf - ret ) )
ratio = tf . exp ( pi . pd . logp ( ac ) - oldpi . pd . logp ( ac ) )
# advantage * pnew / pold
surrgain = tf . reduce_mean ( ratio * atarg )
optimgain = surrgain + entbonus
losses = [ optimgain , meankl , entbonus , surrgain , meanent ]
loss_names = [ "optimgain" , "meankl" , "entloss" , "surrgain" , "entropy" ]
dist = meankl
all_var_list = get_trainable_variables ( "pi" )
# var _ list = [ v for v in all _ var _ list if v . name . split ( " / " ) [ 1 ] . startswith ( " pol " ) ]
# vf _ var _ list = [ v for v in all _ var _ list if v . name . split ( " / " ) [ 1 ] . startswith ( " vf " ) ]
var_list = get_pi_trainable_variables ( "pi" )
vf_var_list = get_vf_trainable_variables ( "pi" )
vfadam = MpiAdam ( vf_var_list )
get_flat = U . GetFlat ( var_list )
set_from_flat = U . SetFromFlat ( var_list )
klgrads = tf . gradients ( dist , var_list )
flat_tangent = tf . placeholder ( dtype = tf . float32 , shape = [ None ] , name = "flat_tan" )
shapes = [ var . get_shape ( ) . as_list ( ) for var in var_list ]
start = 0
tangents = [ ]
for shape in shapes :
    sz = U . intprod ( shape )
    tangents . append ( tf . reshape ( flat_tangent [ start : start + sz ] , shape ) )
    start += sz
gvp = tf . add_n ( [ tf . reduce_sum ( g * tangent ) for ( g , tangent ) in zipsame ( klgrads , tangents ) ] )
# pylint : disable = E1111
fvp = U . flatgrad ( gvp , var_list )
assign_old_eq_new = U . function ( [ ] , [ ] , updates = [ tf . assign ( oldv , newv ) for ( oldv , newv ) in zipsame ( get_variables ( "oldpi" ) , get_variables ( "pi" ) ) ] )
compute_losses = U . function ( [ ob , ac , atarg ] , losses )
compute_lossandgrad = U . function ( [ ob , ac , atarg ] , losses + [ U . flatgrad ( optimgain , var_list ) ] )
compute_fvp = U . function ( [ flat_tangent , ob , ac , atarg ] , fvp )
compute_vflossandgrad = U . function ( [ ob , ret ] , U . flatgrad ( vferr , vf_var_list ) )
@ contextmanager
def timed ( msg ) :
    if rank == 0 :
        print ( colorize ( msg , color = 'magenta' ) )
        tstart = time . time ( )
        yield
        print ( colorize ( "done in %.3f seconds" % ( time . time ( ) - tstart ) , color = 'magenta' ) )
    else :
        yield
def allmean ( x ) :
    assert isinstance ( x , np . ndarray )
    if MPI is not None :
        out = np . empty_like ( x )
        MPI . COMM_WORLD . Allreduce ( x , out , op = MPI . SUM )
        out /= nworkers
    else :
        out = np . copy ( x )
    return out
U . initialize ( )
if load_path is not None :
    pi . load ( load_path )
th_init = get_flat ( )
if MPI is not None :
    MPI . COMM_WORLD . Bcast ( th_init , root = 0 )
set_from_flat ( th_init )
vfadam . sync ( )
print ( "Init param sum" , th_init . sum ( ) , flush = True )
# Prepare for rollouts
seg_gen = traj_segment_generator ( pi , env , timesteps_per_batch , stochastic = True )
episodes_so_far = 0
timesteps_so_far = 0
iters_so_far = 0
tstart = time . time ( )
lenbuffer = deque ( maxlen = 40 )
# rolling buffer for episode lengths
rewbuffer = deque ( maxlen = 40 )
# rolling buffer for episode rewards
if sum ( [ max_iters > 0 , total_timesteps > 0 , max_episodes > 0 ] ) == 0 : # noththing to be done
    return pi
assert sum ( [ max_iters > 0 , total_timesteps > 0 , max_episodes > 0 ] ) < 2 , 'out of max_iters, total_timesteps, and max_episodes only one should be specified'
while True :
    if callback :
        callback ( locals ( ) , globals ( ) )
    if total_timesteps and timesteps_so_far >= total_timesteps :
        break
    elif max_episodes and episodes_so_far >= max_episodes :
        break
    elif max_iters and iters_so_far >= max_iters :
        break
    logger . log ( "********** Iteration %i ************" % iters_so_far )
    with timed ( "sampling" ) :
        seg = seg_gen . __next__ ( )
    add_vtarg_and_adv ( seg , gamma , lam )
    # ob , ac , atarg , ret , td1ret = map ( np . concatenate , ( obs , acs , atargs , rets , td1rets ) )
    ob , ac , atarg , tdlamret = seg [ "ob" ] , seg [ "ac" ] , seg [ "adv" ] , seg [ "tdlamret" ]
    vpredbefore = seg [ "vpred" ]
    # predicted value function before udpate
    atarg = ( atarg - atarg . mean ( ) ) / atarg . std ( )
    # standardized advantage function estimate
    if hasattr ( pi , "ret_rms" ) :
        pi . ret_rms . update ( tdlamret )
    if hasattr ( pi , "ob_rms" ) :
        pi . ob_rms . update ( ob )
    # update running mean / std for policy
    args = seg [ "ob" ] , seg [ "ac" ] , atarg
    fvpargs = [ arr [ : : 5 ] for arr in args ]
    def fisher_vector_product ( p ) :
        return allmean ( compute_fvp ( p , * fvpargs ) ) + cg_damping * p
    assign_old_eq_new ( )
    # set old parameter values to new parameter values
    with timed ( "computegrad" ) :
        * lossbefore , g = compute_lossandgrad ( * args )
    lossbefore = allmean ( np . array ( lossbefore ) )
    g = allmean ( g )
    if np . allclose ( g , 0 ) :
        logger . log ( "Got zero gradient. not updating" )
    else :
        with timed ( "cg" ) :
            stepdir = cg ( fisher_vector_product , g , cg_iters = cg_iters , verbose = rank == 0 )
        assert np . isfinite ( stepdir ) . all ( )
        shs = .5 * stepdir . dot ( fisher_vector_product ( stepdir ) )
        lm = np . sqrt ( shs / max_kl )
        # logger . log ( " lagrange multiplier : " , lm , " gnorm : " , np . linalg . norm ( g ) )
        fullstep = stepdir / lm
        expectedimprove = g . dot ( fullstep )
        surrbefore = lossbefore [ 0 ]
        stepsize = 1.0
        thbefore = get_flat ( )
        for _ in range ( 10 ) :
            thnew = thbefore + fullstep * stepsize
            set_from_flat ( thnew )
            meanlosses = surr , kl , * _ = allmean ( np . array ( compute_losses ( * args ) ) )
            improve = surr - surrbefore
            logger . log ( "Expected: %.3f Actual: %.3f" % ( expectedimprove , improve ) )
            if not np . isfinite ( meanlosses ) . all ( ) :
                logger . log ( "Got non-finite value of losses -- bad!" )
            elif kl > max_kl * 1.5 :
                logger . log ( "violated KL constraint. shrinking step." )
            elif improve < 0 :
                logger . log ( "surrogate didn't improve. shrinking step." )
            else :
                logger . log ( "Stepsize OK!" )
                break
            stepsize *= .5
        else :
            logger . log ( "couldn't compute a good step" )
            set_from_flat ( thbefore )
        if nworkers > 1 and iters_so_far % 20 == 0 :
            paramsums = MPI . COMM_WORLD . allgather ( ( thnew . sum ( ) , vfadam . getflat ( ) . sum ( ) ) )
            # list of tuples
            assert all ( np . allclose ( ps , paramsums [ 0 ] ) for ps in paramsums [ 1 : ] )
    for ( lossname , lossval ) in zip ( loss_names , meanlosses ) :
        logger . record_tabular ( lossname , lossval )
    with timed ( "vf" ) :
        for _ in range ( vf_iters ) :
            for ( mbob , mbret ) in dataset . iterbatches ( ( seg [ "ob" ] , seg [ "tdlamret" ] ) , include_final_partial_batch = False , batch_size = 64 ) :
                g = allmean ( compute_vflossandgrad ( mbob , mbret ) )
                vfadam . update ( g , vf_stepsize )
    logger . record_tabular ( "ev_tdlam_before" , explained_variance ( vpredbefore , tdlamret ) )
    lrlocal = ( seg [ "ep_lens" ] , seg [ "ep_rets" ] )
    # local values
    if MPI is not None :
        listoflrpairs = MPI . COMM_WORLD . allgather ( lrlocal )
        # list of tuples
    else :
        listoflrpairs = [ lrlocal ]
    lens , rews = map ( flatten_lists , zip ( * listoflrpairs ) )
    lenbuffer . extend ( lens )
    rewbuffer . extend ( rews )
    logger . record_tabular ( "EpLenMean" , np . mean ( lenbuffer ) )
    logger . record_tabular ( "EpRewMean" , np . mean ( rewbuffer ) )
    logger . record_tabular ( "EpThisIter" , len ( lens ) )
    episodes_so_far += len ( lens )
    timesteps_so_far += sum ( lens )
    iters_so_far += 1
    logger . record_tabular ( "EpisodesSoFar" , episodes_so_far )
    logger . record_tabular ( "TimestepsSoFar" , timesteps_so_far )
    logger . record_tabular ( "TimeElapsed" , time . time ( ) - tstart )
    if rank == 0 :
        logger . dump_tabular ( )
return pi


signature:
def discount ( x , gamma ) :
    """computes discounted sums along 0th dimension of x .
 inputs
 x : ndarray
 gamma : float
 outputs
 y : ndarray with same shape as x , satisfying
 y [ t ] = x [ t ] + gamma * x [ t + 1 ] + gamma ^ 2 * x [ t + 2 ] + . . . + gamma ^ k x [ t + k ] ,
 where k = len ( x ) - t - 1"""

implementation:
assert x . ndim >= 1
return scipy . signal . lfilter ( [ 1 ] , [ 1 , - gamma ] , x [ : : - 1 ] , axis = 0 ) [ : : - 1 ]


signature:
def explained_variance ( ypred , y ) :
    """Computes fraction of variance that ypred explains about y .
 Returns 1 - Var [ y - ypred ] / Var [ y ]
 interpretation :
 ev = 0 = > might as well have predicted zero
 ev = 1 = > perfect prediction
 ev < 0 = > worse than just predicting zero"""

implementation:
assert y . ndim == 1 and ypred . ndim == 1
vary = np . var ( y )
return np . nan if vary == 0 else 1 - np . var ( y - ypred ) / vary


signature:
def discount_with_boundaries ( X , New , gamma ) :
    """X : 2d array of floats , time x features
 New : 2d array of bools , indicating when a new episode has started"""

implementation:
Y = np . zeros_like ( X )
T = X . shape [ 0 ]
Y [ T - 1 ] = X [ T - 1 ]
for t in range ( T - 2 , - 1 , - 1 ) :
    Y [ t ] = X [ t ] + gamma * Y [ t + 1 ] * ( 1 - New [ t + 1 ] )
return Y


signature:
def sample ( self , batch_size ) :
    """Sample a batch of experiences .
 Parameters
 batch _ size : int
 How many transitions to sample .
 Returns
 obs _ batch : np . array
 batch of observations
 act _ batch : np . array
 batch of actions executed given obs _ batch
 rew _ batch : np . array
 rewards received as results of executing act _ batch
 next _ obs _ batch : np . array
 next set of observations seen after executing act _ batch
 done _ mask : np . array
 done _ mask [ i ] = 1 if executing act _ batch [ i ] resulted in
 the end of an episode and 0 otherwise ."""

implementation:
idxes = [ random . randint ( 0 , len ( self . _storage ) - 1 ) for _ in range ( batch_size ) ]
return self . _encode_sample ( idxes )


signature:
def add ( self , * args , ** kwargs ) :
    """See ReplayBuffer . store _ effect"""

implementation:
idx = self . _next_idx
super ( ) . add ( * args , ** kwargs )
self . _it_sum [ idx ] = self . _max_priority ** self . _alpha
self . _it_min [ idx ] = self . _max_priority ** self . _alpha


signature:
def sample ( self , batch_size , beta ) :
    """Sample a batch of experiences .
 compared to ReplayBuffer . sample
 it also returns importance weights and idxes
 of sampled experiences .
 Parameters
 batch _ size : int
 How many transitions to sample .
 beta : float
 To what degree to use importance weights
 (0 - no corrections , 1 - full correction )
 Returns
 obs _ batch : np . array
 batch of observations
 act _ batch : np . array
 batch of actions executed given obs _ batch
 rew _ batch : np . array
 rewards received as results of executing act _ batch
 next _ obs _ batch : np . array
 next set of observations seen after executing act _ batch
 done _ mask : np . array
 done _ mask [ i ] = 1 if executing act _ batch [ i ] resulted in
 the end of an episode and 0 otherwise .
 weights : np . array
 Array of shape ( batch _ size , ) and dtype np . float32
 denoting importance weight of each sampled transition
 idxes : np . array
 Array of shape ( batch _ size , ) and dtype np . int32
 idexes in buffer of sampled experiences"""

implementation:
assert beta > 0
idxes = self . _sample_proportional ( batch_size )
weights = [ ]
p_min = self . _it_min . min ( ) / self . _it_sum . sum ( )
max_weight = ( p_min * len ( self . _storage ) ) ** ( - beta )
for idx in idxes :
    p_sample = self . _it_sum [ idx ] / self . _it_sum . sum ( )
    weight = ( p_sample * len ( self . _storage ) ) ** ( - beta )
    weights . append ( weight / max_weight )
weights = np . array ( weights )
encoded_sample = self . _encode_sample ( idxes )
return tuple ( list ( encoded_sample ) + [ weights , idxes ] )


signature:
def update_priorities ( self , idxes , priorities ) :
    """Update priorities of sampled transitions .
 sets priority of transition at index idxes [ i ] in buffer
 to priorities [ i ] .
 Parameters
 idxes : [ int ]
 List of idxes of sampled transitions
 priorities : [ float ]
 List of updated priorities corresponding to
 transitions at the sampled idxes denoted by
 variable ` idxes ` ."""

implementation:
assert len ( idxes ) == len ( priorities )
for idx , priority in zip ( idxes , priorities ) :
    assert priority > 0
    assert 0 <= idx < len ( self . _storage )
    self . _it_sum [ idx ] = priority ** self . _alpha
    self . _it_min [ idx ] = priority ** self . _alpha
    self . _max_priority = max ( self . _max_priority , priority )


signature:
def wrap_deepmind_retro ( env , scale = True , frame_stack = 4 ) :
    """Configure environment for retro games , using config similar to DeepMind - style Atari in wrap _ deepmind"""

implementation:
env = WarpFrame ( env )
env = ClipRewardEnv ( env )
if frame_stack > 1 :
    env = FrameStack ( env , frame_stack )
if scale :
    env = ScaledFloatFrame ( env )
return env


signature:
def scope_vars ( scope , trainable_only = False ) :
    """Get variables inside a scope
 The scope can be specified as a string
 Parameters
 scope : str or VariableScope
 scope in which the variables reside .
 trainable _ only : bool
 whether or not to return only the variables that were marked as trainable .
 Returns
 vars : [ tf . Variable ]
 list of variables in ` scope ` ."""

implementation: return tf . get_collection ( tf . GraphKeys . TRAINABLE_VARIABLES if trainable_only else tf . GraphKeys . GLOBAL_VARIABLES , scope = scope if isinstance ( scope , str ) else scope . name )


signature:
def build_act ( make_obs_ph , q_func , num_actions , scope = "deepq" , reuse = None ) :
    """Creates the act function :
 Parameters
 make _ obs _ ph : str - > tf . placeholder or TfInput
 a function that take a name and creates a placeholder of input with that name
 q _ func : ( tf . Variable , int , str , bool ) - > tf . Variable
 the model that takes the following inputs :
 observation _ in : object
 the output of observation placeholder
 num _ actions : int
 number of actions
 scope : str
 reuse : bool
 should be passed to outer variable scope
 and returns a tensor of shape ( batch _ size , num _ actions ) with values of every action .
 num _ actions : int
 number of actions .
 scope : str or VariableScope
 optional scope for variable _ scope .
 reuse : bool or None
 whether or not the variables should be reused . To be able to reuse the scope must be given .
 Returns
 act : ( tf . Variable , bool , float ) - > tf . Variable
 function to select and action given observation .
 ` See the top of the file for details ."""

implementation:
with tf . variable_scope ( scope , reuse = reuse ) :
    observations_ph = make_obs_ph ( "observation" )
    stochastic_ph = tf . placeholder ( tf . bool , ( ) , name = "stochastic" )
    update_eps_ph = tf . placeholder ( tf . float32 , ( ) , name = "update_eps" )
    eps = tf . get_variable ( "eps" , ( ) , initializer = tf . constant_initializer ( 0 ) )
    q_values = q_func ( observations_ph . get ( ) , num_actions , scope = "q_func" )
    deterministic_actions = tf . argmax ( q_values , axis = 1 )
    batch_size = tf . shape ( observations_ph . get ( ) ) [ 0 ]
    random_actions = tf . random_uniform ( tf . stack ( [ batch_size ] ) , minval = 0 , maxval = num_actions , dtype = tf . int64 )
    chose_random = tf . random_uniform ( tf . stack ( [ batch_size ] ) , minval = 0 , maxval = 1 , dtype = tf . float32 ) < eps
    stochastic_actions = tf . where ( chose_random , random_actions , deterministic_actions )
    output_actions = tf . cond ( stochastic_ph , lambda : stochastic_actions , lambda : deterministic_actions )
    update_eps_expr = eps . assign ( tf . cond ( update_eps_ph >= 0 , lambda : update_eps_ph , lambda : eps ) )
    _act = U . function ( inputs = [ observations_ph , stochastic_ph , update_eps_ph ] , outputs = output_actions , givens = { update_eps_ph : - 1.0 , stochastic_ph : True } , updates = [ update_eps_expr ] )
    def act ( ob , stochastic = True , update_eps = - 1 ) :
        return _act ( ob , stochastic , update_eps )
    return act


signature:
def build_act_with_param_noise ( make_obs_ph , q_func , num_actions , scope = "deepq" , reuse = None , param_noise_filter_func = None ) :
    """Creates the act function with support for parameter space noise exploration ( https : / / arxiv . org / abs / 1706.01905 ) :
 Parameters
 make _ obs _ ph : str - > tf . placeholder or TfInput
 a function that take a name and creates a placeholder of input with that name
 q _ func : ( tf . Variable , int , str , bool ) - > tf . Variable
 the model that takes the following inputs :
 observation _ in : object
 the output of observation placeholder
 num _ actions : int
 number of actions
 scope : str
 reuse : bool
 should be passed to outer variable scope
 and returns a tensor of shape ( batch _ size , num _ actions ) with values of every action .
 num _ actions : int
 number of actions .
 scope : str or VariableScope
 optional scope for variable _ scope .
 reuse : bool or None
 whether or not the variables should be reused . To be able to reuse the scope must be given .
 param _ noise _ filter _ func : tf . Variable - > bool
 function that decides whether or not a variable should be perturbed . Only applicable
 if param _ noise is True . If set to None , default _ param _ noise _ filter is used by default .
 Returns
 act : ( tf . Variable , bool , float , bool , float , bool ) - > tf . Variable
 function to select and action given observation .
 ` See the top of the file for details ."""

implementation:
if param_noise_filter_func is None :
    param_noise_filter_func = default_param_noise_filter
with tf . variable_scope ( scope , reuse = reuse ) :
    observations_ph = make_obs_ph ( "observation" )
    stochastic_ph = tf . placeholder ( tf . bool , ( ) , name = "stochastic" )
    update_eps_ph = tf . placeholder ( tf . float32 , ( ) , name = "update_eps" )
    update_param_noise_threshold_ph = tf . placeholder ( tf . float32 , ( ) , name = "update_param_noise_threshold" )
    update_param_noise_scale_ph = tf . placeholder ( tf . bool , ( ) , name = "update_param_noise_scale" )
    reset_ph = tf . placeholder ( tf . bool , ( ) , name = "reset" )
    eps = tf . get_variable ( "eps" , ( ) , initializer = tf . constant_initializer ( 0 ) )
    param_noise_scale = tf . get_variable ( "param_noise_scale" , ( ) , initializer = tf . constant_initializer ( 0.01 ) , trainable = False )
    param_noise_threshold = tf . get_variable ( "param_noise_threshold" , ( ) , initializer = tf . constant_initializer ( 0.05 ) , trainable = False )
    # Unmodified Q .
    q_values = q_func ( observations_ph . get ( ) , num_actions , scope = "q_func" )
    # Perturbable Q used for the actual rollout .
    q_values_perturbed = q_func ( observations_ph . get ( ) , num_actions , scope = "perturbed_q_func" )
    # We have to wrap this code into a function due to the way tf . cond ( ) works . See
    # https : / / stackoverflow . com / questions / 37063952 / confused - by - the - behavior - of - tf - cond for
    # a more detailed discussion .
    def perturb_vars ( original_scope , perturbed_scope ) :
        all_vars = scope_vars ( absolute_scope_name ( original_scope ) )
        all_perturbed_vars = scope_vars ( absolute_scope_name ( perturbed_scope ) )
        assert len ( all_vars ) == len ( all_perturbed_vars )
        perturb_ops = [ ]
        for var , perturbed_var in zip ( all_vars , all_perturbed_vars ) :
            if param_noise_filter_func ( perturbed_var ) : # Perturb this variable .
                op = tf . assign ( perturbed_var , var + tf . random_normal ( shape = tf . shape ( var ) , mean = 0. , stddev = param_noise_scale ) )
            else : # Do not perturb , just assign .
                op = tf . assign ( perturbed_var , var )
            perturb_ops . append ( op )
        assert len ( perturb_ops ) == len ( all_vars )
        return tf . group ( * perturb_ops )
    # Set up functionality to re - compute ` param _ noise _ scale ` . This perturbs yet another copy
    # of the network and measures the effect of that perturbation in action space . If the perturbation
    # is too big , reduce scale of perturbation , otherwise increase .
    q_values_adaptive = q_func ( observations_ph . get ( ) , num_actions , scope = "adaptive_q_func" )
    perturb_for_adaption = perturb_vars ( original_scope = "q_func" , perturbed_scope = "adaptive_q_func" )
    kl = tf . reduce_sum ( tf . nn . softmax ( q_values ) * ( tf . log ( tf . nn . softmax ( q_values ) ) - tf . log ( tf . nn . softmax ( q_values_adaptive ) ) ) , axis = - 1 )
    mean_kl = tf . reduce_mean ( kl )
    def update_scale ( ) :
        with tf . control_dependencies ( [ perturb_for_adaption ] ) :
            update_scale_expr = tf . cond ( mean_kl < param_noise_threshold , lambda : param_noise_scale . assign ( param_noise_scale * 1.01 ) , lambda : param_noise_scale . assign ( param_noise_scale / 1.01 ) , )
        return update_scale_expr
    # Functionality to update the threshold for parameter space noise .
    update_param_noise_threshold_expr = param_noise_threshold . assign ( tf . cond ( update_param_noise_threshold_ph >= 0 , lambda : update_param_noise_threshold_ph , lambda : param_noise_threshold ) )
    # Put everything together .
    deterministic_actions = tf . argmax ( q_values_perturbed , axis = 1 )
    batch_size = tf . shape ( observations_ph . get ( ) ) [ 0 ]
    random_actions = tf . random_uniform ( tf . stack ( [ batch_size ] ) , minval = 0 , maxval = num_actions , dtype = tf . int64 )
    chose_random = tf . random_uniform ( tf . stack ( [ batch_size ] ) , minval = 0 , maxval = 1 , dtype = tf . float32 ) < eps
    stochastic_actions = tf . where ( chose_random , random_actions , deterministic_actions )
    output_actions = tf . cond ( stochastic_ph , lambda : stochastic_actions , lambda : deterministic_actions )
    update_eps_expr = eps . assign ( tf . cond ( update_eps_ph >= 0 , lambda : update_eps_ph , lambda : eps ) )
    updates = [ update_eps_expr , tf . cond ( reset_ph , lambda : perturb_vars ( original_scope = "q_func" , perturbed_scope = "perturbed_q_func" ) , lambda : tf . group ( * [ ] ) ) , tf . cond ( update_param_noise_scale_ph , lambda : update_scale ( ) , lambda : tf . Variable ( 0. , trainable = False ) ) , update_param_noise_threshold_expr , ]
    _act = U . function ( inputs = [ observations_ph , stochastic_ph , update_eps_ph , reset_ph , update_param_noise_threshold_ph , update_param_noise_scale_ph ] , outputs = output_actions , givens = { update_eps_ph : - 1.0 , stochastic_ph : True , reset_ph : False , update_param_noise_threshold_ph : False , update_param_noise_scale_ph : False } , updates = updates )
    def act ( ob , reset = False , update_param_noise_threshold = False , update_param_noise_scale = False , stochastic = True , update_eps = - 1 ) :
        return _act ( ob , stochastic , update_eps , reset , update_param_noise_threshold , update_param_noise_scale )
    return act


signature:
def build_train ( make_obs_ph , q_func , num_actions , optimizer , grad_norm_clipping = None , gamma = 1.0 , double_q = True , scope = "deepq" , reuse = None , param_noise = False , param_noise_filter_func = None ) :
    """Creates the train function :
 Parameters
 make _ obs _ ph : str - > tf . placeholder or TfInput
 a function that takes a name and creates a placeholder of input with that name
 q _ func : ( tf . Variable , int , str , bool ) - > tf . Variable
 the model that takes the following inputs :
 observation _ in : object
 the output of observation placeholder
 num _ actions : int
 number of actions
 scope : str
 reuse : bool
 should be passed to outer variable scope
 and returns a tensor of shape ( batch _ size , num _ actions ) with values of every action .
 num _ actions : int
 number of actions
 reuse : bool
 whether or not to reuse the graph variables
 optimizer : tf . train . Optimizer
 optimizer to use for the Q - learning objective .
 grad _ norm _ clipping : float or None
 clip gradient norms to this value . If None no clipping is performed .
 gamma : float
 discount rate .
 double _ q : bool
 if true will use Double Q Learning ( https : / / arxiv . org / abs / 1509.06461 ) .
 In general it is a good idea to keep it enabled .
 scope : str or VariableScope
 optional scope for variable _ scope .
 reuse : bool or None
 whether or not the variables should be reused . To be able to reuse the scope must be given .
 param _ noise : bool
 whether or not to use parameter space noise ( https : / / arxiv . org / abs / 1706.01905)
 param _ noise _ filter _ func : tf . Variable - > bool
 function that decides whether or not a variable should be perturbed . Only applicable
 if param _ noise is True . If set to None , default _ param _ noise _ filter is used by default .
 Returns
 act : ( tf . Variable , bool , float ) - > tf . Variable
 function to select and action given observation .
 ` See the top of the file for details .
 train : ( object , np . array , np . array , object , np . array , np . array ) - > np . array
 optimize the error in Bellman ' s equation .
 ` See the top of the file for details .
 update _ target : ( ) - > ( )
 copy the parameters from optimized Q function to the target Q function .
 ` See the top of the file for details .
 debug : { str : function }
 a bunch of functions to print debug data like q _ values ."""

implementation:
if param_noise :
    act_f = build_act_with_param_noise ( make_obs_ph , q_func , num_actions , scope = scope , reuse = reuse , param_noise_filter_func = param_noise_filter_func )
else :
    act_f = build_act ( make_obs_ph , q_func , num_actions , scope = scope , reuse = reuse )
with tf . variable_scope ( scope , reuse = reuse ) : # set up placeholders
    obs_t_input = make_obs_ph ( "obs_t" )
    act_t_ph = tf . placeholder ( tf . int32 , [ None ] , name = "action" )
    rew_t_ph = tf . placeholder ( tf . float32 , [ None ] , name = "reward" )
    obs_tp1_input = make_obs_ph ( "obs_tp1" )
    done_mask_ph = tf . placeholder ( tf . float32 , [ None ] , name = "done" )
    importance_weights_ph = tf . placeholder ( tf . float32 , [ None ] , name = "weight" )
    # q network evaluation
    q_t = q_func ( obs_t_input . get ( ) , num_actions , scope = "q_func" , reuse = True )
    # reuse parameters from act
    q_func_vars = tf . get_collection ( tf . GraphKeys . GLOBAL_VARIABLES , scope = tf . get_variable_scope ( ) . name + "/q_func" )
    # target q network evalution
    q_tp1 = q_func ( obs_tp1_input . get ( ) , num_actions , scope = "target_q_func" )
    target_q_func_vars = tf . get_collection ( tf . GraphKeys . GLOBAL_VARIABLES , scope = tf . get_variable_scope ( ) . name + "/target_q_func" )
    # q scores for actions which we know were selected in the given state .
    q_t_selected = tf . reduce_sum ( q_t * tf . one_hot ( act_t_ph , num_actions ) , 1 )
    # compute estimate of best possible value starting from state at t + 1
    if double_q :
        q_tp1_using_online_net = q_func ( obs_tp1_input . get ( ) , num_actions , scope = "q_func" , reuse = True )
        q_tp1_best_using_online_net = tf . argmax ( q_tp1_using_online_net , 1 )
        q_tp1_best = tf . reduce_sum ( q_tp1 * tf . one_hot ( q_tp1_best_using_online_net , num_actions ) , 1 )
    else :
        q_tp1_best = tf . reduce_max ( q_tp1 , 1 )
    q_tp1_best_masked = ( 1.0 - done_mask_ph ) * q_tp1_best
    # compute RHS of bellman equation
    q_t_selected_target = rew_t_ph + gamma * q_tp1_best_masked
    # compute the error ( potentially clipped )
    td_error = q_t_selected - tf . stop_gradient ( q_t_selected_target )
    errors = U . huber_loss ( td_error )
    weighted_error = tf . reduce_mean ( importance_weights_ph * errors )
    # compute optimization op ( potentially with gradient clipping )
    if grad_norm_clipping is not None :
        gradients = optimizer . compute_gradients ( weighted_error , var_list = q_func_vars )
        for i , ( grad , var ) in enumerate ( gradients ) :
            if grad is not None :
                gradients [ i ] = ( tf . clip_by_norm ( grad , grad_norm_clipping ) , var )
        optimize_expr = optimizer . apply_gradients ( gradients )
    else :
        optimize_expr = optimizer . minimize ( weighted_error , var_list = q_func_vars )
    # update _ target _ fn will be called periodically to copy Q network to target Q network
    update_target_expr = [ ]
    for var , var_target in zip ( sorted ( q_func_vars , key = lambda v : v . name ) , sorted ( target_q_func_vars , key = lambda v : v . name ) ) :
        update_target_expr . append ( var_target . assign ( var ) )
    update_target_expr = tf . group ( * update_target_expr )
    # Create callable functions
    train = U . function ( inputs = [ obs_t_input , act_t_ph , rew_t_ph , obs_tp1_input , done_mask_ph , importance_weights_ph ] , outputs = td_error , updates = [ optimize_expr ] )
    update_target = U . function ( [ ] , [ ] , updates = [ update_target_expr ] )
    q_values = U . function ( [ obs_t_input ] , q_t )
    return act_f , train , update_target , { 'q_values' : q_values }


signature:
def profile_tf_runningmeanstd ( ) :
    import time
    from baselines . common import tf_util
    tf_util . get_session ( config = tf . ConfigProto ( inter_op_parallelism_threads = 1 , intra_op_parallelism_threads = 1 , allow_soft_placement = True ) )
    x = np . random . random ( ( 376 , ) )
    n_trials = 10000
    rms = RunningMeanStd ( )
    tfrms = TfRunningMeanStd ( )
    tic1 = time . time ( )
    for _ in range ( n_trials ) :
        rms . update ( x )
    tic2 = time . time ( )
    for _ in range ( n_trials ) :
        tfrms . update ( x )
    tic3 = time . time ( )
    print ( 'rms update time ({} trials): {} s' . format ( n_trials , tic2 - tic1 ) )
    print ( 'tfrms update time ({} trials): {} s' . format ( n_trials , tic3 - tic2 ) )
    tic1 = time . time ( )
    for _ in range ( n_trials ) :
        z1 = rms . mean
    tic2 = time . time ( )
    for _ in range ( n_trials ) :
        z2 = tfrms . mean
    assert z1 == z2
    tic3 = time . time ( )
    print ( 'rms get mean time ({} trials): {} s' . format ( n_trials , tic2 - tic1 ) )
    print ( 'tfrms get mean time ({} trials): {} s' . format ( n_trials , tic3 - tic2 ) )
    '''options = tf . RunOptions ( trace _ level = tf . RunOptions . FULL _ TRACE ) # pylint : disable = E1101
 run _ metadata = tf . RunMetadata ( )
 profile _ opts = dict ( options = options , run _ metadata = run _ metadata )
 from tensorflow . python . client import timeline
 fetched _ timeline = timeline . Timeline ( run _ metadata . step _ stats ) # pylint : disable = E1101
 chrome _ trace = fetched _ timeline . generate _ chrome _ trace _ format ( )
 outfile = ' / tmp / timeline . json '
 with open ( outfile , ' wt ' ) as f :
 f . write ( chrome _ trace )
 print ( ' Successfully saved profile to { } . Exiting . ' . format ( outfile ) )
 exit ( 0)'''


signature:
def model ( inpt , num_actions , scope , reuse = False ) :
    """This model takes as input an observation and returns values of all actions ."""

implementation:
with tf . variable_scope ( scope , reuse = reuse ) :
    out = inpt
    out = layers . fully_connected ( out , num_outputs = 64 , activation_fn = tf . nn . tanh )
    out = layers . fully_connected ( out , num_outputs = num_actions , activation_fn = None )
    return out


signature:
def sample ( self , batch_size ) :
    """Returns a dict { key : array ( batch _ size x shapes [ key ] ) }"""

implementation:
buffers = { }
with self . lock :
    assert self . current_size > 0
    for key in self . buffers . keys ( ) :
        buffers [ key ] = self . buffers [ key ] [ : self . current_size ]
buffers [ 'o_2' ] = buffers [ 'o' ] [ : , 1 : , : ]
buffers [ 'ag_2' ] = buffers [ 'ag' ] [ : , 1 : , : ]
transitions = self . sample_transitions ( buffers , batch_size )
for key in ( [ 'r' , 'o_2' , 'ag_2' ] + list ( self . buffers . keys ( ) ) ) :
    assert key in transitions , "key %s missing from transitions" % key
return transitions


signature:
def store_episode ( self , episode_batch ) :
    """episode _ batch : array ( batch _ size x ( T or T + 1 ) x dim _ key )"""

implementation:
batch_sizes = [ len ( episode_batch [ key ] ) for key in episode_batch . keys ( ) ]
assert np . all ( np . array ( batch_sizes ) == batch_sizes [ 0 ] )
batch_size = batch_sizes [ 0 ]
with self . lock :
    idxs = self . _get_storage_idx ( batch_size )
    # load inputs into buffers
    for key in self . buffers . keys ( ) :
        self . buffers [ key ] [ idxs ] = episode_batch [ key ]
    self . n_transitions_stored += batch_size * self . T


signature:
def store_episode ( self , episode_batch , update_stats = True ) :
    """episode _ batch : array of batch _ size x ( T or T + 1 ) x dim _ key
 ' o ' is of size T + 1 , others are of size T"""

implementation:
self . buffer . store_episode ( episode_batch )
if update_stats : # add transitions to normalizer
    episode_batch [ 'o_2' ] = episode_batch [ 'o' ] [ : , 1 : , : ]
    episode_batch [ 'ag_2' ] = episode_batch [ 'ag' ] [ : , 1 : , : ]
    num_normalizing_transitions = transitions_in_episode_batch ( episode_batch )
    transitions = self . sample_transitions ( episode_batch , num_normalizing_transitions )
    o , g , ag = transitions [ 'o' ] , transitions [ 'g' ] , transitions [ 'ag' ]
    transitions [ 'o' ] , transitions [ 'g' ] = self . _preprocess_og ( o , ag , g )
    # No need to preprocess the o _ 2 and g _ 2 since this is only used for stats
    self . o_stats . update ( transitions [ 'o' ] )
    self . g_stats . update ( transitions [ 'g' ] )
    self . o_stats . recompute_stats ( )
    self . g_stats . recompute_stats ( )


signature:
def parse_cmdline_kwargs ( args ) :
    '''convert a list of ' = ' - spaced command - line arguments to a dictionary , evaluating python objects when possible'''

implementation:
def parse ( v ) :
    assert isinstance ( v , str )
    try :
        return eval ( v )
    except ( NameError , SyntaxError ) :
        return v
return { k : parse ( v ) for k , v in parse_unknown_args ( args ) . items ( ) }


signature:
def cached_make_env ( make_env ) :
    """Only creates a new environment from the provided function if one has not yet already been
 created . This is useful here because we need to infer certain properties of the env , e . g .
 its observation and action spaces , without any intend of actually using it ."""

implementation:
if make_env not in CACHED_ENVS :
    env = make_env ( )
    CACHED_ENVS [ make_env ] = env
return CACHED_ENVS [ make_env ]


signature:
def compute_geometric_median ( X , eps = 1e-5 ) :
    """Estimate the geometric median of points in 2D .
 Code from https : / / stackoverflow . com / a / 30305181
 Parameters
 X : ( N , 2 ) ndarray
 Points in 2D . Second axis must be given in xy - form .
 eps : float , optional
 Distance threshold when to return the median .
 Returns
 (2 , ) ndarray
 Geometric median as xy - coordinate ."""

implementation:
y = np . mean ( X , 0 )
while True :
    D = scipy . spatial . distance . cdist ( X , [ y ] )
    nonzeros = ( D != 0 ) [ : , 0 ]
    Dinv = 1 / D [ nonzeros ]
    Dinvs = np . sum ( Dinv )
    W = Dinv / Dinvs
    T = np . sum ( W * X [ nonzeros ] , 0 )
    num_zeros = len ( X ) - np . sum ( nonzeros )
    if num_zeros == 0 :
        y1 = T
    elif num_zeros == len ( X ) :
        return y
    else :
        R = ( T - y ) * Dinvs
        r = np . linalg . norm ( R )
        rinv = 0 if r == 0 else num_zeros / r
        y1 = max ( 0 , 1 - rinv ) * T + min ( 1 , rinv ) * y
    if scipy . spatial . distance . euclidean ( y , y1 ) < eps :
        return y1
    y = y1


signature:
def project ( self , from_shape , to_shape ) :
    """Project the keypoint onto a new position on a new image .
 E . g . if the keypoint is on its original image at x = ( 10 of 100 pixels )
 and y = ( 20 of 100 pixels ) and is projected onto a new image with
 size ( width = 200 , height = 200 ) , its new position will be ( 20 , 40 ) .
 This is intended for cases where the original image is resized .
 It cannot be used for more complex changes ( e . g . padding , cropping ) .
 Parameters
 from _ shape : tuple of int
 Shape of the original image . ( Before resize . )
 to _ shape : tuple of int
 Shape of the new image . ( After resize . )
 Returns
 imgaug . Keypoint
 Keypoint object with new coordinates ."""

implementation:
xy_proj = project_coords ( [ ( self . x , self . y ) ] , from_shape , to_shape )
return self . deepcopy ( x = xy_proj [ 0 ] [ 0 ] , y = xy_proj [ 0 ] [ 1 ] )


signature:
def shift ( self , x = 0 , y = 0 ) :
    """Move the keypoint around on an image .
 Parameters
 x : number , optional
 Move by this value on the x axis .
 y : number , optional
 Move by this value on the y axis .
 Returns
 imgaug . Keypoint
 Keypoint object with new coordinates ."""

implementation: return self . deepcopy ( self . x + x , self . y + y )


signature:
def draw_on_image ( self , image , color = ( 0 , 255 , 0 ) , alpha = 1.0 , size = 3 , copy = True , raise_if_out_of_image = False ) :
    """Draw the keypoint onto a given image .
 The keypoint is drawn as a square .
 Parameters
 image : ( H , W , 3 ) ndarray
 The image onto which to draw the keypoint .
 color : int or list of int or tuple of int or ( 3 , ) ndarray , optional
 The RGB color of the keypoint . If a single int ` ` C ` ` , then that is
 equivalent to ` ` ( C , C , C ) ` ` .
 alpha : float , optional
 The opacity of the drawn keypoint , where ` ` 1.0 ` ` denotes a fully
 visible keypoint and ` ` 0.0 ` ` an invisible one .
 size : int , optional
 The size of the keypoint . If set to ` ` S ` ` , each square will have
 size ` ` S x S ` ` .
 copy : bool , optional
 Whether to copy the image before drawing the keypoint .
 raise _ if _ out _ of _ image : bool , optional
 Whether to raise an exception if the keypoint is outside of the
 image .
 Returns
 image : ( H , W , 3 ) ndarray
 Image with drawn keypoint ."""

implementation:
if copy :
    image = np . copy ( image )
if image . ndim == 2 :
    assert ia . is_single_number ( color ) , ( "Got a 2D image. Expected then 'color' to be a single number, " "but got %s." % ( str ( color ) , ) )
elif image . ndim == 3 and ia . is_single_number ( color ) :
    color = [ color ] * image . shape [ - 1 ]
input_dtype = image . dtype
alpha_color = color
if alpha < 0.01 : # keypoint invisible , nothing to do
    return image
elif alpha > 0.99 :
    alpha = 1
else :
    image = image . astype ( np . float32 , copy = False )
    alpha_color = alpha * np . array ( color )
height , width = image . shape [ 0 : 2 ]
y , x = self . y_int , self . x_int
x1 = max ( x - size // 2 , 0 )
x2 = min ( x + 1 + size // 2 , width )
y1 = max ( y - size // 2 , 0 )
y2 = min ( y + 1 + size // 2 , height )
x1_clipped , x2_clipped = np . clip ( [ x1 , x2 ] , 0 , width )
y1_clipped , y2_clipped = np . clip ( [ y1 , y2 ] , 0 , height )
x1_clipped_ooi = ( x1_clipped < 0 or x1_clipped >= width )
x2_clipped_ooi = ( x2_clipped < 0 or x2_clipped >= width + 1 )
y1_clipped_ooi = ( y1_clipped < 0 or y1_clipped >= height )
y2_clipped_ooi = ( y2_clipped < 0 or y2_clipped >= height + 1 )
x_ooi = ( x1_clipped_ooi and x2_clipped_ooi )
y_ooi = ( y1_clipped_ooi and y2_clipped_ooi )
x_zero_size = ( x2_clipped - x1_clipped ) < 1
# min size is 1px
y_zero_size = ( y2_clipped - y1_clipped ) < 1
if not x_ooi and not y_ooi and not x_zero_size and not y_zero_size :
    if alpha == 1 :
        image [ y1_clipped : y2_clipped , x1_clipped : x2_clipped ] = color
    else :
        image [ y1_clipped : y2_clipped , x1_clipped : x2_clipped ] = ( ( 1 - alpha ) * image [ y1_clipped : y2_clipped , x1_clipped : x2_clipped ] + alpha_color )
else :
    if raise_if_out_of_image :
        raise Exception ( "Cannot draw keypoint x=%.8f, y=%.8f on image with " "shape %s." % ( y , x , image . shape ) )
if image . dtype . name != input_dtype . name :
    if input_dtype . name == "uint8" :
        image = np . clip ( image , 0 , 255 , out = image )
    image = image . astype ( input_dtype , copy = False )
return image


signature:
def generate_similar_points_manhattan ( self , nb_steps , step_size , return_array = False ) :
    """Generate nearby points to this keypoint based on manhattan distance .
 To generate the first neighbouring points , a distance of S ( step size ) is moved from the
 center point ( this keypoint ) to the top , right , bottom and left , resulting in four new
 points . From these new points , the pattern is repeated . Overlapping points are ignored .
 The resulting points have a shape similar to a square rotated by 45 degrees .
 Parameters
 nb _ steps : int
 The number of steps to move from the center point . nb _ steps = 1 results in a total of
 5 output points ( 1 center point + 4 neighbours ) .
 step _ size : number
 The step size to move from every point to its neighbours .
 return _ array : bool , optional
 Whether to return the generated points as a list of keypoints or an array
 of shape ` ` ( N , 2 ) ` ` , where ` ` N ` ` is the number of generated points and the second axis contains
 the x - ( first value ) and y - ( second value ) coordinates .
 Returns
 points : list of imgaug . Keypoint or ( N , 2 ) ndarray
 If return _ array was False , then a list of Keypoint .
 Otherwise a numpy array of shape ` ` ( N , 2 ) ` ` , where ` ` N ` ` is the number of generated points and
 the second axis contains the x - ( first value ) and y - ( second value ) coordinates .
 The center keypoint ( the one on which this function was called ) is always included ."""

implementation:
# TODO add test
# Points generates in manhattan style with S steps have a shape similar to a 45deg rotated
# square . The center line with the origin point has S + 1 + S = 1 + 2 * S points ( S to the left ,
# S to the right ) . The lines above contain ( S + 1 + S ) - 2 + ( S + 1 + S ) - 2-2 + . . . + 1 points . E . g .
# for S = 2 it would be 3 + 1 = 4 and for S = 3 it would be 5 + 3 + 1 = 9 . Same for the lines below the
# center . Hence the total number of points is S + 1 + S + 2 * ( S ^ 2 ) .
points = np . zeros ( ( nb_steps + 1 + nb_steps + 2 * ( nb_steps ** 2 ) , 2 ) , dtype = np . float32 )
# we start at the bottom - most line and move towards the top - most line
yy = np . linspace ( self . y - nb_steps * step_size , self . y + nb_steps * step_size , nb_steps + 1 + nb_steps )
# bottom - most line contains only one point
width = 1
nth_point = 0
for i_y , y in enumerate ( yy ) :
    if width == 1 :
        xx = [ self . x ]
    else :
        xx = np . linspace ( self . x - ( width - 1 ) // 2 * step_size , self . x + ( width - 1 ) // 2 * step_size , width )
    for x in xx :
        points [ nth_point ] = [ x , y ]
        nth_point += 1
    if i_y < nb_steps :
        width += 2
    else :
        width -= 2
if return_array :
    return points
return [ self . deepcopy ( x = points [ i , 0 ] , y = points [ i , 1 ] ) for i in sm . xrange ( points . shape [ 0 ] ) ]


signature:
def copy ( self , x = None , y = None ) :
    """Create a shallow copy of the Keypoint object .
 Parameters
 x : None or number , optional
 Coordinate of the keypoint on the x axis .
 If ` ` None ` ` , the instance ' s value will be copied .
 y : None or number , optional
 Coordinate of the keypoint on the y axis .
 If ` ` None ` ` , the instance ' s value will be copied .
 Returns
 imgaug . Keypoint
 Shallow copy ."""

implementation: return self . deepcopy ( x = x , y = y )


signature:
def deepcopy ( self , x = None , y = None ) :
    """Create a deep copy of the Keypoint object .
 Parameters
 x : None or number , optional
 Coordinate of the keypoint on the x axis .
 If ` ` None ` ` , the instance ' s value will be copied .
 y : None or number , optional
 Coordinate of the keypoint on the y axis .
 If ` ` None ` ` , the instance ' s value will be copied .
 Returns
 imgaug . Keypoint
 Deep copy ."""

implementation:
x = self . x if x is None else x
y = self . y if y is None else y
return Keypoint ( x = x , y = y )


signature:
def on ( self , image ) :
    """Project keypoints from one image to a new one .
 Parameters
 image : ndarray or tuple of int
 New image onto which the keypoints are to be projected .
 May also simply be that new image ' s shape tuple .
 Returns
 keypoints : imgaug . KeypointsOnImage
 Object containing all projected keypoints ."""

implementation:
shape = normalize_shape ( image )
if shape [ 0 : 2 ] == self . shape [ 0 : 2 ] :
    return self . deepcopy ( )
else :
    keypoints = [ kp . project ( self . shape , shape ) for kp in self . keypoints ]
    return self . deepcopy ( keypoints , shape )


signature:
def draw_on_image ( self , image , color = ( 0 , 255 , 0 ) , alpha = 1.0 , size = 3 , copy = True , raise_if_out_of_image = False ) :
    """Draw all keypoints onto a given image .
 Each keypoint is marked by a square of a chosen color and size .
 Parameters
 image : ( H , W , 3 ) ndarray
 The image onto which to draw the keypoints .
 This image should usually have the same shape as
 set in KeypointsOnImage . shape .
 color : int or list of int or tuple of int or ( 3 , ) ndarray , optional
 The RGB color of all keypoints . If a single int ` ` C ` ` , then that is
 equivalent to ` ` ( C , C , C ) ` ` .
 alpha : float , optional
 The opacity of the drawn keypoint , where ` ` 1.0 ` ` denotes a fully
 visible keypoint and ` ` 0.0 ` ` an invisible one .
 size : int , optional
 The size of each point . If set to ` ` C ` ` , each square will have
 size ` ` C x C ` ` .
 copy : bool , optional
 Whether to copy the image before drawing the points .
 raise _ if _ out _ of _ image : bool , optional
 Whether to raise an exception if any keypoint is outside of the image .
 Returns
 image : ( H , W , 3 ) ndarray
 Image with drawn keypoints ."""

implementation:
image = np . copy ( image ) if copy else image
for keypoint in self . keypoints :
    image = keypoint . draw_on_image ( image , color = color , alpha = alpha , size = size , copy = False , raise_if_out_of_image = raise_if_out_of_image )
return image


signature:
def shift ( self , x = 0 , y = 0 ) :
    """Move the keypoints around on an image .
 Parameters
 x : number , optional
 Move each keypoint by this value on the x axis .
 y : number , optional
 Move each keypoint by this value on the y axis .
 Returns
 out : KeypointsOnImage
 Keypoints after moving them ."""

implementation:
keypoints = [ keypoint . shift ( x = x , y = y ) for keypoint in self . keypoints ]
return self . deepcopy ( keypoints )


signature:
def to_xy_array ( self ) :
    """Convert keypoint coordinates to ` ` ( N , 2 ) ` ` array .
 Returns
 ( N , 2 ) ndarray
 Array containing the coordinates of all keypoints .
 Shape is ` ` ( N , 2 ) ` ` with coordinates in xy - form ."""

implementation:
result = np . zeros ( ( len ( self . keypoints ) , 2 ) , dtype = np . float32 )
for i , keypoint in enumerate ( self . keypoints ) :
    result [ i , 0 ] = keypoint . x
    result [ i , 1 ] = keypoint . y
return result


signature:
def from_xy_array ( cls , xy , shape ) :
    """Convert an array ( N , 2 ) with a given image shape to a KeypointsOnImage object .
 Parameters
 xy : ( N , 2 ) ndarray
 Coordinates of ` ` N ` ` keypoints on the original image , given
 as ` ` ( N , 2 ) ` ` array of xy - coordinates .
 shape : tuple of int or ndarray
 Shape tuple of the image on which the keypoints are placed .
 Returns
 KeypointsOnImage
 KeypointsOnImage object that contains all keypoints from the array ."""

implementation:
keypoints = [ Keypoint ( x = coord [ 0 ] , y = coord [ 1 ] ) for coord in xy ]
return KeypointsOnImage ( keypoints , shape )


signature:
def to_keypoint_image ( self , size = 1 ) :
    """Draws a new black image of shape ` ` ( H , W , N ) ` ` in which all keypoint coordinates are set to 255.
 ( H = shape height , W = shape width , N = number of keypoints )
 This function can be used as a helper when augmenting keypoints with a method that only supports the
 augmentation of images .
 Parameters
 size : int
 Size of each ( squared ) point .
 Returns
 image : ( H , W , N ) ndarray
 Image in which the keypoints are marked . H is the height ,
 defined in KeypointsOnImage . shape [ 0 ] ( analogous W ) . N is the
 number of keypoints ."""

implementation:
ia . do_assert ( len ( self . keypoints ) > 0 )
height , width = self . shape [ 0 : 2 ]
image = np . zeros ( ( height , width , len ( self . keypoints ) ) , dtype = np . uint8 )
ia . do_assert ( size % 2 != 0 )
sizeh = max ( 0 , ( size - 1 ) // 2 )
for i , keypoint in enumerate ( self . keypoints ) : # TODO for float values spread activation over several cells
# here and do voting at the end
    y = keypoint . y_int
    x = keypoint . x_int
    x1 = np . clip ( x - sizeh , 0 , width - 1 )
    x2 = np . clip ( x + sizeh + 1 , 0 , width )
    y1 = np . clip ( y - sizeh , 0 , height - 1 )
    y2 = np . clip ( y + sizeh + 1 , 0 , height )
    if x1 < x2 and y1 < y2 :
        image [ y1 : y2 , x1 : x2 , i ] = 128
    if 0 <= y < height and 0 <= x < width :
        image [ y , x , i ] = 255
return image


signature:
def from_keypoint_image ( image , if_not_found_coords = { "x" : - 1 , "y" : - 1 } , threshold = 1 , nb_channels = None ) : # pylint : disable = locally - disabled , dangerous - default - value , line - too - long
    """Converts an image generated by ` ` to _ keypoint _ image ( ) ` ` back to a KeypointsOnImage object .
 Parameters
 image : ( H , W , N ) ndarray
 The keypoints image . N is the number of keypoints .
 if _ not _ found _ coords : tuple or list or dict or None , optional
 Coordinates to use for keypoints that cannot be found in ` image ` .
 If this is a list / tuple , it must have two integer values .
 If it is a dictionary , it must have the keys ` ` x ` ` and ` ` y ` ` with
 each containing one integer value .
 If this is None , then the keypoint will not be added to the final
 KeypointsOnImage object .
 threshold : int , optional
 The search for keypoints works by searching for the argmax in
 each channel . This parameters contains the minimum value that
 the max must have in order to be viewed as a keypoint .
 nb _ channels : None or int , optional
 Number of channels of the image on which the keypoints are placed .
 Some keypoint augmenters require that information .
 If set to None , the keypoint ' s shape will be set
 to ` ` ( height , width ) ` ` , otherwise ` ` ( height , width , nb _ channels ) ` ` .
 Returns
 out : KeypointsOnImage
 The extracted keypoints ."""

implementation:
ia . do_assert ( len ( image . shape ) == 3 )
height , width , nb_keypoints = image . shape
drop_if_not_found = False
if if_not_found_coords is None :
    drop_if_not_found = True
    if_not_found_x = - 1
    if_not_found_y = - 1
elif isinstance ( if_not_found_coords , ( tuple , list ) ) :
    ia . do_assert ( len ( if_not_found_coords ) == 2 )
    if_not_found_x = if_not_found_coords [ 0 ]
    if_not_found_y = if_not_found_coords [ 1 ]
elif isinstance ( if_not_found_coords , dict ) :
    if_not_found_x = if_not_found_coords [ "x" ]
    if_not_found_y = if_not_found_coords [ "y" ]
else :
    raise Exception ( "Expected if_not_found_coords to be None or tuple or list or dict, got %s." % ( type ( if_not_found_coords ) , ) )
keypoints = [ ]
for i in sm . xrange ( nb_keypoints ) :
    maxidx_flat = np . argmax ( image [ ... , i ] )
    maxidx_ndim = np . unravel_index ( maxidx_flat , ( height , width ) )
    found = ( image [ maxidx_ndim [ 0 ] , maxidx_ndim [ 1 ] , i ] >= threshold )
    if found :
        keypoints . append ( Keypoint ( x = maxidx_ndim [ 1 ] , y = maxidx_ndim [ 0 ] ) )
    else :
        if drop_if_not_found :
            pass
            # dont add the keypoint to the result list , i . e . drop it
        else :
            keypoints . append ( Keypoint ( x = if_not_found_x , y = if_not_found_y ) )
out_shape = ( height , width )
if nb_channels is not None :
    out_shape += ( nb_channels , )
return KeypointsOnImage ( keypoints , shape = out_shape )


signature:
def to_distance_maps ( self , inverted = False ) :
    """Generates a ` ` ( H , W , K ) ` ` output containing ` ` K ` ` distance maps for ` ` K ` ` keypoints .
 The k - th distance map contains at every location ` ` ( y , x ) ` ` the euclidean distance to the k - th keypoint .
 This function can be used as a helper when augmenting keypoints with a method that only supports
 the augmentation of images .
 Parameters
 inverted : bool , optional
 If True , inverted distance maps are returned where each distance value d is replaced
 by ` ` d / ( d + 1 ) ` ` , i . e . the distance maps have values in the range ` ` ( 0.0 , 1.0 ] ` ` with 1.0
 denoting exactly the position of the respective keypoint .
 Returns
 distance _ maps : ( H , W , K ) ndarray
 A ` ` float32 ` ` array containing ` ` K ` ` distance maps for ` ` K ` ` keypoints . Each location
 ` ` ( y , x , k ) ` ` in the array denotes the euclidean distance at ` ` ( y , x ) ` ` to the ` ` k ` ` - th keypoint .
 In inverted mode the distance ` ` d ` ` is replaced by ` ` d / ( d + 1 ) ` ` . The height and width
 of the array match the height and width in ` ` KeypointsOnImage . shape ` ` ."""

implementation:
ia . do_assert ( len ( self . keypoints ) > 0 )
height , width = self . shape [ 0 : 2 ]
distance_maps = np . zeros ( ( height , width , len ( self . keypoints ) ) , dtype = np . float32 )
yy = np . arange ( 0 , height )
xx = np . arange ( 0 , width )
grid_xx , grid_yy = np . meshgrid ( xx , yy )
for i , keypoint in enumerate ( self . keypoints ) :
    y , x = keypoint . y , keypoint . x
    distance_maps [ : , : , i ] = ( grid_xx - x ) ** 2 + ( grid_yy - y ) ** 2
distance_maps = np . sqrt ( distance_maps )
if inverted :
    return 1 / ( distance_maps + 1 )
return distance_maps


signature:
def from_distance_maps ( distance_maps , inverted = False , if_not_found_coords = { "x" : - 1 , "y" : - 1 } , threshold = None , # pylint : disable = locally - disabled , dangerous - default - value , line - too - long
nb_channels = None ) :
    """Converts maps generated by ` ` to _ distance _ maps ( ) ` ` back to a KeypointsOnImage object .
 Parameters
 distance _ maps : ( H , W , N ) ndarray
 The distance maps . N is the number of keypoints .
 inverted : bool , optional
 Whether the given distance maps were generated in inverted or normal mode .
 if _ not _ found _ coords : tuple or list or dict or None , optional
 Coordinates to use for keypoints that cannot be found in ` ` distance _ maps ` ` .
 If this is a list / tuple , it must have two integer values .
 If it is a dictionary , it must have the keys ` ` x ` ` and ` ` y ` ` , with each
 containing one integer value .
 If this is None , then the keypoint will not be added to the final
 KeypointsOnImage object .
 threshold : float , optional
 The search for keypoints works by searching for the argmin ( non - inverted ) or
 argmax ( inverted ) in each channel . This parameters contains the maximum ( non - inverted )
 or minimum ( inverted ) value to accept in order to view a hit as a keypoint .
 Use None to use no min / max .
 nb _ channels : None or int , optional
 Number of channels of the image on which the keypoints are placed .
 Some keypoint augmenters require that information .
 If set to None , the keypoint ' s shape will be set
 to ` ` ( height , width ) ` ` , otherwise ` ` ( height , width , nb _ channels ) ` ` .
 Returns
 imgaug . KeypointsOnImage
 The extracted keypoints ."""

implementation:
ia . do_assert ( len ( distance_maps . shape ) == 3 )
height , width , nb_keypoints = distance_maps . shape
drop_if_not_found = False
if if_not_found_coords is None :
    drop_if_not_found = True
    if_not_found_x = - 1
    if_not_found_y = - 1
elif isinstance ( if_not_found_coords , ( tuple , list ) ) :
    ia . do_assert ( len ( if_not_found_coords ) == 2 )
    if_not_found_x = if_not_found_coords [ 0 ]
    if_not_found_y = if_not_found_coords [ 1 ]
elif isinstance ( if_not_found_coords , dict ) :
    if_not_found_x = if_not_found_coords [ "x" ]
    if_not_found_y = if_not_found_coords [ "y" ]
else :
    raise Exception ( "Expected if_not_found_coords to be None or tuple or list or dict, got %s." % ( type ( if_not_found_coords ) , ) )
keypoints = [ ]
for i in sm . xrange ( nb_keypoints ) : # TODO introduce voting here among all distance values that have min / max values
    if inverted :
        hitidx_flat = np . argmax ( distance_maps [ ... , i ] )
    else :
        hitidx_flat = np . argmin ( distance_maps [ ... , i ] )
    hitidx_ndim = np . unravel_index ( hitidx_flat , ( height , width ) )
    if not inverted and threshold is not None :
        found = ( distance_maps [ hitidx_ndim [ 0 ] , hitidx_ndim [ 1 ] , i ] < threshold )
    elif inverted and threshold is not None :
        found = ( distance_maps [ hitidx_ndim [ 0 ] , hitidx_ndim [ 1 ] , i ] >= threshold )
    else :
        found = True
    if found :
        keypoints . append ( Keypoint ( x = hitidx_ndim [ 1 ] , y = hitidx_ndim [ 0 ] ) )
    else :
        if drop_if_not_found :
            pass
            # dont add the keypoint to the result list , i . e . drop it
        else :
            keypoints . append ( Keypoint ( x = if_not_found_x , y = if_not_found_y ) )
out_shape = ( height , width )
if nb_channels is not None :
    out_shape += ( nb_channels , )
return KeypointsOnImage ( keypoints , shape = out_shape )


signature:
def copy ( self , keypoints = None , shape = None ) :
    """Create a shallow copy of the KeypointsOnImage object .
 Parameters
 keypoints : None or list of imgaug . Keypoint , optional
 List of keypoints on the image . If ` ` None ` ` , the instance ' s
 keypoints will be copied .
 shape : tuple of int , optional
 The shape of the image on which the keypoints are placed .
 If ` ` None ` ` , the instance ' s shape will be copied .
 Returns
 imgaug . KeypointsOnImage
 Shallow copy ."""

implementation:
result = copy . copy ( self )
if keypoints is not None :
    result . keypoints = keypoints
if shape is not None :
    result . shape = shape
return result


signature:
def deepcopy ( self , keypoints = None , shape = None ) :
    """Create a deep copy of the KeypointsOnImage object .
 Parameters
 keypoints : None or list of imgaug . Keypoint , optional
 List of keypoints on the image . If ` ` None ` ` , the instance ' s
 keypoints will be copied .
 shape : tuple of int , optional
 The shape of the image on which the keypoints are placed .
 If ` ` None ` ` , the instance ' s shape will be copied .
 Returns
 imgaug . KeypointsOnImage
 Deep copy ."""

implementation:
# for some reason deepcopy is way slower here than manual copy
if keypoints is None :
    keypoints = [ kp . deepcopy ( ) for kp in self . keypoints ]
if shape is None :
    shape = tuple ( self . shape )
return KeypointsOnImage ( keypoints , shape )


signature:
def contains ( self , other ) :
    """Estimate whether the bounding box contains a point .
 Parameters
 other : tuple of number or imgaug . Keypoint
 Point to check for .
 Returns
 bool
 True if the point is contained in the bounding box , False otherwise ."""

implementation:
if isinstance ( other , tuple ) :
    x , y = other
else :
    x , y = other . x , other . y
return self . x1 <= x <= self . x2 and self . y1 <= y <= self . y2


signature:
def project ( self , from_shape , to_shape ) :
    """Project the bounding box onto a differently shaped image .
 E . g . if the bounding box is on its original image at
 x1 = ( 10 of 100 pixels ) and y1 = ( 20 of 100 pixels ) and is projected onto
 a new image with size ( width = 200 , height = 200 ) , its new position will
 be ( x1 = 20 , y1 = 40 ) . ( Analogous for x2 / y2 . )
 This is intended for cases where the original image is resized .
 It cannot be used for more complex changes ( e . g . padding , cropping ) .
 Parameters
 from _ shape : tuple of int or ndarray
 Shape of the original image . ( Before resize . )
 to _ shape : tuple of int or ndarray
 Shape of the new image . ( After resize . )
 Returns
 out : imgaug . BoundingBox
 BoundingBox object with new coordinates ."""

implementation:
coords_proj = project_coords ( [ ( self . x1 , self . y1 ) , ( self . x2 , self . y2 ) ] , from_shape , to_shape )
return self . copy ( x1 = coords_proj [ 0 ] [ 0 ] , y1 = coords_proj [ 0 ] [ 1 ] , x2 = coords_proj [ 1 ] [ 0 ] , y2 = coords_proj [ 1 ] [ 1 ] , label = self . label )


signature:
def extend ( self , all_sides = 0 , top = 0 , right = 0 , bottom = 0 , left = 0 ) :
    """Extend the size of the bounding box along its sides .
 Parameters
 all _ sides : number , optional
 Value by which to extend the bounding box size along all sides .
 top : number , optional
 Value by which to extend the bounding box size along its top side .
 right : number , optional
 Value by which to extend the bounding box size along its right side .
 bottom : number , optional
 Value by which to extend the bounding box size along its bottom side .
 left : number , optional
 Value by which to extend the bounding box size along its left side .
 Returns
 imgaug . BoundingBox
 Extended bounding box ."""

implementation: return BoundingBox ( x1 = self . x1 - all_sides - left , x2 = self . x2 + all_sides + right , y1 = self . y1 - all_sides - top , y2 = self . y2 + all_sides + bottom )


signature:
def intersection ( self , other , default = None ) :
    """Compute the intersection bounding box of this bounding box and another one .
 Note that in extreme cases , the intersection can be a single point , meaning that the intersection bounding box
 will exist , but then also has a height and width of zero .
 Parameters
 other : imgaug . BoundingBox
 Other bounding box with which to generate the intersection .
 default : any , optional
 Default value to return if there is no intersection .
 Returns
 imgaug . BoundingBox or any
 Intersection bounding box of the two bounding boxes if there is an intersection .
 If there is no intersection , the default value will be returned , which can by anything ."""

implementation:
x1_i = max ( self . x1 , other . x1 )
y1_i = max ( self . y1 , other . y1 )
x2_i = min ( self . x2 , other . x2 )
y2_i = min ( self . y2 , other . y2 )
if x1_i > x2_i or y1_i > y2_i :
    return default
else :
    return BoundingBox ( x1 = x1_i , y1 = y1_i , x2 = x2_i , y2 = y2_i )


signature:
def union ( self , other ) :
    """Compute the union bounding box of this bounding box and another one .
 This is equivalent to drawing a bounding box around all corners points of both
 bounding boxes .
 Parameters
 other : imgaug . BoundingBox
 Other bounding box with which to generate the union .
 Returns
 imgaug . BoundingBox
 Union bounding box of the two bounding boxes ."""

implementation: return BoundingBox ( x1 = min ( self . x1 , other . x1 ) , y1 = min ( self . y1 , other . y1 ) , x2 = max ( self . x2 , other . x2 ) , y2 = max ( self . y2 , other . y2 ) , )


signature:
def iou ( self , other ) :
    """Compute the IoU of this bounding box with another one .
 IoU is the intersection over union , defined as : :
 ` ` area ( intersection ( A , B ) ) / area ( union ( A , B ) ) ` `
 ` ` = area ( intersection ( A , B ) ) / ( area ( A ) + area ( B ) - area ( intersection ( A , B ) ) ) ` `
 Parameters
 other : imgaug . BoundingBox
 Other bounding box with which to compare .
 Returns
 float
 IoU between the two bounding boxes ."""

implementation:
inters = self . intersection ( other )
if inters is None :
    return 0.0
else :
    area_union = self . area + other . area - inters . area
    return inters . area / area_union if area_union > 0 else 0.0


signature:
def is_fully_within_image ( self , image ) :
    """Estimate whether the bounding box is fully inside the image area .
 Parameters
 image : ( H , W , . . . ) ndarray or tuple of int
 Image dimensions to use .
 If an ndarray , its shape will be used .
 If a tuple , it is assumed to represent the image shape
 and must contain at least two integers .
 Returns
 bool
 True if the bounding box is fully inside the image area . False otherwise ."""

implementation:
shape = normalize_shape ( image )
height , width = shape [ 0 : 2 ]
return self . x1 >= 0 and self . x2 < width and self . y1 >= 0 and self . y2 < height


signature:
def is_partly_within_image ( self , image ) :
    """Estimate whether the bounding box is at least partially inside the image area .
 Parameters
 image : ( H , W , . . . ) ndarray or tuple of int
 Image dimensions to use .
 If an ndarray , its shape will be used .
 If a tuple , it is assumed to represent the image shape
 and must contain at least two integers .
 Returns
 bool
 True if the bounding box is at least partially inside the image area . False otherwise ."""

implementation:
shape = normalize_shape ( image )
height , width = shape [ 0 : 2 ]
eps = np . finfo ( np . float32 ) . eps
img_bb = BoundingBox ( x1 = 0 , x2 = width - eps , y1 = 0 , y2 = height - eps )
return self . intersection ( img_bb ) is not None


signature:
def is_out_of_image ( self , image , fully = True , partly = False ) :
    """Estimate whether the bounding box is partially or fully outside of the image area .
 Parameters
 image : ( H , W , . . . ) ndarray or tuple of int
 Image dimensions to use . If an ndarray , its shape will be used . If a tuple , it is
 assumed to represent the image shape and must contain at least two integers .
 fully : bool , optional
 Whether to return True if the bounding box is fully outside fo the image area .
 partly : bool , optional
 Whether to return True if the bounding box is at least partially outside fo the
 image area .
 Returns
 bool
 True if the bounding box is partially / fully outside of the image area , depending
 on defined parameters . False otherwise ."""

implementation:
if self . is_fully_within_image ( image ) :
    return False
elif self . is_partly_within_image ( image ) :
    return partly
else :
    return fully


signature:
def clip_out_of_image ( self , image ) :
    """Clip off all parts of the bounding box that are outside of the image .
 Parameters
 image : ( H , W , . . . ) ndarray or tuple of int
 Image dimensions to use for the clipping of the bounding box .
 If an ndarray , its shape will be used .
 If a tuple , it is assumed to represent the image shape and must contain at least two integers .
 Returns
 result : imgaug . BoundingBox
 Bounding box , clipped to fall within the image dimensions ."""

implementation:
shape = normalize_shape ( image )
height , width = shape [ 0 : 2 ]
ia . do_assert ( height > 0 )
ia . do_assert ( width > 0 )
eps = np . finfo ( np . float32 ) . eps
x1 = np . clip ( self . x1 , 0 , width - eps )
x2 = np . clip ( self . x2 , 0 , width - eps )
y1 = np . clip ( self . y1 , 0 , height - eps )
y2 = np . clip ( self . y2 , 0 , height - eps )
return self . copy ( x1 = x1 , y1 = y1 , x2 = x2 , y2 = y2 , label = self . label )


signature:
def shift ( self , top = None , right = None , bottom = None , left = None ) :
    """Shift the bounding box from one or more image sides , i . e . move it on the x / y - axis .
 Parameters
 top : None or int , optional
 Amount of pixels by which to shift the bounding box from the top .
 right : None or int , optional
 Amount of pixels by which to shift the bounding box from the right .
 bottom : None or int , optional
 Amount of pixels by which to shift the bounding box from the bottom .
 left : None or int , optional
 Amount of pixels by which to shift the bounding box from the left .
 Returns
 result : imgaug . BoundingBox
 Shifted bounding box ."""

implementation:
top = top if top is not None else 0
right = right if right is not None else 0
bottom = bottom if bottom is not None else 0
left = left if left is not None else 0
return self . copy ( x1 = self . x1 + left - right , x2 = self . x2 + left - right , y1 = self . y1 + top - bottom , y2 = self . y2 + top - bottom )


signature:
def draw_on_image ( self , image , color = ( 0 , 255 , 0 ) , alpha = 1.0 , size = 1 , copy = True , raise_if_out_of_image = False , thickness = None ) :
    """Draw the bounding box on an image .
 Parameters
 image : ( H , W , C ) ndarray ( uint8)
 The image onto which to draw the bounding box .
 color : iterable of int , optional
 The color to use , corresponding to the channel layout of the image . Usually RGB .
 alpha : float , optional
 The transparency of the drawn bounding box , where 1.0 denotes no transparency and
 0.0 is invisible .
 size : int , optional
 The thickness of the bounding box in pixels . If the value is larger than 1 , then
 additional pixels will be added around the bounding box ( i . e . extension towards the
 outside ) .
 copy : bool , optional
 Whether to copy the input image or change it in - place .
 raise _ if _ out _ of _ image : bool , optional
 Whether to raise an error if the bounding box is fully outside of the
 image . If set to False , no error will be raised and only the parts inside the image
 will be drawn .
 thickness : None or int , optional
 Deprecated .
 Returns
 result : ( H , W , C ) ndarray ( uint8)
 Image with bounding box drawn on it ."""

implementation:
if thickness is not None :
    ia . warn_deprecated ( "Usage of argument 'thickness' in BoundingBox.draw_on_image() " "is deprecated. The argument was renamed to 'size'." )
    size = thickness
if raise_if_out_of_image and self . is_out_of_image ( image ) :
    raise Exception ( "Cannot draw bounding box x1=%.8f, y1=%.8f, x2=%.8f, y2=%.8f on image with shape %s." % ( self . x1 , self . y1 , self . x2 , self . y2 , image . shape ) )
result = np . copy ( image ) if copy else image
if isinstance ( color , ( tuple , list ) ) :
    color = np . uint8 ( color )
for i in range ( size ) :
    y1 , y2 , x1 , x2 = self . y1_int , self . y2_int , self . x1_int , self . x2_int
    # When y values get into the range ( H - 0.5 , H ) , the * _ int functions round them to H .
    # That is technically sensible , but in the case of drawing means that the border lies
    # just barely outside of the image , making the border disappear , even though the BB
    # is fully inside the image . Here we correct for that because of beauty reasons .
    # Same is the case for x coordinates .
    if self . is_fully_within_image ( image ) :
        y1 = np . clip ( y1 , 0 , image . shape [ 0 ] - 1 )
        y2 = np . clip ( y2 , 0 , image . shape [ 0 ] - 1 )
        x1 = np . clip ( x1 , 0 , image . shape [ 1 ] - 1 )
        x2 = np . clip ( x2 , 0 , image . shape [ 1 ] - 1 )
    y = [ y1 - i , y1 - i , y2 + i , y2 + i ]
    x = [ x1 - i , x2 + i , x2 + i , x1 - i ]
    rr , cc = skimage . draw . polygon_perimeter ( y , x , shape = result . shape )
    if alpha >= 0.99 :
        result [ rr , cc , : ] = color
    else :
        if ia . is_float_array ( result ) :
            result [ rr , cc , : ] = ( 1 - alpha ) * result [ rr , cc , : ] + alpha * color
            result = np . clip ( result , 0 , 255 )
        else :
            input_dtype = result . dtype
            result = result . astype ( np . float32 )
            result [ rr , cc , : ] = ( 1 - alpha ) * result [ rr , cc , : ] + alpha * color
            result = np . clip ( result , 0 , 255 ) . astype ( input_dtype )
return result


signature:
def extract_from_image ( self , image , pad = True , pad_max = None , prevent_zero_size = True ) :
    """Extract the image pixels within the bounding box .
 This function will zero - pad the image if the bounding box is partially / fully outside of
 the image .
 Parameters
 image : ( H , W ) ndarray or ( H , W , C ) ndarray
 The image from which to extract the pixels within the bounding box .
 pad : bool , optional
 Whether to zero - pad the image if the object is partially / fully
 outside of it .
 pad _ max : None or int , optional
 The maximum number of pixels that may be zero - paded on any side ,
 i . e . if this has value ` ` N ` ` the total maximum of added pixels
 is ` ` 4 * N ` ` .
 This option exists to prevent extremely large images as a result of
 single points being moved very far away during augmentation .
 prevent _ zero _ size : bool , optional
 Whether to prevent height or width of the extracted image from becoming zero .
 If this is set to True and height or width of the bounding box is below 1 , the height / width will
 be increased to 1 . This can be useful to prevent problems , e . g . with image saving or plotting .
 If it is set to False , images will be returned as ` ` ( H ' , W ' ) ` ` or ` ` ( H ' , W ' , 3 ) ` ` with ` ` H ` ` or
 ` ` W ` ` potentially being 0.
 Returns
 image : ( H ' , W ' ) ndarray or ( H ' , W ' , C ) ndarray
 Pixels within the bounding box . Zero - padded if the bounding box is partially / fully
 outside of the image . If prevent _ zero _ size is activated , it is guarantueed that ` ` H ' > 0 ` `
 and ` ` W ' > 0 ` ` , otherwise only ` ` H ' > = 0 ` ` and ` ` W ' > = 0 ` ` ."""

implementation:
pad_top = 0
pad_right = 0
pad_bottom = 0
pad_left = 0
height , width = image . shape [ 0 ] , image . shape [ 1 ]
x1 , x2 , y1 , y2 = self . x1_int , self . x2_int , self . y1_int , self . y2_int
# When y values get into the range ( H - 0.5 , H ) , the * _ int functions round them to H .
# That is technically sensible , but in the case of extraction leads to a black border ,
# which is both ugly and unexpected after calling cut _ out _ of _ image ( ) . Here we correct for
# that because of beauty reasons .
# Same is the case for x coordinates .
fully_within = self . is_fully_within_image ( image )
if fully_within :
    y1 , y2 = np . clip ( [ y1 , y2 ] , 0 , height - 1 )
    x1 , x2 = np . clip ( [ x1 , x2 ] , 0 , width - 1 )
# TODO add test
if prevent_zero_size :
    if abs ( x2 - x1 ) < 1 :
        x2 = x1 + 1
    if abs ( y2 - y1 ) < 1 :
        y2 = y1 + 1
if pad : # if the bb is outside of the image area , the following pads the image
# first with black pixels until the bb is inside the image
# and only then extracts the image area
# TODO probably more efficient to initialize an array of zeros
# and copy only the portions of the bb into that array that are
# natively inside the image area
    if x1 < 0 :
        pad_left = abs ( x1 )
        x2 = x2 + pad_left
        width = width + pad_left
        x1 = 0
    if y1 < 0 :
        pad_top = abs ( y1 )
        y2 = y2 + pad_top
        height = height + pad_top
        y1 = 0
    if x2 >= width :
        pad_right = x2 - width
    if y2 >= height :
        pad_bottom = y2 - height
    paddings = [ pad_top , pad_right , pad_bottom , pad_left ]
    any_padded = any ( [ val > 0 for val in paddings ] )
    if any_padded :
        if pad_max is None :
            pad_max = max ( paddings )
        image = ia . pad ( image , top = min ( pad_top , pad_max ) , right = min ( pad_right , pad_max ) , bottom = min ( pad_bottom , pad_max ) , left = min ( pad_left , pad_max ) )
    return image [ y1 : y2 , x1 : x2 ]
else :
    within_image = ( ( 0 , 0 , 0 , 0 ) <= ( x1 , y1 , x2 , y2 ) < ( width , height , width , height ) )
    out_height , out_width = ( y2 - y1 ) , ( x2 - x1 )
    nonzero_height = ( out_height > 0 )
    nonzero_width = ( out_width > 0 )
    if within_image and nonzero_height and nonzero_width :
        return image [ y1 : y2 , x1 : x2 ]
    if prevent_zero_size :
        out_height = 1
        out_width = 1
    else :
        out_height = 0
        out_width = 0
    if image . ndim == 2 :
        return np . zeros ( ( out_height , out_width ) , dtype = image . dtype )
    return np . zeros ( ( out_height , out_width , image . shape [ - 1 ] ) , dtype = image . dtype )


signature:
def to_keypoints ( self ) :
    """Convert the corners of the bounding box to keypoints ( clockwise , starting at top left ) .
 Returns
 list of imgaug . Keypoint
 Corners of the bounding box as keypoints ."""

implementation:
# TODO get rid of this deferred import
from imgaug . augmentables . kps import Keypoint
return [ Keypoint ( x = self . x1 , y = self . y1 ) , Keypoint ( x = self . x2 , y = self . y1 ) , Keypoint ( x = self . x2 , y = self . y2 ) , Keypoint ( x = self . x1 , y = self . y2 ) ]


signature:
def copy ( self , x1 = None , y1 = None , x2 = None , y2 = None , label = None ) :
    """Create a shallow copy of the BoundingBox object .
 Parameters
 x1 : None or number
 If not None , then the x1 coordinate of the copied object will be set to this value .
 y1 : None or number
 If not None , then the y1 coordinate of the copied object will be set to this value .
 x2 : None or number
 If not None , then the x2 coordinate of the copied object will be set to this value .
 y2 : None or number
 If not None , then the y2 coordinate of the copied object will be set to this value .
 label : None or string
 If not None , then the label of the copied object will be set to this value .
 Returns
 imgaug . BoundingBox
 Shallow copy ."""

implementation: return BoundingBox ( x1 = self . x1 if x1 is None else x1 , x2 = self . x2 if x2 is None else x2 , y1 = self . y1 if y1 is None else y1 , y2 = self . y2 if y2 is None else y2 , label = self . label if label is None else label )


signature:
def deepcopy ( self , x1 = None , y1 = None , x2 = None , y2 = None , label = None ) :
    """Create a deep copy of the BoundingBox object .
 Parameters
 x1 : None or number
 If not None , then the x1 coordinate of the copied object will be set to this value .
 y1 : None or number
 If not None , then the y1 coordinate of the copied object will be set to this value .
 x2 : None or number
 If not None , then the x2 coordinate of the copied object will be set to this value .
 y2 : None or number
 If not None , then the y2 coordinate of the copied object will be set to this value .
 label : None or string
 If not None , then the label of the copied object will be set to this value .
 Returns
 imgaug . BoundingBox
 Deep copy ."""

implementation: return self . copy ( x1 = x1 , y1 = y1 , x2 = x2 , y2 = y2 , label = label )


signature:
def on ( self , image ) :
    """Project bounding boxes from one image to a new one .
 Parameters
 image : ndarray or tuple of int
 New image onto which the bounding boxes are to be projected .
 May also simply be that new image ' s shape tuple .
 Returns
 bounding _ boxes : imgaug . BoundingBoxesOnImage
 Object containing all projected bounding boxes ."""

implementation:
shape = normalize_shape ( image )
if shape [ 0 : 2 ] == self . shape [ 0 : 2 ] :
    return self . deepcopy ( )
bounding_boxes = [ bb . project ( self . shape , shape ) for bb in self . bounding_boxes ]
return BoundingBoxesOnImage ( bounding_boxes , shape )


signature:
def from_xyxy_array ( cls , xyxy , shape ) :
    """Convert an ( N , 4 ) ndarray to a BoundingBoxesOnImage object .
 This is the inverse of : func : ` imgaug . BoundingBoxesOnImage . to _ xyxy _ array ` .
 Parameters
 xyxy : ( N , 4 ) ndarray
 Array containing the corner coordinates ( top - left , bottom - right ) of ` ` N ` ` bounding boxes
 in the form ` ` ( x1 , y1 , x2 , y2 ) ` ` . Should usually be of dtype ` ` float32 ` ` .
 shape : tuple of int
 Shape of the image on which the bounding boxes are placed .
 Should usually be ` ` ( H , W , C ) ` ` or ` ` ( H , W ) ` ` .
 Returns
 imgaug . BoundingBoxesOnImage
 Object containing a list of BoundingBox objects following the provided corner coordinates ."""

implementation:
ia . do_assert ( xyxy . shape [ 1 ] == 4 , "Expected input array of shape (N, 4), got shape %s." % ( xyxy . shape , ) )
boxes = [ BoundingBox ( * row ) for row in xyxy ]
return cls ( boxes , shape )


signature:
def to_xyxy_array ( self , dtype = np . float32 ) :
    """Convert the BoundingBoxesOnImage object to an ( N , 4 ) ndarray .
 This is the inverse of : func : ` imgaug . BoundingBoxesOnImage . from _ xyxy _ array ` .
 Parameters
 dtype : numpy . dtype , optional
 Desired output datatype of the ndarray .
 Returns
 ndarray
 ( N , 4 ) ndarray array , where ` ` N ` ` denotes the number of bounding boxes and ` ` 4 ` ` denotes the
 top - left and bottom - right bounding box corner coordinates in form ` ` ( x1 , y1 , x2 , y2 ) ` ` ."""

implementation:
xyxy_array = np . zeros ( ( len ( self . bounding_boxes ) , 4 ) , dtype = np . float32 )
for i , box in enumerate ( self . bounding_boxes ) :
    xyxy_array [ i ] = [ box . x1 , box . y1 , box . x2 , box . y2 ]
return xyxy_array . astype ( dtype )


signature:
def draw_on_image ( self , image , color = ( 0 , 255 , 0 ) , alpha = 1.0 , size = 1 , copy = True , raise_if_out_of_image = False , thickness = None ) :
    """Draw all bounding boxes onto a given image .
 Parameters
 image : ( H , W , 3 ) ndarray
 The image onto which to draw the bounding boxes .
 This image should usually have the same shape as
 set in BoundingBoxesOnImage . shape .
 color : int or list of int or tuple of int or ( 3 , ) ndarray , optional
 The RGB color of all bounding boxes . If a single int ` ` C ` ` , then
 that is equivalent to ` ` ( C , C , C ) ` ` .
 alpha : float , optional
 Alpha / transparency of the bounding box .
 size : int , optional
 Thickness in pixels .
 copy : bool , optional
 Whether to copy the image before drawing the bounding boxes .
 raise _ if _ out _ of _ image : bool , optional
 Whether to raise an exception if any bounding box is outside of the
 image .
 thickness : None or int , optional
 Deprecated .
 Returns
 image : ( H , W , 3 ) ndarray
 Image with drawn bounding boxes ."""

implementation:
image = np . copy ( image ) if copy else image
for bb in self . bounding_boxes :
    image = bb . draw_on_image ( image , color = color , alpha = alpha , size = size , copy = False , raise_if_out_of_image = raise_if_out_of_image , thickness = thickness )
return image


signature:
def remove_out_of_image ( self , fully = True , partly = False ) :
    """Remove all bounding boxes that are fully or partially outside of the image .
 Parameters
 fully : bool , optional
 Whether to remove bounding boxes that are fully outside of the image .
 partly : bool , optional
 Whether to remove bounding boxes that are partially outside of the image .
 Returns
 imgaug . BoundingBoxesOnImage
 Reduced set of bounding boxes , with those that were fully / partially outside of
 the image removed ."""

implementation:
bbs_clean = [ bb for bb in self . bounding_boxes if not bb . is_out_of_image ( self . shape , fully = fully , partly = partly ) ]
return BoundingBoxesOnImage ( bbs_clean , shape = self . shape )


signature:
def clip_out_of_image ( self ) :
    """Clip off all parts from all bounding boxes that are outside of the image .
 Returns
 imgaug . BoundingBoxesOnImage
 Bounding boxes , clipped to fall within the image dimensions ."""

implementation:
bbs_cut = [ bb . clip_out_of_image ( self . shape ) for bb in self . bounding_boxes if bb . is_partly_within_image ( self . shape ) ]
return BoundingBoxesOnImage ( bbs_cut , shape = self . shape )


signature:
def shift ( self , top = None , right = None , bottom = None , left = None ) :
    """Shift all bounding boxes from one or more image sides , i . e . move them on the x / y - axis .
 Parameters
 top : None or int , optional
 Amount of pixels by which to shift all bounding boxes from the top .
 right : None or int , optional
 Amount of pixels by which to shift all bounding boxes from the right .
 bottom : None or int , optional
 Amount of pixels by which to shift all bounding boxes from the bottom .
 left : None or int , optional
 Amount of pixels by which to shift all bounding boxes from the left .
 Returns
 imgaug . BoundingBoxesOnImage
 Shifted bounding boxes ."""

implementation:
bbs_new = [ bb . shift ( top = top , right = right , bottom = bottom , left = left ) for bb in self . bounding_boxes ]
return BoundingBoxesOnImage ( bbs_new , shape = self . shape )


signature:
def deepcopy ( self ) :
    """Create a deep copy of the BoundingBoxesOnImage object .
 Returns
 imgaug . BoundingBoxesOnImage
 Deep copy ."""

implementation:
# Manual copy is far faster than deepcopy for BoundingBoxesOnImage ,
# so use manual copy here too
bbs = [ bb . deepcopy ( ) for bb in self . bounding_boxes ]
return BoundingBoxesOnImage ( bbs , tuple ( self . shape ) )


signature:
def Emboss ( alpha = 0 , strength = 1 , name = None , deterministic = False , random_state = None ) :
    """Augmenter that embosses images and overlays the result with the original
 image .
 The embossed version pronounces highlights and shadows ,
 letting the image look as if it was recreated on a metal plate ( " embossed " ) .
 dtype support : :
 See ` ` imgaug . augmenters . convolutional . Convolve ` ` .
 Parameters
 alpha : number or tuple of number or list of number or imgaug . parameters . StochasticParameter , optional
 Visibility of the sharpened image . At 0 , only the original image is
 visible , at 1.0 only its sharpened version is visible .
 * If an int or float , exactly that value will be used .
 * If a tuple ` ` ( a , b ) ` ` , a random value from the range ` ` a < = x < = b ` ` will
 be sampled per image .
 * If a list , then a random value will be sampled from that list
 per image .
 * If a StochasticParameter , a value will be sampled from the
 parameter per image .
 strength : number or tuple of number or list of number or imgaug . parameters . StochasticParameter , optional
 Parameter that controls the strength of the embossing .
 Sane values are somewhere in the range ` ` ( 0 , 2 ) ` ` with 1 being the standard
 embossing effect . Default value is 1.
 * If an int or float , exactly that value will be used .
 * If a tuple ` ` ( a , b ) ` ` , a random value from the range ` ` a < = x < = b ` ` will
 be sampled per image .
 * If a list , then a random value will be sampled from that list
 per image .
 * If a StochasticParameter , a value will be sampled from the
 parameter per image .
 name : None or str , optional
 See : func : ` imgaug . augmenters . meta . Augmenter . _ _ init _ _ ` .
 deterministic : bool , optional
 See : func : ` imgaug . augmenters . meta . Augmenter . _ _ init _ _ ` .
 random _ state : None or int or numpy . random . RandomState , optional
 See : func : ` imgaug . augmenters . meta . Augmenter . _ _ init _ _ ` .
 Examples
 > > > aug = Emboss ( alpha = ( 0.0 , 1.0 ) , strength = ( 0.5 , 1.5 ) )
 embosses an image with a variable strength in the range ` ` 0.5 < = x < = 1.5 ` `
 and overlays the result with a variable alpha in the range ` ` 0.0 < = a < = 1.0 ` `
 over the old image ."""

implementation:
alpha_param = iap . handle_continuous_param ( alpha , "alpha" , value_range = ( 0 , 1.0 ) , tuple_to_uniform = True , list_to_choice = True )
strength_param = iap . handle_continuous_param ( strength , "strength" , value_range = ( 0 , None ) , tuple_to_uniform = True , list_to_choice = True )
def create_matrices ( image , nb_channels , random_state_func ) :
    alpha_sample = alpha_param . draw_sample ( random_state = random_state_func )
    ia . do_assert ( 0 <= alpha_sample <= 1.0 )
    strength_sample = strength_param . draw_sample ( random_state = random_state_func )
    matrix_nochange = np . array ( [ [ 0 , 0 , 0 ] , [ 0 , 1 , 0 ] , [ 0 , 0 , 0 ] ] , dtype = np . float32 )
    matrix_effect = np . array ( [ [ - 1 - strength_sample , 0 - strength_sample , 0 ] , [ 0 - strength_sample , 1 , 0 + strength_sample ] , [ 0 , 0 + strength_sample , 1 + strength_sample ] ] , dtype = np . float32 )
    matrix = ( 1 - alpha_sample ) * matrix_nochange + alpha_sample * matrix_effect
    return [ matrix ] * nb_channels
if name is None :
    name = "Unnamed%s" % ( ia . caller_name ( ) , )
return Convolve ( create_matrices , name = name , deterministic = deterministic , random_state = random_state )


signature:
def EdgeDetect ( alpha = 0 , name = None , deterministic = False , random_state = None ) :
    """Augmenter that detects all edges in images , marks them in
 a black and white image and then overlays the result with the original
 image .
 dtype support : :
 See ` ` imgaug . augmenters . convolutional . Convolve ` ` .
 Parameters
 alpha : number or tuple of number or list of number or imgaug . parameters . StochasticParameter , optional
 Visibility of the sharpened image . At 0 , only the original image is
 visible , at 1.0 only its sharpened version is visible .
 * If an int or float , exactly that value will be used .
 * If a tuple ` ` ( a , b ) ` ` , a random value from the range ` ` a < = x < = b ` ` will
 be sampled per image .
 * If a list , then a random value will be sampled from that list
 per image .
 * If a StochasticParameter , a value will be sampled from the
 parameter per image .
 name : None or str , optional
 See : func : ` imgaug . augmenters . meta . Augmenter . _ _ init _ _ ` .
 deterministic : bool , optional
 See : func : ` imgaug . augmenters . meta . Augmenter . _ _ init _ _ ` .
 random _ state : None or int or numpy . random . RandomState , optional
 See : func : ` imgaug . augmenters . meta . Augmenter . _ _ init _ _ ` .
 Examples
 > > > aug = EdgeDetect ( alpha = ( 0.0 , 1.0 ) )
 detects edges in an image and overlays the result with a variable alpha
 in the range ` ` 0.0 < = a < = 1.0 ` ` over the old image ."""

implementation:
alpha_param = iap . handle_continuous_param ( alpha , "alpha" , value_range = ( 0 , 1.0 ) , tuple_to_uniform = True , list_to_choice = True )
def create_matrices ( _image , nb_channels , random_state_func ) :
    alpha_sample = alpha_param . draw_sample ( random_state = random_state_func )
    ia . do_assert ( 0 <= alpha_sample <= 1.0 )
    matrix_nochange = np . array ( [ [ 0 , 0 , 0 ] , [ 0 , 1 , 0 ] , [ 0 , 0 , 0 ] ] , dtype = np . float32 )
    matrix_effect = np . array ( [ [ 0 , 1 , 0 ] , [ 1 , - 4 , 1 ] , [ 0 , 1 , 0 ] ] , dtype = np . float32 )
    matrix = ( 1 - alpha_sample ) * matrix_nochange + alpha_sample * matrix_effect
    return [ matrix ] * nb_channels
if name is None :
    name = "Unnamed%s" % ( ia . caller_name ( ) , )
return Convolve ( create_matrices , name = name , deterministic = deterministic , random_state = random_state )


signature:
def DirectedEdgeDetect ( alpha = 0 , direction = ( 0.0 , 1.0 ) , name = None , deterministic = False , random_state = None ) :
    """Augmenter that detects edges that have certain directions and marks them
 in a black and white image and then overlays the result with the original
 image .
 dtype support : :
 See ` ` imgaug . augmenters . convolutional . Convolve ` ` .
 Parameters
 alpha : number or tuple of number or list of number or imgaug . parameters . StochasticParameter , optional
 Visibility of the sharpened image . At 0 , only the original image is
 visible , at 1.0 only its sharpened version is visible .
 * If an int or float , exactly that value will be used .
 * If a tuple ` ` ( a , b ) ` ` , a random value from the range ` ` a < = x < = b ` ` will
 be sampled per image .
 * If a list , then a random value will be sampled from that list
 per image .
 * If a StochasticParameter , a value will be sampled from the
 parameter per image .
 direction : number or tuple of number or list of number or imgaug . parameters . StochasticParameter , optional
 Angle of edges to pronounce , where 0 represents 0 degrees and 1.0
 represents 360 degrees ( both clockwise , starting at the top ) .
 Default value is ` ` ( 0.0 , 1.0 ) ` ` , i . e . pick a random angle per image .
 * If an int or float , exactly that value will be used .
 * If a tuple ` ` ( a , b ) ` ` , a random value from the range ` ` a < = x < = b ` ` will
 be sampled per image .
 * If a list , then a random value will be sampled from that list
 per image .
 * If a StochasticParameter , a value will be sampled from the
 parameter per image .
 name : None or str , optional
 See : func : ` imgaug . augmenters . meta . Augmenter . _ _ init _ _ ` .
 deterministic : bool , optional
 See : func : ` imgaug . augmenters . meta . Augmenter . _ _ init _ _ ` .
 random _ state : None or int or numpy . random . RandomState , optional
 See : func : ` imgaug . augmenters . meta . Augmenter . _ _ init _ _ ` .
 Examples
 > > > aug = DirectedEdgeDetect ( alpha = 1.0 , direction = 0)
 turns input images into edge images in which edges are detected from
 top side of the image ( i . e . the top sides of horizontal edges are
 added to the output ) .
 > > > aug = DirectedEdgeDetect ( alpha = 1.0 , direction = 90/360)
 same as before , but detecting edges from the right ( right side of each
 vertical edge ) .
 > > > aug = DirectedEdgeDetect ( alpha = 1.0 , direction = ( 0.0 , 1.0 ) )
 same as before , but detecting edges from a variable direction ( anything
 between 0 and 1.0 , i . e . 0 degrees and 360 degrees , starting from the
 top and moving clockwise ) .
 > > > aug = DirectedEdgeDetect ( alpha = ( 0.0 , 0.3 ) , direction = 0)
 generates edge images ( edges detected from the top ) and overlays them
 with the input images by a variable amount between 0 and 30 percent
 ( e . g . for 0.3 then ` ` 0.7 * old _ image + 0.3 * edge _ image ` ` ) ."""

implementation:
alpha_param = iap . handle_continuous_param ( alpha , "alpha" , value_range = ( 0 , 1.0 ) , tuple_to_uniform = True , list_to_choice = True )
direction_param = iap . handle_continuous_param ( direction , "direction" , value_range = None , tuple_to_uniform = True , list_to_choice = True )
def create_matrices ( _image , nb_channels , random_state_func ) :
    alpha_sample = alpha_param . draw_sample ( random_state = random_state_func )
    ia . do_assert ( 0 <= alpha_sample <= 1.0 )
    direction_sample = direction_param . draw_sample ( random_state = random_state_func )
    deg = int ( direction_sample * 360 ) % 360
    rad = np . deg2rad ( deg )
    x = np . cos ( rad - 0.5 * np . pi )
    y = np . sin ( rad - 0.5 * np . pi )
    direction_vector = np . array ( [ x , y ] )
    matrix_effect = np . array ( [ [ 0 , 0 , 0 ] , [ 0 , 0 , 0 ] , [ 0 , 0 , 0 ] ] , dtype = np . float32 )
    for x in [ - 1 , 0 , 1 ] :
        for y in [ - 1 , 0 , 1 ] :
            if ( x , y ) != ( 0 , 0 ) :
                cell_vector = np . array ( [ x , y ] )
                distance_deg = np . rad2deg ( ia . angle_between_vectors ( cell_vector , direction_vector ) )
                distance = distance_deg / 180
                similarity = ( 1 - distance ) ** 4
                matrix_effect [ y + 1 , x + 1 ] = similarity
    matrix_effect = matrix_effect / np . sum ( matrix_effect )
    matrix_effect = matrix_effect * ( - 1 )
    matrix_effect [ 1 , 1 ] = 1
    matrix_nochange = np . array ( [ [ 0 , 0 , 0 ] , [ 0 , 1 , 0 ] , [ 0 , 0 , 0 ] ] , dtype = np . float32 )
    matrix = ( 1 - alpha_sample ) * matrix_nochange + alpha_sample * matrix_effect
    return [ matrix ] * nb_channels
if name is None :
    name = "Unnamed%s" % ( ia . caller_name ( ) , )
return Convolve ( create_matrices , name = name , deterministic = deterministic , random_state = random_state )


signature:
def normalize_shape ( shape ) :
    """Normalize a shape tuple or array to a shape tuple .
 Parameters
 shape : tuple of int or ndarray
 The input to normalize . May optionally be an array .
 Returns
 tuple of int
 Shape tuple ."""

implementation:
if isinstance ( shape , tuple ) :
    return shape
assert ia . is_np_array ( shape ) , ( "Expected tuple of ints or array, got %s." % ( type ( shape ) , ) )
return shape . shape