數字圖像處理:圖像縮放和降低灰度級

打開、顯示、存儲圖片

用Python版OpenCV實現

image = cv2.imread("images/2_20_a.jpg", cv2.IMREAD_UNCHANGED)
cv2.imwrite("images/full.jpg", image, [int(cv2.IMWRITE_JPEG_QUALITY), 100])
cv2.imshow("image", image)
cv2.waitKey(0)

打開圖片後,可以看圖片由矩陣構成,shape顯示了圖片的行高和列寬,打開的是一幅灰度圖片,因此只有一個通道
在這裏插入圖片描述
顯示圖片:
在這裏插入圖片描述
保存:
在這裏插入圖片描述

未經壓縮,該圖片佔444 * 338 * 8bit = 444 * 338 B = 146.5KB
原圖在磁盤佔20.1KB
保存的圖片佔53.6KB

圖像縮放

最近領域插值

hh, ww, h0h_0, w0w_0 分別爲原圖高、寬,和目標高、寬
g(x,y)g(x, y)爲新圖像x行y列的灰度等級,f(x,y)f(x, y)爲原圖像
g(x,y)=f(xhh0,yww0)(1)g(x, y) = f(\frac{xh}{h_0}, \frac{yw}{w_0}) (1)
或從原圖像對應目標圖像
g(xh0h,yw0w)=f(x,y)(2) g(\frac{xh_0}{h}, \frac{yw_0}{w}) = f(x, y) (2)
在(1)式中,假如 hh0>1\frac{h}{h_0} > 1 縮小圖像
在(2)式中,若g(x, y)爲原圖像,f(x, y)爲新圖像,則 h0h<1\frac{h_0}{h} < 1 放大圖像
出現小數時,取整。

Python關鍵代碼:

def nearest(img, size):
   """
   Nearest neighbor interpolation
   :param img: source image
   :param size: (height, width)
   :return: destination image
   """
   re = np.zeros([size[0], size[1], 1], np.uint8)
   for x in range(size[0]):
       for y in range(size[1]):
           new_x = int(x * (img.shape[0] / size[0]))
           new_y = int(y * (img.shape[1] / size[1]))
           re[x, y] = img[new_x, new_y]
   return re

雙線性插值

對於一個目的像素,設置座標通過反向變換得到的浮點座標爲(i+u,j+v)(i+u,j+v) (其中i、j均爲浮點座標的整數部分,u、v爲浮點座標的小數部分,是取值[0,1)區間的浮點數),則這個像素得值 f(i+u,j+v)f(i+u,j+v) 可由原圖像中座標爲(i,j),(i+1,j),(i,j+1),(i+1,j+1)(i,j), (i+1,j), (i,j+1), (i+1,j+1)所對應的周圍四個像素的值決定,即:
g(x,y)=f(xhh0,yww0)=f(i+u,j+v)=(1u)(1v)f(i,j)+(1u)vf(i,j+1)+u(1v)f(i+1,j)+uvf(i+1,j+1) g(x, y) = f(\frac{xh}{h_0}, \frac{yw}{w_0}) = 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)

出現小數時考慮周圍情況,離哪個點進,那個點發揮的作用就更大。

Python關鍵代碼:

def bilinear(img, size):
   """
   Bilinear interpolation
   :param img: source image
   :param size: (height, width)
   :return: destination image
   """
   re = np.zeros([size[0], size[1], 1], np.uint8)
   for x in range(size[0]):
       for y in range(size[1]):
           new_x = x * (img.shape[0] / size[0])
           new_y = y * (img.shape[1] / size[1])
           i = int(new_x)
           j = int(new_y)
           u = new_x - i
           v = new_y - j
           if i + 1 >= img.shape[0]:
               i = img.shape[0] - 2
           if j + 1 >= img.shape[1]:
               j = img.shape[1] - 2
           # 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) 
           re[x, y] =  (1-u)*(1-v)*img[i, j]
            + (1-u)*v*img[i, j+1] 
            +  u*(1-v)*img[i+1, j] 
            +  u*v*img[i+1, j+1]
   return re

結果:

從左到右
圖一:原圖
圖二:用最近領域插值縮放0.5,再擴大2倍,恢復原圖大小
圖三:用雙線性插值縮放0.5,再擴大2倍,恢復原圖大小
圖四:OpenCV.resize縮放0.5,再擴大2倍,恢復原圖大小
在這裏插入圖片描述
縮放倍數爲0.2,再恢復原大小時
在這裏插入圖片描述
OpenCV的效過較好,雙線性插值其次,最近領域插值效果非常差。

降低灰度分辨率

下面函數先量化到level+1級,再量化至256級以顯示

def reduce_intensity_levels(img, level):
    img = cv2.copyTo(img, None)
    for x in range(img.shape[0]):
        for y in range(img.shape[1]):
            si = img[x, y]
            ni = int(level * si / 255 + 0.5) * (255 / level)
            img[x, y] = ni
    return img

8灰度級圖像
在這裏插入圖片描述
4灰度級圖像
在這裏插入圖片描述
出現假輪廓

2灰度級圖像(2值化 0~127置0 128~256置255)
在這裏插入圖片描述

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