3
votes

Filtre non linéaire pour le traitement d'image - recherche du minimum à l'intérieur d'un masque

J'ai une idée sur un filtre pour les images mais je ne sais pas comment je peux réaliser cela sans utiliser un double pour la boucle dans MATLAB.

J'ai une image et je souhaite utiliser un masque de filtre linéaire dessus, disons:

[ … image data      …]
[ …                 …]
[ …                 …]
[ … 23 68 20  20 53 …]
[ …                 …]

Ce masque de filtre se déplace sur l'image, pixel par pixel. Pour chaque quartier, le pixel I est défini sur le minimum du quartier environnant.

Voici un exemple:

[ … image data      …]
[ …                 …]
[ …                 …]
[ … 23 68 155 20 53 …]
[ …                 …]

Pour mon exemple, je veux filtrer le pixel de centrage avec la valeur 155. Le résultat serait: p>

[1,1,1,1,1]

Le pixel 155 est remplacé par la valeur minimale de son voisinage.

Je peux le faire avec une boucle double pour, mais c'est vraiment lent , trop lent pour l'utiliser pour mon application.

Je serais heureux d'avoir une bonne idée pour augmenter la vitesse! Merci


0 commentaires

3 Réponses :


0
votes

Si je comprends bien votre question, ce que vous voulez, c'est trouver une valeur minimale mobile avec une largeur de fenêtre spécifiée le long d'une ligne spécifique. Cela peut être fait avec la fonction movmin qui a été introduite dans la version 2016a.

Sachant que movmin traite les colonnes par défaut (comme dim = 1). Donc, dans votre cas, vous pouvez définir l'argument dim sur 2 (déplacer le long des lignes) et ignorer les points de terminaison de la valeur en dehors de la fenêtre. Un exemple de code peut ressembler à:

k = randi(20,20,11); % make some samples
ci = 6; % sample at the center row
wd = 5; % filter window width
k(:,ci) = movmin(k(:,(ci-2:ci+2)),wd,2,'Endpoints','discard') % replace the center row samples

Jetez un œil à movmin pour en savoir plus.


0 commentaires

0
votes

Je travaillais sur une propre solution, lorsque la réponse de Y. Chang est apparue ... Je voulais affichez-le néanmoins. Au moins, le résultat est le même, donc cela semble fonctionner.

A =
    9    2    1    6    7
    2    5    9    1    7
    2    8    5   10    4
    2    0    6    5    8
    8    3   10    7    6

b =
   1   1   1   1   1

B =
   1   1   1   1   1
   2   1   1   1   1
   2   2   2   4   4
   0   0   0   0   5
   3   3   3   3   6

BB =
   1   1   1   1   1
   2   1   1   1   1
   2   2   2   4   4
   0   0   0   0   5
   3   3   3   3   6

Sortie:

% Test input.
A = round(rand(5) * 10)

% Dimensions.
nRows = size(A, 1);
nCols = size(A, 2);

% Kernel.
b = [1, 1, 1, 1, 1]

% Step size.
step = floor(numel(b) / 2);

% Output.
B = zeros(nRows, nCols);
for k = 1:nRows
  temp = repmat(A(k, :), nCols + 2 * step, 1);
  idx = double(triu(ones(size(temp)), -numel(b) + 1) & tril(ones(size(temp)), 0));
  idx(idx == 0) = NaN;
  temp = temp .* idx;
  temp = min(temp, [], 2).';
  B(k, :) = temp(step+1:end-step);
end
B

% Compare with movmin function.
BB = movmin(A, numel(b), 2)


0 commentaires

2
votes

Votre idée de filtre s'appelle érosion . Il est implémenté dans la boîte à outils de traitement d'image dans la fonction imerode code > . Dans votre cas, vous appliqueriez:

[0,1,1,1,0
 1,1,1,1,1
 1,1,1,1,1
 1,1,1,1,1
 0,1,1,1,0]

Le quartier peut avoir n'importe quelle forme. Définissez les éléments sur 0 pour les exclure du voisinage. Par exemple, pour un quartier arrondi, vous pouvez utiliser

result = imerode(image_data, [1,1,1,1,1]);


0 commentaires