Convolve2d seulement par l'utilisation de Numpy
Je suis des études de traitement de l'image à l'aide de Numpy et face à un problème de filtrage avec la convolution.
Je voudrais convolution d'une image en niveaux de gris de l'image. (convolution d'un Tableau 2d avec un petit Tableau 2d)
Quelqu'un a une idée pour affiner ma méthode ?
Je sais que scipy prend en charge convolve2d mais je veux faire un convolve2d que par l'utilisation de Numpy.
Ce que j'ai fait
Tout d'abord, j'ai fait un tableau 2d de la submatrices.
a = np.arange(25).reshape(5,5) # original matrix
submatrices = np.array([
[a[:-2,:-2], a[:-2,1:-1], a[:-2,2:]],
[a[1:-1,:-2], a[1:-1,1:-1], a[1:-1,2:]],
[a[2:,:-2], a[2:,1:-1], a[2:,2:]]])
la submatrices semble compliqué, mais ce que je fais est montré sur le dessin suivant.
Prochaine, je multiplie chaque submatrices avec un filtre.
conv_filter = np.array([[0,-1,0],[-1,4,-1],[0,-1,0]])
multiplied_subs = np.einsum('ij,ijkl->ijkl',conv_filter,submatrices)
et additionnés entre eux.
np.sum(np.sum(multiplied_subs, axis = -3), axis = -3)
#array([[ 6, 7, 8],
# [11, 12, 13],
# [16, 17, 18]])
Donc ce procudure peut être appelé mon convolve2d.
def my_convolve2d(a, conv_filter):
submatrices = np.array([
[a[:-2,:-2], a[:-2,1:-1], a[:-2,2:]],
[a[1:-1,:-2], a[1:-1,1:-1], a[1:-1,2:]],
[a[2:,:-2], a[2:,1:-1], a[2:,2:]]])
multiplied_subs = np.einsum('ij,ijkl->ijkl',conv_filter,submatrices)
return np.sum(np.sum(multiplied_subs, axis = -3), axis = -3)
Cependant, je trouve cette my_convolve2d gênant pour 3 raisons.
- Génération de la submatrices est trop maladroit qui est difficile à lire et peut être utilisé seulement lorsque le filtre est de 3*3
- La taille de la variante submatrices semble être trop grand, car il est environ 9 fois plus grand que la matrice d'origine.
- Le résumé semble un peu non intuitive. Simplement dit, laid.
Je vous remercie pour la lecture de ce jour.
Genre de mise à jour. J'ai écrit un conv3d pour moi-même. Je vais laisser cela comme un domaine public.
def convolve3d(img, kernel):
# calc the size of the array of submatracies
sub_shape = tuple(np.subtract(img.shape, kernel.shape) + 1)
# alias for the function
strd = np.lib.stride_tricks.as_strided
# make an array of submatracies
submatrices = strd(img,kernel.shape + sub_shape,img.strides * 2)
# sum the submatraces and kernel
convolved_matrix = np.einsum('hij,hijklm->klm', kernel, submatrices)
return convolved_matrix
Content que ça aide! Oui. Je vous serais reconnaissant si vous pouvez me donner des conseils pour surmonter les 3 problèmes écrite dans les toutes dernières lignes.
Je dois ajouter que les 3 points sont plutôt disposés dans un ordre de priorité. Le premier est assez important pour moi et le dernier semble un peu trivial. Je serai aussi heureux si il y a d'autres problèmes et les améliorations à apporter à ce sujet.
N'est-ce pas le deuxième dessin (après le signe de l'égalité) de mal? Ne devrait pas chaque submatrix être multipliés (élément-sage) avec le filtre, puis les éléments de chaque résultant de la submatrices résumé?
Ils produisent le même résultat.
OriginalL'auteur Allosteric | 2017-03-29
Vous devez vous connecter pour publier un commentaire.
Vous pouvez générer les sous-réseaux à l'aide de
as_strided
[1]:Pour se débarrasser de votre deuxième "laid" somme, modifier votre
einsum
de sorte que le tableau de sortie uniquement aj
etk
. Cela implique votre deuxième sommation.Merci pour l'astuce. J'essaie moi-même maintenant. Peut-être trivial, mais je crois que le nom du filtre n'est pas approprié parce qu'il est une fonction intégrée de python.
Vous pouvez faire la somme directement dans le Einstein de sommation. Voir la réponse
Astuce sur le
einsum
, ne voir qu'une seule.Dans cette question, n'est-il pas mieux écrire,
sub_shape = conv_filter.shape
?OriginalL'auteur Crispin
Vous pouvez également utiliser la fft (l'une des méthodes plus rapides pour effectuer des circonvolutions)
cheers,
Dan
OriginalL'auteur Dan Erez
Nettoyés à l'aide d'
as_strided
et @Crispin 'seinsum
truc à partir de ci-dessus. Applique le filtre de taille dans l'élargissement de la forme. Devraient même permettre à des non-carré entrées si les indices sont compatibles.Je ne sais pas pourquoi que les œuvres @NaN, car il est certainement pas en faisant ce que le problème posé - mais il le fait, même pour arbitraire
a
matricesau moins à numpy v12, une.la forme et la f.la forme est un n-uplet de sorte
s
devrait êtretuple(np.subtract(a.shape, f.shape)+1)
, je pense.Vrai! Toujours utilisé pour
shape
donner unndarray
. Fixe qui.Salut @DanielF, est-il une généralisation de ce qui fonctionne pour le RVB? Pas super familier avec einsum notation, donc une idée de comment généraliser serait génial.
OriginalL'auteur Daniel F