Java Canny边缘检测

import java.awt.image.BufferedImage;

public class CannyUtil {
	int Y;
	int X;
	int src[][];
	int dest[][];
	double tan[][];
	BufferedImage bufferedImage;
	BufferedImage bufferedImage_old;
	public CannyUtil(BufferedImage bi) {
		bufferedImage_old = bi;
		bufferedImage = bi;
		Y = bi.getWidth();
		X = bi.getHeight();
		src = new int[Y][X];
		dest = new int[Y][X];
		tan = new double[Y][X];
	}
	
	//灰度
	public BufferedImage Gray() {
		for(int y=0;y<Y;y++) {
			for(int x=0;x<X;x++) {
				int r=(bufferedImage.getRGB(y,x)>>16)&0x000000ff;
		    	int g=(bufferedImage.getRGB(y,x)>>8)&0x000000ff;
		    	int b=bufferedImage.getRGB(y,x)&0x000000ff;
		    	src[y][x]=(int)(0.2989*r+0.587*g+0.114*b);
				//bufferedImage.setRGB(y,x,0xff000000|src[y][x]|(src[y][x]<<8)|(src[y][x]<<16));
			}
		}
		return bufferedImage;
	}
	
	//高斯平滑
	public BufferedImage Gauss()
	{
		int M[][]={{1,2,1},{2,4,2},{1,2,1}};
    	bufferedImage=new BufferedImage(Y,X,BufferedImage.TYPE_INT_RGB);
		for(int y=1;y<Y-1;y++)
			for(int x=1;x<X-1;x++)
			{
				dest[y][x]= src[y-1][x-1]*M[0][0]+src[y][x-1]*M[1][0]+src[y+1][x-1]*M[2][0]
						+src[y-1][x]  *M[0][1]+src[y][x]  *M[1][1]+src[y+1][x]  *M[2][1]
						+src[y-1][x+1]*M[0][2]+src[y][x+1]*M[1][2]+src[y+1][x+1]*M[2][2];
				dest[y][x]/=16;
				bufferedImage.setRGB(y,x,0xff000000|dest[y][x]|(dest[y][x]<<8)|(dest[y][x]<<16));
			}
		for(int y=1;y<Y-1;y++)
			for(int x=1;x<X-1;x++)
				src[y][x]=dest[y][x];
		return bufferedImage;
	}
	//索贝尔边缘提取
	public BufferedImage Sobel()
    {
    	int Mx[][]={{-1,0,1},{-2,0,2},{-1,0,1}};
    	int My[][]={{-1,-2,-1},{0,0,0},{1,2,1}};
    	bufferedImage=new BufferedImage(Y,X,BufferedImage.TYPE_INT_RGB);
		for(int y=1;y<Y-1;y++)
			for(int x=1;x<X-1;x++)
			{
				int dx=	 src[y-1][x-1]*Mx[0][0]+src[y][x-1]*Mx[1][0]+src[y+1][x-1]*Mx[2][0]
						+src[y-1][x]  *Mx[0][1]+src[y][x]  *Mx[1][1]+src[y+1][x]  *Mx[2][1]
						+src[y-1][x+1]*Mx[0][2]+src[y][x+1]*Mx[1][2]+src[y+1][x+1]*Mx[2][2];
				int dy=	 src[y-1][x-1]*My[0][0]+src[y][x-1]*My[1][0]+src[y+1][x-1]*My[2][0]
						+src[y-1][x]  *My[0][1]+src[y][x]  *My[1][1]+src[y+1][x]  *My[2][1]
						+src[y-1][x+1]*My[0][2]+src[y][x+1]*My[1][2]+src[y+1][x+1]*My[2][2];
				dest[y][x]=(int)(Math.sqrt(dx*dx+dy*dy)+0.5);
				if(dest[y][x]>255) dest[y][x]=255;
				if(dest[y][x]<0) dest[y][x]=0;
				bufferedImage.setRGB(y,x,0xff000000|dest[y][x]|(dest[y][x]<<8)|(dest[y][x]<<16));
				tan[y][x]=1.0*dy/dx;
			}
		for(int y=1;y<Y-1;y++)
			for(int x=1;x<X-1;x++)
				src[y][x]=dest[y][x];
		return bufferedImage;
    }
    //非极大值抑制
	public BufferedImage NMS()
	{
		for(int y=1;y<Y-1;y++)
			for(int x=1;x<X-1;x++)
			{
				if(Math.abs(tan[y][x])<=0.5)
				{
					if(src[y][x]>=src[y][x-1]&&src[y][x]>=src[y][x+1])
						dest[y][x]=src[y][x];
					else
						dest[y][x]=0;
				}
				else if(-2<=tan[y][x]&&tan[y][x]<=-0.5)
				{
					if(src[y][x]>=src[y+1][x-1]&&src[y][x]>=src[y-1][x+1])
						dest[y][x]=src[y][x];
					else
						dest[y][x]=0;
				}
				else if(0.5<=tan[y][x]&&tan[y][x]<=2)
				{
					if(src[y][x]>=src[y-1][x-1]&&src[y][x]>=src[y+1][x+1])
						dest[y][x]=src[y][x];
					else
						dest[y][x]=0;
				}
				else if(2<=Math.abs(tan[y][x]))
				{
					if(src[y][x]>=src[y-1][x]&&src[y][x]>=src[y+1][x])
						dest[y][x]=src[y][x];
					else
						dest[y][x]=0;
				}
				bufferedImage.setRGB(y,x,0xff000000|dest[y][x]|(dest[y][x]<<8)|(dest[y][x]<<16));
			}
		for(int y=1;y<Y-1;y++)
			for(int x=1;x<X-1;x++)
				src[y][x]=dest[y][x];
		return bufferedImage;
	}
	//双阈值连接
	public BufferedImage DT()
	{
		int th1=127;
		int th2=63;
		for(int y=1;y<Y-1;y++)
			for(int x=1;x<X-1;x++)
			{
				if(src[y][x]>=th1)
					dest[y][x]=255;
				else if(src[y][x]<=th2)
					dest[y][x]=0;
				else
				{
					if(src[y-1][x-1]>=th1||src[y-1][x]>=th1||src[y-1][x+1]>=th1||src[y][x-1]>=th1||src[y][x+1]>=th1||src[y+1][x-1]>=th1||src[y+1][x]>=th1||src[y+1][x+1]>=th1)
						dest[y][x]=255;
					else
						dest[y][x]=0;
				}	
				bufferedImage.setRGB(y,x,0xff000000|dest[y][x]|(dest[y][x]<<8)|(dest[y][x]<<16));
			}
		for(int y=1;y<Y-1;y++)
			for(int x=1;x<X-1;x++)
				src[y][x]=dest[y][x];
		return bufferedImage;
	}
	
