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

转:http://blog.csdn.net/qianchenglenger/article/details/38989565

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

作用,通常情况下:

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

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

常见的算子有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. import java.awt.Graphics2D;  
  2. import java.awt.image.BufferedImage;  
  3. import java.awt.image.ColorModel;  
  4. import java.io.BufferedInputStream;  
  5. import java.io.IOException;  
  6. import java.io.InputStream;  
  7. import java.io.File;  
  8.   
  9. import javax.imageio.ImageIO;  
  10.   
  11. public class GaussianDerivativeFilter  {  
  12.   
  13.     public final static int X_DIRECTION = 0;  
  14.     public final static int Y_DIRECTION = 16;  
  15.     public final static int XY_DIRECTION = 2;  
  16.     public final static int XX_DIRECTION = 4;  
  17.     public final static int YY_DIRECTION = 8;  
  18.       
  19.     // private attribute and settings  
  20.     private int DIRECTION_TYPE = 16;  
  21.     private int GAUSSIAN_WIN_SIZE = 1// N*2 + 1  
  22.     private double sigma = 10// default  
  23.   
  24.     public GaussianDerivativeFilter()  
  25.     {  
  26.         System.out.println("高斯一阶及多阶导数滤镜");  
  27.     }     
  28.       
  29.     public int getGaussianWinSize() {  
  30.         return GAUSSIAN_WIN_SIZE;  
  31.     }  
  32.   
  33.     public void setGaussianWinSize(int gAUSSIAN_WIN_SIZE) {  
  34.         GAUSSIAN_WIN_SIZE = gAUSSIAN_WIN_SIZE;  
  35.     }  
  36.     public int getDirectionType() {  
  37.         return DIRECTION_TYPE;  
  38.     }  
  39.   
  40.     public void setDirectionType(int dIRECTION_TYPE) {  
  41.         DIRECTION_TYPE = dIRECTION_TYPE;  
  42.     }  
  43.   
  44.     public BufferedImage filter(BufferedImage src, BufferedImage dest) {  
  45.         int width = src.getWidth();  
  46.         int height = src.getHeight();  
  47.   
  48.         if ( dest == null )  
  49.             dest = createCompatibleDestImage( src, null );  
  50.   
  51.         int[] inPixels = new int[width*height];  
  52.         int[] outPixels = new int[width*height];  
  53.         getRGB( src, 00, width, height, inPixels );  
  54.         int index = 0, index2 = 0;  
  55.         double xred = 0, xgreen = 0, xblue = 0;  
  56.         //double yred = 0, ygreen = 0, yblue = 0;  
  57.         int newRow, newCol;  
  58.         double[][] winDeviationData = getDirectionData();  
  59.   
  60.         for(int row=0; row<height; row++) {  
  61.             int ta = 255, tr = 0, tg = 0, tb = 0;  
  62.             for(int col=0; col<width; col++) {  
  63.                 index = row * width + col;  
  64.                 for(int subrow = -GAUSSIAN_WIN_SIZE; subrow <= GAUSSIAN_WIN_SIZE; subrow++) {  
  65.                     for(int subcol = -GAUSSIAN_WIN_SIZE; subcol <= GAUSSIAN_WIN_SIZE; subcol++) {  
  66.                         newRow = row + subrow;  
  67.                         newCol = col + subcol;  
  68.                         if(newRow < 0 || newRow >= height) {  
  69.                             newRow = row;  
  70.                         }  
  71.                         if(newCol < 0 || newCol >= width) {  
  72.                             newCol = col;  
  73.                         }  
  74.                         index2 = newRow * width + newCol;  
  75.                         tr = (inPixels[index2] >> 16) & 0xff;  
  76.                         tg = (inPixels[index2] >> 8) & 0xff;  
  77.                         tb = inPixels[index2] & 0xff;  
  78.                         xred += (winDeviationData[subrow + GAUSSIAN_WIN_SIZE][subcol + GAUSSIAN_WIN_SIZE] * tr);  
  79.                         xgreen +=(winDeviationData[subrow + GAUSSIAN_WIN_SIZE][subcol + GAUSSIAN_WIN_SIZE] * tg);  
  80.                         xblue +=(winDeviationData[subrow + GAUSSIAN_WIN_SIZE][subcol + GAUSSIAN_WIN_SIZE] * tb);  
  81.                     }  
  82.                 }  
  83.                   
  84.                 outPixels[index] = (ta << 24) | (clamp((int)xred) << 16) | (clamp((int)xgreen) << 8) | clamp((int)xblue);  
  85.                   
  86.                 // clean up values for next pixel  
  87.                 newRow = newCol = 0;  
  88.                 xred = xgreen = xblue = 0;  
  89.                 //yred = ygreen = yblue = 0;  
  90.             }  
  91.         }  
  92.   
  93.         setRGB( dest, 00, width, height, outPixels );  
  94.         return dest;  
  95.     }  
  96.   
  97.       
  98.     private void setRGB(BufferedImage dest, int i, int j, int width,  
  99.             int height, int[] outPixels) {  
  100.            dest.setRGB( 00, width, height, outPixels, 0, width );   
  101.     }  
  102.   
  103.     private void getRGB(BufferedImage src, int i, int j, int width, int height,  
  104.             int[] inPixels) {  
  105.         src.getRGB(00, width, height, inPixels, 0, width);  
  106.     }  
  107.       
  108.       
  109.   
  110.     public BufferedImage createCompatibleDestImage(BufferedImage src, ColorModel dstCM) {    
  111.         if ( dstCM == null )    
  112.             dstCM = src.getColorModel();    
  113.         return new BufferedImage(dstCM, dstCM.createCompatibleWritableRaster(src.getWidth(), src.getHeight()), dstCM.isAlphaPremultiplied(), null);    
  114.     }  
  115.       
  116.       
  117.       
  118.     private double[][] getDirectionData()  
  119.     {  
  120.         double[][] winDeviationData = null;  
  121.         if(DIRECTION_TYPE == X_DIRECTION)  
  122.         {  
  123.             winDeviationData = this.getXDirectionDeviation();  
  124.         }  
  125.         else if(DIRECTION_TYPE == Y_DIRECTION)  
  126.         {  
  127.             winDeviationData = this.getYDirectionDeviation();  
  128.         }  
  129.         else if(DIRECTION_TYPE == XY_DIRECTION)  
  130.         {  
  131.             winDeviationData = this.getXYDirectionDeviation();  
  132.         }  
  133.         else if(DIRECTION_TYPE == XX_DIRECTION)  
  134.         {  
  135.             winDeviationData = this.getXXDirectionDeviation();  
  136.         }  
  137.         else if(DIRECTION_TYPE == YY_DIRECTION)  
  138.         {  
  139.             winDeviationData = this.getYYDirectionDeviation();  
  140.         }  
  141.         return winDeviationData;  
  142.     }  
  143.       
  144.     public int clamp(int value) {  
  145.         // trick, just improve the lightness otherwise image is too darker...  
  146.         if(DIRECTION_TYPE == X_DIRECTION || DIRECTION_TYPE == Y_DIRECTION)  
  147.         {  
  148.             value = value * 10 + 50;  
  149.         }  
  150.         return value < 0 ? 0 : (value > 255 ? 255 : value);  
  151.     }  
  152.       
  153.     // centered on zero and with Gaussian standard deviation  
  154.     // parameter : sigma  
  155.     public double[][] get2DGaussianData()  
  156.     {  
  157.         int size = GAUSSIAN_WIN_SIZE * 2 + 1;  
  158.         double[][] winData = new double[size][size];  
  159.         double sigma2 = this.sigma * sigma;  
  160.         for(int i=-GAUSSIAN_WIN_SIZE; i<=GAUSSIAN_WIN_SIZE; i++)  
  161.         {  
  162.             for(int j=-GAUSSIAN_WIN_SIZE; j<=GAUSSIAN_WIN_SIZE; j++)  
  163.             {  
  164.                 double r = i*1 + j*j;  
  165.                 double sum = -(r/(2*sigma2));  
  166.                 winData[i + GAUSSIAN_WIN_SIZE][j + GAUSSIAN_WIN_SIZE] = Math.exp(sum);  
  167.             }  
  168.         }  
  169.         return winData;  
  170.     }  
  171.       
  172.     public double[][] getXDirectionDeviation()  
  173.     {  
  174.         int size = GAUSSIAN_WIN_SIZE * 2 + 1;  
  175.         double[][] data = get2DGaussianData();  
  176.         double[][] xDeviation = new double[size][size];  
  177.         double sigma2 = this.sigma * sigma;  
  178.         for(int x=-GAUSSIAN_WIN_SIZE; x<=GAUSSIAN_WIN_SIZE; x++)  
  179.         {  
  180.             double c = -(x/sigma2);  
  181.             for(int i=0; i<size; i++)  
  182.             {  
  183.                 xDeviation[i][x + GAUSSIAN_WIN_SIZE] = c * data[i][x + GAUSSIAN_WIN_SIZE];                
  184.             }  
  185.         }  
  186.         return xDeviation;  
  187.     }  
  188.       
  189.     public double[][] getYDirectionDeviation()  
  190.     {  
  191.         int size = GAUSSIAN_WIN_SIZE * 2 + 1;  
  192.         double[][] data = get2DGaussianData();  
  193.         double[][] yDeviation = new double[size][size];  
  194.         double sigma2 = this.sigma * sigma;  
  195.         for(int y=-GAUSSIAN_WIN_SIZE; y<=GAUSSIAN_WIN_SIZE; y++)  
  196.         {  
  197.             double c = -(y/sigma2);  
  198.             for(int i=0; i<size; i++)  
  199.             {  
  200.                 yDeviation[y + GAUSSIAN_WIN_SIZE][i] = c * data[y + GAUSSIAN_WIN_SIZE][i];                
  201.             }  
  202.         }  
  203.         return yDeviation;  
  204.     }  
  205.       
  206.     /*** 
  207.      *  
  208.      * @return 
  209.      */  
  210.     public double[][] getXYDirectionDeviation()  
  211.     {  
  212.         int size = GAUSSIAN_WIN_SIZE * 2 + 1;  
  213.         double[][] data = get2DGaussianData();  
  214.         double[][] xyDeviation = new double[size][size];  
  215.         double sigma2 = sigma * sigma;  
  216.         double sigma4 = sigma2 * sigma2;  
  217.         // TODO:zhigang  
  218.         for(int x=-GAUSSIAN_WIN_SIZE; x<=GAUSSIAN_WIN_SIZE; x++)  
  219.         {  
  220.             for(int y=-GAUSSIAN_WIN_SIZE; y<=GAUSSIAN_WIN_SIZE; y++)  
  221.             {  
  222.                 double c = -((x*y)/sigma4);  
  223.                 xyDeviation[x + GAUSSIAN_WIN_SIZE][y + GAUSSIAN_WIN_SIZE] = c * data[x + GAUSSIAN_WIN_SIZE][y + GAUSSIAN_WIN_SIZE];  
  224.             }  
  225.         }  
  226.         return normalizeData(xyDeviation);  
  227.     }  
  228.       
  229.     private double[][] normalizeData(double[][] data)  
  230.     {  
  231.         // normalization the data  
  232.         double min = data[0][0];  
  233.         for(int x=-GAUSSIAN_WIN_SIZE; x<=GAUSSIAN_WIN_SIZE; x++)  
  234.         {  
  235.             for(int y=-GAUSSIAN_WIN_SIZE; y<=GAUSSIAN_WIN_SIZE; y++)  
  236.             {  
  237.                 if(min > data[x + GAUSSIAN_WIN_SIZE][y + GAUSSIAN_WIN_SIZE])  
  238.                 {  
  239.                     min = data[x + GAUSSIAN_WIN_SIZE][y + GAUSSIAN_WIN_SIZE];  
  240.                 }  
  241.             }  
  242.         }  
  243.           
  244.         for(int x=-GAUSSIAN_WIN_SIZE; x<=GAUSSIAN_WIN_SIZE; x++)  
  245.         {  
  246.             for(int y=-GAUSSIAN_WIN_SIZE; y<=GAUSSIAN_WIN_SIZE; y++)  
  247.             {  
  248.                 data[x + GAUSSIAN_WIN_SIZE][y + GAUSSIAN_WIN_SIZE] = data[x + GAUSSIAN_WIN_SIZE][y + GAUSSIAN_WIN_SIZE] /min;  
  249.             }  
  250.         }  
  251.           
  252.         return data;  
  253.     }  
  254.       
  255.     public double[][] getXXDirectionDeviation()  
  256.     {  
  257.         int size = GAUSSIAN_WIN_SIZE * 2 + 1;  
  258.         double[][] data = get2DGaussianData();  
  259.         double[][] xxDeviation = new double[size][size];  
  260.         double sigma2 = this.sigma * sigma;  
  261.         double sigma4 = sigma2 * sigma2;  
  262.         for(int x=-GAUSSIAN_WIN_SIZE; x<=GAUSSIAN_WIN_SIZE; x++)  
  263.         {  
  264.             double c = -((x - sigma2)/sigma4);  
  265.             for(int i=0; i<size; i++)  
  266.             {  
  267.                 xxDeviation[i][x + GAUSSIAN_WIN_SIZE] = c * data[i][x + GAUSSIAN_WIN_SIZE];               
  268.             }  
  269.         }  
  270.         return xxDeviation;  
  271.     }  
  272.       
  273.     public double[][] getYYDirectionDeviation()  
  274.     {  
  275.         int size = GAUSSIAN_WIN_SIZE * 2 + 1;  
  276.         double[][] data = get2DGaussianData();  
  277.         double[][] yyDeviation = new double[size][size];  
  278.         double sigma2 = this.sigma * sigma;  
  279.         double sigma4 = sigma2 * sigma2;  
  280.         for(int y=-GAUSSIAN_WIN_SIZE; y<=GAUSSIAN_WIN_SIZE; y++)  
  281.         {  
  282.             double c = -((y - sigma2)/sigma4);  
  283.             for(int i=0; i<size; i++)  
  284.             {  
  285.                 yyDeviation[y + GAUSSIAN_WIN_SIZE][i] = c * data[y + GAUSSIAN_WIN_SIZE][i];               
  286.             }  
  287.         }  
  288.         return yyDeviation;  
  289.     }  
  290.       
  291.     public static void main(String argv[]) throws IOException  
  292.     {  
  293.         GaussianDerivativeFilter gd = new GaussianDerivativeFilter();  
  294.           
  295.         BufferedImage src = ImageIO.read(new File("lenac.jpg"));//读取图片  
  296.           
  297.         BufferedImage t = gd.filter(src, null);  
  298.         File file = new File("lenacy.jpg");  
  299.         ImageIO.write(t, "JPEG", file); //保存处理后的图像  
  300.     }  
  301.   
  302. }  

该文章转自http://blog.csdn.net/jia20003/article/details/16369143,但是我对其代码进行了部分加工,去除继承部分,增加了主函数及部分方法,可以直接进行编译运行

猜你喜欢

转载自blog.csdn.net/zhouxianen1987/article/details/78963379
今日推荐