目錄
一、問題描述
我們在處理圖像的時候常常會遇到圖像放大的問題,那麼選擇什麼樣的圖像放大算法,能有什麼樣的效果,就是我們比較關心的問題了。最近(其實是很久以前),我根據網上大神們,關於雙線性內插算法的資料,總結了一個用於圖像縮放的算法的代碼,我把它總結在博客裏,希望能夠方便自己和大家隨時的使用。
二、算法原理
首先要介紹一下雙線性內插算法的基本原理,這部分轉載自 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哈哈~