坎尼算法:磁滞故障 [英] Canny's Algorithm: Hysteresis Mal-function

查看:96
本文介绍了坎尼算法:磁滞故障的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在编写Canny的算法,但似乎存在滞后问题。阈值似乎正在处理,但是我的磁滞似乎根本没有起作用。以及出于某些奇怪原因的方法消除弱点。

I am writing Canny's Algorithm, and I seem to have an issue with hysteresis. The Thresholds Appears to process, however my hysteresis does not seem to function at all. As well as method remove weak for some odd reason. Please help!


低@ 10

高@ 75

滞后后,对于问题A,使用performHysteresis方法无法增强边缘;

Low @ 10 High @ 75 After Hysteresis, with problem A, edges were not strengthen with method performHysteresis; B weak non-edges are not removed with method 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;
}
}


推荐答案

I弄清楚了。滞后起作用了,鉴于图像的质量很难说。

I figured it out. The hysteresis was working, it was just hard to tell given the quality of the image.

至于去除弱点,我使用了增强的for循环,我开始看到仅获得和更改了元素的副本,而实际上未获取和更改数组本身中的元素。一旦将其更改为常规的for循环,它就起作用了!

As for the remove weak, I used the enhanced for loop which I am starting to see that only a copy of the element is obtained and changed, not actually the element in the array itself. Once I changed that to a regular for loop it worked!

这篇关于坎尼算法:磁滞故障的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