基本思想:
利用x方向與y方向分别實作一階微分,求取振幅,實作圖像梯度效果。
使用的兩種微分算子分别為prewitt與sobel,其中soble在x, y兩個方向算子分别為:

prewitt在x, y方向上梯度算子分别為:
二:程式思路及實作
梯度濾鏡提供了兩個參數:
– 方向,用來要決定圖像完成x方向梯度計算, y方向梯度計算,或者是振幅計算
– 算子類型,用來決定是使用sobel算子或者是prewitt算子。
計算振幅的公式可以參見以前《圖像處理之一階微分應用》的文章
三:運作效果
原圖像如下:
基于prewitt與sobel算子的xy方向振幅效果如下:
該濾鏡的源代碼如下:
package com.process.blur.study;
import java.awt.image.bufferedimage;
/**
*
* @author gloomy-fish
* @date 2012-06-11
* prewitt operator
* x-direction
* -1, 0, 1
* y-direction
* -1, -1, -1
* 0, 0, 0
* 1, 1, 1
*
* sobel operator
* -2, 0, 2
* -1, -2, -1
* 1, 2, 1
*
*/
public class gradientfilter extends abstractbufferedimageop {
// prewitt operator
public final static int[][] prewitt_x = new int[][]{{-1, 0, 1}, {-1, 0, 1}, {-1, 0, 1}};
public final static int[][] prewitt_y = new int[][]{{-1, -1, -1}, {0, 0, 0}, {1, 1, 1}};
// sobel operator
public final static int[][] sobel_x = new int[][]{{-1, 0, 1}, {-2, 0, 2}, {-1, 0, 1}};
public final static int[][] sobel_y = new int[][]{{-1, -2, -1}, {0, 0, 0}, {1, 2, 1}};
// direction parameter
public final static int x_direction = 0;
public final static int y_direction = 2;
public final static int xy_direction = 4;
private int direction;
private boolean issobel;
public gradientfilter() {
direction = xy_direction;
issobel = true;
}
public void setsoble(boolean sobel) {
this.issobel = sobel;
public int getdirection() {
return direction;
public void setdirection(int direction) {
this.direction = direction;
@override
public bufferedimage filter(bufferedimage src, bufferedimage dest) {
int width = src.getwidth();
int height = src.getheight();
if (dest == null )
dest = createcompatibledestimage( src, null );
int[] inpixels = new int[width*height];
int[] outpixels = new int[width*height];
getrgb( src, 0, 0, width, height, inpixels );
int index = 0, index2 = 0;
double xred = 0, xgreen = 0, xblue = 0;
double yred = 0, ygreen = 0, yblue = 0;
int newrow, newcol;
for(int row=0; row<height; row++) {
int ta = 255, tr = 0, tg = 0, tb = 0;
for(int col=0; col<width; col++) {
index = row * width + col;
for(int subrow = -1; subrow <= 1; subrow++) {
for(int subcol = -1; subcol <= 1; subcol++) {
newrow = row + subrow;
newcol = col + subcol;
if(newrow < 0 || newrow >= height) {
newrow = row;
}
if(newcol < 0 || newcol >= width) {
newcol = col;
index2 = newrow * width + newcol;
tr = (inpixels[index2] >> 16) & 0xff;
tg = (inpixels[index2] >> 8) & 0xff;
tb = inpixels[index2] & 0xff;
if(issobel) {
xred += (sobel_x[subrow + 1][subcol + 1] * tr);
xgreen +=(sobel_x[subrow + 1][subcol + 1] * tg);
xblue +=(sobel_x[subrow + 1][subcol + 1] * tb);
yred += (sobel_y[subrow + 1][subcol + 1] * tr);
ygreen +=(sobel_y[subrow + 1][subcol + 1] * tg);
yblue +=(sobel_y[subrow + 1][subcol + 1] * tb);
} else {
xred += (prewitt_x[subrow + 1][subcol + 1] * tr);
xgreen +=(prewitt_x[subrow + 1][subcol + 1] * tg);
xblue +=(prewitt_x[subrow + 1][subcol + 1] * tb);
yred += (prewitt_y[subrow + 1][subcol + 1] * tr);
ygreen +=(prewitt_y[subrow + 1][subcol + 1] * tg);
yblue +=(prewitt_y[subrow + 1][subcol + 1] * tb);
}
}
double mred = math.sqrt(xred * xred + yred * yred);
double mgreen = math.sqrt(xgreen * xgreen + ygreen * ygreen);
double mblue = math.sqrt(xblue * xblue + yblue * yblue);
if(xy_direction == direction)
{
outpixels[index] = (ta << 24) | (clamp((int)mred) << 16) | (clamp((int)mgreen) << 8) | clamp((int)mblue);
}
else if(x_direction == direction)
outpixels[index] = (ta << 24) | (clamp((int)yred) << 16) | (clamp((int)ygreen) << 8) | clamp((int)yblue);
else if(y_direction == direction)
outpixels[index] = (ta << 24) | (clamp((int)xred) << 16) | (clamp((int)xgreen) << 8) | clamp((int)xblue);
else
// as default, always xy gradient
// cleanup for next loop
newrow = newcol = 0;
xred = xgreen = xblue = 0;
yred = ygreen = yblue = 0;
}
}
setrgb(dest, 0, 0, width, height, outpixels );
return dest;
public static int clamp(int value) {
return value < 0 ? 0 : (value > 255 ? 255 : value);
}