|
| 1 | +#! /usr/bin/python |
| 2 | +# -*- coding: utf8 -*- |
| 3 | + |
| 4 | +import sys, os |
| 5 | +sys.path.append(os.path.join(os.getcwd(), 'wrappers'+os.path.sep+'Waifu2x')) |
| 6 | +sys.path.append(os.path.join(os.getcwd(), 'wrappers'+os.path.sep+'rife')) |
| 7 | +import numpy as np |
| 8 | +from filter import filters, FilterArgumentError |
| 9 | +from wrappers.dif.filter import DifFilter |
| 10 | +#import time |
| 11 | +from tqdm import tqdm |
| 12 | +import flogging |
| 13 | + |
| 14 | +TILE_SIZE = 512 |
| 15 | +MAX_SIZE = 512 |
| 16 | +MAX_SIZE_F = MAX_SIZE*2 |
| 17 | +PADDING = 2 |
| 18 | +UPSCALE = 4 |
| 19 | + |
| 20 | +def rgb2ycbcr(im): |
| 21 | + xform = np.array([[.299, .587, .114], [-.1687, -.3313, .5], [.5, -.4187, -.0813]]) |
| 22 | + ycbcr = im.dot(xform.T) |
| 23 | + ycbcr[:,:,[1,2]] += 128 |
| 24 | + return ycbcr |
| 25 | + |
| 26 | +def ycbcr2rgb(im): |
| 27 | + xform = np.array([[1, 0, 1.402], [1, -0.34414, -.71414], [1, 1.772, 0]]) |
| 28 | + rgb = im.astype(np.float) |
| 29 | + rgb[:,:,[1,2]] -= 128 |
| 30 | + return np.uint8(rgb.dot(xform.T).clip(0.0, 255.0)) |
| 31 | + |
| 32 | +def rgb2yuv( rgb ): |
| 33 | + |
| 34 | + m = np.array([[ 0.29900, -0.16874, 0.50000], |
| 35 | + [0.58700, -0.33126, -0.41869], |
| 36 | + [ 0.11400, 0.50000, -0.08131]]) |
| 37 | + |
| 38 | + yuv = np.dot(rgb,m) |
| 39 | + yuv[:,:,1:]+=128.0 |
| 40 | + return yuv |
| 41 | + |
| 42 | +#input is an YUV numpy array with shape (height,width,3) can be uint,int, float or double, values expected in the range 0..255 |
| 43 | +#output is a double RGB numpy array with shape (height,width,3), values in the range 0..255 |
| 44 | +def yuv2rgb( yuv ): |
| 45 | + |
| 46 | + m = np.array([[ 1.0, 1.0, 1.0], |
| 47 | + [-0.000007154783816076815, -0.3441331386566162, 1.7720025777816772], |
| 48 | + [ 1.4019975662231445, -0.7141380310058594 , 0.00001542569043522235] ]) |
| 49 | + |
| 50 | + rgb = np.dot(yuv,m) |
| 51 | + rgb[:,:,0]-=179.45477266423404 |
| 52 | + rgb[:,:,1]+=135.45870971679688 |
| 53 | + rgb[:,:,2]-=226.8183044444304 |
| 54 | + return np.uint8(rgb.clip(0.0, 255.0)) |
| 55 | + |
| 56 | +def getTileImages(image, width=TILE_SIZE, height=TILE_SIZE): |
| 57 | + _nrows, _ncols, depth = image.shape |
| 58 | + _size = image.size |
| 59 | + |
| 60 | + nrows, _m = divmod(_nrows, height) |
| 61 | + ncols, _n = divmod(_ncols, width) |
| 62 | + if _m != 0 or _n != 0: |
| 63 | + image2 = np.zeros(((nrows+1) * height, (ncols+1) * width, depth), dtype=np.float32) |
| 64 | + image2[:_nrows, :_ncols, :] = image[:, :, :] |
| 65 | + nrows += 1 |
| 66 | + ncols += 1 |
| 67 | + else: |
| 68 | + image2 = image |
| 69 | + _strides = image2.strides |
| 70 | + |
| 71 | + return np.lib.stride_tricks.as_strided( |
| 72 | + np.ravel(image2), |
| 73 | + shape=(nrows, ncols, height, width, depth), |
| 74 | + strides=(height * _strides[0], width * _strides[1], *_strides), |
| 75 | + writeable=False |
| 76 | + ) |
| 77 | + |
| 78 | +def subdivide(image, max_size=MAX_SIZE, repeat=False): |
| 79 | + height, width, depth = image.shape |
| 80 | + newWidth, newHeight = width, height |
| 81 | + nx, ny = 1, 1 |
| 82 | + |
| 83 | + while newHeight > max_size: |
| 84 | + if newHeight & 1 == 0: |
| 85 | + newHeight >>= 1 |
| 86 | + else: |
| 87 | + newHeight >>= 1 |
| 88 | + newHeight += 1 |
| 89 | + nx <<= 1 |
| 90 | + |
| 91 | + while newWidth > max_size: |
| 92 | + if newWidth & 1 == 0: |
| 93 | + newWidth >>= 1 |
| 94 | + else: |
| 95 | + newWidth >>= 1 |
| 96 | + newWidth += 1 |
| 97 | + ny <<= 1 |
| 98 | + |
| 99 | + paddedImage = np.zeros((nx * newHeight + 2*PADDING, ny * newWidth + 2*PADDING, depth), dtype=np.float32) |
| 100 | + paddedImage[PADDING:(height+PADDING), PADDING:(width+PADDING), :] = image[:, :, :] |
| 101 | + |
| 102 | + if repeat and height >= PADDING and width >= PADDING: |
| 103 | + ph, pw, pd = paddedImage.shape |
| 104 | + #upper left corner |
| 105 | + paddedImage[0:PADDING, 0:PADDING, :] = image[(height-PADDING):height, (width-PADDING):width, :] |
| 106 | + #lower right corner |
| 107 | + paddedImage[(ph-PADDING):ph, (pw-PADDING):pw, :] = image[0:PADDING, 0:PADDING, :] |
| 108 | + #upper right corner |
| 109 | + paddedImage[0:PADDING, (pw-PADDING):pw, :] = image[(height-PADDING):height, 0:PADDING, :] |
| 110 | + #lower left corner |
| 111 | + paddedImage[(ph-PADDING):ph, 0:PADDING, :] = image[0:PADDING, (width-PADDING):width, :] |
| 112 | + #up side |
| 113 | + paddedImage[0:PADDING, PADDING:(width+PADDING), :] = image[(height-PADDING):height, :, :] |
| 114 | + #down side |
| 115 | + paddedImage[(ph-PADDING):ph, PADDING:(width+PADDING), :] = image[0:PADDING, :, :] |
| 116 | + #left side |
| 117 | + paddedImage[PADDING:(height+PADDING), 0:PADDING, :] = image[:, (width-PADDING):width, :] |
| 118 | + #right side |
| 119 | + paddedImage[PADDING:(height+PADDING), (pw-PADDING):pw, :] = image[:, 0:PADDING, :] |
| 120 | + |
| 121 | + out = np.zeros((nx, ny, newHeight + 2*PADDING, newWidth + 2*PADDING, depth), dtype=np.float32) |
| 122 | + |
| 123 | + for i in range(nx): |
| 124 | + for j in range(ny): |
| 125 | + out[i, j, :, :, :] = paddedImage[i*newHeight:((i+1)*newHeight + 2*PADDING), j*newWidth:((j+1)*newWidth + 2*PADDING), :] |
| 126 | + |
| 127 | + return out |
| 128 | + |
| 129 | +def fillFullImage(subUpscaledImg, image, nx, ny): |
| 130 | + height, width, depth = subUpscaledImg.shape |
| 131 | + uPadding = PADDING * UPSCALE |
| 132 | + tHeight, tWidth = height-2*uPadding, width-2*uPadding |
| 133 | + |
| 134 | + up = nx*tHeight |
| 135 | + down = min((nx+1)*tHeight, image.shape[0]) |
| 136 | + left = ny*tWidth |
| 137 | + right = min((ny+1)*tWidth, image.shape[1]) |
| 138 | + |
| 139 | + image[up:down, left:right, :] = subUpscaledImg[uPadding:uPadding+(down-up), uPadding:uPadding+(right-left), :] |
| 140 | + |
| 141 | +def imageFromTiled(imageShape, imageTile, x, y, out): |
| 142 | + tilesX = imageShape[0] |
| 143 | + tilesY = imageShape[1] |
| 144 | + tilesSizeX = imageShape[2] * 4 |
| 145 | + tilesSizeY = imageShape[3] * 4 |
| 146 | + |
| 147 | + out[x*tilesSizeX:(x+1)*tilesSizeX, y*tilesSizeY:(y+1)*tilesSizeY, :] = imageTile[:, :, :] |
| 148 | + |
| 149 | +def m11to255(npData): |
| 150 | + '''Convert -1..1 to 0..255''' |
| 151 | + return ((npData + 1.0) * 127.5).astype(np.uint8) |
| 152 | + |
| 153 | +def m01to255(npData): |
| 154 | + '''Convert 0..1 to 0..255''' |
| 155 | + return (npData * 255.0).astype(np.uint8) |
| 156 | + |
| 157 | +def m11to255Float(npData): |
| 158 | + '''Convert -1..1 to 0..255''' |
| 159 | + return ((npData + 1.0) * 127.5) |
| 160 | + |
| 161 | +def _255tom11(npData): |
| 162 | + '''Convert 0..255 to -1..1''' |
| 163 | + return (npData / 127.5 - 1.0).astype(np.float32) |
| 164 | + |
| 165 | +def _255tom01(npData): |
| 166 | + '''Convert 0..255 to 0..1''' |
| 167 | + return (npData / 255.0).astype(np.float32) |
| 168 | + |
| 169 | +def secToTime(sec): |
| 170 | + return "{:d}:{:02d}:{:02d}".format(int(sec) // 3600, (int(sec) // 60) % 60, int(sec) % 60) |
| 171 | + |
| 172 | +#ltime = time.time() |
| 173 | +def convertFrames(reader, writer, args): |
| 174 | + global filter |
| 175 | + try: |
| 176 | + if args['filter'] in filters: |
| 177 | + filter = filters[args['filter']](args) |
| 178 | + if reader.useDifFilter: |
| 179 | + filter = DifFilter(args, filter) |
| 180 | + else: |
| 181 | + args["logger"].error("Filter {} not found".format(args['filter'])) |
| 182 | + return |
| 183 | + except FilterArgumentError as e: |
| 184 | + logger = flogging.FilterLogging(args["loglevel"], e.filter) |
| 185 | + logger.error(e.text) |
| 186 | + return |
| 187 | + #ltime = time.time() |
| 188 | + #times = [] |
| 189 | + bar = tqdm(total=reader.numFrames*filter.outBatchSize) |
| 190 | + li = 0 |
| 191 | + for frame in reader: |
| 192 | + i = reader.readFrames |
| 193 | + #t = time.time() - ltime |
| 194 | + #ltime = time.time() |
| 195 | + #fps = 1.0 / max(t, 0.000001) |
| 196 | + #times.append(t) |
| 197 | + #if len(times) > reader.fps * 10: |
| 198 | + # times.pop(0) |
| 199 | + #mean_t = sum(times)/len(times) |
| 200 | + #print("Upscaling frame {}, {}, {:.3f} FPS, {} seconds remainings".format(i, secToTime(i / reader.fps), fps, secToTime(mean_t * (reader.numFrames - i - 1)))) |
| 201 | + bar.update(i-li) |
| 202 | + li = i |
| 203 | + |
| 204 | + out = filter.process(frame, i) |
| 205 | + if not out is None: |
| 206 | + writer.write(out) |
| 207 | + |
| 208 | + logger = flogging.FilterLogging(args["loglevel"], "converter") |
| 209 | + logger.print("Converted!") |
0 commit comments