Files
Robust_image_source_identif…/datasets/fake/generate_dataset.py

120 lines
5.0 KiB
Python

import numpy as np
from matplotlib import pyplot as plt
from PIL import Image
import sys
sys.path.insert(0, '../../algorithms/distance/')
from rms_diff import rmsDiffPil
sys.path.insert(0, '../../algorithms/context_adaptive_interpolator/')
from context_adaptive_interpolator import contextAdaptiveInterpolator
from tqdm import tqdm
IMAGE_SIZE = 64
NUMBER_OF_PHONES = 1#0
NUMBER_OF_IMAGES_PER_PHONE = 100
# 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.random.normal(loc = 0, scale = scale, size = (IMAGE_SIZE, IMAGE_SIZE))
imagesWithoutPrnu = [[randomImage(scale = 1) for _ in range(NUMBER_OF_IMAGES_PER_PHONE)] for phoneIndex in range(NUMBER_OF_PHONES)]
prnus = [randomImage(scale = PRNU_FACTOR) for _ in range(NUMBER_OF_PHONES)]
imagesWithPrnu = [[imageWithoutPrnu + prnus[phoneIndex] for imageWithoutPrnu in imagesWithoutPrnu[phoneIndex]] for phoneIndex in range(NUMBER_OF_PHONES)]
allImages = np.max([np.max(imagesWithoutPrnu) + np.max(prnus) + np.max(imagesWithPrnu)])
def toPilImage(npArray):
return Image.fromarray(npArray)
def showImageWithPil(npArray):
npArray -= npArray.min()
npArray = (npArray / npArray.max()) * 255
Image.fromarray(npArray).show()
def showImageWithMatplotlib(npArray):
plt.imshow(npArray)
plt.show()
fig, axs = plt.subplots(1, 4)
fig.suptitle('Single PRNU estimation with images being Gaussian noise')
prnusPil = [toPilImage(prnu) for prnu in prnus]
#showImageWithMatplotlib(prnus[0])
axs[0].set_title('Actual PRNU')
axs[0].imshow(prnus[0])
axs[1].set_title('Image without PRNU')
axs[1].imshow(imagesWithPrnu[0][0])
imagesWithPrnuPil = [[toPilImage(imageWithPrnu) for imageWithPrnu in imagesWithPrnu[phoneIndex]] for phoneIndex in range(NUMBER_OF_PHONES)]
#showImageWithMatplotlib(imagesWithPrnu[0][0])
axs[2].set_title(f'First image with PRNU (RMS with image without PRNU: {rmsDiffPil(toPilImage(imagesWithPrnu[0][0]), toPilImage(imagesWithoutPrnu[0][0]))})')
axs[2].imshow(imagesWithPrnu[0][0])
imagesWithPrnuPil0Mean = np.array(imagesWithPrnuPil[0]).mean(axis = 0)
#showImageWithMatplotlib(imagesWithPrnuPil0Mean)
axs[3].set_title('Mean of images with PRNU')
axs[3].imshow(imagesWithPrnuPil0Mean)
plt.show()
##
# Compute CAI of phone images.
caiImages = [[contextAdaptiveInterpolator(image.load(), image) for image in imagesWithPrnuPil[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(prnusPil):
prnuRmsDiff = rmsDiffPil(estimatedPrnu, prnu)
if nearestPrnuRmsDiff is None or prnuRmsDiff < nearestPrnuRmsDiff:
nearestPrnuRmsDiff = prnuRmsDiff
nearestPrnuPhoneIndex = phoneIndex
return nearestPrnuPhoneIndex
# Predict the phones based on the estimated PRNUs and compute each method accuracy.
# 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 = imagesWithPrnuPil[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 = prnusPil[phoneIndex]
print('RMS diff with mean image =', rmsDiffPil(phoneImagesMean, phonePrnu))
print('RMS diff with mean CAI images =', rmsDiffPil(caiImagesMean, phonePrnu))
print('RMS diff with CAI images mean =', rmsDiffPil(caiOverPhoneImagesMean, phonePrnu))
guessedPhoneIndexByMeanImages = getPhoneIndexByNearestPrnu(phoneImagesMean)
guessedPhoneIndexByMeanCAIImages = getPhoneIndexByNearestPrnu(caiImagesMean)
guessedPhoneIndexByCAIImagesMean = getPhoneIndexByNearestPrnu(caiOverPhoneImagesMean)
print(f'Actual phone index {phoneIndex}, guessed phone index {guessedPhoneIndexByMeanImages} by mean images, {guessedPhoneIndexByMeanCAIImages} by mean CAI images and {guessedPhoneIndexByCAIImagesMean} by CAI images mean')
correctGuessesByMeanImages += 1 if phoneIndex == guessedPhoneIndexByMeanImages else 0
correctGuessesByMeanCAIImages += 1 if phoneIndex == guessedPhoneIndexByMeanCAIImages else 0
correctGuessesByCAIImagesMean += 1 if phoneIndex == guessedPhoneIndexByCAIImagesMean else 0
print(f'{correctGuessesByMeanImages / NUMBER_OF_PHONES=}')
print(f'{correctGuessesByMeanCAIImages / NUMBER_OF_PHONES=}')
print(f'{correctGuessesByCAIImagesMean / NUMBER_OF_PHONES=}')