图像插值——线性差值

理论基础

线性插值:两点确定一条直线,线上的未知点的值可由直线方程确定。
线性插值
在二维空间中,需要将线性差值拓展到双线性插值。
二维双线性插值
设A、B、C、D的像素值分别为A、B、C、D。
P1的像素值为 P 1 = 1 / r o w × ( ( r o w − a ) A + a B ) P1 = 1/row \times ((row-a)A + aB) P1=1/row×((rowa)A+aB)
P2的像素值为 P 2 = 1 / r o w × ( ( r o w − a ) C + a D ) P2 = 1/row \times ((row-a)C + aD) P2=1/row×((rowa)C+aD)
P的像素值为 P = 1 / c o l × ( ( c o l − b ) P 1 + b P 2 ) P = 1/col \times ((col-b)P1 + bP2) P=1/col×((colb)P1+bP2)
将P1、P2代入得
P = 1 c o l × r o w × [ ( r o w − a ) ( c l o − b ) A + a ( c o l − b ) B ) + a ( r o w − a ) C + a b D ] P = \frac{1}{col \times row} \times \left[ (row-a)(clo-b)A + a(col-b)B) + a(row-a)C + abD\right] P=col×row1×[(rowa)(clob)A+a(colb)B)+a(rowa)C+abD]
注:如果将P点投影到原图像进行插值,则row和col值为1、1。


编码实现(Python)

# coding=utf-8
import cv2
import numpy as np

def Bilinear(img, up_height, up_width, channels):
    bilinear_img = np.zeros(shape=(up_height, up_width, channels), dtype=np.uint8)
    img_height, img_width, img_channels = img.shape
    for i in range(up_height):
        for j in range(up_width):
            row_up = int(i * img_height/up_height) # 原图像左像素点
            col_left = int(j * img_width/up_width) # 原图像上像素点
            row_bottom = row_up + 1
            col_right = col_left + 1
            if row_bottom == img_height: 
                row_bottom -= 1 
            if col_right == img_width:
                col_right -= 1
            a =  j * img_width / up_width - col_left
            b = i * img_height / up_height - row_up
            # 这里定义bilinear_img已经强制了数据类型\
            bilinear_img[i][j] = (  \
                (1 - a) * (1 - b) * img[row_up][col_left] + \
                a * (1 - b) * img[row_up][col_right] + \
                (1 - a) * b * img[row_bottom][col_left] + \
                a * b * img[row_bottom][col_right] \
            )

    return bilinear_img

if __name__ == "__main__":
    # 无法处理透明度通道(压根就没读进来)
    img_source = cv2.imread(r"Image_restoration\source\1.png")
    img_height, img_width, img_channels = img_source.shape
    print("height {}, width {}, channels {}".format( img_height, img_width, img_channels))

    times = 3 # 放大3倍
    up_height = int(img_height * times)
    up_width = int(img_width * times)
    print("up_height {}, up_width {}".format(up_height, up_width))
    bilinear_img = Bilinear(img_source, up_height, up_width, img_channels)

    cv2.imshow("img_source", img_source)
    cv2.imshow("bilinear_img", bilinear_img)
    cv2.imwrite(r"Image_restoration\result\1_bilinear.png", bilinear_img)
    cv2.waitKey(0)
    cv2.destroyAllWindows()

效果展示

  1. 利用双线性插值将图像放大后,色块减少,但清晰效果依然十分有限。
    双线性插值

其他权重

双线性插值公式为P点附近四个点设计了一个权重。
我们也可以采用其他形式的权重。如:

  1. 高斯分布
    设距离为r,则利用高斯公式计算其权重为:
    ω ( r ) = e − ( ε r ) 2 \bf \omega(r) = e^{-(\varepsilon r)^2} ω(r)=e(εr)2
    注:因为要对权重进行归一化,所以这里直接舍去了将会被约去的系数。
    一维高斯分布
    在如下二维空间中。
    距离权重
    P点像素值为
    P = 1 ω ( a ) + ω ( b ) + ω ( c ) + ω ( d ) [ ω ( a ) × A + ω ( b ) × B + ω ( c ) × C + ω ( d ) × D ] P = \frac{1}{\omega(a)+\omega(b)+\omega(c)+\omega(d)}[\omega(a)\times A+\omega(b)\times B+\omega(c)\times C+\omega(d)\times D] P=ω(a)+ω(b)+ω(c)+ω(d)1[ω(a)×A+ω(b)×B+ω(c)×C+ω(d)×D]

博主做出来的效果一般般。
高斯分布权重

猜你喜欢

转载自blog.csdn.net/2201_75691823/article/details/129636579
今日推荐