边缘检测算法的基本步骤 (1)滤波。边缘检测主要基于导数计算,但受噪声影响。但滤波器在降低噪声的同时也导致边缘强度的损失。 (2)增强。增强算法将邻域中灰度有显著变化的点突出显示。一般通过计算梯度幅值完成。 (3)检测。但在有些图象中梯度幅值较
边缘检测算法的基本步骤(1)滤波。边缘检测主要基于导数计算,但受噪声影响。但滤波器在降低噪声的同时也导致边缘强度的损失。 (2)增强。增强算法将邻域中灰度有显著变化的点突出显示。一般通过计算梯度幅值完成。
(3)检测。但在有些图象中梯度幅值较大的并不是边缘点。最简单的边缘检测是梯度幅值阈值判定。
(4)定位。精确确定边缘的位置。
Canny边缘检测算法step1:用高斯滤波器平滑图象;
step2:用一阶偏导的有限差分来计算梯度的幅值和方向;
step3:对梯度幅值进行非极大值抑制;
step4:用双阈值算法检测和连接边缘。
效果图如下:
代码如下:packagetools;importjava.awt.*;importjava.awt.image.*;publicclassEdgeDetectorextendsComponent{publicEdgeDetector(){threshold1 = 50;threshold2 = 230;setThreshold(128);setWidGaussianKernel(15);}publicvoidprocess()throwsEdgeDetectorException{if(threshold < 0 || threshold > 255)thrownewEdgeDetectorException("The value of the threshold is out of its valid range.");if(widGaussianKernel < 3 || widGaussianKernel > 40)thrownewEdgeDetectorException("The value of the widGaussianKernel is out of its valid range.");width = sourceImage.getWidth(this);height = sourceImage.getHeight(this);picsize = width * height;data =newint[picsize];magnitude =newint[picsize];orientation =newint[picsize];floatf = 1.0F;canny_core(f, widGaussianKernel);thresholding_tracker(threshold1, threshold2);for(inti = 0; i < picsize; i++)if(data[i] > threshold)data[i] = 0xff000000;elsedata[i] = -1;edgeImage = pixels2image(data);data =null;magnitude =null;orientation =null;}privatevoidcanny_core(floatf,inti){booleanflag =false;booleanflag1 =false;derivative_mag =newint[picsize];floataf4[] =newfloat[i];floataf5[] =newfloat[i];floataf6[] =newfloat[i];data = image2pixels(sourceImage);intk4 = 0;do{if(k4 >= i)break;floatf1 = gaussian(k4, f);if(f1 <= 0.005F && k4 >= 2)break;floatf2 = gaussian((float) k4 - 0.5F, f);floatf3 = gaussian((float) k4 + 0.5F, f);floatf4 = gaussian(k4, f * 0.5F);af4[k4] = (f1 + f2 + f3) / 3F / (6.283185F * f * f);af5[k4] = f3 - f2;af6[k4] = 1.6F * f4 - f1;k4++;}while(true);intj = k4;floataf[] =newfloat[picsize];floataf1[] =newfloat[picsize];intj1 = width - (j - 1);intl = width * (j - 1);inti1 = width * (height - (j - 1));for(intl4 = j - 1; l4 < j1; l4++){for(intl5 = l; l5 < i1; l5 += width){intk1 = l4 + l5;floatf8 = (float) data[k1] * af4[0];floatf10 = f8;intl6 = 1;intk7 = k1 - width;for(inti8 = k1 + width; l6 < j; i8 += width){f8 += af4[l6] * (float) (data[k7] + data[i8]);f10 += af4[l6] * (float) (data[k1 - l6] + data[k1 + l6]);l6++;k7 -= width;}af[k1] = f8;af1[k1] = f10;}}floataf2[] =newfloat[picsize];for(inti5 = j - 1; i5 < j1; i5++){for(inti6 = l; i6 < i1; i6 += width){floatf9 = 0.0F;intl1 = i5 + i6;for(inti7 = 1; i7 < j; i7++)f9 += af5[i7] * (af[l1 - i7] - af[l1 + i7]);af2[l1] = f9;}}af =null;floataf3[] =newfloat[picsize];for(intj5 = k4; j5 < width - k4; j5++){for(intj6 = l; j6 < i1; j6 += width){floatf11 = 0.0F;inti2 = j5 + j6;intj7 = 1;for(intl7 = width; j7 < j; l7 += width){f11 += af5[j7] * (af1[i2 - l7] - af1[i2 + l7]);j7++;}af3[i2] = f11;}}af1 =null;j1 = width - j;l = width * j;i1 = width * (height - j);for(intk5 = j; k5 < j1; k5++){for(intk6 = l; k6 < i1; k6 += width){intj2 = k5 + k6;intk2 = j2 - width;intl2 = j2 + width;inti3 = j2 - 1;intj3 = j2 + 1;intk3 = k2 - 1;intl3 = k2 + 1;inti4 = l2 - 1;intj4 = l2 + 1;floatf6 = af2[j2];floatf7 = af3[j2];floatf12 = hypotenuse(f6, f7);intk = (int) ((double) f12 * 20D);derivative_mag[j2] = k >= 256 ? 255 : k;floatf13 = hypotenuse(af2[k2], af3[k2]);floatf14 = hypotenuse(af2[l2], af3[l2]);floatf15 = hypotenuse(af2[i3], af3[i3]);floatf16 = hypotenuse(af2[j3], af3[j3]);floatf18 = hypotenuse(af2[l3], af3[l3]);floatf20 = hypotenuse(af2[j4], af3[j4]);floatf19 = hypotenuse(af2[i4], af3[i4]);floatf17 = hypotenuse(af2[k3], af3[k3]);floatf5;if(f6 * f7 <= (float) 0? Math.abs(f6) >= Math.abs(f7)? (f5 = Math.abs(f6 * f12))>= Math.abs(f7 * f18 - (f6 + f7) * f16)&& f5> Math.abs(f7 * f19 - (f6 + f7) * f15) : (f5 = Math.abs(f7 * f12))>= Math.abs(f6 * f18 - (f7 + f6) * f13)&& f5> Math.abs(f6 * f19 - (f7 + f6) * f14) : Math.abs(f6)>= Math.abs(f7)? (f5 = Math.abs(f6 * f12))>= Math.abs(f7 * f20 + (f6 - f7) * f16)&& f5> Math.abs(f7 * f17 + (f6 - f7) * f15) : (f5 = Math.abs(f7 * f12))>= Math.abs(f6 * f20 + (f7 - f6) * f14)&& f5 > Math.abs(f6 * f17 + (f7 - f6) * f13)){magnitude[j2] = derivative_mag[j2];orientation[j2] = (int) (Math.atan2(f7, f6) * (double) 40F);}}}derivative_mag =null;af2 =null;af3 =null;}privatefloathypotenuse(floatf,floatf1){if(f == 0.0F && f1 == 0.0F)return0.0F;elsereturn(float) Math.sqrt(f * f + f1 * f1);}privatefloatgaussian(floatf,floatf1){return(float) Math.exp((-f * f) / ((float) 2 * f1 * f1));}privatevoidthresholding_tracker(inti,intj){for(intk = 0; k < picsize; k++)data[k] = 0;for(intl = 0; l < width; l++){for(inti1 = 0; i1 < height; i1++)if(magnitude[l + width * i1] >= i)follow(l, i1, j);}}privatebooleanfollow(inti,intj,intk){intj1 = i + 1;intk1 = i - 1;intl1 = j + 1;inti2 = j - 1;intj2 = i + j * width;if(l1 >= height)l1 = height - 1;if(i2 < 0)i2 = 0;if(j1 >= width)j1 = width - 1;if(k1 < 0)k1 = 0;if(data[j2] == 0){data[j2] = magnitude[j2];booleanflag =false;intl = k1;do{if(l > j1)break;inti1 = i2;do{if(i1 > l1)break;intk2 = l + i1 * width;if((i1 != j || l != i)&& magnitude[k2] >= k&& follow(l, i1, k)){flag =true;break;}i1++;}while(true);if(!flag)break;l++;}while(true);returntrue;}else{returnfalse;}}privateImage pixels2image(intai[]){MemoryImageSource memoryimagesource =newMemoryImageSource(width,height,ColorModel.getRGBdefault(),ai,0,width);returnToolkit.getDefaultToolkit().createImage(memoryimagesource);}privateint[] image2pixels(Image image){intai[] =newint[picsize];PixelGrabber pixelgrabber =newPixelGrabber(image, 0, 0, width, height, ai, 0, width);try{pixelgrabber.grabPixels();}catch(InterruptedException interruptedexception){interruptedexception.printStackTrace();}booleanflag =false;intk1 = 0;do{if(k1 >= 16)break;inti = (ai[k1] & 0xff0000) >> 16;intk = (ai[k1] & 0xff00) >> 8;inti1 = ai[k1] & 0xff;if(i != k || k != i1){flag =true;break;}k1++;}while(true);if(flag){for(intl1 = 0; l1 < picsize; l1++){intj = (ai[l1] & 0xff0000) >> 16;intl = (ai[l1] & 0xff00) >> 8;intj1 = ai[l1] & 0xff;ai[l1] =(int) (0.29799999999999999D * (double) j+ 0.58599999999999997D * (double) l+ 0.113D * (double) j1);}}else{for(inti2 = 0; i2 < picsize; i2++)ai[i2] = ai[i2] & 0xff;}returnai;}publicvoidsetSourceImage(Image image){sourceImage = image;}publicImage getEdgeImage(){returnedgeImage;}publicvoidsetThreshold(inti){threshold = i;}publicvoidsetWidGaussianKernel(inti){widGaussianKernel = i;}finalfloatORIENT_SCALE = 40F;privateintheight;privateintwidth;privateintpicsize;privateintdata[];privateintderivative_mag[];privateintmagnitude[];privateintorientation[];privateImage sourceImage;privateImage edgeImage;privateintthreshold1;privateintthreshold2;privateintthreshold;privateintwidGaussianKernel;}//second filepackagetools;publicclassEdgeDetectorExceptionextendsException{publicEdgeDetectorException(){//do something?}publicEdgeDetectorException(String s){super(s);}}
//使用示例EdgeDetector edgeDetector=newEdgeDetector();edgeDetector.setSourceImage(sourceImage);edgeDetector.setThreshold(128);edgeDetector.setWidGaussianKernel(5);try{edgeDetector.process();}catch(EdgeDetectorException e){System.out.println(e.getMessage());}Image edgeImage=edgeDetector.getEdgeImage();yourPanel.show(edgeImage);