2013-09-03 11 views
5

Ich habe eine Matrix, die aus positiven und negativen Werten besteht. Ich muss diese Dinge tun.schnellste Möglichkeit zur Berechnung der Nachbarschaft von Pixeln

Lassen Sie u(i,j) die Pixel der Matrix u bezeichnen.

  1. Berechnen Sie die Nulldurchgangspixel. Dies sind die Pixel im Raster, wenn u(i-1,j) und u(i+1,j) entgegengesetzte Vorzeichen haben oder u(i,j-1) und u(i,j+1) entgegengesetzte Vorzeichen haben.
  2. Dann muss ich das schmale Band um diese Nulldurchgangspixel berechnen. Die Breite des Schmalbands ist (2r+1)X(2r+1) für jedes Pixel. Ich nehme r=1, also muss ich tatsächlich die 8 Nachbarschafts-Pixel von jedem Nulldurchgangspixel bekommen.

Ich habe dies in einem Programm getan. Bitte sehen Sie es unten.

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

Ich füge auch die isfront und isband Funktionen.

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 

Die Ausgänge werden im Folgenden :, sowie die Rechenzeit gegeben:

Figure

%// Computation time 

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

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

Wenn ich den Code ausführen ich die richtigen Antworten erhalten tun, aber die Berechnung für die Aufgaben ist zu viel nach meinem Geschmack. Gibt es einen besseren Weg, es zu tun? Vor allem die isband Funktion? Wie kann ich meinen Code weiter optimieren?

Vielen Dank im Voraus.

+3

Haben Sie morphologische Operationen betrachtet, sagen [ 'bwmorph'] (http://www.mathworks.com/help/images/ref/bwmorph.html)? –

+1

Vorsicht: Zugriff auf die unteren rechten zwei benachbarten Pixel in Ihrem 'isband' ist falsch codiert; Sie haben wahrscheinlich kopiert und eingefügt und vergessen, die -1 in eine +1 und +0 zu korrigieren. –

+0

@RodyOldenhuis danke für den Kommentar. Ja, ich habe es kopiert und eingefügt, also war es ein Fehler. Bearbeitete meine Frage, um es zu korrigieren. – roni

Antwort

5

Wie von EitanT vorgeschlagen, gibt es mindestens bwmorph, die bereits tun, was Sie wollen.

Wenn Sie noch keinen Zugriff auf die Bildverarbeitung Toolbox, oder darauf bestehen, nur auf es selbst zu tun:

Sie den Triple-Loop in isfront mit den vektorisiert

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; 

ersetzen und Sie können ersetzen isband durch diese einzige Schleife:

[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 

Alternativ kann, wie von Mailand vorgeschlagen, können Sie die Bild dilati anwenden ein durch :

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

, die noch schneller sein sollte.

Und Sie können natürlich einige andere kleinere Optimierungen haben (isband erfordert keine phi als Argument, Sie front als logische Array übergeben werden kann, so dass find schneller ist, etc.).

+0

Eine schnelle Information Ich habe versucht, es mit meinen Bildern zu messen, die eine Größe von 75X79 hatten, und ich habe sowohl meine Funktion is_front als auch deine Funktion is_front zeitlich festgelegt. Hier sind die Ergebnisse: run1: Die verstrichene Zeit beträgt 0,003101 Sekunden. Die verstrichene Zeit beträgt 0,004594 Sekunden. run2: Die verstrichene Zeit beträgt 0,002801 Sekunden. Die abgelaufene Zeit beträgt 0,004535 Sekunden. – roni

+0

Dann änderte ich mein Bild auf 4000X4000 und ich bekomme diese Timing-Ergebnisse: run1: Die verstrichene Zeit beträgt 2,646254 Sekunden. Die verstrichene Zeit beträgt 0,766821 Sekunden. run2: Die verstrichene Zeit beträgt 2,853837 Sekunden. Die abgelaufene Zeit beträgt 0,737387 Sekunden. Warum ist mein Code schneller für kleinere Arrays und langsamer für größere Arrays? Können Sie erklären ? Sollte nicht immer der Vektorcode viel schneller laufen? – roni

+0

Ähnlich für die Funktion is_band run1: my func: 0.006310 Sekunden. Ihre Funktion: 0,004052 Sekunden. run2: meine Funktion: 0.005674 Sekunden. Ihre Funktion: 0.004003 Sekunden. run3: meine Funktion: 0.005919 Sekunden. Ihre Funktion: 0,003908 Sekunden. – roni

1

Wenn Sie nur an r == 1 interessiert sind, sehen Sie und die entsprechende Funktion 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

kannst du mir zeigen wie? Ich habe das Material durchgesehen und es ist mir nicht klar. Ich habe sehr wenig Vorstellungen von morphologischen Methoden. Bitte geben Sie mir einige Tipps zur Anwendung. – roni