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();
}
}
}