我正在写Canny的算法,我似乎有一个滞后问题.阈值似乎正在处理,但是我的滞后似乎根本不起作用.以及由于一些奇怪的原因删除弱的方法.请帮忙!
低@ 10
高@ 75
在滞后后,问题A,边缘没有加强,方法执行滞后;使用方法removeWeak不会删除B弱边缘.
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,-2.0f,1.0f,-1.0f}; private static final float[] sobelY = { 1.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,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,width,height,x); sobelYImg.getRaster().getPixels(0,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,height); performHysteresis(pixelNew,width); removeWeak(pixelNew); BufferedImage result = new BufferedImage(width,BufferedImage.TYPE_BYTE_GRAY); result.getRaster().setPixels(0,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,pixelNew); else pixelNew[i] = 0; break; case 90: if (pixelM[i] > pixelM[i+width] && pixelM[i] > pixelM[i-width]) setPixel(i,pixelNew); else pixelNew[i] = 0; break; case 135:if (pixelM[i] > pixelM[i+width] && pixelM[i] > pixelM[i-width]) setPixel(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),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; } }
解决方法
我想到了.迟滞是有效的,考虑到图像的质量,这很难说.
至于删除弱,我使用增强的for循环,我开始看到只获得并更改了元素的副本,而不是数组本身的元素.一旦我将其更改为常规for循环,它就可以了!