From 319ca8fb60d64793a6e17ce5993d1a6648f2c49b Mon Sep 17 00:00:00 2001 From: Benjamin Loison <12752145+Benjamin-Loison@users.noreply.github.com> Date: Tue, 30 Apr 2024 04:48:02 +0200 Subject: [PATCH] Add `attribute_source_camera.py` It is a modified copy of `split_and_compare_prnus_of_subgroups.py`. --- datasets/raise/attribute_source_camera.py | 83 +++++++++++++++++++++++ 1 file changed, 83 insertions(+) create mode 100755 datasets/raise/attribute_source_camera.py diff --git a/datasets/raise/attribute_source_camera.py b/datasets/raise/attribute_source_camera.py new file mode 100755 index 0000000..f1bd461 --- /dev/null +++ b/datasets/raise/attribute_source_camera.py @@ -0,0 +1,83 @@ +#!/usr/bin/env python + +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 +import sys +import os +import random + +sys.path.insert(0, '../../algorithms/distance/') + +from rms_diff import rmsDiffNumpy + +DENOISER = 'wavelet' +IMAGES_CAMERAS_FOLDER = { + 'RAISE': 'flat-field/nef', + 'Rafael 23/04/24': 'rafael/230424', +} +TRAINING_PORTION = 0.5 + +setting = ','.join([escapeFilePath(imageCameraFolder) for imageCameraFolder in IMAGES_CAMERAS_FOLDER]) + f'_{DENOISER}' + +imagesCamerasFileNames = {camera: os.listdir(imageCameraFolder) for camera, imageCameraFolder in IMAGES_CAMERAS_FOLDER.items()} +random.seed(0) +# To not have a bias (chronological for instance) when split to make training and testing sets. +for camera in IMAGES_CAMERAS_FOLDER: + #print(imagesCamerasFileNames[camera][:3]) + random.shuffle(imagesCamerasFileNames[camera]) + #print(imagesCamerasFileNames[camera][:3]) + #exit(1) + +minimumNumberOfImagesCameras = 10#min([len(imagesCamerasFileNames[camera]) for camera in IMAGES_CAMERAS_FOLDER]) +#print(minimumNumberOfImagesCameras) +#exit(1) +for camera in IMAGES_CAMERAS_FOLDER: + IMAGES_CAMERAS_FOLDER[camera] = IMAGES_CAMERAS_FOLDER[camera][:minimumNumberOfImagesCameras] + +numberOfCameras = len(IMAGES_CAMERAS_FOLDER) +camerasIterativeMean = [iterativeMean() for _ in range(numberOfCameras)] + +minColor = None +maxColor = None + +accuracy = [] + +returnSingleColorChannelImage = lambda singleColorChannelImage, _minColor, _maxColor: singleColorChannelImage + +for computeExtremes in tqdm(([True] if minColor is None or maxColor is None else []) + [False], 'Compute extremes'): + rescaleIfNeeded = returnSingleColorChannelImage if computeExtremes else rescaleRawImageForDenoiser + for cameraImageIndex in tqdm(range(minimumNumberOfImagesCameras * TRAINING_PORTION), 'Camera image index'): + for cameraIndex, camera in enumerate(tqdm(IMAGES_CAMERAS_FOLDER, 'Camera')): + imageFileName = imagesCamerasFileNames[camera][cameraImageIndex] + imageFilePath = f'{IMAGES_CAMERAS_FOLDER[camera]}/{imageFileName}' + singleColorChannelImages = {color: rescaleIfNeeded(getColorChannel(imageFilePath, color), minColor, maxColor) for color in Color} + multipleColorsImage = mergeSingleColorChannelImagesAccordingToBayerFilter(singleColorChannelImages) + + if computeExtremes: + minColor, maxColor = updateExtremes(multipleColorsImage, minColor, maxColor) + continue + + singleColorChannelDenoisedImages = {color: denoise(singleColorChannelImages[color], DENOISER) for color in Color} + multipleColorsDenoisedImage = mergeSingleColorChannelImagesAccordingToBayerFilter(singleColorChannelDenoisedImages) + + imagePrnuEstimateNpArray = multipleColorsImage - multipleColorsDenoisedImage + cameraIterativeMean = subgroupsIterativeMean[cameraIndex] + cameraIterativeMean.add(imagePrnuEstimateNpArray) + if cameraIndex == numberOfCameras - 1: + rms = rmsDiffNumpy(subgroupIterativeMean.mean, subgroupsIterativeMean[1 - cameraIndex].mean) + rmss += [rms] + if computeExtremes: + print(f'{minColor=} {maxColor=}') + +for camera in range(IMAGES_CAMERAS_FOLDER): + plt.imsave(f'{setting}_estimated_prnu_subgroup_{escapeFilePath(camera)}.png', (subgroupsIterativeMean[cameraIndex].mean)) + +plt.title(f'Accuracy of camera source attribution thanks to a given number of images to estimate PRNUs with {DENOISER} denoiser') +plt.xlabel('Number of images to estimate PRNU') +plt.ylabel('Accuracy of camera source attribution') +plt.plot(accuracy) +internalTitle = f'{setting}_accuracy_of_camera_source_attribution' +saveNpArray(internalTitle, accuracy) +plt.savefig(f'{internalTitle}.svg')