雙線性內插法--圖像縮放算法

目錄

一、問題描述

二、算法原理

雙線性內插法

雙線性內插法參數計算

三、算法效果

四、算法代碼


一、問題描述

我們在處理圖像的時候常常會遇到圖像放大的問題,那麼選擇什麼樣的圖像放大算法,能有什麼樣的效果,就是我們比較關心的問題了。最近(其實是很久以前),我根據網上大神們,關於雙線性內插算法的資料,總結了一個用於圖像縮放的算法的代碼,我把它總結在博客裏,希望能夠方便自己和大家隨時的使用。

二、算法原理

首先要介紹一下雙線性內插算法的基本原理,這部分轉載自 GoldBeetle 大佬的博客

https://www.cnblogs.com/GoldBeetle/archive/2018/09/17/9662871.html

 

雙線性內插法

v(x,y) = ax + by + cxy + d

雙線性內插法參數計算

已知Q11, Q12, Q21, Q22,要插值的點爲P點,首先在x軸上,對R1,R2兩個點進行插值

然後根據R1和R2對P點進行插值

化簡得

             

對於邊界值的處理,若x1 < 0 ,則直接令f(Q11), f(Q12) = 0

 

 

 

三、算法效果

這個算法期初被我用在了Qt的圖像處理中,後來被我移植到了ESP8266的LCD屏幕驅動中,還是比較好用的,下面我先展示一下再Qt中放大的效果。

 

基於此算法,我爲了方便只使用了灰度值進行數據處理,效果就是如圖所示,當然也可以分爲多個通道處理彩色圖像。

後來我又修改此算法處理二值圖像,用在ESP8266中作爲文字的放大函數,使用小字庫就可以在LCD屏幕上顯示任意大的字體,也是非常方便的,節省了超大字體的字符所佔用的空間。

四、算法代碼

接下來我將代碼展示一下,

輸入參數分別是 輸入圖像的數組指針,輸入圖像的大小,輸出圖像指針,輸出圖像大小。

int offset_x=0,offset_y=0;

#define gray_to_RGB(gray) qRgb(gray,gray,gray)
void Bilinear(uint8_t* inpBmpBuf, int src_x,int src_y,uint8_t* outpBmpBuf,int dstWidth,int dstHeight)
{
    double lx=1,ly=1;//縮小倍數
    if(src_x/dstWidth>1) {lx=src_x/(double)dstWidth;} 
    else{lx=src_x/(double)dstWidth;}

    if(src_y/dstHeight>1){ly=src_y/(double)dstHeight;}
    else{ly=src_y/(double)dstHeight;}

    int x1, x2, y1, y2, Fq11, Fq12, Fq21, Fq22;
        double x, y, r1, Fr1, Fr2, Fp;
        for (int i = 0; i < dstHeight; ++i){
            for (int j = 0; j < dstWidth; ++j){
                x = lx*j; // 原圖像座標
                y = ly*i;
                // 四個座標值
                x1 = floor(x); x2 = x1 + 1;// 取整ceil向上,floor向下
                y1 = floor(y); y2 = y1 + 1;
                // 四個座標對應的灰度值
                Fq11 = inpBmpBuf[x1*src_y+y1] ;
                Fq12 = inpBmpBuf[x1*src_y+y2];
                Fq21 = inpBmpBuf[x2*src_y+y1];
                Fq22 = inpBmpBuf[x2*src_y+y2];
                // x方向插值和y方向插值
                Fr1 = 0; Fr2 = 0;

                Fr1 = (x2 - x) / (x2 - x1)*Fq11 + (x - x1) / (x2 - x1)*Fq21;
                Fr2 = (x2 - x) / (x2 - x1)*Fq12 + (x - x1) / (x2 - x1)*Fq22;
                Fp = (y2 - y) / (y2 - y1)*Fr1 + (y - y1) / (y2 - y1)*Fr2;
                // 新圖像灰度值賦值
                if (Fp >= 0 && Fp <= 255){
                    outpBmpBuf[i+j*dstHeight]=round(Fp); // 新圖像
                }
            }
        }

        //將計算得到的像素值放入圖像畫布
        for(int i=0;i<dstWidth && i<Show_image.size().width();i++)
        {
            for(int j=0;j<dstHeight && j<Show_image.size().height();j++)
            {
                Show_image.setPixel(i,j,gray_to_RGB(outpBmpBuf[(i+offset_x)*dstHeight+(j+offset_y)]));
            }
        }

}

今天的總結就到這裏啦,歡迎大家給我點贊關注、與我交流討論呀。O(∩_∩)O哈哈~

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章