java数字图像处理常用算法

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了java数字图像处理常用算法相关的知识,希望对你有一定的参考价值。

参考技术A


     前些时候做毕业设计 用java做的数字图像处理方面的东西 这方面的资料ms比较少 发点东西上来大家共享一下 主要就是些算法 有自己写的 有人家的 还有改人家的 有的算法写的不好 大家不要见笑

   一 读取bmp图片数据

  

  //  获取待检测图像  数据保存在数组 nData[] nB[]  nG[]  nR[]中

  public  void getBMPImage(String source) throws Exception                     clearNData();                        //清除数据保存区         FileInputStream fs = null;               try             fs = new FileInputStream(source);            int bfLen = ;            byte bf[] = new byte[bfLen];            fs read(bf bfLen); // 读取 字节BMP文件头            int biLen = ;            byte bi[] = new byte[biLen];            fs read(bi biLen); // 读取 字节BMP信息头

  // 源图宽度            nWidth = (((int) bi[ ] & xff) << )                    | (((int) bi[ ] & xff) << )                    | (((int) bi[ ] & xff) << ) | (int) bi[ ] & xff;

  // 源图高度            nHeight = (((int) bi[ ] & xff) << )                    | (((int) bi[ ] & xff) << )                    | (((int) bi[ ] & xff) << ) | (int) bi[ ] & xff;

  // 位数            nBitCount = (((int) bi[ ] & xff) << ) | (int) bi[ ] & xff;

  // 源图大小            int nSizeImage = (((int) bi[ ] & xff) << )                    | (((int) bi[ ] & xff) << )                    | (((int) bi[ ] & xff) << ) | (int) bi[ ] & xff;

  // 对 位BMP进行解析            if (nBitCount == )                int nPad = (nSizeImage / nHeight) nWidth * ;                nData = new int[nHeight * nWidth];                nB=new int[nHeight * nWidth];                nR=new int[nHeight * nWidth];                nG=new int[nHeight * nWidth];                byte bRGB[] = new byte[(nWidth + nPad) * * nHeight];                fs read(bRGB (nWidth + nPad) * * nHeight);                int nIndex = ;                for (int j = ; j < nHeight; j++)                    for (int i = ; i < nWidth; i++)                         nData[nWidth * (nHeight j ) + i] = ( & xff) <<                                 | (((int) bRGB[nIndex + ] & xff) << )                                 | (((int) bRGB[nIndex + ] & xff) << )                                | (int) bRGB[nIndex] & xff;                                              nB[nWidth * (nHeight j ) + i]=(int) bRGB[nIndex]& xff;                        nG[nWidth * (nHeight j ) + i]=(int) bRGB[nIndex+ ]& xff;                        nR[nWidth * (nHeight j ) + i]=(int) bRGB[nIndex+ ]& xff;                        nIndex += ;                                        nIndex += nPad;                 //               Toolkit kit = Toolkit getDefaultToolkit(); //               image = kit createImage(new MemoryImageSource(nWidth nHeight  //                       nData nWidth));

  /*               //调试数据的读取

  FileWriter fw = new FileWriter( C:\\\\Documents and Settings\\\\Administrator\\\\My Documents\\\\nDataRaw txt );//创建新文件                PrintWriter out = new PrintWriter(fw);                for(int j= ;j<nHeight;j++)                 for(int i= ;i<nWidth;i++)                  out print(( * +nData[nWidth * (nHeight j ) + i])+ _                     +nR[nWidth * (nHeight j ) + i]+ _                     +nG[nWidth * (nHeight j ) + i]+ _                     +nB[nWidth * (nHeight j ) + i]+ );                                                    out println( );                                out close();*/                                      catch (Exception e)             e printStackTrace();            throw new Exception(e);                finally             if (fs != null)                 fs close();                         //   return image;     

    

   二 由r g b 获取灰度数组

       public  int[] getBrightnessData(int rData[] int gData[] int bData[])          int brightnessData[]=new int[rData length];     if(rData length!=gData length || rData length!=bData length       || bData length!=gData length)      return brightnessData;          else       for(int i= ;i<bData length;i++)       double temp= *rData[i]+ *gData[i]+ *bData[i];       brightnessData[i]=(int)(temp)+((temp (int)(temp))> ? : );            return brightnessData;                

   三 直方图均衡化

       public int [] equilibrateGray(int[] PixelsGray int width int height)                       int gray;         int length=PixelsGray length;         int FrequenceGray[]=new int[length];          int SumGray[]=new int[ ];          int ImageDestination[]=new int[length];         for(int i = ; i <length ;i++)                    gray=PixelsGray[i];               FrequenceGray[gray]++;                   //    灰度均衡化          SumGray[ ]=FrequenceGray[ ];          for(int i= ;i< ;i++)               SumGray[i]=SumGray[i ]+FrequenceGray[i];                    for(int i= ;i< ;i++)                SumGray[i]=(int)(SumGray[i]* /length);                    for(int i= ;i<height;i++)                         for(int j= ;j<width;j++)                                 int k=i*width+j;                   ImageDestination[k]= xFF | ((SumGray[PixelsGray[k]]<<                             ) | (SumGray[PixelsGray[k]]<< ) | SumGray[PixelsGray[k]]);                                   return ImageDestination;       

   四 laplace 阶滤波 增强边缘 图像锐化

       public int[] laplace DFileter(int []data int width int height)         int filterData[]=new int[data length];     int min= ;     int max= ;     for(int i= ;i<height;i++)      for(int j= ;j<width;j++)       if(i== || i==height || j== || j==width )               filterData[i*width+j]=data[i*width+j];       else        filterData[i*width+j]= *data[i*width+j] data[i*width+j ] data[i*width+j+ ]                             data[(i )*width+j] data[(i )*width+j ] data[(i )*width+j+ ]                             data[(i+ )*width+j] data[(i+ )*width+j ] data[(i+ )*width+j+ ];              if(filterData[i*width+j]<min)        min=filterData[i*width+j];       if(filterData[i*width+j]>max)        max=filterData[i*width+j];             //     System out println( max: +max);//     System out println( min: +min);          for(int i= ;i<width*height;i++)      filterData[i]=(filterData[i] min)* /(max min);          return filterData;     

    

   五 laplace 阶增强滤波 增强边缘 增强系数delt

       public int[] laplaceHigh DFileter(int []data int width int height double delt)          int filterData[]=new int[data length];     int min= ;     int max= ;     for(int i= ;i<height;i++)      for(int j= ;j<width;j++)       if(i== || i==height || j== || j==width )               filterData[i*width+j]=(int)(( +delt)*data[i*width+j]);       else        filterData[i*width+j]=(int)(( +delt)*data[i*width+j] data[i*width+j ]) data[i*width+j+ ]                             data[(i )*width+j] data[(i )*width+j ] data[(i )*width+j+ ]                             data[(i+ )*width+j] data[(i+ )*width+j ] data[(i+ )*width+j+ ];              if(filterData[i*width+j]<min)        min=filterData[i*width+j];       if(filterData[i*width+j]>max)        max=filterData[i*width+j];                  for(int i= ;i<width*height;i++)      filterData[i]=(filterData[i] min)* /(max min);          return filterData;      六 局部阈值处理 值化

       //   局部阈值处理 值化 niblack s   method    /*原理             T(x y)=m(x y)   +   k*s(x y)            取一个宽度为w的矩形框 (x y)为这个框的中心          统计框内数据 T(x y)为阈值 m(x y)为均值 s(x y)为均方差 k为参数(推荐 )计算出t再对(x y)进行切割 /             这个算法的优点是     速度快 效果好             缺点是     niblack s   method会产生一定的噪声        */        public int[] localThresholdProcess(int []data int width int height int w int h double coefficients double gate)     int[] processData=new int[data length];     for(int i= ;i<data length;i++)      processData[i]= ;               if(data length!=width*height)      return processData;          int wNum=width/w;     int hNum=height/h;     int delt[]=new int[w*h];          //System out println( w; +w+   h: +h+   wNum: +wNum+ hNum: +hNum);          for(int j= ;j<hNum;j++)      for(int i= ;i<wNum;i++)     //for(int j= ;j< ;j++)     // for(int i= ;i< ;i++)         for(int n= ;n<h;n++)               for(int k= ;k<w;k++)                delt[n*w+k]=data[(j*h+n)*width+i*w+k];                //System out print( delt[ +(n*w+k)+ ]: +delt[n*w+k]+ );                       //System out println();        /*        for(int n= ;n<h;n++)               for(int k= ;k<w;k++)                System out print( data[ +((j*h+n)*width+i*w+k)+ ]: +data[(j*h+n)*width+i*w+k]+ );                       System out println();        */        delt=thresholdProcess(delt w h coefficients gate);        for(int n= ;n<h;n++)               for(int k= ;k<w;k++)                processData[(j*h+n)*width+i*w+k]=delt[n*w+k];               // System out print( delt[ +(n*w+k)+ ]: +delt[n*w+k]+ );                       //System out println();        /*        for(int n= ;n<h;n++)               for(int k= ;k<w;k++)                System out print( processData[ +((j*h+n)*width+i*w+k)+ ]: +processData[(j*h+n)*width+i*w+k]+ );                       System out println();        */                      return processData;     

   七 全局阈值处理 值化

       public int[] thresholdProcess(int []data int width int height double coefficients double gate)     int [] processData=new int[data length];     if(data length!=width*height)      return processData;     else      double sum= ;      double average= ;      double variance= ;      double threshold;            if( gate!= )       threshold=gate;             else            for(int i= ;i<width*height;i++)            sum+=data[i];                        average=sum/(width*height);                  for(int i= ;i<width*height;i++)              variance+=(data[i] average)*(data[i] average);                        variance=Math sqrt(variance);            threshold=average coefficients*variance;                     for(int i= ;i<width*height;i++)          if(data[i]>threshold)             processData[i]= ;          else                 processData[i]= ;                        return processData;            

    

   八  垂直边缘检测 sobel算子

       public int[] verticleEdgeCheck(int []data int width int height int sobelCoefficients) throws Exception     int filterData[]=new int[data length];     int min= ;     int max= ;     if(data length!=width*height)      return filterData;          try            for(int i= ;i<height;i++)       for(int j= ;j<width;j++)        if(i== || i== || i==height || i==height            ||j== || j== || j==width || j==width )               filterData[i*width+j]=data[i*width+j];                  else          double average;            //中心的九个像素点             //average=data[i*width+j] Math sqrt( )*data[i*width+j ]+Math sqrt( )*data[i*width+j+ ]          average=data[i*width+j] sobelCoefficients*data[i*width+j ]+sobelCoefficients*data[i*width+j+ ]                         data[(i )*width+j ]+data[(i )*width+j+ ]                     data[(i+ )*width+j ]+data[(i+ )*width+j+ ];             filterData[i*width+j]=(int)(average);                        if(filterData[i*width+j]<min)         min=filterData[i*width+j];         if(filterData[i*width+j]>max)         max=filterData[i*width+j];                       for(int i= ;i<width*height;i++)        filterData[i]=(filterData[i] min)* /(max min);                        catch (Exception e)                  e printStackTrace();            throw new Exception(e);                    return filterData;     

   九  图像平滑 * 掩模处理(平均处理) 降低噪声    

