2014-12-17 7 views
7

Ich schreibe Canny-Algorithmus, und ich habe ein Problem mit der Hysterese. Die Thresholds scheint zu verarbeiten, aber meine Hysterese scheint überhaupt nicht zu funktionieren. Sowie Methode entfernen schwach aus irgendeinem seltsamen Grund. Bitte helfen Sie!Canny Algorithmus: Hysterese Mal-Funktion

Low @ 10 Low @ 10 High @ 75 Hoch @ 75 After Hysteresis Nach Hysterese, mit Problem A, Kanten wurden stärken nicht mit Methode performHysteresis; B schwache Nicht-Kanten werden nicht mit der Methode removeWeak entfernt.

Quellcode für das Verfahren wie folgt:

import java.awt.image.BufferedImage; 
import java.awt.image.ConvolveOp; 
import java.awt.image.Kernel; 

class CannyMethod { 

private static final float[] sobelX = { 1.0f, 0.0f, -1.0f, 
             2.0f, 0.0f, -2.0f, 
             1.0f, 0.0f, -1.0f}; 
private static final float[] sobelY = { 1.0f, 2.0f, 1.0f, 
             0.0f, 0.0f, 0.0f, 
             -1.0f,-2.0f,-1.0f}; 
private static int low, high; 


public CannyMethod() {} 

private ConvolveOp getSobel(boolean xy) { 
    Kernel kernel; 
    if (xy) kernel = new Kernel(3, 3, sobelX); 
    else kernel = new Kernel(3, 3, sobelY); 

    return new ConvolveOp(kernel, ConvolveOp.EDGE_ZERO_FILL, null); 
} 

public BufferedImage getCannyFilter(BufferedImage img) { 
    return getCannyFilter(img, low, high); 
} 

public BufferedImage getCannyFilter(BufferedImage img, int l, int h) { 
    int width = img.getWidth(); 
    int height = img.getHeight(); 
    low = l; 
    high = h; 

    int size = width * height; 
    int[] x = new int[size]; 
    int[] y = new int[size]; 
    int[] pixelM = new int[size]; 
    double[] pixelD = new double[size]; 
    int[] pixelNew = new int[size]; 

    BufferedImage sobelXImg = getSobel(true).filter(img, null); 
    BufferedImage sobelYImg = getSobel(false).filter(img, null); 


    // returns arrays for x and y direction after convultion with Sobel Operator 
    sobelXImg.getRaster().getPixels(0, 0, width, height, x); 
    sobelYImg.getRaster().getPixels(0, 0, width, height, y); 

// Calculates Gradient and Magnitude 
    for(int i = 0; i < size; i++) { 
     pixelM[i] = (int) Math.hypot(x[i], y[i]); 
     pixelD[i] = Math.atan2((double) y[i], (double) x[i]); 
    } 

//Operations for Canny Algorithm takes magnitude and gradient and input into new array fo WritableRaster 
    normalizeDirection(pixelD); 
    nonMaximaSupression(pixelM, pixelD, pixelNew, width, height); 
    performHysteresis(pixelNew, width); 
    removeWeak(pixelNew); 

    BufferedImage result = 
     new BufferedImage(width, height, 
          BufferedImage.TYPE_BYTE_GRAY); 
    result.getRaster().setPixels(0, 0, width, height, pixelNew); 

    return result; 
} 

private void normalizeDirection(double[] dArray) { 
//Round degrees 

    double pi = Math.PI; 
    for(double i : dArray) { 
     if (i < pi/8d && i >= -pi/8d) i = 0; 
     else if (i < 3d*pi/8d && i >= pi/8d) i = 45; 
     else if (i < -3d*pi/8d || i >= 3d*pi/8d) i = 90; 
     else if (i < -pi/8d && i >= -3d*pi/8d) i = 135; 
    } 
} 

private void nonMaximaSupression(int[] pixelM, double[] pixelD, 
    int[] pixelNew, int width, int height) { 
//non-Maxima Supression 
//Since array is not in 2-D, positions are calulated with width - functions properly 

    for(int i = 0; i < pixelNew.length; i++) { 
     if (i % width == 0 || (i + 1) % width == 0 || 
      i <= width || i >= width * height - 1) pixelNew[i] = 0; 
     else { 
      switch ((int) pixelD[i]) { 
       case 0: if (pixelM[i] > pixelM[i+1] 
          && pixelM[i] > pixelM[i-1]) 
          setPixel(i, pixelM[i], pixelNew); 
         else pixelNew[i] = 0; 
         break; 
       case 45: if (pixelM[i] > pixelM[i+(width-1)] 
          && pixelM[i] > pixelM[i-(width-1)]) 
          setPixel(i, pixelM[i], pixelNew); 
         else pixelNew[i] = 0; 
         break; 
       case 90: if (pixelM[i] > pixelM[i+width] 
          && pixelM[i] > pixelM[i-width]) 
          setPixel(i, pixelM[i], pixelNew); 
         else pixelNew[i] = 0; 
         break; 
       case 135:if (pixelM[i] > pixelM[i+width] 
          && pixelM[i] > pixelM[i-width]) 
          setPixel(i, pixelM[i], pixelNew); 
         else pixelNew[i] = 0; 
         break; 
       default: pixelNew[i] = 0; 
      } 
     } 
    } 
} 

private void performHysteresis(int[] array, int width) { 
//performs hysteresis 

    int[] temp; 
    for(int i = width; i < array.length - width; i++) { 
     if (i % width == 0 || (i + 1) % width == 0) {} 
     else { 
      if (array[i] == 255) { 
    //found strong one, track surrounding weak ones 
    //temp is the positions of surrounding pixels 
       temp = new int[] 
        {i - (width + 1), i - width, i - (width - 1), 
        i - 1,      i + 1, 
        i + (width - 1), i + width, i + (width + 1)}; 
       trackWeak(array, temp, width); 
      } 
     } 
    } 
} 

private void trackWeak(int[] array, int[] pos, int width) { 
    int[] temp; 
    for (int i : pos) { 
     if (array[i] > 0 && array[i] < 255) { 
      array[i] = 255; 
    //set weak one to strong one 

      if (i % width == 0 || (i + 1) % width == 0) {} 
      else { 
    //temp is the positions of surrounding pixels 
       temp = new int[] 
        {i - (width + 1), i - width, i - (width - 1), 
        i - 1,      i + 1, 
        i + (width - 1), i + width, i + (width + 1)}; 
       trackWeak(array, temp, width); 
      } 
     } 
    } 
} 

private void removeWeak(int[] array) { 
//remove remaining weak ones from lew Threshold 

    for(int i : array) { 
     if (i < 255) {i = 0;} 
    } 
} 

private void setPixel(int pos, int value, int[] pixelNew) { 
    if (value > high) pixelNew[pos] = 255; 
    else if (value > low) pixelNew[pos] = 128; 
    else pixelNew[pos] = 0; 
} 

public void setThreshold(int l, int h) { 
    low = l; 
    high = h; 
} 
} 
+3

