1. 程式人生 > >影象的放大與縮小(3)——雙立方插值演算法

影象的放大與縮小(3)——雙立方插值演算法

-----------------------------轉載自jia20003的部落格"

-----------------------------------

一:數學原理

如果已知一個函式f(x)以及它在x=0,x=1處的導數,那麼函式可以在[0,1]之間插值,當函式

表達為三次多項式時我們稱之謂立方插值。一個三次多項式及其導數:

        f(x) =ax^3 +bx^2 + cx + d

         f’(x)=3ax^2 + 2bx +c

多項式在x=0, x=1處值及其導數值為:

         f(0)= d;

         f(1)= a + b + c + d;

         f’(0)=c

         f’(1)=3a + 2b + c

上述的四個等式可以等價的變換為:

         a= 2f(0) – 2f(1) + f’(0) + f’(1)

         b= -3f(0) + 3f(1) – 2f’(0) – f’(1)

         c= f’(0)

         d= f’(1)

假設你有四個點值p0, p1, p2, p3分別在x=-1, x=0, x=1, x=2, 把值分別指定到f(0), f(1), f’(0),

f’(1)中為:

         f(0)= p1

         f(1)= p2

         f’(0)= (p2 – p0)/2

         f’(1)= (p3-p1)/2

這個我們的立方插值公式變成:

f(p0,p1,p2,p3, x) = (-1/2p0 + 3/2p1 -3/2p2+ 1/2p3)x^3 + (p0-5/2p1 + 2p2 -1/2d)x^2 + (-1/2p0 +

1/2p2)x + p1

雙立方插值是立方插值在二維空間的表達, 插值公式可以表述為:

G(x, y) = f (f (p00, p01, p02, p03, y), f(p10,p11, p12, p13, y), f(p20, p21, p22, p23, y), f(p30, p31, p32, p33, y), x)

解出其中的16個引數,即可得帶G(x, y)目標插值點的值。

二:雙立方插值優缺點

雙立方插值在影象放大過程可以保留更多的影象細節,放大以後的影象帶有反鋸齒的功能,

同時影象和源影象相比效果更加真實, 缺點是計算量比較大,是常見的三種影象放大演算法中

計算量最大的一種,據說Photoshop的影象放大就是基本雙立方插值的優化演算法

三:程式執行效果如下:


四:關鍵程式碼解析

不想解釋太多,最重要的是代入計算的是浮點數座標的小數部分,即 x, y的取值範圍均在[0,1]之間