lishixinzhi/Article/program/Java/hx/201311/26286

数字图像处理图像细化处理

 

图像细化

细化技术:把一个平面区域简化成图的结构形状表示法
骨架:一种细化结构,它是目标的重要拓扑描述,具有非常广泛的应用。在图像识别或数据压缩时,经常用细化结构。
例如:在识别字符之前,往往要先对字符作细化处理,求出字符的细化结构。
细化的作用:目的将图像的骨架提取出来的同时,保持图像细小部分的连通性,对被处理的图像进行细化有助于突出形状特点和减少冗余信息量。

 

细化算法

细化算法:采取逐次去除边界的方法进行的,不能破化图像的连通性。
通常选择一组结构元素对,不断在这些结构对中循环,如果所得结果不再变化,则终止迭代过程,随着迭代的进行,集合也不断细化。
结构对的选择:仅受结构元素不相交的限制(不同的结构对),事实上,我们可以使用同一个结构对,即在不断重复的迭代细化过程使用同一个结构对。
细化满足的条件:
1.在细化的过程中,图像应该有规律地缩小;
2.在图像逐步缩小的过程中,应当使图像的连通性质保持不变。

 

 

 

 

细化算法过程详解

      我们对一副二值图像进行骨架提取,就是删除不需要的轮廓点,只保留其骨架点。假设一个像素点,我们定义该点为p1,则它的八邻域点p2->p9位置如下图所示,该算法考虑p1点邻域的实际情况,以便决定是否删除p1点。假设我们处理的为二值图像,背景为黑色,值为0,要细化的前景物体像素值为1。

 

