From 36f5b69f5e1b0165fe3975c8896c833a86cb9f28 Mon Sep 17 00:00:00 2001 From: Benjamin Loison Date: Fri, 22 Mar 2024 12:46:13 +0100 Subject: [PATCH] First PRNU classifier acting randomly it seems --- datasets/fake/generate_dataset.py | 65 +++++++++++++++++++++++-------- 1 file changed, 49 insertions(+), 16 deletions(-) diff --git a/datasets/fake/generate_dataset.py b/datasets/fake/generate_dataset.py index cb09315..898b227 100644 --- a/datasets/fake/generate_dataset.py +++ b/datasets/fake/generate_dataset.py @@ -10,35 +10,68 @@ from rmsdiff import rmsdiff sys.path.insert(0, '../../algorithms/context_adaptive_interpolator/') from context_adaptive_interpolator import contextAdaptiveInterpolator +from tqdm import tqdm IMAGE_SIZE = 64 +NUMBER_OF_PHONES = 10 +NUMBER_OF_IMAGES_PER_PHONE = 100 +# Compared to images. +PRNU_FACTOR = 0.1 -# Is such `np.maximum` probabilistically correct with our theoretical method? +# 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) -prnu = randomImage(scale = 1) +prnus = [randomImage(scale = 0.1) for _ in range(NUMBER_OF_PHONES)] -images = [randomImage(scale = 10) + prnu for _ in range(100)] -allImages = [prnu] + images +images = [[randomImage(scale = 10) + 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)) -prnu = toPilImage(prnu) -#prnu.show() +prnus = [toPilImage(prnu) for prnu in prnus] +#prnus[0].show() -images = [toPilImage(image) for image in images] -#images[0].show() +images = [[toPilImage(image) for image in images[phoneIndex]] for phoneIndex in range(NUMBER_OF_PHONES)] +#images[0][0].show() -caiImages = [contextAdaptiveInterpolator(image.load(), image) for image in images] -for image, caiImage in zip(images, caiImages): - initialRmsDiff = rmsdiff(image, prnu) - caiRmsDiff = rmsdiff(caiImage, prnu) - #print(f'{initialRmsDiff=} {caiRmsDiff=}') +caiImages = [[contextAdaptiveInterpolator(image.load(), image) for image in images[phoneIndex]] for phoneIndex in tqdm(range(NUMBER_OF_PHONES))] -print('RMS diff with average image =', rmsdiff(toPilImage(np.array(images).mean(axis = 0)), prnu)) -# Should be better than above one. Maybe not the case here as the images are Gaussian noise. -print('RMS diff with average CAI images =', rmsdiff(toPilImage(np.array(caiImages).mean(axis = 0)), prnu)) +def getPhoneIndexByNearestPrnu(estimatedPrnu): + nearestPrnuRmsDiff = None + nearestPrnuPhoneIndex = None + for phoneIndex, prnu in enumerate(prnus): + prnuRmsDiff = rmsdiff(estimatedPrnu, prnu) + if nearestPrnuRmsDiff is None or prnuRmsDiff < nearestPrnuRmsDiff: + nearestPrnuRmsDiff = prnuRmsDiff + nearestPrnuPhoneIndex = phoneIndex + return phoneIndex + +# What about CAI on `phoneImagesMean`? +correctGuessesByAverageImages = 0 +correctGuessesByAverageCAIImages = 0 +for phoneIndex in range(NUMBER_OF_PHONES): + phoneImages = images[phoneIndex] + phoneCaiImages = caiImages[phoneIndex] + + phoneImagesMean = toPilImage(np.array(phoneImages).mean(axis = 0)) + caiImagesMean = toPilImage(np.array(phoneCaiImages).mean(axis = 0)) + phonePrnu = prnus[phoneIndex] + print('RMS diff with average image =', rmsdiff(phoneImagesMean, phonePrnu)) + print('RMS diff with average CAI images =', rmsdiff(caiImagesMean, phonePrnu)) + guessedPhoneIndexByAverageImages = getPhoneIndexByNearestPrnu(phoneImagesMean) + guessedPhoneIndexByAverageCAIImages = getPhoneIndexByNearestPrnu(caiImagesMean) + #print(f'Actual phone index {phoneIndex}, guessed phone index {guessedPhoneIndex}') + correctGuessesByAverageImages += 1 if phoneIndex == guessedPhoneIndexByAverageImages else 0 + correctGuessesByAverageCAIImages += 1 if phoneIndex == guessedPhoneIndexByAverageCAIImages else 0 + #correct = phoneIndex == guessedPhoneIndex + #if correct: + # correctGuesses += 1 + +print(correctGuessesByAverageImages / NUMBER_OF_PHONES) +print(correctGuessesByAverageCAIImages / NUMBER_OF_PHONES)