2017-09-07 4 views
0

Goalmode sur un axe spécifique dans le tableau numpy

Étant donné une liste d'images, je voudrais créer une nouvelle image où chaque pixel contient les valeurs (R, G, B) qui a eu lieu le plus souvent dans la liste d'entrée à cet endroit.

Détails

entrée: une liste L qui a une longueur> = 2. Chaque image/objet de la liste est un tableau flottant float32 avec des dimensions (288, 512, 3) où 3 représente les canaux de couleur R/V/B.

Sortie: Un tableau numérique avec la même forme (288,512,3). Si aucun pixel n'est apparu le plus fréquemment, l'un des pixels de cet emplacement peut être renvoyé.

Tentative

image = stats.mode(L)[0][0] 

Le problème avec cette approche est qu'il examine chaque valeur R/G/B d'un pixel individuellement. Mais je veux qu'un pixel ne soit considéré comme identique qu'à un autre pixel si tous les canaux de couleur correspondent (c'est-à-dire que R1 = R2, G1 = G2, B1 = B2).

+0

Quelle est la forme d'entrée? L'entrée est-elle un tableau? – Divakar

+0

@Divakar une liste de 10 images où chaque image est [100,100,3] – megashigger

+0

Si 'imgs' est la liste d'entrée, je pense:' mode (imgs) [0] [0] ', avec [mode SciPy] (https : //docs.scipy.org/doc/scipy/reference/generated/scipy.stats.mode.html). – Divakar

Répondre

1

Essayez ceci:

def packRGB(RGB): 
    return np.left_shift(RGB, [0, 8, 16]).sum(-1) 

def unpackRGB(i24): 
    B = np.right_shift(i24, 16) 
    G = np.right_shift(i24, 8) - np.left_shift(B, 8) 
    R = i24 - np.left_shift(G, 8) - np.left_shift(B, 16) 
    return np.stack([R, G, B]).T 

def img_mode(imgs_list, average_singles = True): 
    imgs = np.array(imgs_list) #(10, 100, 100, 3) 
    imgs24 = packRGB(imgs) # (10, 100, 100) 
    mode, count = scipy.stats.mode(imgs24, axis = 0) # (1, 100,100) 
    mode, count = mode.squeeze(), count.squeeze() #(100, 100) 
    if average_singles: 
     out = np.empty(imgs.shape[1:]) 
     out[count == 1] = np.rint(np.average(imgs[:, count == 1], axis = 0)) 
     out[count > 1] = unpackRGB(mode[count > 1]) 
    else: 
     out = unpackRGB(mode) 
    return out 

EDIT: erreur fixe et l'option ajoutée de votre autre question: valeur Ttoute dans le jeu si aucun mode, qui devrait être plus rapide en raison de pas de division ou l'arrondissement. scipy.stats.mode renvoie la valeur la plus faible, qui dans ce cas sera le pixel avec la valeur bleue la plus basse. Vous pouvez également essayer median, comme mode va être instable à très petites différences dans les entrées (surtout s'il y a seulement dix)

Ce sera également beaucoup plus lent que, par exemple, la fonction de statistiques de Photoshop (Je suppose que vous essayez de faire quelque chose comme this), car vous voudriez paralléliser la fonction pour la rendre plus efficace.

+0

Je reçois une erreur sur out [count == 1] = np.rint (np.average (imgs [:, count == 1], axis = 0)). C'est "IndexError: l'index 33 est hors limites pour l'axe 3 avec la taille 3". Cette étape fonctionne également mais nécessite plusieurs minutes pour s'exécuter. mode, count = scipy.stats.mode (imgs24, axis = 0) – megashigger

+0

Je ne peux pas dire quel est le problème sans les entrées et les sorties que vous utilisez. Avez-vous entré une liste de tableaux ou un seul? –

+0

J'ai entré une liste de tableaux numpy, chacun avec la forme (288,512,3). La liste a une longueur de 10. – megashigger