技术图片

算法的描述如下。

首先复制源图像到目地图像,然后建立一个临时图像,接着执行下面操作:

1. 把目地图像复制给临时图像,对临时图像进行一次扫描,对于不为0的点,如果满足以下四个条件,则在目地图像中删除该点(就是设置该像素为0),这里p2,…,p9是对应位置的像素灰度值(其为1或者0)。

   a. 2<= p2+p3+p4+p5+p6+p7+p8+p9<=6

    大于等于2会保证p1点不是端点或孤立点,因为删除端点和孤立点是不合理的,小于等于6保证p1点是一个边界点,而不是一个内部点。等于0时候,周围没有等于1的像素,所以p1为孤立点,等于1的时候,周围只有1个灰度等于1的像素,所以是端点(注:端点是周围有且只能有1个值为1的像素)。

技术图片

 

   b. p2->p9的排列顺序中,01模式的数量为1,比如下面的图中,有p2p3 => 01, p6p7=>01,所以该像素01模式的数量为2。

技术图片

     之所以要01模式数量为1,是要保证删除当前像素点后的连通性。比如下面的图中,01模式数量大于1,如果删除当前点p1,则连通性不能保证。

技术图片

    c. P2*p4*p6 = 0

    d. p4*p6*p8 = 0

技术图片

      在第一次子迭代中,只是移去东南的边界点,而不考虑西北的边界点,注意p4,p6出现了2次,就是说它们有一个为0,则c,d就满足。