entschuldige dich nicht für Kommentare - Kommentare hinzufügen. Beides, um uns zu helfen, Ihren Code zu verstehen, und damit Sie nächste Woche Ihren eigenen Code verstehen können. Verknüpfen Sie auch nicht mit Code, von dem Sie glauben, dass er möglicherweise vor dem Kompilieren bearbeitet werden muss: Postleitzahl, die Sie kompilieren. Erinnere dich, wir sind nur Menschen, so wie du. Je mehr Zeit wir damit verbringen, Ihren Code zu verstehen oder sogar auszuführen, desto mehr gehen wir stattdessen zur nächsten Frage über. –

+0

Danke für den Vorschlag, für Ihren Vorschlag habe ich Kommentare für die betreffende Klasse abgegeben und sichergestellt, dass die Klasse fehlerfrei kompiliert wird. Ich habe ein Problem mit meinem Code festgestellt, aber es gibt immer noch ein Problem in meiner Operation für und nach Hysterese, ich würde Ihre Hilfe sehr schätzen, wenn Sie eine anbieten können. – DVCode

Antwort

2

ich es herausgefunden. Die Hysterese funktionierte, es war nur schwer zu sagen angesichts der Qualität des Bildes.

Für die Entfernung schwach, ich habe die erweiterte for-Schleife, die ich zu sehen beginnen, dass nur eine Kopie des Elements erhalten und geändert wird, nicht wirklich das Element im Array selbst. Sobald ich das zu einer normalen for-Schleife änderte, funktionierte es!