From 96bbd50a3b378b6dbf0ee1e67af131cef9582868 Mon Sep 17 00:00:00 2001 From: Benjamin Loison Date: Fri, 29 Mar 2024 12:57:56 +0100 Subject: [PATCH] Generalize with a partial image `SPLIT_N_X_N` --- algorithms/image_utils/image_utils.py | 19 +++++++++++++++++-- .../noise_free_test_images/estimate_prnu.py | 16 ++++++++-------- 2 files changed, 25 insertions(+), 10 deletions(-) diff --git a/algorithms/image_utils/image_utils.py b/algorithms/image_utils/image_utils.py index 7a0e495..625f611 100644 --- a/algorithms/image_utils/image_utils.py +++ b/algorithms/image_utils/image_utils.py @@ -1,6 +1,7 @@ -from PIL import Image +from PIL import Image, ImageFont, ImageDraw import numpy as np from matplotlib import pyplot as plt +import os def randomGaussianImage(scale, size): return np.random.normal(loc = 0, scale = scale, size = size) @@ -13,4 +14,18 @@ def showImageWithMatplotlib(npArray, title = None, cmap = 'viridis'): plt.show() def toPilImage(npArray): - return Image.fromarray(npArray) \ No newline at end of file + return Image.fromarray(npArray) + +def getPrnuShownAsSuch(size): + # Supports `WIDTH` > `HEIGHT` and conversely. + WIDTH, HEIGHT = size + TEXT = 'PRNU' + + image = Image.new('L', size) + draw = ImageDraw.Draw(image) + # I guess that the maximal character height is higher than the maximal character width. Hence, the `TEXT` may not be spanned on the full width. + fontSize = min(HEIGHT, WIDTH // len(TEXT)) + font = ImageFont.truetype(os.path.expanduser('~/.local/share/fonts/impact.ttf'), fontSize) + # Center vertically, especially in the case `HEIGHT` > `WIDTH`. + draw.text((0, HEIGHT // 2 - fontSize // 2), TEXT, 255, font = font) + return np.array(image) \ No newline at end of file diff --git a/datasets/noise_free_test_images/estimate_prnu.py b/datasets/noise_free_test_images/estimate_prnu.py index 6b13fab..6833b24 100644 --- a/datasets/noise_free_test_images/estimate_prnu.py +++ b/datasets/noise_free_test_images/estimate_prnu.py @@ -8,7 +8,7 @@ import sys sys.path.insert(0, '../../algorithms/image_utils/') -from image_utils import showImageWithMatplotlib, randomGaussianImage, toPilImage +from image_utils import showImageWithMatplotlib, randomGaussianImage, toPilImage, getPrnuShownAsSuch sys.path.insert(0, '../../algorithms/context_adaptive_interpolator/') @@ -25,15 +25,15 @@ datasetPath = 'no_noise_images' # In addition to the range difference, note that the distribution in the first set of images was a Gaussian and here is very different and specific. PRNU_FACTOR = 0.01 NOISE_FACTOR = 0.1 -IMAGE_SIZE_SHAPE = (469, 704) -IMAGE_SIZE_SHAPE_4x4 = [size // 4 for size in IMAGE_SIZE_SHAPE] +SPLIT_N_X_N = 1 + +IMAGE_SIZE_SHAPE = [dimension // SPLIT_N_X_N for dimension in (704, 469)] np.random.seed(0) -splitNxN = 4 #prnuNpArray = 255 * randomGaussianImage(scale = PRNU_FACTOR, size = IMAGE_SIZE_SHAPE) -prnuPil = Image.open(f'prnu_{"4x4_" if splitNxN == 4 else ""}noise.png').convert('F') -prnuNpArray = np.array(prnuPil) * PRNU_FACTOR +prnuNpArray = getPrnuShownAsSuch(IMAGE_SIZE_SHAPE) * PRNU_FACTOR +showImageWithMatplotlib(prnuNpArray) def isIn256Range(x): return 0 <= x and x <= 255 @@ -46,8 +46,8 @@ for imageName in os.listdir(datasetPath): imageWithoutPrnuPil = Image.open(imagePath).convert('F') imageWithoutPrnuNpArray = np.array(imageWithoutPrnuPil) - m = imageWithoutPrnuNpArray.shape[0] // splitNxN - n = imageWithoutPrnuNpArray.shape[1] // splitNxN + m = imageWithoutPrnuNpArray.shape[0] // SPLIT_N_X_N + n = imageWithoutPrnuNpArray.shape[1] // SPLIT_N_X_N imageWithoutPrnuNpArrayTiles = [imageWithoutPrnuNpArray[x : x + m, y : y + n] for x in range(0, imageWithoutPrnuNpArray.shape[0], m) for y in range(0, imageWithoutPrnuNpArray.shape[1], n)] for imageWithoutPrnuNpArrayTile in imageWithoutPrnuNpArrayTiles: