First PRNU classifier acting randomly it seems

This commit is contained in:
Benjamin Loison 2024-03-22 12:46:13 +01:00
parent a9adf2d53d
commit 36f5b69f5e
Signed by: Benjamin_Loison
SSH Key Fingerprint: SHA256:BtnEgYTlHdOg1u+RmYcDE0mnfz1rhv5dSbQ2gyxW8B8

View File

@ -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)