Java – Canny’s algorithm: lag error function
•
Java
I'm writing Canny's algorithm. I seem to have a lag problem The threshold seems to be working, but my lag doesn't seem to work at all And delete weak methods for some strange reasons Please help!
Low @ 10
High @ 75
After the lag, problem a, the edge is not strengthened, and the method implementation lags behind; Using the method removebreak does not delete the B weak edge
The source code of this method is as follows:
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;
}
}
Solution
I thought of it Hysteresis is effective, which is hard to say considering the quality of the image
As for removing weak, I used the enhanced for loop, and I began to see that only copies of the elements were obtained and changed, not the elements of the array itself Once I change it to a regular for loop, it's OK!
The content of this article comes from the network collection of netizens. It is used as a learning reference. The copyright belongs to the original author.
THE END
二维码
