2013-09-03 6 views
5

J'ai une matrice composée de valeurs positives et négatives. J'ai besoin de faire ces choses.moyen le plus rapide pour calculer le voisinage des pixels

Soit u(i,j) désignons les pixels de la matrice u.

  1. Calculez les pixels qui traversent le zéro. Ce sont les pixels de la grille si u(i-1,j) et u(i+1,j) sont de signes opposés ou u(i,j-1) et u(i,j+1) sont de signes opposés.
  2. Ensuite, j'ai besoin de calculer la bande étroite autour de ces pixels de passage à zéro. La largeur de la bande étroite est (2r+1)X(2r+1) pour chaque pixel. Je prends r=1 donc pour cela je dois réellement obtenir les 8 pixels de voisinage de chaque pixel de passage à zéro.

Je l'ai fait dans un programme. S'il vous plaît voir ci-dessous.

%// calculate the zero crossing pixels 
front = isfront(u); 
%// calculate the narrow band of around the zero crossing pixels 
band = isband(u,front,1); 

Je joins également les fonctions isfront et isband.

function front = isfront(phi) 
%// grab the size of phi 
[n, m] = size(phi); 

%// create an boolean matrix whose value at each pixel is 0 or 1 
%// depending on whether that pixel is a front point or not 
front = zeros(size(phi)); 

%// A piecewise(Segmentation) linear approximation to the front is contructed by 
%// checking each pixels neighbour. Do not check pixels on border. 
for i = 2 : n - 1; 
    for j = 2 : m - 1; 
    if (phi(i-1,j)*phi(i+1,j)<0) || (phi(i,j-1)*phi(i,j+1)<0) 
     front(i,j) = 100; 
    else 
     front(i,j) = 0; 
    end 
    end 
end 

function band = isband(phi, front, width) 
%// grab size of phi 
[m, n] = size(phi); 

%// width=r=1; 
width = 1; 

[x,y] = find(front==100); 

%// create an boolean matrix whose value at each pixel is 0 or 1 
%// depending on whether that pixel is a band point or not 
band = zeros(m, n); 

%// for each pixel in phi 
for ii = 1:m 
    for jj = 1:n 
    for k = 1:size(x,1) 
     if (ii==x(k)) && (jj==y(k)) 
      band(ii-1,jj-1) = 100; band(ii-1,jj) = 100; band(ii-1,jj+1) = 100; 
      band(ii ,jj-1) = 100; band(ii ,jj) = 100; band(ii,jj+1) = 100; 
      band(ii+1,jj-1) = 100; band(ii+1,jj) = 100; band(ii+1,jj+1) = 100; 
     end 
    end 
    end 
end 

Les sorties sont donnés ci-dessous :, ainsi que le temps de calcul:

Figure

%// Computation time 

%// for isfront function 
Elapsed time is 0.003413 seconds. 

%// for isband function 
Elapsed time is 0.026188 seconds. 

Quand je lance le code je reçois les réponses correctes, mais le calcul pour les tâches est trop à mon goût. Y a-t-il une meilleure façon de le faire? Surtout la fonction isband? Comment puis-je optimiser mon code davantage?

Merci d'avance.

+3

