Spaces:
Sleeping
Sleeping
| # %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | |
| # | |
| # Copyright (c) 2018 Image Processing Research Group of University Federico II of Naples ('GRIP-UNINA'). | |
| # All rights reserved. | |
| # This work should only be used for nonprofit purposes. | |
| # | |
| # By downloading and/or using any of these files, you implicitly agree to all the | |
| # terms of the license, as specified in the document LICENSE.txt | |
| # (included in this package) and online at | |
| # http://www.grip.unina.it/download/LICENSE_OPEN.txt | |
| # | |
| try: | |
| from PIL.JpegImagePlugin import convert_dict_qtables | |
| except ImportError: | |
| # For newer Pillow versions where convert_dict_qtables might be moved or removed | |
| # We might need to implement a fallback or check where it moved. | |
| # However, looking at Pillow source, it seems it might be gone in very recent versions or just not exposed. | |
| # Let's try to handle it or define a dummy if not critical, but it is used in jpeg_qtableinv. | |
| # Actually, let's check if we can just use the quantization table directly. | |
| pass | |
| from PIL import Image | |
| import numpy as np | |
| def imread2f_pil(stream, channel = 1, dtype = np.float32): | |
| img = Image.open(stream) | |
| mode = img.mode | |
| if channel == 3: | |
| img = img.convert('RGB') | |
| img = np.asarray(img).astype(dtype) / 256.0 | |
| elif channel == 1: | |
| if img.mode == 'L': | |
| img = np.asarray(img).astype(dtype) / 256.0 | |
| else: | |
| img = img.convert('RGB') | |
| img = np.asarray(img).astype(dtype) | |
| img = (0.299 * img[:, :, 0] + 0.587 * img[:, :, 1] + 0.114 * img[:, :, 2])/256.0 | |
| else: | |
| img = np.asarray(img).astype(dtype) / 256.0 | |
| return img, mode | |
| try: | |
| import rawpy | |
| def imread2f_raw(stream, channel = 1, dtype = np.float32): | |
| raw = rawpy.imread(stream) | |
| img = raw.postprocess() | |
| raw.close() | |
| ori_dtype = img.dtype | |
| img = np.asarray(img).astype(dtype) | |
| if channel == 1: | |
| img = (0.299 * img[:, :, 0] + 0.587 * img[:, :, 1] + 0.114 * img[:, :, 2]) | |
| if ori_dtype == np.uint8: | |
| img = img / 256.0 | |
| elif ori_dtype == np.uint16: | |
| img = img / (2.0 ** 16) | |
| elif ori_dtype == np.uint32: | |
| img = img / (2.0 ** 32) | |
| elif ori_dtype == np.uint64: | |
| img = img / (2.0 ** 64) | |
| elif ori_dtype == np.uint128: | |
| img = img / (2.0 ** 128) | |
| return img, 'RAW' | |
| except: | |
| pass | |
| def imread2f(stream, channel = 1, dtype = np.float32): | |
| try: | |
| return imread2f_raw(stream, channel=channel, dtype=dtype) | |
| except: | |
| return imread2f_pil(stream, channel=channel, dtype=dtype) | |
| def jpeg_qtableinv(stream, tnum=0, force_baseline=None): | |
| assert tnum == 0 or tnum == 1, 'Table number must be 0 or 1' | |
| if force_baseline is None: | |
| th_high = 32767 | |
| elif force_baseline == 0: | |
| th_high = 32767 | |
| else: | |
| th_high = 255 | |
| try: | |
| h = np.asarray(convert_dict_qtables(Image.open(stream).quantization)[tnum]).reshape((8, 8)) | |
| except NameError: | |
| # Fallback if convert_dict_qtables is not available | |
| # In newer Pillow, quantization might be a dictionary or list directly usable or we need another way. | |
| # However, Image.open(stream).quantization returns a dictionary {0: [...], 1: [...]} usually. | |
| # Let's try to use it directly if it's already a list/array-like. | |
| q = Image.open(stream).quantization | |
| if isinstance(q, dict): | |
| h = np.asarray(q[tnum]).reshape((8, 8)) | |
| elif isinstance(q, list): | |
| # Sometimes it might be a list of tables? | |
| h = np.asarray(q[tnum]).reshape((8, 8)) | |
| else: | |
| # If we can't get it, default to 100 quality (all 1s) | |
| return 100 | |
| if tnum == 0: | |
| # This is table 0 (the luminance table): | |
| t = np.matrix( | |
| [[16, 11, 10, 16, 24, 40, 51, 61], | |
| [12, 12, 14, 19, 26, 58, 60, 55], | |
| [14, 13, 16, 24, 40, 57, 69, 56], | |
| [14, 17, 22, 29, 51, 87, 80, 62], | |
| [18, 22, 37, 56, 68, 109, 103, 77], | |
| [24, 35, 55, 64, 81, 104, 113, 92], | |
| [49, 64, 78, 87, 103, 121, 120, 101], | |
| [72, 92, 95, 98, 112, 100, 103, 99]]) | |
| elif tnum == 1: | |
| # This is table 1 (the chrominance table): | |
| t = np.matrix( | |
| [[17, 18, 24, 47, 99, 99, 99, 99], | |
| [18, 21, 26, 66, 99, 99, 99, 99], | |
| [24, 26, 56, 99, 99, 99, 99, 99], | |
| [47, 66, 99, 99, 99, 99, 99, 99], | |
| [99, 99, 99, 99, 99, 99, 99, 99], | |
| [99, 99, 99, 99, 99, 99, 99, 99], | |
| [99, 99, 99, 99, 99, 99, 99, 99], | |
| [99, 99, 99, 99, 99, 99, 99, 99]]) | |
| else: | |
| raise ValueError(tnum, 'Table number must be 0 or 1') | |
| h_down = np.divide((2 * h-1), (2 * t)) | |
| h_up = np.divide((2 * h+1), (2 * t)) | |
| if np.all(h == 1): return 100 | |
| x_down = (h_down[h > 1]).max() | |
| x_up = (h_up[h < th_high]).min() if (h < th_high).any() else None | |
| if x_up is None: | |
| s = 1 | |
| elif x_down > 1 and x_up > 1: | |
| s = np.ceil(50 / x_up) | |
| elif x_up < 1: | |
| s = np.ceil(50*(2 - x_up)) | |
| else: | |
| s = 50 | |
| return s | |
| from scipy.interpolate import interp1d | |
| def resizeMapWithPadding(x, range0, range1, shapeOut): | |
| range0 = range0.flatten() | |
| range1 = range1.flatten() | |
| xv = np.arange(shapeOut[1]) | |
| yv = np.arange(shapeOut[0]) | |
| y = interp1d(range1, x , axis=1, kind='nearest', fill_value='extrapolate', assume_sorted=True, bounds_error=False) | |
| y = interp1d(range0, y(xv), axis=0, kind='nearest', fill_value='extrapolate', assume_sorted=True, bounds_error=False) | |
| return y(yv).astype(x.dtype) | |
| def computeMetricsContinue(values, gt0, gt1): | |
| values = values.flatten().astype(np.float32) | |
| gt0 = gt0.flatten().astype(np.float32) | |
| gt1 = gt1.flatten().astype(np.float32) | |
| inds = np.argsort(values) | |
| inds = inds[(gt0[inds]+gt1[inds])>0] | |
| vet_th = values[inds] | |
| gt0 = gt0[inds] | |
| gt1 = gt1[inds] | |
| TN = np.cumsum(gt0) | |
| FN = np.cumsum(gt1) | |
| FP = np.sum(gt0) - TN | |
| TP = np.sum(gt1) - FN | |
| return FP, TP, FN, TN, vet_th | |
| def computeMCC(values, gt0, gt1): | |
| FP, TP, FN, TN, vet_th = computeMetricsContinue(values, gt0, gt1) | |
| mcc = np.abs(TP*TN - FP*FN) / np.maximum(np.sqrt((TP + FP)*(TP + FN)*(TN+ FP)*(TN + FN) ), 1e-32) | |
| return mcc, vet_th |