图像处理之高斯一阶及二阶导数计算

标签:
高斯导数图像高斯导数算子高斯求导 |
本质:图像×高斯函数的导数的mask(所谓算子)
以下为转载,看官有自己的看法和理解请留言。
图像处理之高斯一阶及二阶导数计算
图像的一阶与二阶导数计算在图像特征提取与边缘提取中十分重要。一阶与二阶导数的
作用,通常情况下:
一阶导数可以反应出图像灰度梯度的变化情况
二阶导数可以提取出图像的细节同时双响应图像梯度变化情况
常见的算子有Robot, Sobel算子,二阶常见多数为拉普拉斯算子,如图所示:
http://img.blog.csdn.net/20131117125855281
对于一个1D的有限集合数据f(x) = {1…N}, 假设dx的间隔为1则一阶导数计算公式如下:
Df(x) = f(x+1) – f(x-1) 二阶导数的计算公式为:df(x)= f(x+1) + f(x-1) – 2f(x);
稍微难一点的则是基于高斯的一阶导数与二阶导数求取,首先看一下高斯的1D与2D的
公式。一维高斯对应的X阶导数公式:
http://img.blog.csdn.net/20131117125946187
二维高斯对应的导数公式:
http://img.blog.csdn.net/20131117130148000
二:算法实现
1.
2.
3.
4.
注意点:计算高斯函数一定要以零为中心点, 如果窗口函数大小为3,则表达为-1, 0, 1
三:程序实现关键点
1.
2.
3.
四:运行效果:
高斯一阶导数X方向效果
http://img.blog.csdn.net/20131117130521750
高斯一阶导数Y方向效果
http://img.blog.csdn.net/20131117130608515
五:算法全部源代码:
-
-
package
com.gloomyfish.image.harris.corner; -
import
java.awt.image.BufferedImage; -
-
import
com.gloomyfish.filter.study.AbstractBufferedImageOp; -
-
public
class GaussianDerivativeFilter extendsAbstractBufferedImageOp { -
-
public final static int X_DIRECTION 0;= -
public final static int Y_DIRECTION 16;= -
public final static int XY_DIRECTION 2;= -
public final static int XX_DIRECTION 4;= -
public final static int YY_DIRECTION 8;= -
-
// private attribute and settings -
private int DIRECTION_TYPE 0;= -
private int GAUSSIAN_WIN_SIZE 1;= // N*2 + 1 -
private double sigma 10;= // default -
-
public GaussianDerivativeFilter () -
{ -
System.out.println("高斯一阶及多阶导数滤镜"); -
} -
-
public int getGaussianWinSize() { -
return GAUSSIAN_WIN_SIZE; -
} -
-
public void setGaussianWinSize( intgAUSSIAN_WIN_SIZE) { -
GAUSSIAN_WIN_SIZE = gAUSSIAN_WIN_SIZE; -
} -
public int getDirectionType() { -
return DIRECTION_TYPE; -
} -
-
public void setDirectionType( intdIRECTION_TYPE) { -
DIRECTION_TYPE = dIRECTION_TYPE; -
} -
-
@Override -
public BufferedImage filter(BufferedImage src, BufferedImage dest) { -
int width = src.getWidth(); -
int height = src.getHeight(); -
-
if ( nulldest == ) -
dest = createCompatibleDestImag e( 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; -
double[][] winDeviationData = getDirectionData(); -
-
for(int row= 0;row -
int ta 255,= tr 0,= tg 0,= tb 0;= -
for(int col= 0;col -
index = row * width + col; -
for(int subrow = -GAUSSIAN_WIN_SIZE; subrow <= GAUSSIAN_WIN_SIZE; subrow++) { -
for(int subcol = -GAUSSIAN_WIN_SIZE; subcol <= GAUSSIAN_WIN_SIZE; 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; -
xred += (winDeviationData[subrow + GAUSSIAN_WIN_SIZE][subcol + GAUSSIAN_WIN_SIZE] * tr); -
xgreen +=(winDeviationData[subrow + GAUSSIAN_WIN_SIZE][subcol + GAUSSIAN_WIN_SIZE] * tg); -
xblue +=(winDeviationData[subrow + GAUSSIAN_WIN_SIZE][subcol + GAUSSIAN_WIN_SIZE] * tb); -
} -
} -
-
outPixels[index] = (ta << 24) | int)xred)(clamp(( << 16)| int)xgreen)(clamp(( << 8)| int)xblue);clamp(( -
-
// clean up values for next pixel -
newRow = newCol = 0; -
xred = xgreen = xblue = 0; -
// yred = ygreen = yblue = 0; -
} -
} -
-
setRGB( dest, 0, 0, width, height, outPixels ); -
return dest; -
} -
-
private double[][] getDirectionData() -
{ -
double[][] winDeviationData null;= -
if(DIRECTION_TYPE == X_DIRECTION) -
{ -
winDeviationData = this.getXDirectionDeviation(); -
} -
else if(DIRECTION_TYPE == Y_DIRECTION) -
{ -
winDeviationData = this.getYDirectionDeviation(); -
} -
else if(DIRECTION_TYPE == XY_DIRECTION) -
{ -
winDeviationData = this.getXYDirectionDeviation(); -
} -
else if(DIRECTION_TYPE == XX_DIRECTION) -
{ -
winDeviationData = this.getXXDirectionDeviation(); -
} -
else if(DIRECTION_TYPE == YY_DIRECTION) -
{ -
winDeviationData = this.getYYDirectionDeviation(); -
} -
return winDeviationData; -
} -
-
public int clamp( intvalue) { -
// trick, just improve the lightness otherwise image is too darker... -
if(DIRECTION_TYPE == X_DIRECTION || DIRECTION_TYPE == Y_DIRECTION) -
{ -
value = value * 10 + 50; -
} -
return value 0< ? 0: 255(value > ? 255: value); -
} -
-
// centered on zero and with Gaussian standard deviation -
// parameter : sigma -
public double[][] get2DGaussianData() -
{ -
int size 2= GAUSSIAN_WIN_SIZE * + 1; -
double[][] winData new= double[size][size]; -
double sigma2 this.sigma= * sigma; -
for(int i=-GAUSSIAN_WIN_SIZE; i<=GAUSSIAN_WIN_SIZE; i++) -
{ -
for(int j=-GAUSSIAN_WIN_SIZE; j<=GAUSSIAN_WIN_SIZE; j++) -
{ -
double r 1= i* + j*j; -
double sum 2*sigma2));= -(r/( -
winData[i + GAUSSIAN_WIN_SIZE][j + GAUSSIAN_WIN_SIZE] = Math.exp(sum); -
} -
} -
return winData; -
} -
-
public double[][] getXDirectionDeviation() -
{ -
int size 2= GAUSSIAN_WIN_SIZE * + 1; -
double[][] data = get2DGaussianData(); -
double[][] xDeviation new= double[size][size]; -
double sigma2 this.sigma= * sigma; -
for(int x=-GAUSSIAN_WIN_SIZE; x<=GAUSSIAN_WIN_SIZE; x++) -
{ -
double c = -(x/sigma2); -
for(int i= 0;i -
{ -
xDeviation[i][x + GAUSSIAN_WIN_SIZE] = c * data[i][x + GAUSSIAN_WIN_SIZE]; -
} -
} -
return xDeviation; -
} -
-
public double[][] getYDirectionDeviation() -
{ -
int size 2= GAUSSIAN_WIN_SIZE * + 1; -
double[][] data = get2DGaussianData(); -
double[][] yDeviation new= double[size][size]; -
double sigma2 this.sigma= * sigma; -
for(int y=-GAUSSIAN_WIN_SIZE; y<=GAUSSIAN_WIN_SIZE; y++) -
{ -
double c = -(y/sigma2); -
for(int i= 0;i -
{ -
yDeviation[y + GAUSSIAN_WIN_SIZE][i] = c * data[y + GAUSSIAN_WIN_SIZE][i]; -
} -
} -
return yDeviation; -
} -
-
-
public double[][] getXYDirectionDeviation() -
{ -
int size 2= GAUSSIAN_WIN_SIZE * + 1; -
double[][] data = get2DGaussianData(); -
double[][] xyDeviation new= double[size][size]; -
double sigma2 = sigma * sigma; -
double sigma4 = sigma2 * sigma2; -
// TODO:zhigang -
for(int x=-GAUSSIAN_WIN_SIZE; x<=GAUSSIAN_WIN_SIZE; x++) -
{ -
for(int y=-GAUSSIAN_WIN_SIZE; y<=GAUSSIAN_WIN_SIZE; y++) -
{ -
double c = -((x*y)/sigma4); -
xyDeviation[x + GAUSSIAN_WIN_SIZE][y + GAUSSIAN_WIN_SIZE] = c * data[x + GAUSSIAN_WIN_SIZE][y + GAUSSIAN_WIN_SIZE]; -
} -
} -
return normalizeData(xyDeviation); -
} -
-
private double[][] normalizeData( double[][]data) -
{ -
// normalization the data -
double min 0][0];= data[ -
for(int x=-GAUSSIAN_WIN_SIZE; x<=GAUSSIAN_WIN_SIZE; x++) -
{ -
for(int y=-GAUSSIAN_WIN_SIZE; y<=GAUSSIAN_WIN_SIZE; y++) -
{ -
if(min > data[x + GAUSSIAN_WIN_SIZE][y + GAUSSIAN_WIN_SIZE]) -
{ -
min = data[x + GAUSSIAN_WIN_SIZE][y + GAUSSIAN_WIN_SIZE]; -
} -
} -
} -
-
for(int x=-GAUSSIAN_WIN_SIZE; x<=GAUSSIAN_WIN_SIZE; x++) -
{ -
for(int y=-GAUSSIAN_WIN_SIZE; y<=GAUSSIAN_WIN_SIZE; y++) -
{ -
data[x + GAUSSIAN_WIN_SIZE][y + GAUSSIAN_WIN_SIZE] = data[x + GAUSSIAN_WIN_SIZE][y + GAUSSIAN_WIN_SIZE] /min; -
} -
} -
-
return data; -
} -
-
public double[][] getXXDirectionDeviation() -
{ -
int size 2= GAUSSIAN_WIN_SIZE * + 1; -
double[][] data = get2DGaussianData(); -
double[][] xxDeviation new= double[size][size]; -
double sigma2 this.sigma= * sigma; -
double sigma4 = sigma2 * sigma2; -
for(int x=-GAUSSIAN_WIN_SIZE; x<=GAUSSIAN_WIN_SIZE; x++) -
{ -
double c = -((x - sigma2)/sigma4); -
for(int i= 0;i -
{ -
xxDeviation[i][x + GAUSSIAN_WIN_SIZE] = c * data[i][x + GAUSSIAN_WIN_SIZE]; -
} -
} -
return xxDeviation; -
} -
-
public double[][] getYYDirectionDeviation() -
{ -
int size 2= GAUSSIAN_WIN_SIZE * + 1; -
double[][] data = get2DGaussianData(); -
double[][] yyDeviation new= double[size][size]; -
double sigma2 this.sigma= * sigma; -
double sigma4 = sigma2 * sigma2; -
for(int y=-GAUSSIAN_WIN_SIZE; y<=GAUSSIAN_WIN_SIZE; y++) -
{ -
double c = -((y - sigma2)/sigma4); -
for(int i= 0;i -
{ -
yyDeviation[y + GAUSSIAN_WIN_SIZE][i] = c * data[y + GAUSSIAN_WIN_SIZE][i]; -
} -
} -
return yyDeviation; -
} -
-
}
部分转自:http://blog.csdn.net/jia20003/article/details/16369143