7

私はキャニーのアルゴリズムを書いていますが、ヒステリシスに問題があるようです。しきい値は処理されているように見えますが、ヒステリシスがまったく機能していないようです。メソッドと同様に、何らかの奇妙な理由でweakを削除します。助けてください!

低 @ 10 Low @ 10 高 @ 75 High @ 75 ヒステリシス後 ヒステリシスの後、問題 A により、performHysteresis メソッドでエッジが強化されませんでした。B 弱い非エッジは、メソッド removeWeak では削除されません。

メソッドのソース コードは次のとおりです。

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;
}
}
4

1 に答える 1