	//自动裁剪
	public BufferedImage autoClip(int GaussCount) {
		bufferedImage = Gray();
		for(int i=0;i<GaussCount;i++) {
			bufferedImage = Gauss();
		}
		bufferedImage = Sobel();		
		bufferedImage = NMS();
		bufferedImage = DT();
		
		boolean minXb = false, minYb = false;
	    int minX = 0, minY = 0, maxX = 0, maxY = 0;
	    
		for (int x = 0; x < bufferedImage.getWidth(); x++) {
	        for (int y = 0; y < bufferedImage.getHeight(); y++) {
	            // 如果是透明像素 跳过
	            if (bufferedImage.getRGB(x,y) == 0) continue;

	            // 获取该点像素,并以object类型表示
	            Object data = bufferedImage.getRaster().getDataElements(x, y, null);
	            int r = bufferedImage.getColorModel().getRed(data);
	            int g = bufferedImage.getColorModel().getGreen(data);
	            int b = bufferedImage.getColorModel().getBlue(data);
	            
	            if (r == 0 && g == 0 && b == 0) continue;

	            if (!minXb) {
	                minX = x;
	                minXb = true;
	            }

	            if (!minYb) {
	                minY = y;
	                minYb = true;
	            }

	            minX = Math.min(minX, x);
	            minY = Math.min(minY, y);

	            maxX = Math.max(maxX, x);
	            maxY = Math.max(maxY, y);
	        }
	    }
		System.out.printf("minX=%d,minY=%d,maxX=%d,maxY=%d\n", minX,minY,maxX,maxY);
		return bufferedImage_old.getSubimage(minX, minY, maxX - minX, maxY - minY);
	}
}

Java Canny边缘检测