圖像分辨率增強或者改變圖像大小

来源:互联网 发布:银行it人 编辑:程序博客网 时间:2024/06/14 07:57

http://blog.csdn.net/cxf7394373/article/details/5788040

 最近有一段時間做圖像處理方面的東西,遇到了一些樣張需要進行分辨率的增強或者說是放大圖像,如何在圖像不失真的情況下放大圖像呢?總的來說就是插值,插值包括零階插值、雙線性插值(Bilinear Interpolation)、立方卷積法(Bicubic Interpolation)等方法。

     我實驗了雙線性插值和雙三次插值,雙三次插值的計算量比較大,但是效果也相對較好。有一篇叫「數字圖像最佳插值算法研究」的中文論文中詳細介紹了這三種方法的理論,還做了簡單的比較。

     Bilinear Interpolation的公式很簡單,就是一個線性插值,f(i+u,j+ v)=(1-u)(1-v)f(i,j)+(1-u)vf(i,j+1) + u(1-v)f(i+1,j)+uvf(i+1,j+1),與(i,j)相鄰的四個像素點乘以權值的加和即為插值後的灰度值。

     Bicubic Interpolation相對比較復雜,公式如下:    

         f(x,y) = A*B*C,其中:

 

    由此可以計算插值像素點的灰度值。該插值方法的C#代碼如下:

[c-sharp] view plaincopy
  1. //把圖像放大兩倍  
  2.         private void resizeToolStripMenuItem_Click(object sender, EventArgs e)  
  3.         {  
  4.             Graphics dc = this.CreateGraphics();  
  5.             dc.DrawImage(picture, 10, 30, this.ClientSize.Width - 20, this.ClientSize.Height - 20);  
  6.             Color color;  
  7.             pic = new Bitmap(picture);  
  8.               
  9.             int i, j;  
  10.             int width = picture.Width;  
  11.             int height = picture.Height;  
  12.   
  13.             int newWidth = Convert.ToInt32(picture.Width * 2);  
  14.             int newHeight = Convert.ToInt32(picture.Height * 2);  
  15.             Bitmap newpic = new Bitmap(newWidth, newHeight);  
  16.             //int pixelSize =3;  
  17.             int pixelSize = 1;  
  18.             int srcStride = width-1;  
  19.   
  20.             int dstOffset = newWidth - pixelSize * newWidth;  
  21.   
  22.             double xFactor = (double)width / newWidth;  
  23.             double yFactor = (double)height / newHeight;  
  24.   
  25.   
  26.             // do the job  
  27.             byte[,] src = new byte[width, height]; //(byte*)sourceData.ImageData.ToPointer();  
  28.             byte[,] dst = new byte[newWidth, newHeight];//(byte*)destinationData.ImageData.ToPointer();  
  29.   
  30.             //double[,] pBuffer = new double[usW, usH];  
  31.             //double[,] pBuffer1 = new double[usW, usH];  
  32.             // coordinates of source points and coefficiens  
  33.             double ox, oy, dx, dy, k1, k2;  
  34.             int ox1, oy1, ox2, oy2;  
  35.             // destination pixel values  
  36.             double r, g, b;  
  37.             // width and height decreased by 1  
  38.             int ymax = height - 1;  
  39.             int xmax = width - 1;  
  40.             // temporary pointer  
  41.             //byte* p;  
  42.   
  43.             for (i = 0; i < width; i++)  
  44.             {  
  45.                 for (j = 0; j < height; j++)  
  46.                 {  
  47.                     color = pic.GetPixel(i, j);  
  48.                     src[i, j] =(byte)((color.R + color.G + color.B) / 3);  
  49.                 }  
  50.             }  
  51.   
  52.             for (int y = 0; y < newHeight; y++)  
  53.             {  
  54.                 // Y coordinates  
  55.                 oy = (double)y * yFactor - 0.5;  
  56.                 oy1 = (int)oy;  
  57.                 dy = oy - (double)oy1;  
  58.   
  59.                 for (int x = 0; x < newWidth; x++)  
  60.                 {  
  61.                     // X coordinates  
  62.                     ox = (double)x * xFactor - 0.5f;  
  63.                     ox1 = (int)ox;  
  64.                     dx = ox - (double)ox1;  
  65.   
  66.                     // initial pixel value  
  67.                     g = 0;  
  68.   
  69.                     for (int n = -1; n < 3; n++)  
  70.                     {  
  71.                         // get Y cooefficient  
  72.                         k1 = BiCubicKernel(dy - (double)n);  
  73.   
  74.                         oy2 = oy1 + n;  
  75.                         if (oy2 < 0)  
  76.                             oy2 = 0;  
  77.                         if (oy2 > ymax)  
  78.                             oy2 = ymax;  
  79.   
  80.                         for (int m = -1; m < 3; m++)  
  81.                         {  
  82.                             // get X cooefficient  
  83.                             k2 = k1 * BiCubicKernel((double)m - dx);  
  84.   
  85.                             ox2 = ox1 + m;  
  86.                             if (ox2 < 0)  
  87.                                 ox2 = 0;  
  88.                             if (ox2 > xmax)  
  89.                                 ox2 = xmax;  
  90.                         //    int tmp = oy2 * srcStride;  
  91.                             g += k2 * src[ox2, oy2];  
  92.                         }  
  93.                     }  
  94.                     dst[x,y] = (byte)g;  
  95.                 }  
  96.             }  
  97.   
  98.             int gray = 0;  
  99.             for (i = 0; i < newWidth; i++)  
  100.             {  
  101.                 for (j = 0; j < newHeight; j++)  
  102.                 {  
  103.                     gray = dst[i, j];  
  104.                     color = Color.FromArgb(gray, gray, gray);  
  105.   
  106.                     newpic.SetPixel(i, j, color);  
  107.                 }  
  108.             }  
  109.             //Show the processing result  
  110.             dc.DrawImage(newpic, 10, 30, this.ClientSize.Width - 20, this.ClientSize.Height - 20);  
  111.             image = new Bitmap(newpic);  
  112.             pic.Dispose();  
  113.         }  
  114.   
  115.         public  double BiCubicKernel(double x)  
  116.         {  
  117.             if (x > 2.0)  
  118.                 return 0.0;  
  119.   
  120.             double a, b, c, d;  
  121.             double xm1 = x - 1.0;  
  122.             double xp1 = x + 1.0;  
  123.             double xp2 = x + 2.0;  
  124.   
  125.             a = (xp2 <= 0.0) ? 0.0 : xp2 * xp2 * xp2;  
  126.             b = (xp1 <= 0.0) ? 0.0 : xp1 * xp1 * xp1;  
  127.             c = (x <= 0.0) ? 0.0 : x * x * x;  
  128.             d = (xm1 <= 0.0) ? 0.0 : xm1 * xm1 * xm1;  
  129.   
  130.             return (0.16666666666666666667 * (a - (4.0 * b) + (6.0 * c) - (4.0 * d)));  
  131.         }  

    大家不一定有耐心去看懂它,雙線性插值的方法也是這樣寫,只不過比這個要簡單!


原创粉丝点击