Image interpolation - linear difference

Theoretical basis

Linear interpolation: Two points determine a straight line, and the values ​​of unknown points on the line can be determined by the equation of the straight line.
linear interpolation
In two-dimensional space, linear difference needs to be extended to bilinear interpolation.
Two-dimensional bilinear interpolation
Let the pixel values ​​of A, B, C, and D be A, B, C, and D respectively.
The pixel value of P1 is P 1 = 1 / row × ( ( row − a ) A + a B ) P1 = 1/row \times ((row-a)A + aB)P1 _=1/row×((rowa)A+a B )
The pixel value of P2 isP 2 = 1 / row × ( ( row − a ) C + a D ) P2 = 1/row \times ((row-a)C + aD)P2 _=1/row×((rowa)C+a D )
The pixel value of P isP = 1 / col × ( ( col − 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+ab D ]
Note: If point P is projected to the original image for interpolation, the row and col values ​​are 1 and 1.


Coding implementation (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()

Show results

  1. After enlarging the image using bilinear interpolation, the color blocks are reduced, but the clarity effect is still very limited.
    bilinear interpolation

Other weights

The bilinear interpolation formula designs a weight for the four points near point P.
We can also use other forms of weighting. like:

  1. Gaussian distribution
    If the distance is r, then use Gaussian formula to calculate its weight:
    ω ( r ) = e − ( ε r ) 2 \bf \omega(r) = e^{-(\varepsilon r)^2}ω ( r )=e(εr)2
    Note: Because the weights need to be normalized, the coefficients that will be omitted are directly discarded here.
    One-dimensional Gaussian distribution
    In the following two-dimensional space.
    distance weight
    The pixel value of point P is
    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=o ( a )+o ( b )+o ( c )+o ( d )1[ o ( a )×A+o ( b )×B+o ( c )×C+o ( d )×D]

The effect produced by the blogger is average.
Gaussian distribution weight

Guess you like

Origin blog.csdn.net/2201_75691823/article/details/129636579