diff --git a/bicubic.py b/bicubic.py index 7c11806..4a3426f 100644 --- a/bicubic.py +++ b/bicubic.py @@ -1,97 +1,102 @@ import cv2 import numpy as np import math -import sys, time +import sys +import time + # Interpolation kernel -def u(s,a): - if (abs(s) >=0) & (abs(s) <=1): - return (a+2)*(abs(s)**3)-(a+3)*(abs(s)**2)+1 - elif (abs(s) > 1) & (abs(s) <= 2): - return a*(abs(s)**3)-(5*a)*(abs(s)**2)+(8*a)*abs(s)-4*a +def u(s, a): + abs_s = abs(s) + if 0 <= abs_s <= 1: + return (a + 2) * (abs_s ** 3) - (a + 3) * (abs_s ** 2) + 1 + elif 1 < abs_s <= 2: + return a * (abs_s ** 3) - (5 * a) * (abs_s ** 2) + (8 * a) * abs_s - 4 * a return 0 -#Paddnig -def padding(img,H,W,C): - zimg = np.zeros((H+4,W+4,C)) - zimg[2:H+2,2:W+2,:C] = img - #Pad the first/last two col and row - zimg[2:H+2,0:2,:C]=img[:,0:1,:C] - zimg[H+2:H+4,2:W+2,:]=img[H-1:H,:,:] - zimg[2:H+2,W+2:W+4,:]=img[:,W-1:W,:] - zimg[0:2,2:W+2,:C]=img[0:1,:,:C] - #Pad the missing eight points - zimg[0:2,0:2,:C]=img[0,0,:C] - zimg[H+2:H+4,0:2,:C]=img[H-1,0,:C] - zimg[H+2:H+4,W+2:W+4,:C]=img[H-1,W-1,:C] - zimg[0:2,W+2:W+4,:C]=img[0,W-1,:C] + +# Paddnig +def padding(img, H, W, C): + zimg = np.zeros((H + 4, W + 4, C)) + zimg[2:H + 2, 2:W + 2, :C] = img + # Pad the first/last two col and row + zimg[2:H + 2, 0:2, :C] = img[:, 0:1, :C] + zimg[H + 2:H + 4, 2:W + 2, :] = img[H - 1:H, :, :] + zimg[2:H + 2, W + 2:W + 4, :] = img[:, W - 1:W, :] + zimg[0:2, 2:W + 2, :C] = img[0:1, :, :C] + # Pad the missing eight points + zimg[0:2, 0:2, :C] = img[0, 0, :C] + zimg[H + 2:H + 4, 0:2, :C] = img[H - 1, 0, :C] + zimg[H + 2:H + 4, W + 2:W + 4, :C] = img[H - 1, W - 1, :C] + zimg[0:2, W + 2:W + 4, :C] = img[0, W - 1, :C] return zimg + # https://github.com/yunabe/codelab/blob/master/misc/terminal_progressbar/progress.py -def get_progressbar_str(progress): - END = 170 - MAX_LEN = 30 - BAR_LEN = int(MAX_LEN * progress) - return ('Progress:[' + '=' * BAR_LEN + - ('>' if BAR_LEN < MAX_LEN else '') + - ' ' * (MAX_LEN - BAR_LEN) + - '] %.1f%%' % (progress * 100.)) +def get_progressbar_str(progress, max_len=30): + bar_len = int(max_len * progress) + progr_part = '=' * bar_len + progr_marker = '>' if bar_len < max_len else '' + progr_empty = ' ' * (max_len - bar_len) + return f'Progress:[{progr_part}{progr_marker}{progr_empty}] {progress * 100:.1f}%' + # Bicubic operation def bicubic(img, ratio, a): - #Get image size - H,W,C = img.shape + # Get image size + H, W, C = img.shape - img = padding(img,H,W,C) - #Create new image - dH = math.floor(H*ratio) - dW = math.floor(W*ratio) + img = padding(img, H, W, C) + # Create new image + dH = math.floor(H * ratio) + dW = math.floor(W * ratio) dst = np.zeros((dH, dW, 3)) - h = 1/ratio + h = 1 / ratio print('Start bicubic interpolation') print('It will take a little while...') inc = 0 - for c in range(C): - for j in range(dH): - for i in range(dW): - x, y = i * h + 2 , j * h + 2 - - x1 = 1 + x - math.floor(x) - x2 = x - math.floor(x) - x3 = math.floor(x) + 1 - x - x4 = math.floor(x) + 2 - x - - y1 = 1 + y - math.floor(y) - y2 = y - math.floor(y) - y3 = math.floor(y) + 1 - y - y4 = math.floor(y) + 2 - y - - mat_l = np.matrix([[u(x1,a),u(x2,a),u(x3,a),u(x4,a)]]) - mat_m = np.matrix([[img[int(y-y1),int(x-x1),c],img[int(y-y2),int(x-x1),c],img[int(y+y3),int(x-x1),c],img[int(y+y4),int(x-x1),c]], - [img[int(y-y1),int(x-x2),c],img[int(y-y2),int(x-x2),c],img[int(y+y3),int(x-x2),c],img[int(y+y4),int(x-x2),c]], - [img[int(y-y1),int(x+x3),c],img[int(y-y2),int(x+x3),c],img[int(y+y3),int(x+x3),c],img[int(y+y4),int(x+x3),c]], - [img[int(y-y1),int(x+x4),c],img[int(y-y2),int(x+x4),c],img[int(y+y3),int(x+x4),c],img[int(y+y4),int(x+x4),c]]]) - mat_r = np.matrix([[u(y1,a)],[u(y2,a)],[u(y3,a)],[u(y4,a)]]) - dst[j, i, c] = np.dot(np.dot(mat_l, mat_m),mat_r) - - # Print progress - inc = inc + 1 - sys.stderr.write('\r\033[K' + get_progressbar_str(inc/(C*dH*dW))) - sys.stderr.flush() - sys.stderr.write('\n') - sys.stderr.flush() + for j in range(dH): + for i in range(dW): + x, y = i * h + 2, j * h + 2 + + xdec, xint = math.modf(x) + xds = [abs(xdec - k) for k in range(-1, 3)] + xint = int(xint) + ydec, yint = math.modf(y) + yds = [abs(ydec - k) for k in range(-1, 3)] + yint = int(yint) + + mat_l = np.matrix([[u(xd, a) for xd in xds]]) + mat_r = np.matrix([[u(yd, a)] for yd in yds]) + for c in range(C): + mat_m = np.transpose(np.matrix(img[yint - 1:yint + 3, xint - 1:xint + 3, c])) + dst[j, i, c] = (mat_l @ mat_m) @ mat_r + + # Print progress + inc = inc + 1 + if inc % 100 == 1: + print(f'\r\033[K{get_progressbar_str(inc / (dH * dW))}', file = sys.stderr, end='') + print(f'\r\033[K{get_progressbar_str(1.0)}', file=sys.stderr) return dst -# Read image -img = cv2.imread('butterfly.png') -# Scale factor -ratio = 2 -# Coefficient -a = -1/2 +if __name__ == '__main__': + # Read image + orig_img = cv2.imread('butterfly.png') + + # Scale factor + ratio = 2 + # Coefficient + a = -1 / 2 + + start_time = time.time() + + result_img = bicubic(orig_img, ratio, a) + print('Completed!') + + stop_time = time.time() + print(f'Elapsed time: {stop_time - start_time:.3f}s') -dst = bicubic(img, ratio, a) -print('Completed!') -cv2.imwrite('bicubic_butterfly.png', dst) + cv2.imwrite('bicubic_butterfly.png', result_img) diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..b96544b --- /dev/null +++ b/requirements.txt @@ -0,0 +1,2 @@ +opencv-python +numpy