diff --git a/datasets/raise/attribute_source_camera.py b/datasets/raise/attribute_source_camera.py index def1d0c..f0832b3 100755 --- a/datasets/raise/attribute_source_camera.py +++ b/datasets/raise/attribute_source_camera.py @@ -3,15 +3,10 @@ import numpy as np import matplotlib.pyplot as plt from tqdm import tqdm -from utils import denoise, iterativeMean, getColorChannel, escapeFilePath, Color, mergeSingleColorChannelImagesAccordingToBayerFilter, rescaleRawImageForDenoiser, updateExtremes, saveNpArray, getColorMeans, getImageCrop, Denoiser -import sys +from utils import denoise, iterativeMean, getColorChannel, escapeFilePath, Color, mergeSingleColorChannelImagesAccordingToBayerFilter, rescaleRawImageForDenoiser, updateExtremes, saveNpArray, getColorMeans, getImageCrop, Denoiser, Distance import os import random -sys.path.insert(0, '../../algorithms/distance/') - -from rms_diff import rmsDiffNumpy - # Configuration: DENOISER = Denoiser.MEAN @@ -21,6 +16,17 @@ IMAGES_CAMERAS_FOLDER = { } TRAINING_PORTION = 0.5 PREDICT_ONLY_ON_WHOLE_TRAINING_SET = False +DISTANCE = Distance.ROOT_MEAN_SQUARE + +# See [Robust_image_source_identification_on_modern_smartphones/issues/22](https://gitea.lemnoslife.com/Benjamin_Loison/Robust_image_source_identification_on_modern_smartphones/issues/22). +match DISTANCE: + case Distance.ROOT_MEAN_SQUARE: + import sys + sys.path.insert(0, '../../algorithms/distance/') + from rms_diff import rmsDiffNumpy + case PEARSON_CORRELATION: + import scipy + from utils import getPearsonCorrelation setting = ','.join([escapeFilePath(imageCameraFolder) for imageCameraFolder in IMAGES_CAMERAS_FOLDER]) + f'_{DENOISER}' @@ -180,7 +186,11 @@ for computeExtremes in tqdm(([True] if minColor is None or maxColor is None else multipleColorsImage = getMultipleColorsImage(singleColorChannelImages) cameraTestingImageNoise = getImagePrnuEstimateNpArray(singleColorChannelImages, multipleColorsImage, camera) - distance = rmsDiffNumpy(cameraTestingImageNoise, camerasIterativeMean[camera].mean) + match DISTANCE: + case ROOT_MEAN_SQUARE: + distance = rmsDiffNumpy(cameraTestingImageNoise, camerasIterativeMean[camera].mean) + case PEARSON_CORRELATION: + distance = getPearsonCorrelation(cameraTestingImagesNoise[actualCamera][cameraTestingImageIndex], camerasIterativeMean[camera].mean) print(f'{cameraTrainingImageIndex=} {cameraTestingImageIndex=} {camera=} {actualCamera=} {distance=}') if minimalDistance is None or distance < minimalDistance: minimalDistance = distance diff --git a/datasets/raise/split_and_compare_prnus_of_subgroups.py b/datasets/raise/split_and_compare_prnus_of_subgroups.py index 0348d87..a42bdc5 100755 --- a/datasets/raise/split_and_compare_prnus_of_subgroups.py +++ b/datasets/raise/split_and_compare_prnus_of_subgroups.py @@ -3,18 +3,24 @@ import numpy as np import matplotlib.pyplot as plt from tqdm import tqdm -from utils import denoise, iterativeMean, getColorChannel, escapeFilePath, Color, mergeSingleColorChannelImagesAccordingToBayerFilter, rescaleRawImageForDenoiser, updateExtremes, saveNpArray, Denoiser -import sys +from utils import denoise, iterativeMean, getColorChannel, escapeFilePath, Color, mergeSingleColorChannelImagesAccordingToBayerFilter, rescaleRawImageForDenoiser, updateExtremes, saveNpArray, Denoiser, Distance import os import random -sys.path.insert(0, '../../algorithms/distance/') - -from rms_diff import rmsDiffNumpy - NUMBER_OF_SUBGROUPS = 2 DENOISER = Denoiser.WAVELET IMAGES_FOLDER = 'flat-field/NEF' +DISTANCE = Distance.ROOT_MEAN_SQUARE + +# See [Robust_image_source_identification_on_modern_smartphones/issues/22](https://gitea.lemnoslife.com/Benjamin_Loison/Robust_image_source_identification_on_modern_smartphones/issues/22). +match DISTANCE: + case Distance.ROOT_MEAN_SQUARE: + import sys + sys.path.insert(0, '../../algorithms/distance/') + from rms_diff import rmsDiffNumpy + case PEARSON_CORRELATION: + import scipy + from utils import getPearsonCorrelation setting = escapeFilePath(IMAGES_FOLDER) + f'_{DENOISER}' @@ -26,7 +32,7 @@ random.shuffle(imagesFileNames) numberOfImagesPerSubgroup = len(imagesFileNames) // NUMBER_OF_SUBGROUPS subgroupsIterativeMean = [iterativeMean() for _ in range(NUMBER_OF_SUBGROUPS)] -rmss = [] +distances = [] minColor = None maxColor = None @@ -55,16 +61,22 @@ for computeExtremes in tqdm(([True] if minColor is None or maxColor is None else subgroupIterativeMean.add(imagePrnuEstimateNpArray) if subgroupIndex == NUMBER_OF_SUBGROUPS - 1: assert NUMBER_OF_SUBGROUPS == 2 - rms = rmsDiffNumpy(subgroupIterativeMean.mean, subgroupsIterativeMean[1 - subgroupIndex].mean) - rmss += [rms] + firstImage = subgroupIterativeMean.mean + secondImage = subgroupsIterativeMean[1 - subgroupIndex].mean + match DISTANCE: + case ROOT_MEAN_SQUARE: + distance = rmsDiffNumpy(firstImage, secondImage) + case PEARSON_CORRELATION: + distance = getPearsonCorrelation(firstImage, secondImage) + distances += [distance] for subgroupIndex in range(NUMBER_OF_SUBGROUPS): plt.imsave(f'{setting}_estimated_prnu_subgroup_{subgroupIndex}.png', (subgroupsIterativeMean[subgroupIndex].mean)) -plt.title(f'RMS between both subgroups estimated PRNUs with {DENOISER} denoiser for a given number of images among them') +plt.title(f'{DISTANCE.getEndUserName()} between both subgroups estimated PRNUs with {DENOISER} denoiser for a given number of images among them') plt.xlabel('Number of images of each subgroup') -plt.ylabel('RMS between both subgroups estimated PRNUs') -plt.plot(rmss) -saveNpArray(f'{setting}_rmss', rmss) -plt.savefig(f'{setting}_rms_between_estimated_prnu_of_2_subgroups.svg') +plt.ylabel(f'{DISTANCE.getEndUserName()} between both subgroups estimated PRNUs') +plt.plot(distances) +saveNpArray(f'{setting}_{DISTANCE}s', distances) +plt.savefig(f'{setting}_{DISTANCE}_between_estimated_prnu_of_2_subgroups.svg') #plt.show() diff --git a/datasets/raise/utils.py b/datasets/raise/utils.py index 6c699a0..60c802f 100644 --- a/datasets/raise/utils.py +++ b/datasets/raise/utils.py @@ -33,6 +33,19 @@ class Denoiser(Enum): def __str__(self): return self.name.lower() +class Distance(Enum) + ROOT_MEAN_SQUARE = auto() + PEARSON_CORRELATION = auto() + + def __str__(self): + return self.name.lower() + + def getEndUserName(self): + return self.name.replace('_', '').title() + +def getPearsonCorrelation(firstImage, secondImage): + return abs(scipy.stats.pearsonr(firstImage.flatten(), secondImage.flatten()).statistic - 1) + # Source: https://stackoverflow.com/a/43346070 def getGaussianKernel(size, sigma): axis = np.linspace(-(size - 1) / 2., (size - 1) / 2., size)