2. 接下来,把目地图像再次复制到临时图像,接着对临时图像进行一次扫描,如果不为0的点它的八邻域满足以下4个条件,则在目地图像中删除该点(就是设置该像素为0)

    a. 2<= p2+p3+p4+p5+p6+p7+p8+p9<=6

    b. p2->p9的排列顺序中,01模式的数量(这里假设二值图非零值为1)为1。

    c. p2*p4*p8 = 0

    d. p2*p6*p8 = 0

技术图片

第二次迭代则相反,会移去西北的边界点,注意p2,p8出现了2次,就是说它们有一个为0,则c,d就满足。

执行完上面两个步骤后,就完成了一次细化算法,我们可以多次迭代执行上述过程,得到最终的骨架图。

 


细化实例编程

1.首先对图像进行二值化,白色为255,黑色为0。
2.设置一个3*3的领域S模板。
3.S模板中各个位置上的取值取决于模板所对应图像中不同位置的像素,如果S模板某一个位置上所对应的像素值为白,模板上该位置赋为0,否则赋为1。
4.循环所有的前景像素点,对符合如下条件的像素点标记为删除:

  • 2 ≤ N(p1) ≤ 6——N(p1)表示跟P1相邻的8个像素点中,为前景像素点的个数
  • S(P1) = 1——S(P1)表示将p2-p9-p2之间按序前后分别成对值为0、1的个数
  • P2 * P4 * P6 = 0
  • P4 * P6 * P8 = 0

5.循环所有的前景像素点,对符合如下条件的像素点标记为删除:

  •  2 ≤ N(p1) ≤ 6——N(p1)表示跟P1相邻的8个像素点中,为前景像素点的个数
  •  S(P1) = 1——S(P1)表示将p2-p9-p2之间按序前后分别成对值为0、1的个数
  •  P2 * P4 * P8 = 0
  • P2 * P6 * P8 = 0

 6.如果没有满足的点,则结束细化过程。

 

下面:

Image_Use为目标图像:高120,长180,处理时不考虑边界(四边)
                   