五:基於Java的程式完全原始碼

  1. package cn.edu.jxau.luoweifu;  
  2. publicclass BiCubicInterpolationScale {  
  3.     privatestaticdouble a00, a01, a02, a03;  
  4.     privatestaticdouble a10, a11, a12, a13;  
  5.     privatestaticdouble a20, a21, a22, a23;  
  6.     privatestaticdouble a30, a31, a32, a33;  
  7.     privatestaticint srcWidth;  
  8.     privatestaticint srcHeight;  
  9.     /** 
  10.      * 雙立方插值 
  11.      * @param inPixelsData 畫素矩陣陣列 
  12.      * @param srcW 原影象的寬 
  13.      * @param srcH 原影象的高 
  14.      * @param destW 目標影象的寬 
  15.      * @param destH 目標影象的高 
  16.      * @return 處理後的推三矩陣陣列 
  17.      */
  18.     publicstaticint[] imgScale(int[] inPixelsData, int srcW, int srcH, int destW, int destH) {  
  19.         double[][][] input3DData = processOneToThreeDeminsion(inPixelsData, srcH, srcW);  
  20.         int[][][] outputThreeDeminsionData = newint[destH][destW][4];  
  21.         double[][] tempPixels = newdouble[4][4];  
  22.         float rowRatio = ((float)srcH)/((float)destH);  
  23.         float colRatio = ((float)srcW)/((float)destW);  
  24.         srcWidth = srcW;  
  25.         srcHeight = srcH;  
  26.         for(int row=0; row<destH; row++) {  
  27.             // convert to three dimension data
  28.             double srcRow = ((float)row)*rowRatio;  
  29.             double j = Math.floor(srcRow);  
  30.             double t = srcRow - j;  
  31.             for(int col=0; col<destW; col++) {  
  32.                 double srcCol = ((float)col)*colRatio;  
  33.                 double k = Math.floor(srcCol);  
  34.                 double u = srcCol - k;  
  35.                 for(int i=0; i<4; i++) {  
  36.                     tempPixels[0][0] = getRGBValue(input3DData,j-1, k-1,i);  
  37.                     tempPixels[0][1] = getRGBValue(input3DData,j-1, k, i);  
  38.                     tempPixels[0][2] = getRGBValue(input3DData, j-1,k+1, i);  
  39.                     tempPixels[0][3] = getRGBValue(input3DData, j-1, k+2,i);  
  40.                     tempPixels[1][0] = getRGBValue(input3DData, j, k-1, i);  
  41.                     tempPixels[1][1] = getRGBValue(input3DData, j, k, i);  
  42.                     tempPixels[1][2] = getRGBValue(input3DData, j, k+1, i);  
  43.                     tempPixels[1][3] = getRGBValue(input3DData, j, k+2, i);  
  44.                     tempPixels[2][0] = getRGBValue(input3DData, j+1,k-1,i);  
  45.                     tempPixels[2][1] = getRGBValue(input3DData, j+1, k, i);  
  46.                     tempPixels[2][2] = getRGBValue(input3DData, j+1, k+1, i);  
  47.                     tempPixels[2][3] = getRGBValue(input3DData, j+1, k+2, i);  
  48.                     tempPixels[3][0] = getRGBValue(input3DData, j+2, k-1, i);  
  49.                     tempPixels[3][1] = getRGBValue(input3DData, j+2, k, i);  
  50.                     tempPixels[3][2] = getRGBValue(input3DData, j+2, k+1, i);  
  51.                     tempPixels[3][3] = getRGBValue(input3DData, j+2, k+2, i);  
  52.                     // update coefficients
  53.                     updateCoefficients(tempPixels);  
  54.                     outputThreeDeminsionData[row][col][i] = getPixelValue(getValue(t, u));  
  55.                 }  
  56.             }  
  57.         }  
  58.         return convertToOneDim(outputThreeDeminsionData, destW, destH);  
  59.     }  
  60.     privatestaticdouble getRGBValue(double[][][] input3DData, double row, double col, int index) {  
  61.         if(col >= srcWidth) {  
  62.             col = srcWidth - 1;  
  63.         }  
  64.         if(col < 0) {  
  65. 相關推薦

    影象放大縮小(3)——立方演算法

    -----------------------------轉載自jia20003的部落格" ----------------------------------- 一:數學原理 如果已知一個函式f(x)以及它在x=0,x=1處的導數,那麼

    影象放大縮小(2)——線性放大均值縮小

    概述 基於上一節“等距取樣法”實現圖片放大與縮小的缺點。要對其進行改進,對影象的縮小則可以用“區域性均值法”,對於影象的放大則可以用“雙線性插值法”。 效果如下:                           2048*1536縮小為10

    C/C++ BMP(24位真彩色)影象處理(3)------影象放大縮小線性

        影象的放大縮小其實是一回事,都是先建立一張空白目標影象(放大縮小後的影象),其大小就是想要放大縮小後所得到的影象大小。建立影象後我們並不知道這張影象裡面的各個畫素點RGB(或灰度)值是多少,這個時候就需要經過一個演算法去算目標影象的畫素點RGB(或灰度)值。基本上所

    圖像處理之三種常見立方算法

    log views 實現 ack oar 過程 線表 const filter http://blog.csdn.net/jia20003/article/details/40020775 圖像處理之三種常見雙立方插值算法 雙立方插值計算涉及到16個像素點,其中(i’, j

    影象縮放——線性演算法

    在數學上,雙線性插值是有兩個變數的插值函式的線性插值擴充套件,其核心思想是在兩個方向分別進行一次線性插值。如果選擇一個座標系統使得  的四個已知點座標分別為 (0, 0)、(0, 1)、(1, 0) 和 (1, 1),那麼插值公式就可以化簡為: 用矩陣運算來表示的話就

    影象處理中兩種基本的演算法(最鄰近法和線性內法)

    在影象的基本仿射變換中,經常會碰到經過旋轉、縮放後灰度值如何賦值的問題。因為變換之後,影象的座標位置有可能是小數,所以就需要插值演算法來確定到底將該畫素賦予哪個位置。 1、最鄰近插值法(Nearest Interpolation) 這是最簡單的一種插值方法,不需要計算。在待

    線性演算法進行影象縮放及效能效果優化

    一)轉自http://handspeaker.iteye.com/blog/1545126 最近在程式設計時用到了雙線性插值演算法,對影象進行縮放。網上有很多這方面的資料,介紹的也算明白。但是,這些文章只介紹了演算法,並沒有具體說怎麼實現以及怎麼實現最好,舉個例子,你可以按照網上文章的演算法自己寫一個雙線性

    Image Resize 線性和立方

    I.影象處理-雙線性插值(轉載) 影象的縮放很好理解,就是影象的放大和縮小。傳統的繪畫工具中,有一種叫做“放大尺”的繪畫工具,畫家常用它來放大圖畫。當然,在計算機上,我們不再需要用放大尺去放大或縮小影象了,把這個工作交給程式來完成就可以了。下面就來講講計算機怎麼來放大縮小圖象;在本文中,我們所說

    opencv 學習--- 線性演算法原理簡述

    ***好記性不如爛筆頭*** 轉自: https://www.cnblogs.com/yssongest/p/5303151.html 1,原理   在影象的仿射變換中,很多地方需要用到插值運算,常見的插值運算包括最鄰近插值,雙線性插值,雙三次插值,蘭索思插值等方法,Op

    線性演算法的詳細總結

           最近在做視訊拼接的專案,裡面用到了影象的單應性矩陣變換,在最後的影象重對映,由於目標影象的座標是非整數的,所以需要用到插值的方法,用的就是雙線性插值,下面的博文主要是查看了前輩的部落格對雙線性插值演算法原理進行了一個總結,在這裡也感謝一些大牛的博文。

    線性演算法詳解並用matlab實現

    雙線性插值演算法 介紹 雙線性插值法又稱為二次線性插值法。在傳統的插值演算法中,它的插值效果比nearest插值法要好的多,但是速度上也必然會慢很多,比bicubic(二次立方法)效果要差, 但速度上要優於bicubic。 它主要思想就是利用某

    c語言數字影象處理(二):圖片放大縮小-線性內

    int is_in_array(short x, short y, short height, short width) { if (x >= 0 && x < width && y >= 0 && y < height)

    影象-線性三次

    在現實生活中,我們經常會遇到把影象進行放大、幾何空間變換的情況等等,這些操作都需要在源影象和目標影象之間建立一個對映規則,使得兩影象畫素座標之間建立起一種對應關係,從而為目標影象的每一個畫素賦值。 從源影象到目標影象的對映叫前向對映,但是這種對映方法可能會出現這樣的兩個問題

    自定義ImageView: 實現自由縮放 ,自由移動縮放後的圖片 .放大縮小圖片 相容ViewPager

    直接擼程式碼, 複製就能用 package com.zhf.baselibrary.view; import android.annotation.SuppressLint; import android.content.Context; import android.graphi

    影象放大縮小

    實現效果:    知識運用:   PictureBox控制元件的Height和Width屬性   和PictureBox控制元件的SizeMode屬性  //PictureBoxSizeMode列舉值    實現程式碼: private void trackBar1_Scr

    線性影象縮放演算法的研究實現

    Opencv學堂 http://mp.weixin.qq.com/s?__biz=MzA4MDExMDEyMw==&mid=100000109&idx=1&sn=7540b49e869c3e27f87c84f6f3dfe9a8&chksm

    【短道速滑一】OpenCV中cvResize函式使用線性縮小影象到長寬大小一半時速度飛快(比最近鄰還快)之異象解析和自我實現。

      今天,一個朋友想使用我的SSE優化Demo裡的雙線性插值演算法,他已經在專案裡使用了OpenCV,因此,我就建議他直接使用OpenCV,朋友的程式非常注意效率和實時性(因為是處理視訊),因此希望我能測試下我的速度和OpenCV相比到底那一個更有速度優勢,恰好前一段時間也有朋友有這方面的需求,因此我就隨意編

    1.5 Illustrator視圖的放大縮小

    illustrator 本節課將為您演示,如何通過放大畫面的顯示比例,以清晰查看畫面的細節,和縮小畫面比例,以查看整體的畫面效果。依次點擊[視圖 > 放大]命令。 每執行一次[放大]命令,畫面就會按照一定的比例放大顯示。 依次點擊[視圖 > 縮小]命令。 每執行一次[縮小]命令,

    影象演算法的基礎知識(線性,協方差矩陣,矩陣的特徵值、特徵向量)

    0. 前言 MATLAB或者OpenCV裡有很多封裝好的函式,我們可以使用一行程式碼直接呼叫並得到處理結果。然而當問到具體是怎麼實現的時候,卻總是一臉懵逼,答不上來。前兩天參加一個演算法工程師的筆試題,其中就考到了這幾點,感到非常汗顏!趕緊補習! 1. 雙線性插值 在影象處

    線性影象縮放問題

           初次開始寫部落格,想記錄下自己在公司實習所做過的事情以及學習到的東西,雖然還是有很多東西不瞭解也還沒做出來,但是也希望這是一種體驗。        我於2018.9.3入職進行實習,到現在也快過去兩個月了,我在公司