最近在查找有關圖像縮放之類的算法,因工做中須要用到諸如此類的圖像處理算法就在網上了解了一下相關算法,以及其原理,並用Python實現,且親自驗證過,在次與你們分享。python
聲明:本文代碼示例針對的是planar格式的YUV數據,且只對Y份量作了縮放,由於日常工做中接觸較多的是YUV格式的黑白圖片,UV份量都是固定的0x80,因此針對UV份量沒有作縮放操做。算法
先大概講一下圖像所方的原理,假設縮放以前的圖像爲src_img,分辨率爲src_w*src_h,縮放以後的圖像爲dst_img,分辨率爲dst_w*dst_h,那麼咱們能夠利用縮放先後圖像分辨率的比率來找兩幅圖像中像素點的對應關係,以及像素點值的對應關係。如src_im中的點S(x,y)通過縮放以後變成了dst_img中的點D(x',y'),那麼點S到點D的映射存在這麼一種關係:x / src_w = x' / dst_w; y / src_h = y' / dst_h。利用上述公式咱們就能夠獲得,dst_img中全部點對應到src_img中的那個點,咱們再去把這個點的像素值賦給dst_img中對應的點。這是鄰近插值縮放算法最基本的思想,可是咱們會發現有時候算出的座標是個小數如(0.6,0.25)等等,那麼這個點對應src_img中那個點呢?若是採起簡單的四捨五入的話,那麼這個點應該對應src_img中的點(1,0),這種四捨五入近似的插值算法,在圖像放大後圖像嚴重失真,容易造成嚴重的馬賽克,那麼虛擬點(0.6,0.25)像素值到底該怎麼取值呢?最鄰近雙線性而插值算法認爲,應該有點(0.6,0.25)周圍四個點(0,0),(0,1),(1,0),(1,1)的像素值共同決定,那麼到底是怎麼一種決定方式呢?很簡單,按距離來分配權重,離得越近的點的像素值的權重天然要越大。公式以下:app
f(i+u,j+v) = (1-u)*(1-v)*f(i,j) + (1-u)*v*f(i,j+1) + u*(1-v)*f(i+1,j) + u*v*f(i+1,j+1)函數
關於最鄰近雙線插值算法的原理,網上有不少詳細的解釋和推導,在此我也再也不詳細贅述了,直接上python的實現代碼:oop
最近在工做中碰到了,本身的寫的雙線性縮放函數出來的結果和opencv resize函數出來的像素點的值不同,在網上查了一下緣由,是由於我選取的座標頂點是圖像的左上角(0,0)的位置,這樣也能獲得正確的縮放圖像,可是質量不高,由於最右邊和最下邊幾乎沒有參與計算,因此opencv中選取了幾何中心重合的方式去計算,具體能夠再往上搜一下,先講算法修 1 """ 2 @description:this module will use two classic way to scaling img.Read a img from a file and scale it to dst s 3this
4 @author:GWB 5 6 @version:v0.0.0 7 """ 8 import os 9 import binascii 10 def get_min(a,b): 11 if a > b: 12 return b 13 else: 14 return a 15 16 def get_max(a,b): 17 if a > b: 18 return a 19 else: 20 return b 21 22 def read_img_from_bin_file(in_filename,list_data): 23 with open(in_filename,'rb') as fd: #open file 24 fd.seek(0,0) #relocate fd 25 while True: #while loop 26 t_byte = fd.read(1) #read one byte 27 if len(t_byte) == 0: #if reach the end of the file then break 28 break 29 else: #store the the t_byte into hex format 30 list_data.append(ord(t_byte)) 31 fd.close() 32 33 def img_scale_fuc(in_list_data,srcW,srcH,dstW,dstH,out_list_data): 34 rateW = (srcW*1.0 / dstW) 35 rateH = (srcH*1.0 / dstH) 36 data = 0 37 for i in range(0,dstH):
38 temp = rateH * (i + 0.5) -0.5
y0 = int(temp)
u = temp - y0
y0 = get_max(0,get_min(y0,dstH - 2))
39 y1 = get_min((y0 + 1),(srcH - 1)) 40 for j in range(0,dstW):
temp = rateW * (j + 0.5) - 0.5 42 x0 = int(temp)
v = temp - x0
x0 = get_max(0,get_min(x0,srcW - 2)) 43 x1 = get_min((x0 + 1),(srcW - 1)) 45 w0 = ((1 - u)*(1 - v)) 46 w1 = ((1 - u)*v) 47 w2 = (u*(1 - v)) 48 w3 = (u*v) 49 p0 = in_list_data[y0*srcW + x0] 50 p1 = in_list_data[y1*srcW + x0] 51 p2 = in_list_data[y0*srcW + x1] 52 p3 = in_list_data[y1*srcW + x1] 53 #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) 54 data = int(w0*p0+w1*p1+w2*p2+w3*p3) 55 out_list_data.append('%.2X' % data) 56 57 def write_data_to_text(out_filename,out_list_data): 58 with open(out_filename,'wb') as fd: 59 fd.seek(0,0) 60 for data in out_list_data: 61 fd.write(binascii.a2b_hex(data)) 62 fd.close() 63 64 list_data = [] 65 out_list_data = [] 66 67 in_filename = raw_input("Please input src file name:\n") 68 out_filename = raw_input("Please input dst file name:\n") 69 srcH = input("Please input srcH:\n") 70 srcW = input("Please input srcW:\n") 71 dstH = input("Please input dstH:\n") 72 dstW = input("Please input dstW:\n") 73 74 read_img_from_bin_file(in_filename,list_data) 75 img_scale_fuc(list_data,srcW,srcH,dstW,dstH,out_list_data) 76 write_data_to_text(out_filename,out_list_data)