//背景为黑色,值为0,要细化的前景物体像素值为1。
int temp[3][3];
int count = 0,flinsh_flag = 0;
while(1){
  flinsh_flag = 0;
  for(int i = 1;i<120-1;i++)
  {
          for(int j = 1;j<180-1;j++)    
          {
                  if(Image_Use[i][j] == 255) continue;
                  //第一步初始化模板
                  memset(temp, 0, sizeof(temp));
                  count = 0;
                  //第二步根据模板所对应的像素点,对模板进行赋值
                  //如果S模板某一个位置上所对应的像素值为白,模板上该位置赋为0,否则赋为1
                  if(Image_Use[i][j-1] == 0) temp[1][0] = 1;
                  if(Image_Use[i][j+1] == 0) temp[1][2] = 1;
                  if(Image_Use[i-1][j-1] == 0) temp[0][0] = 1;
                  if(Image_Use[i-1][j+1] == 0) temp[0][2] = 1;
                  if(Image_Use[i-1][j] == 0) temp[0][1] = 1;
                  if(Image_Use[i+1][j-1] == 0) temp[2][0] = 1;
                  if(Image_Use[i+1][j+1] == 0) temp[2][2] = 1;
                  if(Image_Use[i+1][j] == 0) temp[2][1] = 1;    
                  //
                  for(int x = 0;x<3;x++)
                          for(int y = 0;y<3;y++)
                          {      
                                  if(x == 1 && y == 1) continue;
                                  if(temp[x][y] == 1)
                                  count ++;
                          }
                  
                  if(count>=2&&count<=6)
                  { 
                    int ap = 0;
                    if (temp[0][1] == 0 && temp[0][2] == 1) ++ap;
                    if (temp[0][2] == 0 && temp[1][2] == 1) ++ap;
                    if (temp[1][2] == 0 && temp[2][2] == 1) ++ap;
                    if (temp[2][2] == 0 && temp[2][1] == 1) ++ap;
                    if (temp[2][1] == 0 && temp[2][0] == 1) ++ap;
                    if (temp[2][0] == 0 && temp[1][0] == 1) ++ap;
                    if (temp[1][0] == 0 && temp[0][0] == 1) ++ap;
                    if (temp[0][0] == 0 && temp[0][1] == 1) ++ap;
                    if(ap == 1&&((temp[0][1]*temp[1][2]*temp[2][1])== 0)&&((temp[1][2]*temp[2][1]*temp[1][0])== 0))
                    {
                      Image_Use[i][j] = 255;
                      flinsh_flag ++;
                    }
                  }
                  
          }
}
  if(flinsh_flag == 0) 
  {
    break;
  }
  
  flinsh_flag = 0;
  for(int i = 1;i<120-1;i++)
  {
          for(int j = 1;j<180-1;j++)    
          {
                  if(Image_Use[i][j] == 255) continue;
                  //第一步初始化模板
                   memset(temp, 0, sizeof(temp));
                  count = 0;
                  //第二步根据模板所对应的像素点,对模板进行赋值
                  //如果S模板某一个位置上所对应的像素值为白,模板上该位置赋为0,否则赋为1
                  if(Image_Use[i][j-1] == 0) temp[1][0] = 1;
                  if(Image_Use[i][j+1] == 0) temp[1][2] = 1;
                  if(Image_Use[i-1][j-1] == 0) temp[0][0] = 1;
                  if(Image_Use[i-1][j+1] == 0) temp[0][2] = 1;
                  if(Image_Use[i-1][j] == 0) temp[0][1] = 1;
                  if(Image_Use[i+1][j-1] == 0) temp[2][0] = 1;
                  if(Image_Use[i+1][j+1] == 0) temp[2][2] = 1;
                  if(Image_Use[i+1][j] == 0) temp[2][1] = 1;    
                  //
                  for(int x = 0;x<3;x++)
                          for(int y = 0;y<3;y++)
                          {       
                                  if(x == 1 && y == 1) continue;
                                  if(temp[x][y] == 1)
                                  count ++;
                          }
                   if(count>=2&&count<=6)
                  {    
                    int ap = 0;
                    if (temp[0][1] == 0 && temp[0][2] == 1) ++ap;
                    if (temp[0][2] == 0 && temp[1][2] == 1) ++ap;
                    if (temp[1][2] == 0 && temp[2][2] == 1) ++ap;
                    if (temp[2][2] == 0 && temp[2][1] == 1) ++ap;
                    if (temp[2][1] == 0 && temp[2][0] == 1) ++ap;
                    if (temp[2][0] == 0 && temp[1][0] == 1) ++ap;
                    if (temp[1][0] == 0 && temp[0][0] == 1) ++ap;
                    if (temp[0][0] == 0 && temp[0][1] == 1) ++ap;
                    if(ap == 1&&((temp[0][1]*temp[1][2]*temp[1][0])== 0)&&((temp[0][1]*temp[2][1]*temp[1][0]) == 0))
                    {
                      Image_Use[i][j] = 255;
                      flinsh_flag++;
                    }
                  }
          }
  }
  if(flinsh_flag == 0)
  { 
    break;
  }
}

 测试结果:

技术图片

 

 

 

 技术图片

 

 

 

refer:

图像处理细化算法

C/C++ 图像处理(19)------细化算法

以上是关于java数字图像处理常用算法的主要内容,如果未能解决你的问题,请参考以下文章

JAVA数字证书制作生成

数字图像处理中一张常用图片

常用的签名算法

常用数字滤波算法总结

学习Java绝对要懂的,Java编程中最常用的几种排序算法!

Java常用排序算法