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

简介: <p style="color: rgb(51, 51, 51); font-family: Arial; font-size: 14px; line-height: 26px;"><span style="font-size: 18px;">图像的一阶与二阶导数计算在图像特征提取与边缘提取中十分重要。一阶与二阶导数的</span></p><p style="color: rgb(51, 5

图像的一阶与二阶导数计算在图像特征提取与边缘提取中十分重要。一阶与二阶导数的

作用,通常情况下:

一阶导数可以反应出图像灰度梯度的变化情况

二阶导数可以提取出图像的细节同时双响应图像梯度变化情况

常见的算子有Robot, Sobel算子,二阶常见多数为拉普拉斯算子,如图所示:


对于一个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阶导数公式:


二维高斯对应的导数公式:


二:算法实现

1.      高斯采样,基于间隔1计算,计算mask窗口计算,这样就跟普通的卷积计算差不多

2.      设置sigma的值,本例默认为10,首先计算高斯窗口函数,默认为3 * 3

3.      根据2的结果,计算高斯导数窗口值

4.      卷积计算像素中心点值。

注意点计算高斯函数一定要以零为中心点, 如果窗口函数大小为3,则表达为-1, 0, 1

三:程序实现关键点

1.      归一化处理,由于高斯计算出来的窗口值非常的小,必须实现归一化处理。

2.      亮度提升,对X,Y的梯度计算结果进行了亮度提升,目的是让大家看得更清楚。

3.      支持一阶与二阶单一方向X,Y偏导数计算

四:运行效果:

高斯一阶导数X方向效果


高斯一阶导数Y方向效果


五:算法全部源代码:

