图像边缘检测算子

package com.chipmunk.util;

import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;

import javax.imageio.ImageIO;

/**
 * 算子
 * 
 * sobel,prewitt,roberts,laplace,canny
 * 均有卷积因子,小矩阵
 * 
 * @author Administrator
 *
 */
public class OperatorUtil {

	/**
	 * 索贝尔算子(Sobel operator)
	 * 
	 * 横向矩阵 卷积因子
	 * Gx=  -1  0 +1
	 * 		-2  0 +2    *   A  
	 * 		-1  0 +1
	 * 
	 * 纵向矩阵 卷积因子
	 * Gy=  +1 +2 +1
	 * 		 0  0  0    *   A
	 * 		-1 -2 -1
	 * 		
	 * A= a  b  c
	 *    d  e  f
	 *    g  h  i
	 * 
	 * 		
	 * G=Math.hypot(Gx,Gy);
	 * 为了简便,用|G|=|Gx|+|Gy|
	 * 
	 * @param data
	 * @param w
	 * @param h
	 * @return
	 */
	public static int[] sobel(int[]data,int w,int h){
		
		int[] d= new int[w*h];  
		for(int j=1;j<h-1;j++){  
			for(int i=1;i<w-1;i++){  
				int s1 = data[i-1+(j+1)*w]+2*data[i+(j+1)*w]+data[i+1+(j+1)*w]-data[i-1+(j-1)*w]-2*data[i+(j-1)*w]-data[i+1+(j-1)*w];  
				int s2 = data[i+1+(j-1)*w]+2*data[i+1+(j)*w]+data[i+1+(j+1)*w]-data[i-1+(j-1)*w]-2*data[i-1+(j)*w]-data[i-1+(j+1)*w];  
				int s  = Math.abs(s1)+Math.abs(s2);  
				if(s < 0)  
					s =0;  
				if(s > 255)  
					s = 255;  
				d[i + j * w] = s;  
			}      
		}  
		return d;
	}  
	/**
	 * 普利维特算子(Prewitt operate)
	 * 
	 * 横向矩阵 卷积因子
	 * Gx=  -1  0 +1
	 * 		-1  0 +1    *   A  
	 * 		-1  0 +1
	 * 
	 * 纵向矩阵 卷积因子
	 * Gy=  +1 +1 +1
	 * 		 0  0  0    *   A
	 * 		-1 -1 -1
	 * 	
	 * @param data
	 * @param w
	 * @param h
	 * @return
	 */
	public static int[] prewitt(int[]data,int w,int h){
		
        int[] d= new int[w*h];  
        for(int j=1;j<h-1;j++){  
            for(int i=1;i<w-1;i++){  
                int s1 = data[i-1+(j+1)*w]+data[i+(j+1)*w]+data[i+1+(j+1)*w]-data[i-1+(j-1)*w]-data[i+(j-1)*w]-data[i+1+(j-1)*w];  
                int s2 = data[i+1+(j-1)*w]+data[i+1+(j)*w]+data[i+1+(j+1)*w]-data[i-1+(j-1)*w]-data[i-1+(j)*w]-data[i-1+(j+1)*w];  
                int s  = Math.abs(s1)+Math.abs(s2);  
                if(s < 0)  
                    s =0;  
                if(s > 255)  
                    s = 255;  
                d[i + j * w] = s;   
            }      
        }  
        return d;
    } 
	/**
	 * 罗伯茨交叉边缘检测(Roberts Cross operator)
	 *
	 * 横向矩阵 卷积因子
	 * Gx=  +1  0 	 *   A 
	 * 		 0 -1     
	 * 		
	 * 
	 * 纵向矩阵 卷积因子
	 * Gy=  0  +1 
	 * 		-1  0    *   A
	 * 	
	 * A = x,y     x+1,y     =      a   b
	 *     x,y+1   x+1,y+1          c   d
	 *     
	 * Gx=  a+b-c-d
	 * Gy= -a-b+c+d    	
	 * 
	 * @param data
	 * @param w
	 * @param h
	 * @return
	 */
	public static int[] roberts(int[]data,int w,int h){
		
		int[] d= new int[w*h];  
		for(int j=0;j<h-1;j++){  
			for(int i=0;i<w-1;i++){  
				int s1 = data[i+j*w]+data[i+1+j*w]-data[i+(j+1)*w]-data[i+1+(j+1)*w];  
				int s2 = data[i+(j+1)*w]+data[i+1+(j+1)*w]-data[i+j*w]-data[i+1+j*w];  
				int s  = Math.abs(s1)+Math.abs(s2);  
				if(s < 0)  
					s =0;  
				if(s > 255)  
					s = 255;  
				d[i + j * w] = s;  
			}      
		}  
		return d;
	}  
	/**
	 * 拉普拉斯算子laplace
	 * 
	 * 离散拉普拉斯算子的模板:
	 * 0   1   0
	 * 1   4   1
	 * 0   1   0
	 * 
	 * 其扩展模板: 
	 * 1   1   1
	 * 1   8   1
	 * 1   1   1
	 * @param data
	 * @param w
	 * @param h
	 * @return
	 */
	//TODO 未完待续
	public static int[] laplace(int[]data,int w,int h){
		
		int[] d= new int[w*h];  
	    for(int j=1;j<h-1;j++){  
            for(int i=1;i<w-1;i++){  
            	// 1	1	1
            	// 6	6	6
            	// 1	1	1
            	int s1 = data[i-1+(j-1)*w]
            	         +data[i+(j-1)*w]
            	         +data[i+1+(j-1)*w]
    	                 +6*data[i-1+j*w]
		            	 +6*data[i+j*w]
		            	 +6*data[i+1+j*w]
		            	 +data[i-1+(j+1)*w]
		            	 +data[i+(j+1)*w]
		            	 +data[i+1+(j+1)*w];
				int s  = Math.abs(s1);  
				if(s < 0)  
					s =0;  
				if(s > 255)  
					s = 255;  
				d[i + j * w] = s;   
            }      
        }
		return d;
	}  
	/**
	 * 各种边界算子
	 * @param src
	 * @param dest
	 * @param type:1-sobel,2-prewitt,3-roberts,4-laplace
	 */
	public static void suanzis(File src,File dest,int type){
		try {
			BufferedImage bi = ImageIO.read(src);
			int w = bi.getWidth();
			int h = bi.getHeight();
			int[]data = ImageUtil.getImageBW(src);
			int[]d = null;
			if (type==1) {
				d = sobel(data, w, h);
			}else if (type==2) {
				d = prewitt(data, w, h);
			}else if (type==3) {
				d = roberts(data, w, h);
			}else if (type==4) {
				d = laplace(data, w, h);
			}
			ImageUtil.writeImageRGB(d, dest, w, h);
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}

猜你喜欢

转载自itace.iteye.com/blog/2352482