| | |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| |
|
| | import imageio |
| | import numpy as np |
| | import os |
| | import struct |
| |
|
| | ROOT_DIR = os.path.dirname(os.path.dirname(os.path.realpath(__file__))) |
| |
|
| | def mse2psnr(x): |
| | return -10.*np.log(x)/np.log(10.) |
| |
|
| | def write_image_imageio(img_file, img, quality): |
| | img = (np.clip(img, 0.0, 1.0) * 255.0 + 0.5).astype(np.uint8) |
| | kwargs = {} |
| | if os.path.splitext(img_file)[1].lower() in [".jpg", ".jpeg"]: |
| | if img.ndim >= 3 and img.shape[2] > 3: |
| | img = img[:,:,:3] |
| | kwargs["quality"] = quality |
| | kwargs["subsampling"] = 0 |
| | imageio.imwrite(img_file, img, **kwargs) |
| |
|
| | def read_image_imageio(img_file): |
| | img = imageio.imread(img_file) |
| | img = np.asarray(img).astype(np.float32) |
| | if len(img.shape) == 2: |
| | img = img[:,:,np.newaxis] |
| | return img / 255.0 |
| |
|
| | def srgb_to_linear(img): |
| | limit = 0.04045 |
| | return np.where(img > limit, np.power((img + 0.055) / 1.055, 2.4), img / 12.92) |
| |
|
| | def linear_to_srgb(img): |
| | limit = 0.0031308 |
| | return np.where(img > limit, 1.055 * (img ** (1.0 / 2.4)) - 0.055, 12.92 * img) |
| |
|
| | def read_image(file): |
| | if os.path.splitext(file)[1] == ".bin": |
| | with open(file, "rb") as f: |
| | bytes = f.read() |
| | h, w = struct.unpack("ii", bytes[:8]) |
| | img = np.frombuffer(bytes, dtype=np.float16, count=h*w*4, offset=8).astype(np.float32).reshape([h, w, 4]) |
| | else: |
| | img = read_image_imageio(file) |
| | if img.shape[2] == 4: |
| | img[...,0:3] = srgb_to_linear(img[...,0:3]) |
| | |
| | img[...,0:3] *= img[...,3:4] |
| | else: |
| | img = srgb_to_linear(img) |
| | return img |
| |
|
| | def write_image(file, img, quality=95): |
| | if os.path.splitext(file)[1] == ".bin": |
| | if img.shape[2] < 4: |
| | img = np.dstack((img, np.ones([img.shape[0], img.shape[1], 4 - img.shape[2]]))) |
| | with open(file, "wb") as f: |
| | f.write(struct.pack("ii", img.shape[0], img.shape[1])) |
| | f.write(img.astype(np.float16).tobytes()) |
| | else: |
| | if img.shape[2] == 4: |
| | img = np.copy(img) |
| | |
| | img[...,0:3] = np.divide(img[...,0:3], img[...,3:4], out=np.zeros_like(img[...,0:3]), where=img[...,3:4] != 0) |
| | img[...,0:3] = linear_to_srgb(img[...,0:3]) |
| | else: |
| | img = linear_to_srgb(img) |
| | write_image_imageio(file, img, quality) |
| |
|
| | def trim(error, skip=0.000001): |
| | error = np.sort(error.flatten()) |
| | size = error.size |
| | skip = int(skip * size) |
| | return error[skip:size-skip].mean() |
| |
|
| | def luminance(a): |
| | a = np.maximum(0, a)**0.4545454545 |
| | return 0.2126 * a[:,:,0] + 0.7152 * a[:,:,1] + 0.0722 * a[:,:,2] |
| |
|
| | def L1(img, ref): |
| | return np.abs(img - ref) |
| |
|
| | def APE(img, ref): |
| | return L1(img, ref) / (1e-2 + ref) |
| |
|
| | def SAPE(img, ref): |
| | return L1(img, ref) / (1e-2 + (ref + img) / 2.) |
| |
|
| | def L2(img, ref): |
| | return (img - ref)**2 |
| |
|
| | def RSE(img, ref): |
| | return L2(img, ref) / (1e-2 + ref**2) |
| |
|
| | def rgb_mean(img): |
| | return np.mean(img, axis=2) |
| |
|
| | def compute_error_img(metric, img, ref): |
| | img[np.logical_not(np.isfinite(img))] = 0 |
| | img = np.maximum(img, 0.) |
| | if metric == "MAE": |
| | return L1(img, ref) |
| | elif metric == "MAPE": |
| | return APE(img, ref) |
| | elif metric == "SMAPE": |
| | return SAPE(img, ref) |
| | elif metric == "MSE": |
| | return L2(img, ref) |
| | elif metric == "MScE": |
| | return L2(np.clip(img, 0.0, 1.0), np.clip(ref, 0.0, 1.0)) |
| | elif metric == "MRSE": |
| | return RSE(img, ref) |
| | elif metric == "MtRSE": |
| | return trim(RSE(img, ref)) |
| | elif metric == "MRScE": |
| | return RSE(np.clip(img, 0, 100), np.clip(ref, 0, 100)) |
| |
|
| | raise ValueError(f"Unknown metric: {metric}.") |
| |
|
| | def compute_error(metric, img, ref): |
| | metric_map = compute_error_img(metric, img, ref) |
| | metric_map[np.logical_not(np.isfinite(metric_map))] = 0 |
| | if len(metric_map.shape) == 3: |
| | metric_map = np.mean(metric_map, axis=2) |
| | mean = np.mean(metric_map) |
| | return mean |
| |
|