基本思想:
利用X方向與Y方向分別實現(xiàn)一階微分,求取振幅,實現(xiàn)圖像梯度效果。關(guān)于如何計算圖像
一階微分參見這里:http://blog.csdn.net/jia20003/article/details/7562092
使用的兩種微分算子分別為Prewitt與Sobel,其中Soble在X, Y兩個方向算子分別為:
Prewitt在X, Y方向上梯度算子分別為:
二:程序思路及實現(xiàn)
梯度濾鏡提供了兩個參數(shù):
– 方向,用來要決定圖像完成X方向梯度計算, Y方向梯度計算,或者是振幅計算
– 算子類型,用來決定是使用sobel算子或者是prewitt算子。
計算振幅的公式可以參見以前《圖像處理之一階微分應(yīng)用》的文章
三:運行效果
原圖像如下:
基于Prewitt與sobel算子的XY方向振幅效果如下:
該濾鏡的源代碼如下:
package com.process.blur.study;
import java.awt.image.BufferedImage;
public class GradientFilter extends AbstractBufferedImageOp {
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}};
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}};
public final static int X_DIRECTION = 0;
public final static int Y_DIRECTION = 2;
public final static int XY_DIRECTION = 4;
public GradientFilter() {
direction = XY_DIRECTION;
public void setSoble(boolean sobel) {
public int getDirection() {
public void setDirection(int direction) {
this.direction = direction;
public BufferedImage filter(BufferedImage src, BufferedImage dest) {
int width = src.getWidth();
int height = src.getHeight();
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;
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++) {
if(newRow < 0 || newRow >= height) {
if(newCol < 0 || newCol >= width) {
index2 = newRow * width + newCol;
tr = (inPixels[index2] >> 16) & 0xff;
tg = (inPixels[index2] >> 8) & 0xff;
tb = inPixels[index2] & 0xff;
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);
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);
// as default, always XY gradient
outPixels[index] = (ta << 24) | (clamp((int)mred) << 16) | (clamp((int)mgreen) << 8) | clamp((int)mblue);
xred = xgreen = xblue = 0;
yred = ygreen = yblue = 0;
setRGB(dest, 0, 0, width, height, outPixels );
public static int clamp(int value) {
return value < 0 ? 0 : (value > 255 ? 255 : value);