图像的放大与缩小(2)——双线性插值放大与均值缩小

概述

基于上一节“等距采样法”实现图片放大与缩小的缺点。要对其进行改进,对图像的缩小则可以用“局部均值法”,对于图像的放大则可以用“双线性插值法”。

效果如下:

      

                   2048*1536缩小为100*80时的效果               100*80放大到600*400的效果

局部均值法缩小图像

(1)计算采样间隔

设原图的大小为W*H,将其放大(缩小)为(k1*W)*(K2*H),则采样区间为

ii=1/k1;       jj=1/k2;

当k1==k2时为等比例缩小;当k1!=k2时为不等比例放大(缩小);k1<1 && k2<1时为图片缩小,k1>1 && k2>1时图片放大。

(2)求出局部子块

设原图为F(x,y)(i=1,2,……W; j=1,2,……H),缩小的图像为G(x,y)(x=1,2, ……M; y=1,2,……N,其中M=W*k1,N=H*k2),则有原图像局部子块为

f’(x,y) = f(ii*i, jj*j)        …… f(ii*i + ii-1, jj*j)

                ……                   ……

             f(ii*i, jj*j+jj-1) …… f(ii*i + ii-1, jj*j+jj-1)

(3)求出缩小的图像

G(x, y) = f’(x,y)的均值

例:


缩小后的图像

 

 

例如g11=(f11 +f12 + f21 + f22)/4

 

