2017-05-29 3 views
3

Je suis totalement novice en Python et j'essaye de créer une matrice BOOLEAN 1280x720 qui est VRAIE quand x-index et y-index sont satisfaits dans des conditions. Plus précisément, la zone noire est l'endroit où je veux que toutes les valeurs soient VRAIES, les autres sont FAUX. This is the image geometry of the matrix Jusqu'à présent, je l'ai fait un code comme ceci:Comment créer une matrice booléenne avec une condition d'index correspondante dans Python?

mask_mat = np.zeros((1280,720),np.bool) 
for i in range(640,1220): 
    for j in range(0,360): 
     if ((j > (-9/16*i + 690))&(j < (-9/16*i + 750))): 
      mask_mat[i][j] = True; 

Mais la boucle prennent beaucoup de temps. Alors s'il vous plaît aidez!

Répondre

1

Créer les tableaux de gamme en fonction des limites de iterator à l'aide NumPy's powerful broadcasting feature puis utiliser directement la formule, comme si -

mask_mat = np.zeros((1280,720),np.bool)   
I = np.arange(640,1220)[:,None] 
J = np.arange(0,360) 
mask_mat[640:1220,0:360] = ((J > (-9/16*I + 690))&(J < (-9/16*I + 750))) 

notez-de l'étape: I = np.arange(640,1220)[:,None]. Nous y ajoutons un nouvel axe, qui représente le premier axe de la sortie. Cela introduit la fonction de diffusion pour effectuer des ajouts élémentaires de manière vectorisée. L'autre tableau de plage J suit le deuxième axe de la sortie.

Pour améliorer encore les performances, nous pouvons souhaiter calculer -9/16*I et le réutiliser aux deux emplacements de la formule.

test Runtime

approches -

# Original loopy soln 
def loopy_app(): 
    mask_mat = np.zeros((1280,720),np.bool) 
    for i in range(640,1220): 
     for j in range(0,360): 
      if ((j > (-9/16*i + 690))&(j < (-9/16*i + 750))): 
       mask_mat[i][j] = True; 
    return mask_mat 

# @donkopotamus's soln 
def fromfunc_app(): 
    return np.fromfunction(
     lambda i, j: ((640 <= i) & (i < 1220) & 
        (j < 360) & 
        (j > (-9/16 * i + 690)) & 
        (j < (-9/16*i + 750))), (1280, 720)) 

# Proposed in this post      
def vectorized_app(): 
    mask_mat = np.zeros((1280,720),np.bool)   
    I = np.arange(640,1220)[:,None] 
    J = np.arange(0,360) 
    mask_mat[640:1220,0:360] = ((J > (-9/16*I + 690))&(J < (-9/16*I + 750))) 
    return mask_mat 

synchronisations -

In [86]: %timeit loopy_app() 
10 loops, best of 3: 29.7 ms per loop 

In [87]: %timeit fromfunc_app() 
100 loops, best of 3: 11.9 ms per loop 

In [88]: %timeit vectorized_app() 
1000 loops, best of 3: 370 µs per loop 

In [90]: 29700/370.0 
Out[90]: 80.27027027027027 

80x+ avec l'approche speedup vectorisé basée diffusion!

boost plus avec numexpr

Nous pourrions augmenter davantage en apportant numexpr module pour effectuer ces opérations arithmétiques comme une expression:

import numexpr as ne 

def vectorized_expr_app(): 
    mask_mat = np.zeros((1280,720),np.bool)   
    I = np.arange(640,1220)[:,None] 
    J = np.arange(0,360) 
    vals = ne.evaluate('((J > (-9/16*I + 690))&(J < (-9/16*I + 750)))') 
    mask_mat[640:1220,0:360] = vals 
    return mask_mat 

synchronisations:

In [101]: %timeit vectorized_expr_app() 
1000 loops, best of 3: 321 µs per loop 

In [102]: 29700/321.0 
Out[102]: 92.5233644859813 

90x+ accélérer maintenant!

+1

ce que je cherche, je vous remercie beaucoup –

0

Une option consiste à utiliser np.fromfunction:

np.fromfunction(
    lambda i, j: ((640 <= i) & (i < 1220) & 
       (j < 360) & 
       (j > (-9/16 * i + 690)) & 
       (j < (-9/16 * i + 750))), (1280, 720)) 

Il ne peut être le plus rapide puisque nous évaluons un tas de lignes qui sont toujours False, mais il peut être assez rapide pour vous (16ms sur ce machine particulière)

REMARQUE:

Comme il utilise les opérations de matrice pour évaluer la truthiness, plutôt que les appels de fonction, @ Divakar c'est beaucoup plus rapide à 511 s