From 8575da5b1d5a4a98db770bb10082470109572f67 Mon Sep 17 00:00:00 2001 From: Benjamin Loison Date: Mon, 25 Mar 2024 17:45:01 +0100 Subject: [PATCH] WIP: Getting PRNU by averaging on fake dataset --- .../context_adaptive_interpolator.py | 6 ++-- .../wiener_filter.py | 1 - datasets/fake/generate_dataset.py | 33 +++++++++++-------- 3 files changed, 22 insertions(+), 18 deletions(-) diff --git a/algorithms/context_adaptive_interpolator/context_adaptive_interpolator.py b/algorithms/context_adaptive_interpolator/context_adaptive_interpolator.py index f96f28f..e6fec66 100644 --- a/algorithms/context_adaptive_interpolator/context_adaptive_interpolator.py +++ b/algorithms/context_adaptive_interpolator/context_adaptive_interpolator.py @@ -19,11 +19,11 @@ def contextAdaptiveInterpolator(I, IImage, showProgress = False): # Accelerate computation. See #15. for m in range(1, IImage.size[0] - 1): for n in range(1, IImage.size[1] - 1): - e = I[m, n + 1] + e = I[m , n + 1] se = I[m + 1, n + 1] - s = I[m + 1, n] + s = I[m + 1, n] sw = I[m + 1, n - 1] - w = I[m, n - 1] + w = I[m , n - 1] nw = I[m - 1, n - 1] no = I[m - 1, n] ne = I[m - 1, n + 1] diff --git a/algorithms/context_adaptive_interpolator/wiener_filter.py b/algorithms/context_adaptive_interpolator/wiener_filter.py index 3e0343e..6ce003a 100644 --- a/algorithms/context_adaptive_interpolator/wiener_filter.py +++ b/algorithms/context_adaptive_interpolator/wiener_filter.py @@ -5,7 +5,6 @@ def wienerFilter(r, rImage, Q, sigma_0, showProgress): h_wImage = Image.new('L', (rImage.size[0], rImage.size[1])) h_wImagePixels = h_wImage.load() - # Wiener filter. def h_w(hImage, h, i, j): # Equation (7) return h[i, j] * sigma(hImage, h, i, j) / (sigma(hImage, h, i, j) + sigma_0 ** 2) diff --git a/datasets/fake/generate_dataset.py b/datasets/fake/generate_dataset.py index 9206cf3..84a07f9 100644 --- a/datasets/fake/generate_dataset.py +++ b/datasets/fake/generate_dataset.py @@ -13,41 +13,45 @@ from context_adaptive_interpolator import contextAdaptiveInterpolator from tqdm import tqdm IMAGE_SIZE = 64 -NUMBER_OF_PHONES = 10 +NUMBER_OF_PHONES = 1#0 NUMBER_OF_IMAGES_PER_PHONE = 100 -# Compared to images. +# Compared to images being 1. PRNU_FACTOR = 0.1 # Generate PRNUs and images of phones. # Is such `np.maximum` probabilistically correct with our theoretical method? See #19. def randomImage(scale): - return np.maximum(np.random.normal(loc = 0, scale = scale, size = (IMAGE_SIZE, IMAGE_SIZE)), 0) + return np.random.normal(loc = 0, scale = scale, size = (IMAGE_SIZE, IMAGE_SIZE)) prnus = [randomImage(scale = PRNU_FACTOR) for _ in range(NUMBER_OF_PHONES)] images = [[randomImage(scale = 1) + prnus[phoneIndex] for _ in range(NUMBER_OF_IMAGES_PER_PHONE)] for phoneIndex in range(NUMBER_OF_PHONES)] -# How to simplify? allImages = np.max([np.max(prnus) + np.max(images)]) def toPilImage(npArray): - npArray = (255 * npArray / np.max(allImages)).round() - return Image.fromarray(np.uint8(npArray)) + return Image.fromarray(npArray) -prnus = [toPilImage(prnu) for prnu in prnus] -#prnus[0].show() +def showImage(npArray): + npArray -= npArray.min() + npArray = (npArray / npArray.max()) * 255 + Image.fromarray(npArray).show() -images = [[toPilImage(image) for image in images[phoneIndex]] for phoneIndex in range(NUMBER_OF_PHONES)] -#images[0][0].show() +prnusPil = [toPilImage(prnu) for prnu in prnus] +#showImage(prnus[0]) + +imagesPil = [[toPilImage(image) for image in images[phoneIndex]] for phoneIndex in range(NUMBER_OF_PHONES)] +#showImage(images[0][0]) # Compute CAI of phone images. -caiImages = [[contextAdaptiveInterpolator(image.load(), image) for image in images[phoneIndex]] for phoneIndex in tqdm(range(NUMBER_OF_PHONES))] +caiImages = [[contextAdaptiveInterpolator(image.load(), image) for image in imagesPil[phoneIndex]] for phoneIndex in tqdm(range(NUMBER_OF_PHONES))] +#caiImages[0][0].show() # Guess the phone by consider the one reaching the lowest RMS difference between the estimated PRNU and the actual one. def getPhoneIndexByNearestPrnu(estimatedPrnu): nearestPrnuRmsDiff = None nearestPrnuPhoneIndex = None - for phoneIndex, prnu in enumerate(prnus): + for phoneIndex, prnu in enumerate(prnusPil): prnuRmsDiff = rmsdiff(estimatedPrnu, prnu) if nearestPrnuRmsDiff is None or prnuRmsDiff < nearestPrnuRmsDiff: nearestPrnuRmsDiff = prnuRmsDiff @@ -58,15 +62,16 @@ def getPhoneIndexByNearestPrnu(estimatedPrnu): # What about CAI on `phoneImagesMean`? See https://gitea.lemnoslife.com/Benjamin_Loison/Robust_image_source_identification_on_modern_smartphones/issues/9#issuecomment-1369. correctGuessesByMeanImages = 0 correctGuessesByMeanCAIImages = 0 +# Maybe make sense only because Gaussian images here. correctGuessesByCAIImagesMean = 0 for phoneIndex in range(NUMBER_OF_PHONES): - phoneImages = images[phoneIndex] + phoneImages = imagesPil[phoneIndex] phoneCaiImages = caiImages[phoneIndex] phoneImagesMean = toPilImage(np.array(phoneImages).mean(axis = 0)) caiImagesMean = toPilImage(np.array(phoneCaiImages).mean(axis = 0)) caiOverPhoneImagesMean = contextAdaptiveInterpolator(phoneImagesMean.load(), phoneImagesMean) - phonePrnu = prnus[phoneIndex] + phonePrnu = prnusPil[phoneIndex] print('RMS diff with mean image =', rmsdiff(phoneImagesMean, phonePrnu)) print('RMS diff with mean CAI images =', rmsdiff(caiImagesMean, phonePrnu)) print('RMS diff with CAI images mean =', rmsdiff(caiOverPhoneImagesMean, phonePrnu))