算法源代码(Java

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. /** 
  2.      * 局部均值的图像缩小 
  3.      * @param img 要缩小的图像对象 
  4.      * @param m 缩小后图像的宽 
  5.      * @param n 缩小后图像的高 
  6.      * @return 返回处理后的图像对象 
  7.      */  
  8.     public static BufferedImage shrink(BufferedImage img, int m, int n) {  
  9.         float k1 = (float)m/img.getWidth();  
  10.         float k2 = (float)n/img.getHeight();          
  11.         return shrink(img, k1, k2);  
  12.     }  
  13.       
  14.     /** 
  15.       * 局部均值的图像缩小 
  16.      * @param img 要缩小的图像对象 
  17.      * @param k1 要缩小的列比列 
  18.      * @param k2 要缩小的行比列 
  19.      * @return 返回处理后的图像对象 
  20.      */  
  21.     public static BufferedImage shrink(BufferedImage img, float k1, float k2) {  
  22.         if(k1 >1 || k2>1) {//如果k1 >1 || k2>1则是图片放大,不是缩小  
  23.             System.err.println("this is shrink image funcation, please set k1<=1 and k2<=1!");  
  24.             return null;  
  25.         }   
  26.         float ii = 1/k1;    //采样的行间距  
  27.         float jj = 1/k2; //采样的列间距         
  28.         int dd = (int)(ii*jj);   
  29.         //int m=0 , n=0;                  
  30.         int imgType = img.getType();  
  31.         int w = img.getWidth();  
  32.         int h = img.getHeight();  
  33.         int m = (int) (k1*w);  
  34.         int n = (int) (k2*h);  
  35.         int[] pix = new int[w*h];  
  36.         pix = img.getRGB(00, w, h, pix, 0, w);  
  37.         System.out.println(w + " * " + h);  
  38.         System.out.println(m + " * " + n);  
  39.         int[] newpix = new int[m*n];  
  40.           
  41.         for(int j=0; j<n; j++) {  
  42.             for(int i=0; i<m; i++) {  
  43.                 int r = 0, g=0, b=0;  
  44.                 ColorModel cm = ColorModel.getRGBdefault();               
  45.                 for(int k=0; k<(int)jj; k++) {  
  46.                     for(int l=0; l<(int)ii; l++) {  
  47.                         r = r + cm.getRed(pix[(int)(jj*j+k)*w + (int)(ii*i+l)]);  
  48.                         g = g + cm.getGreen(pix[(int)(jj*j+k)*w + (int)(ii*i+l)]);  
  49.                         b = b + cm.getBlue(pix[(int)(jj*j+k)*w + (int)(ii*i+l)]);  
  50.                     }  
  51.                 }  
  52.                 r = r/dd;  
  53.                 g = g/dd;  
  54.                 b = b/dd;  
  55.                 newpix[j*m + i] = 255<<24 | r<<16 | g<<8 | b;  
  56.                 //255<<24 | r<<16 | g<<8 | b  这个公式解释一下,颜色的RGB在内存中是  
  57.                 //以二进制的形式保存的,从右到左1-8位表示blue,9-16表示green,17-24表示red  
  58.                 //所以"<<24" "<<16" "<<8"分别表示左移24,16,8位  
  59.                   
  60.                 //newpix[j*m + i] = new Color(r,g,b).getRGB();  
  61.             }  
  62.         }  
  63.           
  64.         BufferedImage imgOut = new BufferedImage( m, n, imgType);  
  65.           
  66.         imgOut.setRGB(00, m, n, newpix, 0, m);              
  67.         return imgOut;  
  68.     }  

 
[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. /** 
  2.      * 局部均值的图像缩小 
  3.      * @param img 要缩小的图像对象 
  4.      * @param m 缩小后图像的宽 
  5.      * @param n 缩小后图像的高 
  6.      * @return 返回处理后的图像对象 
  7.      */  
  8.     public static BufferedImage shrink(BufferedImage img, int m, int n) {  
  9.         float k1 = (float)m/img.getWidth();  
  10.         float k2 = (float)n/img.getHeight();          
  11.         return shrink(img, k1, k2);  
  12.     }  
  13.       
  14.     /** 
  15.       * 局部均值的图像缩小 
  16.      * @param img 要缩小的图像对象 
  17.      * @param k1 要缩小的列比列 
  18.      * @param k2 要缩小的行比列 
  19.      * @return 返回处理后的图像对象 
  20.      */  
  21.     public static BufferedImage shrink(BufferedImage img, float k1, float k2) {  
  22.         if(k1 >1 || k2>1) {//如果k1 >1 || k2>1则是图片放大,不是缩小  
  23.             System.err.println("this is shrink image funcation, please set k1<=1 and k2<=1!");  
  24.             return null;  
  25.         }   
  26.         float ii = 1/k1;    //采样的行间距  
  27.         float jj = 1/k2; //采样的列间距         
  28.         int dd = (int)(ii*jj);   
  29.         //int m=0 , n=0;                  
  30.         int imgType = img.getType();  
  31.         int w = img.getWidth();  
  32.         int h = img.getHeight();  
  33.         int m = (int) (k1*w);  
  34.         int n = (int) (k2*h);  
  35.         int[] pix = new int[w*h];  
  36.         pix = img.getRGB(00, w, h, pix, 0, w);  
  37.         System.out.println(w + " * " + h);  
  38.         System.out.println(m + " * " + n);  
  39.         int[] newpix = new int[m*n];  
  40.           
  41.         for(int j=0; j<n; j++) {  
  42.             for(int i=0; i<m; i++) {  
  43.                 int r = 0, g=0, b=0;  
  44.                 ColorModel cm = ColorModel.getRGBdefault();               
  45.                 for(int k=0; k<(int)jj; k++) {  
  46.                     for(int l=0; l<(int)ii; l++) {  
  47.                         r = r + cm.getRed(pix[(int)(jj*j+k)*w + (int)(ii*i+l)]);  
  48.                         g = g + cm.getGreen(pix[(int)(jj*j+k)*w + (int)(ii*i+l)]);  
  49.                         b = b + cm.getBlue(pix[(int)(jj*j+k)*w + (int)(ii*i+l)]);  
  50.                     }  
  51.                 }  
  52.                 r = r/dd;  
  53.                 g = g/dd;  
  54.                 b = b/dd;  
  55.                 newpix[j*m + i] = 255<<24 | r<<16 | g<<8 | b;  
  56.                 //255<<24 | r<<16 | g<<8 | b  这个公式解释一下,颜色的RGB在内存中是  
  57.                 //以二进制的形式保存的,从右到左1-8位表示blue,9-16表示green,17-24表示red  
  58.                 //所以"<<24" "<<16" "<<8"分别表示左移24,16,8位  
  59.                   
  60.                 //newpix[j*m + i] = new Color(r,g,b).getRGB();  
  61.             }  
  62.         }  
  63.           
  64.         BufferedImage imgOut = new BufferedImage( m, n, imgType);  
  65.           
  66.         imgOut.setRGB(00, m, n, newpix, 0, m);              
  67.         return imgOut;  
  68.     }  

双线性差值法放图像

子块四个顶点的坐标分别设为(0,0)、(1,0)、(0,1)、(1,1),对应的带处理的像素的坐标(c1,c2),0<c1<1, 0<y<1.则f(x,y)由上到下得到


f(x,0) = f(0,0) + c1*(f(1,0)-f(0,0))
f(x,1) = f(0,1) + c1*(f(1,1)-f(0,1))
f(x,y) = f(x,0) + c2*f(f(x,1)-f(x,0))

例,原图的像素矩阵如下。


将其放大成2.5*1.2倍,双线性插值发,填充顶点如下:


(1)

 

(2)

1  2  3  4  5  6  7  7

2  3  4  5  7  8  8  8

3  4  5  6  7  8  9  9

3  4  5  6  7  8  9  9

(3)

算法源代码(java)


[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. /** 
  2.      * 双线性插值法图像的放大 
  3.      * @param img 要缩小的图像对象 
  4.      * @param k1 要缩小的列比列 
  5.      * @param k2 要缩小的行比列 
  6.      * @return 返回处理后的图像对象 
  7.      */  
  8.     public static BufferedImage amplify(BufferedImage img, float k1, float k2) {  
  9.         if(k1 <1 || k2<1) {//如果k1 <1 || k2<1则是图片缩小,不是放大  
  10.             System.err.println("this is shrink image funcation, please set k1<=1 and k2<=1!");  
  11.             return null;  
  12.         }   
  13.         float ii = 1/k1;    //采样的行间距  
  14.         float jj = (1/k2); //采样的列间距       
  15.         int dd = (int)(ii*jj);   
  16.         //int m=0 , n=0;  
  17.         int imgType = img.getType();  
  18.         int w = img.getWidth();     //原图片的宽  
  19.         int h = img.getHeight();    //原图片的宽  
  20.         int m = Math.round(k1*w);   //放大后图片的宽  
  21.         int n = Math.round(k2*h);   //放大后图片的宽  
  22.         int[] pix = new int[w*h];  
  23.         pix = img.getRGB(00, w, h, pix, 0, w);  
  24.         /*System.out.println(w + " * " + h); 
  25.         System.out.println(m + " * " + n);*/  
  26.         int[] newpix = new int[m*n];  
  27.           
  28.         for(int j=0; j<h-1; j++){  
  29.             for(int i=0; i<w-1; i++) {  
  30.                 int x0 = Math.round(i*k1);  
  31.                 int y0 = Math.round(j*k2);  
  32.                 int x1, y1;  
  33.                 if(i == w-2) {  
  34.                     x1 = m-1;  
  35.                 } else {  
  36.                     x1 = Math.round((i+1)*k1);  
  37.                 }                 
  38.                 if(j == h-2) {  
  39.                     y1 = n-1;  
  40.                 } else {  
  41.                     y1 = Math.round((j+1)*k2);  
  42.                 }                 
  43.                 int d1 = x1 - x0;  
  44.                 int d2 = y1 - y0;  
  45.                 if(0 == newpix[y0*m + x0]) {  
  46.                     newpix[y0*m + x0] =  pix[j*w+i];  
  47.                 }  
  48.                 if(0 == newpix[y0*m + x1]) {  
  49.                     if(i == w-2) {  
  50.                         newpix[y0*m + x1] = pix[j*w+w-1];  
  51.                     } else {  
  52.                         newpix[y0*m + x1] =  pix[j*w+i+1];  
  53.                     }                     
  54.                 }  
  55.                 if(0 == newpix[y1*m + x0]){  
  56.                     if(j == h-2) {  
  57.                         newpix[y1*m + x0] = pix[(h-1)*w+i];  
  58.                     } else {  
  59.                         newpix[y1*m + x0] =  pix[(j+1)*w+i];  
  60.                     }                     
  61.                 }  
  62.                 if(0 == newpix[y1*m + x1]) {  
  63.                     if(i==w-2 && j==h-2) {  
  64.                         newpix[y1*m + x1] = pix[(h-1)*w+w-1];  
  65.                     } else {  
  66.                         newpix[y1*m + x1] = pix[(j+1)*w+i+1];  
  67.                     }                     
  68.                 }  
  69.                 int r, g, b;  
  70.                 float c;  
  71.                 ColorModel cm = ColorModel.getRGBdefault();               
  72.                 for(int l=0; l<d2; l++) {  
  73.                     for(int k=0; k<d1; k++) {  
  74.                         if(0 == l) {  
  75.                             //f(x,0) = f(0,0) + c1*(f(1,0)-f(0,0))  
  76.                             if(j<h-1 && newpix[y0*m + x0 + k] == 0) {  
  77.                                 c = (float)k/d1;  
  78.                                  r = cm.getRed(newpix[y0*m + x0]) + (int)(c*(cm.getRed(newpix[y0*m + x1]) - cm.getRed(newpix[y0*m + x0])));//newpix[(y0+l)*m + k]  
  79.                                  g = cm.getGreen(newpix[y0*m + x0]) + (int)(c*(cm.getGreen(newpix[y0*m + x1]) - cm.getGreen(newpix[y0*m + x0])));  
  80.                                  b = cm.getBlue(newpix[y0*m + x0]) + (int)(c*(cm.getBlue(newpix[y0*m + x1]) - cm.getBlue(newpix[y0*m + x0])));  
  81.                                  newpix[y0*m + x0 + k] = new Color(r,g,b).getRGB();  
  82.                             }  
  83.                             if(j+1<h && newpix[y1*m + x0 + k] == 0) {  
  84.                                  c = (float)k/d1;  
  85.                                     r = cm.getRed(newpix[y1*m + x0]) + (int)(c*(cm.getRed(newpix[y1*m + x1]) - cm.getRed(newpix[y1*m + x0])));  
  86.                                     g = cm.getGreen(newpix[y1*m + x0]) + (int)(c*(cm.getGreen(newpix[y1*m + x1]) - cm.getGreen(newpix[y1*m + x0])));  
  87.                                     b = cm.getBlue(newpix[y1*m + x0]) + (int)(c*(cm.getBlue(newpix[y1*m + x1]) - cm.getBlue(newpix[y1*m + x0])));  
  88.                                     newpix[y1*m + x0 + k] = new Color(r,g,b).getRGB();  
  89.                              }  
  90.                             //System.out.println(c);  
  91.                         } else {  
  92.                             //f(x,y) = f(x,0) + c2*f(f(x,1)-f(x,0))  
  93.                             c = (float)l/d2;  
  94.                             r = cm.getRed(newpix[y0*m + x0+k]) + (int)(c*(cm.getRed(newpix[y1*m + x0+k]) - cm.getRed(newpix[y0*m + x0+k])));  
  95.                             g = cm.getGreen(newpix[y0*m + x0+k]) + (int)(c*(cm.getGreen(newpix[y1*m + x0+k]) - cm.getGreen(newpix[y0*m + x0+k])));  
  96.                             b = cm.getBlue(newpix[y0*m + x0+k]) + (int)(c*(cm.getBlue(newpix[y1*m + x0+k]) - cm.getBlue(newpix[y0*m + x0+k])));  
  97.                             newpix[(y0+l)*m + x0 + k] = new Color(r,g,b).getRGB();   
  98.                             //System.out.println((int)(c*(cm.getRed(newpix[y1*m + x0+k]) - cm.getRed(newpix[y0*m + x0+k]))));  
  99.                         }                 
  100.                     }                     
  101.                     if(i==w-2 || l==d2-1) { //最后一列的计算  
  102.                         //f(1,y) = f(1,0) + c2*f(f(1,1)-f(1,0))  
  103.                         c = (float)l/d2;  
  104.                         r = cm.getRed(newpix[y0*m + x1]) + (int)(c*(cm.getRed(newpix[y1*m + x1]) - cm.getRed(newpix[y0*m + x1])));  
  105.                         g = cm.getGreen(newpix[y0*m + x1]) + (int)(c*(cm.getGreen(newpix[y1*m + x1]) - cm.getGreen(newpix[y0*m + x1])));  
  106.                         b = cm.getBlue(newpix[y0*m + x1]) + (int)(c*(cm.getBlue(newpix[y1*m + x1]) - cm.getBlue(newpix[y0*m + x1])));  
  107.                         newpix[(y0+l)*m + x1] = new Color(r,g,b).getRGB();   
  108.                     }  
  109.                 }  
  110.             }  
  111.         }  
  112.         /* 
  113.         for(int j=0; j<50; j++){ 
  114.             for(int i=0; i<50; i++) { 
  115.                 System.out.print(new Color(newpix[j*m + i]).getRed() + "\t");                
  116.             } 
  117.             System.out.println(); 
  118.         } 
  119.         */  
  120.         BufferedImage imgOut = new BufferedImage( m, n, imgType);  
  121.           
  122.         imgOut.setRGB(00, m, n, newpix, 0, m);          
  123.         return imgOut;  
  124.     }  

猜你喜欢

转载自blog.csdn.net/salonzhou/article/details/51911777
今日推荐