• 图像处理------高斯一阶及二阶导数计算 分类: 视频图像处理 2015-07-24 15:07 72人阅读 评论(0) 收藏


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

    作用,通常情况下:

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

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

    常见的算子有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方向效果


    五:算法全部源代码:

    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. }  

    版权声明:本文为博主原创文章,未经博主允许不得转载。

  • 相关阅读:
    [Redis-CentOS7]Redis设置连接密码(九)
    [Redis-CentOS7]Redis数据持久化(八)
    PAT Advanced 1101 Quick Sort (25分)
    PAT Advanced 1043 Is It a Binary Search Tree (25分)
    HTTP协议
    PAT Advanced 1031 Hello World for U (20分)
    自然码双拼快速记忆方案
    macOS 原生输入法设置自然码
    PAT Advanced 1086 Tree Traversals Again (25分)
    PAT Advanced 1050 String Subtraction (20分)
  • 原文地址:https://www.cnblogs.com/mao0504/p/4705501.html
Copyright © 2020-2023  润新知