Avez-vous envisagé des opérations morphologiques, disent [ 'bwmorph'] (http://www.mathworks.com/help/images/ref/bwmorph.html)? –

+1

Attention: L'accès aux deux pixels voisins dans votre 'isband' est incorrectement codé; vous avez probablement copié-collé et oublié de corriger le -1 en +1 et +0. –

+0

@RodyOldenhuis merci pour le commentaire. Oui, je l'ai copié et collé, donc c'était une erreur. Edited ma question pour le corriger. – roni

Répondre

5

Comme suggéré par EitanT, il y a au moins bwmorph qui fait déjà ce que vous voulez.

Si vous ne pas avoir accès à la boîte à outils de traitement d'images, ou tout simplement insistez pour le faire vous-même:

Vous pouvez remplacer le triple boucle isfront avec le vectorisé

front = zeros(n,m); 

zero_crossers = ... 
    phi(1:end-2,2:end-1).*phi(3:end,2:end-1) < 0 | ... 
    phi(2:end-1,1:end-2).*phi(2:end-1,3:end) < 0; 

front([... 
        false(1,m) 
    false(n-2,1) zero_crossers false(n-2,1) 
        false(1,m)     ]... 
) = 100; 

Et vous pouvez remplacer isband par cette seule boucle:

[n,m] = size(front); 
band = zeros(n,m); 
[x,y] = find(front); 
for ii = 1:numel(x) 
    band(... 
     max(x(ii)-width,1) : min(x(ii)+width,n),... 
     max(y(ii)-width,1) : min(y(ii)+width,m)) = 1; 
end 

Alternativement, comme suggéré par Milan, vous pouvez appliquer l'image dilati à travers convolution:

kernel = ones(2*width+1);  
band = conv2(front, kernel); 
band = 100 * (band(width+1:end-width, width+1:end-width) > 0); 

qui devrait être encore plus rapide.

Et vous pouvez bien sûr avoir d'autres optimisations mineures (isband ne nécessite pas phi comme argument, vous pouvez passer front comme un tableau logique afin que find est plus rapide, etc.).

+0

Une info rapide J'essayais de le chronométrer avec mes images qui avaient une taille de 75X79 et j'ai chronométré à la fois ma fonction is_front et votre fonction is_front. Voici les résultats: run1: Le temps écoulé est 0.003101 secondes. Le temps écoulé est de 0,004594 secondes. run2: le temps écoulé est 0,002801 secondes. Le temps écoulé est de 0,004535 secondes. – roni

+0

Ensuite, j'ai redimensionné mon image à 4000X4000 et j'obtiens ce résultat de synchronisation: run1: Le temps écoulé est 2,646254 secondes. Le temps écoulé est de 0,766821 secondes. run2: Le temps écoulé est 2.853837 secondes. Le temps écoulé est de 0,737387 secondes. Pourquoi mon code est-il plus rapide pour les réseaux plus petits et plus lent pour les réseaux plus grands? Peux-tu expliquer ? Le code vectoriel ne devrait-il pas toujours fonctionner plus vite? – roni

+0

De même pour la fonction is_band run1: ma fonction: 0,006310 secondes. votre func: 0.004052 secondes. run2: ma fonction: 0,005674 secondes. votre func: 0.004003 secondes. run3: ma fonction: 0,005919 secondes. votre func: 0.003908 secondes. – roni

1

Si vous êtes seulement intéressé par r == 1, regardez makelut et la fonction correspondante bwloolup.

[EDIT]

% Let u(i,j) denote the pixels of the matrix u. Calculate the zero crossing 
% pixels. These are the pixels in the grid if u(i-1,j) and u(i+1,j) are of 
% opposite signs or u(i,j-1) and u(i,j+1) are of opposite signs. 

% First, create a function which will us if a pixel is a zero crossing 
% pixel, given its 8 neighbors. 

% uSign = u>0; % Note - 0 is treated as negative here. 

% uSign is 3x3, we are evaluating the center pixel uSign(2,2) 
zcFun = @(uSign) (uSign(1,2)~=uSign(3,2)) || (uSign(2,1)~=uSign(2,3)); 

% Make a look up table which tells us what the output should be for the 2^9 
% = 512 possible patterns of 3x3 arrays with 1's and 0's. 
lut = makelut(zcFun,3); 

% Test image 
im = double(imread('pout.tif')); 
% Create positve and negative values 
im = im -mean(im(:)); 

% Apply lookup table 
imSign = im>0; 
imZC = bwlookup(imSign,lut); 

imshowpair(im, imZC); 
+0

pouvez-vous me montrer comment? J'ai regardé à travers le matériel et ce n'est pas clair pour moi. J'ai très peu d'idées sur les méthodes morphologiques. Veuillez me donner quelques conseils sur la façon de l'appliquer. – roni

Questions connexes