[java]  view plain copy
  1. /* 
  2.  * @author: gloomyfish 
  3.  * @date: 2013-11-17 
  4.  *  
  5.  * Title - Gaussian fist order derivative and second derivative filter 
  6.  */  
  7. package com.gloomyfish.image.harris.corner;  
  8. import java.awt.image.BufferedImage;  
  9.   
  10. import com.gloomyfish.filter.study.AbstractBufferedImageOp;  
  11.   
  12. public class GaussianDerivativeFilter extends AbstractBufferedImageOp {  
  13.   
  14.     public final static int X_DIRECTION = 0;  
  15.     public final static int Y_DIRECTION = 16;  
  16.     public final static int XY_DIRECTION = 2;  
  17.     public final static int XX_DIRECTION = 4;  
  18.     public final static int YY_DIRECTION = 8;  
  19.       
  20.     // private attribute and settings  
  21.     private int DIRECTION_TYPE = 0;  
  22.     private int GAUSSIAN_WIN_SIZE = 1// N*2 + 1  
  23.     private double sigma = 10// default  
  24.   
  25.     public GaussianDerivativeFilter()  
  26.     {  
  27.         System.out.println("高斯一阶及多阶导数滤镜");  
  28.     }     
  29.       
  30.     public int getGaussianWinSize() {  
  31.         return GAUSSIAN_WIN_SIZE;  
  32.     }  
  33.   
  34.     public void setGaussianWinSize(int gAUSSIAN_WIN_SIZE) {  
  35.         GAUSSIAN_WIN_SIZE = gAUSSIAN_WIN_SIZE;  
  36.     }  
  37.     public int getDirectionType() {  
  38.         return DIRECTION_TYPE;  
  39.     }  
  40.   
  41.     public void setDirectionType(int dIRECTION_TYPE) {  
  42.         DIRECTION_TYPE = dIRECTION_TYPE;  
  43.     }  
  44.   
  45.     @Override  
  46.     public BufferedImage filter(BufferedImage src, BufferedImage dest) {  
  47.         int width = src.getWidth();  
  48.         int height = src.getHeight();  
  49.   
  50.         if ( dest == null )  
  51.             dest = createCompatibleDestImage( src, null );  
  52.   
  53.         int[] inPixels = new int[width*height];  
  54.         int[] outPixels = new int[width*height];  
  55.         getRGB( src, 00, width, height, inPixels );  
  56.         int index = 0, index2 = 0;  
  57.         double xred = 0, xgreen = 0, xblue = 0;  
  58.         // double yred = 0, ygreen = 0, yblue = 0;  
  59.         int newRow, newCol;  
  60.         double[][] winDeviationData = getDirectionData();  
  61.   
  62.         for(int row=0; row<height; row++) {  
  63.             int ta = 255, tr = 0, tg = 0, tb = 0;  
  64.             for(int col=0; col<width; col++) {  
  65.                 index = row * width + col;  
  66.                 for(int subrow = -GAUSSIAN_WIN_SIZE; subrow <= GAUSSIAN_WIN_SIZE; subrow++) {  
  67.                     for(int subcol = -GAUSSIAN_WIN_SIZE; subcol <= GAUSSIAN_WIN_SIZE; subcol++) {  
  68.                         newRow = row + subrow;  
  69.                         newCol = col + subcol;  
  70.                         if(newRow < 0 || newRow >= height) {  
  71.                             newRow = row;  
  72.                         }  
  73.                         if(newCol < 0 || newCol >= width) {  
  74.                             newCol = col;  
  75.                         }  
  76.                         index2 = newRow * width + newCol;  
  77.                         tr = (inPixels[index2] >> 16) & 0xff;  
  78.                         tg = (inPixels[index2] >> 8) & 0xff;  
  79.                         tb = inPixels[index2] & 0xff;  
  80.                         xred += (winDeviationData[subrow + GAUSSIAN_WIN_SIZE][subcol + GAUSSIAN_WIN_SIZE] * tr);  
  81.                         xgreen +=(winDeviationData[subrow + GAUSSIAN_WIN_SIZE][subcol + GAUSSIAN_WIN_SIZE] * tg);  
  82.                         xblue +=(winDeviationData[subrow + GAUSSIAN_WIN_SIZE][subcol + GAUSSIAN_WIN_SIZE] * tb);  
  83.                     }  
  84.                 }  
  85.                   
  86.                 outPixels[index] = (ta << 24) | (clamp((int)xred) << 16) | (clamp((int)xgreen) << 8) | clamp((int)xblue);  
  87.                   
  88.                 // clean up values for next pixel  
  89.                 newRow = newCol = 0;  
  90.                 xred = xgreen = xblue = 0;  
  91.                 // yred = ygreen = yblue = 0;  
  92.             }  
  93.         }  
  94.   
  95.         setRGB( dest, 00, width, height, outPixels );  
  96.         return dest;  
  97.     }  
  98.       
  99.     private double[][] getDirectionData()  
  100.     {  
  101.         double[][] winDeviationData = null;  
  102.         if(DIRECTION_TYPE == X_DIRECTION)  
  103.         {  
  104.             winDeviationData = this.getXDirectionDeviation();  
  105.         }  
  106.         else if(DIRECTION_TYPE == Y_DIRECTION)  
  107.         {  
  108.             winDeviationData = this.getYDirectionDeviation();  
  109.         }  
  110.         else if(DIRECTION_TYPE == XY_DIRECTION)  
  111.         {  
  112.             winDeviationData = this.getXYDirectionDeviation();  
  113.         }  
  114.         else if(DIRECTION_TYPE == XX_DIRECTION)  
  115.         {  
  116.             winDeviationData = this.getXXDirectionDeviation();  
  117.         }  
  118.         else if(DIRECTION_TYPE == YY_DIRECTION)  
  119.         {  
  120.             winDeviationData = this.getYYDirectionDeviation();  
  121.         }  
  122.         return winDeviationData;  
  123.     }  
  124.       
  125.     public int clamp(int value) {  
  126.         // trick, just improve the lightness otherwise image is too darker...  
  127.         if(DIRECTION_TYPE == X_DIRECTION || DIRECTION_TYPE == Y_DIRECTION)  
  128.         {  
  129.             value = value * 10 + 50;  
  130.         }  
  131.         return value < 0 ? 0 : (value > 255 ? 255 : value);  
  132.     }  
  133.       
  134.     // centered on zero and with Gaussian standard deviation  
  135.     // parameter : sigma  
  136.     public double[][] get2DGaussianData()  
  137.     {  
  138.         int size = GAUSSIAN_WIN_SIZE * 2 + 1;  
  139.         double[][] winData = new double[size][size];  
  140.         double sigma2 = this.sigma * sigma;  
  141.         for(int i=-GAUSSIAN_WIN_SIZE; i<=GAUSSIAN_WIN_SIZE; i++)  
  142.         {  
  143.             for(int j=-GAUSSIAN_WIN_SIZE; j<=GAUSSIAN_WIN_SIZE; j++)  
  144.             {  
  145.                 double r = i*1 + j*j;  
  146.                 double sum = -(r/(2*sigma2));  
  147.                 winData[i + GAUSSIAN_WIN_SIZE][j + GAUSSIAN_WIN_SIZE] = Math.exp(sum);  
  148.             }  
  149.         }  
  150.         return winData;  
  151.     }  
  152.       
  153.     public double[][] getXDirectionDeviation()  
  154.     {  
  155.         int size = GAUSSIAN_WIN_SIZE * 2 + 1;  
  156.         double[][] data = get2DGaussianData();  
  157.         double[][] xDeviation = new double[size][size];  
  158.         double sigma2 = this.sigma * sigma;  
  159.         for(int x=-GAUSSIAN_WIN_SIZE; x<=GAUSSIAN_WIN_SIZE; x++)  
  160.         {  
  161.             double c = -(x/sigma2);  
  162.             for(int i=0; i<size; i++)  
  163.             {  
  164.                 xDeviation[i][x + GAUSSIAN_WIN_SIZE] = c * data[i][x + GAUSSIAN_WIN_SIZE];                
  165.             }  
  166.         }  
  167.         return xDeviation;  
  168.     }  
  169.       
  170.     public double[][] getYDirectionDeviation()  
  171.     {  
  172.         int size = GAUSSIAN_WIN_SIZE * 2 + 1;  
  173.         double[][] data = get2DGaussianData();  
  174.         double[][] yDeviation = new double[size][size];  
  175.         double sigma2 = this.sigma * sigma;  
  176.         for(int y=-GAUSSIAN_WIN_SIZE; y<=GAUSSIAN_WIN_SIZE; y++)  
  177.         {  
  178.             double c = -(y/sigma2);  
  179.             for(int i=0; i<size; i++)  
  180.             {  
  181.                 yDeviation[y + GAUSSIAN_WIN_SIZE][i] = c * data[y + GAUSSIAN_WIN_SIZE][i];                
  182.             }  
  183.         }  
  184.         return yDeviation;  
  185.     }  
  186.       
  187.     /*** 
  188.      *  
  189.      * @return 
  190.      */  
  191.     public double[][] getXYDirectionDeviation()  
  192.     {  
  193.         int size = GAUSSIAN_WIN_SIZE * 2 + 1;  
  194.         double[][] data = get2DGaussianData();  
  195.         double[][] xyDeviation = new double[size][size];  
  196.         double sigma2 = sigma * sigma;  
  197.         double sigma4 = sigma2 * sigma2;  
  198.         // TODO:zhigang  
  199.         for(int x=-GAUSSIAN_WIN_SIZE; x<=GAUSSIAN_WIN_SIZE; x++)  
  200.         {  
  201.             for(int y=-GAUSSIAN_WIN_SIZE; y<=GAUSSIAN_WIN_SIZE; y++)  
  202.             {  
  203.                 double c = -((x*y)/sigma4);  
  204.                 xyDeviation[x + GAUSSIAN_WIN_SIZE][y + GAUSSIAN_WIN_SIZE] = c * data[x + GAUSSIAN_WIN_SIZE][y + GAUSSIAN_WIN_SIZE];  
  205.             }  
  206.         }  
  207.         return normalizeData(xyDeviation);  
  208.     }  
  209.       
  210.     private double[][] normalizeData(double[][] data)  
  211.     {  
  212.         // normalization the data  
  213.         double min = data[0][0];  
  214.         for(int x=-GAUSSIAN_WIN_SIZE; x<=GAUSSIAN_WIN_SIZE; x++)  
  215.         {  
  216.             for(int y=-GAUSSIAN_WIN_SIZE; y<=GAUSSIAN_WIN_SIZE; y++)  
  217.             {  
  218.                 if(min > data[x + GAUSSIAN_WIN_SIZE][y + GAUSSIAN_WIN_SIZE])  
  219.                 {  
  220.                     min = data[x + GAUSSIAN_WIN_SIZE][y + GAUSSIAN_WIN_SIZE];  
  221.                 }  
  222.             }  
  223.         }  
  224.           
  225.         for(int x=-GAUSSIAN_WIN_SIZE; x<=GAUSSIAN_WIN_SIZE; x++)  
  226.         {  
  227.             for(int y=-GAUSSIAN_WIN_SIZE; y<=GAUSSIAN_WIN_SIZE; y++)  
  228.             {  
  229.                 data[x + GAUSSIAN_WIN_SIZE][y + GAUSSIAN_WIN_SIZE] = data[x + GAUSSIAN_WIN_SIZE][y + GAUSSIAN_WIN_SIZE] /min;  
  230.             }  
  231.         }  
  232.           
  233.         return data;  
  234.     }  
  235.       
  236.     public double[][] getXXDirectionDeviation()  
  237.     {  
  238.         int size = GAUSSIAN_WIN_SIZE * 2 + 1;  
  239.         double[][] data = get2DGaussianData();  
  240.         double[][] xxDeviation = new double[size][size];  
  241.         double sigma2 = this.sigma * sigma;  
  242.         double sigma4 = sigma2 * sigma2;  
  243.         for(int x=-GAUSSIAN_WIN_SIZE; x<=GAUSSIAN_WIN_SIZE; x++)  
  244.         {  
  245.             double c = -((x - sigma2)/sigma4);  
  246.             for(int i=0; i<size; i++)  
  247.             {  
  248.                 xxDeviation[i][x + GAUSSIAN_WIN_SIZE] = c * data[i][x + GAUSSIAN_WIN_SIZE];               
  249.             }  
  250.         }  
  251.         return xxDeviation;  
  252.     }  
  253.       
  254.     public double[][] getYYDirectionDeviation()  
  255.     {  
  256.         int size = GAUSSIAN_WIN_SIZE * 2 + 1;  
  257.         double[][] data = get2DGaussianData();  
  258.         double[][] yyDeviation = new double[size][size];  
  259.         double sigma2 = this.sigma * sigma;  
  260.         double sigma4 = sigma2 * sigma2;  
  261.         for(int y=-GAUSSIAN_WIN_SIZE; y<=GAUSSIAN_WIN_SIZE; y++)  
  262.         {  
  263.             double c = -((y - sigma2)/sigma4);  
  264.             for(int i=0; i<size; i++)  
  265.             {  
  266.                 yyDeviation[y + GAUSSIAN_WIN_SIZE][i] = c * data[y + GAUSSIAN_WIN_SIZE][i];               
  267.             }  
  268.         }  
  269.         return yyDeviation;  
  270.     }  
  271.   
  272. }  
相关文章
|
移动开发 算法
科学计算与仿真-高斯牛顿法的非线性最小二乘问题简单介绍与应用
科学计算与仿真-高斯牛顿法的非线性最小二乘问题简单介绍与应用
674 0
科学计算与仿真-高斯牛顿法的非线性最小二乘问题简单介绍与应用
|
5月前
|
资源调度 算法 机器人
图像处理之高斯一阶及二阶导数计算
图像处理之高斯一阶及二阶导数计算
72 6
|
5月前
|
Java API 计算机视觉
图像处理之添加高斯与泊松噪声
图像处理之添加高斯与泊松噪声
62 1
|
5月前
|
计算机视觉
图像处理之一阶微分应用
图像处理之一阶微分应用
39 0
|
5月前
|
Java API 计算机视觉
图像处理之形态学梯度计算
图像处理之形态学梯度计算
50 0
|
5月前
高等数学II-知识点(3)——广义积分、定积分几何应用、定积分求曲线弧长、常微分方程、可分离变量的微分方程、一阶微分方程-齐次方程、一阶线性微分方程
高等数学II-知识点(3)——广义积分、定积分几何应用、定积分求曲线弧长、常微分方程、可分离变量的微分方程、一阶微分方程-齐次方程、一阶线性微分方程
43 0
|
算法 图形学
计算机图形学 之 DDA直线算法(数值微分法)
计算机图形学 之 DDA直线算法(数值微分法)
397 0
|
机器学习/深度学习 传感器 算法
【图像重建】基于离散余弦变换DCT图像重建含MSE、PSNR、压缩比附matlab代码
【图像重建】基于离散余弦变换DCT图像重建含MSE、PSNR、压缩比附matlab代码