图像边缘检测(Canny 算法)的Java实现

边缘检测算法的基本步骤 (1)滤波。边缘检测主要基于导数计算,但受噪声影响。但滤波器在降低噪声的同时也导致边缘强度的损失。 (2)增强。增强算法将邻域中灰度有显著变化的点突出显示。一般通过计算梯度幅值完成。 (3)检测。但在有些图象中梯度幅值较大的并不是边缘点。最简单的边缘检测是梯度幅值阈值判定。 (4)定位。精确确定边缘的位置。

Canny边缘检测算法 step1:用高斯滤波器平滑图象; step2:用一阶偏导的有限差分来计算梯度的幅值和方向; step3:对梯度幅值进行非极大值抑制; step4:用双阈值算法检测和连接边缘。

效果图如下:

代码如下:

package tools;

import java.awt.*;
import java.awt.image.*;

publicclass EdgeDetector extends Component {

 public EdgeDetector() {
 threshold1 = 50;
 threshold2 = 230;
 setThreshold(128);
 setWidGaussianKernel(15);
 }

 publicvoid process() throws EdgeDetectorException {
 if (threshold < 0 || threshold > 255)
 thrownew EdgeDetectorException("The value of the threshold is out of its valid range.");
 if (widGaussianKernel < 3 || widGaussianKernel > 40)
 thrownew EdgeDetectorException("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];
 float f = 1.0F;
 canny_core(f, widGaussianKernel);
 thresholding_tracker(threshold1, threshold2);
 for (int i = 0; i < picsize; i++)
 if (data[i] > threshold)
 data[i] = 0xff000000;
 else
 data[i] = -1;

 edgeImage = pixels2image(data);
 data = null;
 magnitude = null;
 orientation = null;
 }

 privatevoid canny_core(float f, int i) {
 boolean flag = false;
 boolean flag1 = false;
 derivative_mag = newint[picsize];
 float af4[] = newfloat[i];
 float af5[] = newfloat[i];
 float af6[] = newfloat[i];
 data = image2pixels(sourceImage);
 int k4 = 0;
 do{
 if (k4 >= i)
 break;
 float f1 = gaussian(k4, f);
 if (f1 <= 0.005F && k4 >= 2)
 break;
 float f2 = gaussian((float) k4 - 0.5F, f);
 float f3 = gaussian((float) k4 + 0.5F, f);
 float f4 = 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);
 int j = k4;
 float af[] = newfloat[picsize];
 float af1[] = newfloat[picsize];
 int j1 = width - (j - 1);
 int l = width * (j - 1);
 int i1 = width * (height - (j - 1));
 for (int l4 = j - 1; l4 < j1; l4++) {
 for (int l5 = l; l5 < i1; l5 += width) {
 int k1 = l4 + l5;
 float f8 = (float) data[k1] * af4[0];
 float f10 = f8;
 int l6 = 1;
 int k7 = k1 - width;
 for (int i8 = 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;
 }

 }

 float af2[] = newfloat[picsize];
 for (int i5 = j - 1; i5 < j1; i5++) {
 for (int i6 = l; i6 < i1; i6 += width) {
 float f9 = 0.0F;
 int l1 = i5 + i6;
 for (int i7 = 1; i7 < j; i7++)
 f9 += af5[i7] * (af[l1 - i7] - af[l1 + i7]);

 af2[l1] = f9;
 }

 }

 af = null;
 float af3[] = newfloat[picsize];
 for (int j5 = k4; j5 < width - k4; j5++) {
 for (int j6 = l; j6 < i1; j6 += width) {
 float f11 = 0.0F;
 int i2 = j5 + j6;
 int j7 = 1;
 for (int l7 = 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 (int k5 = j; k5 < j1; k5++) {
 for (int k6 = l; k6 < i1; k6 += width) {
 int j2 = k5 + k6;
 int k2 = j2 - width;
 int l2 = j2 + width;
  int i3 = j2 - 1;
 int j3 = j2 + 1;
 int k3 = k2 - 1;
 int l3 = k2 + 1;
 int i4 = l2 - 1;
 int j4 = l2 + 1;
 float f6 = af2[j2];
 float f7 = af3[j2];
 float f12 = hypotenuse(f6, f7);
 int k = (int) ((double) f12 * 20D);
 derivative_mag[j2] = k >= 256 ? 255 : k;
 float f13 = hypotenuse(af2[k2], af3[k2]);
 float f14 = hypotenuse(af2[l2], af3[l2]);
 float f15 = hypotenuse(af2[i3], af3[i3]);
 float f16 = hypotenuse(af2[j3], af3[j3]);
 float f18 = hypotenuse(af2[l3], af3[l3]);
 float f20 = hypotenuse(af2[j4], af3[j4]);
 float f19 = hypotenuse(af2[i4], af3[i4]);
 float f17 = hypotenuse(af2[k3], af3[k3]);
 float f5;
 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;
 }

 privatefloat hypotenuse(float f, float f1) {
 if (f == 0.0F && f1 == 0.0F)
 return 0.0F;
 else
 return (float) Math.sqrt(f * f + f1 * f1);
 }

 privatefloat gaussian(float f, float f1) {
 return (float) Math.exp((-f * f) / ((float) 2 * f1 * f1));
 }

 privatevoid thresholding_tracker(int i, int j) {
 for (int k = 0; k < picsize; k++)
 data[k] = 0;

 for (int l = 0; l < width; l++) {
 for (int i1 = 0; i1 < height; i1++)
 if (magnitude[l + width * i1] >= i)
 follow(l, i1, j);

 }

 }

 privateboolean follow(int i, int j, int k) {
 int j1 = i + 1;
 int k1 = i - 1;
 int l1 = j + 1;
 int i2 = j - 1;
 int j2 = 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];
 boolean flag = false;
 int l = k1;
 do{
 if (l > j1)
 break;
 int i1 = i2;
 do{
 if (i1 > l1)
 break;
 int k2 = 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;
 }
 }

 private Image pixels2image(int ai[]) {
 MemoryImageSource memoryimagesource =
 new MemoryImageSource(
 width,
 height,
 ColorModel.getRGBdefault(),
 ai,
 0,
 width);
 return Toolkit.getDefaultToolkit().createImage(memoryimagesource);
 }

 privateint[] image2pixels(Image image) {
 int ai[] = newint[picsize];
 PixelGrabber pixelgrabber =
 new PixelGrabber(image, 0, 0, width, height, ai, 0, width);
 try{
 pixelgrabber.grabPixels();
 }catch (InterruptedException interruptedexception) {
 interruptedexception.printStackTrace();
 }
 boolean flag = false;
 int k1 = 0;
 do{
 if (k1 >= 16)
 break;
 int i = (ai[k1] & 0xff0000) >> 16;
 int k = (ai[k1] & 0xff00) >> 8;
 int i1 = ai[k1] & 0xff;
 if (i != k || k != i1) {
 flag = true;
 break;
 }
 k1++;
 }while (true);
 if (flag) {
 for (int l1 = 0; l1 < picsize; l1++) {
 int j = (ai[l1] & 0xff0000) >> 16;
 int l = (ai[l1] & 0xff00) >> 8;
 int j1 = ai[l1] & 0xff;
 ai[l1] =
 (int) (0.29799999999999999D * (double) j
 + 0.58599999999999997D * (double) l
 + 0.113D * (double) j1);
 }

 }else{
 for (int i2 = 0; i2 < picsize; i2++)
 ai[i2] = ai[i2] & 0xff;

 }
 return ai;
 }

 publicvoid setSourceImage(Image image) {
 sourceImage = image;
 }

 public Image getEdgeImage() {
 return edgeImage;
 }

 publicvoid setThreshold(int i) {
 threshold = i;
 }

 publicvoid setWidGaussianKernel(int i) {
 widGaussianKernel = i;
 }

 finalfloat ORIENT_SCALE = 40F;
 privateint height;
 privateint width;
 privateint picsize;
 privateint data[];
 privateint derivative_mag[];
 privateint magnitude[];
 privateint orientation[];
 private Image sourceImage;
 private Image edgeImage;
 privateint threshold1;
 privateint threshold2;
 privateint threshold;
 privateint widGaussianKernel;
}

//second file

package tools;

publicclass EdgeDetectorException extends Exception
{
 public EdgeDetectorException()
 {
 //do something?
 }
 public EdgeDetectorException(String s)
 {
 super(s);
 }
}

//使用示例

EdgeDetector edgeDetector=new EdgeDetector();
 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);

没有口水与汗水,就没有成功的泪水。

图像边缘检测(Canny 算法)的Java实现

相关文章:

你感兴趣的文章:

标签云: