基于圖像元數(shù)據的旋轉及縮放

前言


當我們在相機預覽時,需要對視頻流buffer進行旋轉及縮放時,往往是將buffer轉換成image再進行旋轉及縮放操作,然后轉回視頻流buffer,這樣一次圖像處理的操作消耗了太多性能,如果引入opencv,又會使得項目變大變重,這種情況下,我們可以直接操作圖像元數(shù)據,這樣更便捷,性能相對來說也有提升。

圖像處理方案


圖像數(shù)據基本屬性


像素點:組成圖像的基本元素,圖像包含的像素越多,圖像越大

色彩空間:描述像素點顏色的色彩集,相同的RGB值對應不同的色彩空間,所展示的顏色可能不一樣

通道數(shù):像素點對應色彩通道(RGB三通道,RGBA四通道)

位圖信息:像素點中通道排列順序

位深度:一個像素所用的位數(shù)

進行圖像旋轉及縮放暫時只需要了解以上圖像屬性即可


圖像旋轉及縮放


圖像旋轉及縮放的實際上就是像素點的處理,想要得到處理后圖像中每個像素點的顏色值,我們需要在原圖像中找到對應的像素點,經過處理后,賦值到新圖像中。所以圖像旋轉及縮放本質上就是一個找像素點的過程。

映射像素點


圖像旋轉


以向左旋轉為例,推導圖像左旋轉的公式??

圖像左旋轉

像素點映射關系(這里只列出圖像中有顏色的色塊):

圖像左旋轉像素點映射關系

從像素點的映射關系可以得出目標像素點坐標與原始圖像坐標之間的映射公式:

dst(x,y)=org(orgW-y-1, x)

另外附上右旋轉,180°旋轉,鏡像的公式,具體推理過程可以參考上面的方法自己進行推理

右旋轉:

dst(x,y)=org(y, orgH-x-1)

180°旋轉:

dst(x,y)=org(orgH-x-1, orgW-y-1)

水平鏡像:

dst(x,y)=org(orgW-x-1, y)

垂直鏡像:

dst(x,y)=org(x, orgH-y-1)


圖像縮放


以圖像放大為例,我們將一張2*2的圖像放大到4*4,如下圖所示:

圖像縮放

先計算縮放比,目標圖像的坐標除以縮放比就可以得到對應的原始圖像的坐標

scaleW=\frac{dstW}{orgW}

scaleH=\frac{dstH}{orgH}

dst(x,y)=org(\frac{x}{scaleW},\frac{y}{scaleH})

通過公式,得出2*2映射到4*4圖像的像素點映射關系(這里只列出圖像中有顏色的色塊):

圖像縮放映射關系

可以發(fā)現(xiàn)映射到原始圖像的坐標點中包含很多小數(shù)點坐標,無法具體到某個像素點取值,所以在這里就需要進行算法運算,以求出目標像素點的最佳取值。

目前圖像縮放算法已經比較成熟,較為常用的有三種縮放算法:

1.最鄰近插值法:

最鄰近插值法通常是直接將小數(shù)點后的數(shù)值舍去,直接取整:

x=floorf(x)

使用floor函數(shù)可以對float值進行取整,取整之后的對應結果:

最鄰近插值法

優(yōu)缺點:最鄰近插值非常簡單,但得到的圖像質量較差,進行縮放的比例較大時會產生較為明顯的鋸齒。

2.雙線性插值法:

雙線性插值法是根據映射像素點周圍4個像素點的綜合求值得出來的。

假設我們的映射的像素點坐標為P0(1.3,1.7)。

這時候四周的像素點就是P1(1,1),P2(1,2),P3(2,1),P4(2,2)。

以P0到P1,P2,P3,P4的距離為權重關系,計算4個像素點的綜合像素值,得到P0的像素值。

雙線性插值法

看到這張圖,有木有想起初中老師經常出的一道題,求陰影部分面積!

映射像素點坐標用org(i+v,j+u)表示

其中i、j代表整數(shù)部分,v、u代表小數(shù)部分

org(i+v,j+u)=org(i,j)*(1-v)*(1-u)+org(i+1,j)*v*(1-u)+org(i,j+1)*(1-v)*u+org(i+1,j+1)*v*u

了解卷積的朋友看著這個式子是不是有點眼熟,這個式子可以用卷積公式來表達:

org(i+v,j+u)=\sum_{row=0}^1\sum_{col=0}^1f(i+row,j+col)S(row-v)S(col-u)

其中函數(shù)表達式的值為:

f(i+row,j+col)=org(i+row,j+col)

S(row-v)=S(col-u)=S(x)=1-|x|

通過卷積公式,我們可以認為org(i+v,j+u)為周圍4個像素的卷積和。

優(yōu)缺點:雙線性內插值法計算量較大,縮放后圖像質量相對較高,不會出現(xiàn)像素值不連續(xù)的的情況。

3.三次卷積法(雙立方差值算法)

三次卷積法是根據映射像素點周圍16個像素點的綜合求值得出來的。

映射像素點坐標用org(i+v,j+u)表示

其中i、j代表整數(shù)部分,v、u代表小數(shù)部分

運算所涉及到的像素點如下圖:

三次卷積法

org(i+v,j+u)為以上16個點卷積之和

我們已經通過雙線性插值推導出圖像縮放的卷積公式,只是設計的像素點數(shù)量不一樣,我們將16個像素點帶入到卷積公式:

org(i+v,j+u)=\sum_{row=-1}^2\sum_{col=-1}^2f(i+row,j+col)S(row-v)S(col-u)

在雙線性差之中,決定相關像素點的權重函數(shù)S(x)在16像素點的卷積中已經不適用了,這里使用Bicubic interpolation中三次卷積的權重公式:

三次卷積權重公式

這個公式有3個特別重要的特點:

1)S(0) = 1

2)當n為整數(shù)時,S(n) = 0

3)當x超出范圍時,S(x)為0

這里依照Cubic Hermite spline,a取值-0.5

a=-0.5
Cubic Hermite spline曲線

S(x)=S(row-v)=S(col-u)

-2<x<-11<x<2時,S(x)函數(shù)取值為正

-1<x<1時,S(x)函數(shù)取值為負

我們嘗試幾個特殊值:

當u=0,v=0時,S(x)函數(shù)在16個像素點中的權重表現(xiàn):

第一行和第一列為對應行和列的權重系數(shù),我們可以看到,只有在org(i,j)時系數(shù)為1,當u,v為0時,我們映射像素點就是org(i,j)

當u,v等于0時

當u=0,v=0.5時,S(x)函數(shù)在16個像素點中的權重表現(xiàn):

當u=0時,只有col=0那一列參與了像素值計算,

u=0,v=0.5時的權重表現(xiàn)

當u=0.2,v=0.7時,S(x)函數(shù)在16個像素點中的權重表現(xiàn):

當u,v都不為0時,16個像素點全都參與計算,權重表現(xiàn)如下,至于為什么中間及四個角的權重為正,側邊為負,我也還沒想明白,不知道是不是因為人的視覺原因才這么去計算的,如果有知道的朋友可以告知下。

u=0.2,v=0.7時的權重表現(xiàn)

優(yōu)缺點:三次卷積法能計算量比較大,縮放后的圖像質量很高,是三種算法中效果最好的。

實際測試效果


基于iOS實現(xiàn)了下這套原理,將一張180*180的圖片放大到480*480

最鄰近插值法
雙線性插值法
三次卷積法

可以明顯看到使用最鄰近插值法縮放的圖片鋸齒感明顯,使用雙線性插值法后,平滑感明顯提升,三次卷積法縮放的圖片的圖片在平滑感上略有提升,圖片層次更好。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

友情鏈接更多精彩內容