Showing preview only (1,526K chars total). Download the full file or copy to clipboard to get everything.
Repository: grip-unina/noiseprint
Branch: master
Commit: c06034eedc92
Files: 199
Total size: 28.1 MB
Directory structure:
gitextract_pvls8abb/
├── .gitignore
├── LICENSE.txt
├── README.md
├── demo/
│ ├── demo_extraction.sh
│ ├── demo_heatmap.sh
│ └── outs/
│ ├── NC2016_2564_map.mat
│ ├── faceswap_map.mat
│ ├── faceswap_np.mat
│ ├── inpainting_np.mat
│ ├── seamcarving_map.mat
│ ├── splicing_map.mat
│ └── splicing_np.mat
├── docs/
│ ├── _config.yml
│ └── index.md
├── main_blind.py
├── main_extraction.py
├── main_map2uint8.py
├── main_showout.py
├── main_showres.py
├── noiseprint/
│ ├── __init__.py
│ ├── feat_spam/
│ │ ├── __init__.py
│ │ ├── mapping.py
│ │ ├── residue.py
│ │ └── spam_np_opt.py
│ ├── nets/
│ │ ├── net_jpg100/
│ │ │ ├── model.data-00000-of-00001
│ │ │ ├── model.index
│ │ │ └── model.meta
│ │ ├── net_jpg101/
│ │ │ ├── model.data-00000-of-00001
│ │ │ ├── model.index
│ │ │ └── model.meta
│ │ ├── net_jpg51/
│ │ │ ├── model.data-00000-of-00001
│ │ │ ├── model.index
│ │ │ └── model.meta
│ │ ├── net_jpg52/
│ │ │ ├── model.data-00000-of-00001
│ │ │ ├── model.index
│ │ │ └── model.meta
│ │ ├── net_jpg53/
│ │ │ ├── model.data-00000-of-00001
│ │ │ ├── model.index
│ │ │ └── model.meta
│ │ ├── net_jpg54/
│ │ │ ├── model.data-00000-of-00001
│ │ │ ├── model.index
│ │ │ └── model.meta
│ │ ├── net_jpg55/
│ │ │ ├── model.data-00000-of-00001
│ │ │ ├── model.index
│ │ │ └── model.meta
│ │ ├── net_jpg56/
│ │ │ ├── model.data-00000-of-00001
│ │ │ ├── model.index
│ │ │ └── model.meta
│ │ ├── net_jpg57/
│ │ │ ├── model.data-00000-of-00001
│ │ │ ├── model.index
│ │ │ └── model.meta
│ │ ├── net_jpg58/
│ │ │ ├── model.data-00000-of-00001
│ │ │ ├── model.index
│ │ │ └── model.meta
│ │ ├── net_jpg59/
│ │ │ ├── model.data-00000-of-00001
│ │ │ ├── model.index
│ │ │ └── model.meta
│ │ ├── net_jpg60/
│ │ │ ├── model.data-00000-of-00001
│ │ │ ├── model.index
│ │ │ └── model.meta
│ │ ├── net_jpg61/
│ │ │ ├── model.data-00000-of-00001
│ │ │ ├── model.index
│ │ │ └── model.meta
│ │ ├── net_jpg62/
│ │ │ ├── model.data-00000-of-00001
│ │ │ ├── model.index
│ │ │ └── model.meta
│ │ ├── net_jpg63/
│ │ │ ├── model.data-00000-of-00001
│ │ │ ├── model.index
│ │ │ └── model.meta
│ │ ├── net_jpg64/
│ │ │ ├── model.data-00000-of-00001
│ │ │ ├── model.index
│ │ │ └── model.meta
│ │ ├── net_jpg65/
│ │ │ ├── model.data-00000-of-00001
│ │ │ ├── model.index
│ │ │ └── model.meta
│ │ ├── net_jpg66/
│ │ │ ├── model.data-00000-of-00001
│ │ │ ├── model.index
│ │ │ └── model.meta
│ │ ├── net_jpg67/
│ │ │ ├── model.data-00000-of-00001
│ │ │ ├── model.index
│ │ │ └── model.meta
│ │ ├── net_jpg68/
│ │ │ ├── model.data-00000-of-00001
│ │ │ ├── model.index
│ │ │ └── model.meta
│ │ ├── net_jpg69/
│ │ │ ├── model.data-00000-of-00001
│ │ │ ├── model.index
│ │ │ └── model.meta
│ │ ├── net_jpg70/
│ │ │ ├── model.data-00000-of-00001
│ │ │ ├── model.index
│ │ │ └── model.meta
│ │ ├── net_jpg71/
│ │ │ ├── model.data-00000-of-00001
│ │ │ ├── model.index
│ │ │ └── model.meta
│ │ ├── net_jpg72/
│ │ │ ├── model.data-00000-of-00001
│ │ │ ├── model.index
│ │ │ └── model.meta
│ │ ├── net_jpg73/
│ │ │ ├── model.data-00000-of-00001
│ │ │ ├── model.index
│ │ │ └── model.meta
│ │ ├── net_jpg74/
│ │ │ ├── model.data-00000-of-00001
│ │ │ ├── model.index
│ │ │ └── model.meta
│ │ ├── net_jpg75/
│ │ │ ├── model.data-00000-of-00001
│ │ │ ├── model.index
│ │ │ └── model.meta
│ │ ├── net_jpg76/
│ │ │ ├── model.data-00000-of-00001
│ │ │ ├── model.index
│ │ │ └── model.meta
│ │ ├── net_jpg77/
│ │ │ ├── model.data-00000-of-00001
│ │ │ ├── model.index
│ │ │ └── model.meta
│ │ ├── net_jpg78/
│ │ │ ├── model.data-00000-of-00001
│ │ │ ├── model.index
│ │ │ └── model.meta
│ │ ├── net_jpg79/
│ │ │ ├── model.data-00000-of-00001
│ │ │ ├── model.index
│ │ │ └── model.meta
│ │ ├── net_jpg80/
│ │ │ ├── model.data-00000-of-00001
│ │ │ ├── model.index
│ │ │ └── model.meta
│ │ ├── net_jpg81/
│ │ │ ├── model.data-00000-of-00001
│ │ │ ├── model.index
│ │ │ └── model.meta
│ │ ├── net_jpg82/
│ │ │ ├── model.data-00000-of-00001
│ │ │ ├── model.index
│ │ │ └── model.meta
│ │ ├── net_jpg83/
│ │ │ ├── model.data-00000-of-00001
│ │ │ ├── model.index
│ │ │ └── model.meta
│ │ ├── net_jpg84/
│ │ │ ├── model.data-00000-of-00001
│ │ │ ├── model.index
│ │ │ └── model.meta
│ │ ├── net_jpg85/
│ │ │ ├── model.data-00000-of-00001
│ │ │ ├── model.index
│ │ │ └── model.meta
│ │ ├── net_jpg86/
│ │ │ ├── model.data-00000-of-00001
│ │ │ ├── model.index
│ │ │ └── model.meta
│ │ ├── net_jpg87/
│ │ │ ├── model.data-00000-of-00001
│ │ │ ├── model.index
│ │ │ └── model.meta
│ │ ├── net_jpg88/
│ │ │ ├── model.data-00000-of-00001
│ │ │ ├── model.index
│ │ │ └── model.meta
│ │ ├── net_jpg89/
│ │ │ ├── model.data-00000-of-00001
│ │ │ ├── model.index
│ │ │ └── model.meta
│ │ ├── net_jpg90/
│ │ │ ├── model.data-00000-of-00001
│ │ │ ├── model.index
│ │ │ └── model.meta
│ │ ├── net_jpg91/
│ │ │ ├── model.data-00000-of-00001
│ │ │ ├── model.index
│ │ │ └── model.meta
│ │ ├── net_jpg92/
│ │ │ ├── model.data-00000-of-00001
│ │ │ ├── model.index
│ │ │ └── model.meta
│ │ ├── net_jpg93/
│ │ │ ├── model.data-00000-of-00001
│ │ │ ├── model.index
│ │ │ └── model.meta
│ │ ├── net_jpg94/
│ │ │ ├── model.data-00000-of-00001
│ │ │ ├── model.index
│ │ │ └── model.meta
│ │ ├── net_jpg95/
│ │ │ ├── model.data-00000-of-00001
│ │ │ ├── model.index
│ │ │ └── model.meta
│ │ ├── net_jpg96/
│ │ │ ├── model.data-00000-of-00001
│ │ │ ├── model.index
│ │ │ └── model.meta
│ │ ├── net_jpg97/
│ │ │ ├── model.data-00000-of-00001
│ │ │ ├── model.index
│ │ │ └── model.meta
│ │ ├── net_jpg98/
│ │ │ ├── model.data-00000-of-00001
│ │ │ ├── model.index
│ │ │ └── model.meta
│ │ └── net_jpg99/
│ │ ├── model.data-00000-of-00001
│ │ ├── model.index
│ │ └── model.meta
│ ├── network.py
│ ├── noiseprint.py
│ ├── noiseprint_blind.py
│ ├── post_em.py
│ ├── requirements-cpu.txt
│ ├── requirements-gpu.txt
│ └── utility/
│ ├── __init__.py
│ ├── gaussianMixture.py
│ └── utilityRead.py
└── training/
├── LICENSE.txt
├── README.md
├── code/
│ ├── FCnet.py
│ ├── Producer2.py
│ ├── create_data.py
│ ├── db_utility.py
│ ├── train_denoiser.py
│ ├── train_noiseprint.py
│ └── train_utility.py
└── dataset/
├── README.txt
├── download_images.py
├── list_images.csv
└── list_models.csv
================================================
FILE CONTENTS
================================================
================================================
FILE: .gitignore
================================================
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class
# C extensions
*.so
# Distribution / packaging
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
*.egg-info/
.installed.cfg
*.egg
MANIFEST
# PyInstaller
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec
# Installer logs
pip-log.txt
pip-delete-this-directory.txt
# Unit test / coverage reports
htmlcov/
.tox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*.cover
.hypothesis/
.pytest_cache/
# Translations
*.mo
*.pot
# Django stuff:
*.log
local_settings.py
db.sqlite3
# Flask stuff:
instance/
.webassets-cache
# Scrapy stuff:
.scrapy
# Sphinx documentation
docs/_build/
# PyBuilder
target/
# Jupyter Notebook
.ipynb_checkpoints
# pyenv
.python-version
# celery beat schedule file
celerybeat-schedule
# SageMath parsed files
*.sage.py
# Environments
.env
.venv
env/
venv/
ENV/
env.bak/
venv.bak/
# Spyder project settings
.spyderproject
.spyproject
# Rope project settings
.ropeproject
# mkdocs documentation
/site
# mypy
.mypy_cache/
================================================
FILE: LICENSE.txt
================================================
THIS DOCUMENT CONSTITUTES A LICENCE TO USE THE SOFTWARE ON THE TERMS AND CONDITIONS APPEARING BELOW.
Preamble
This License applies to the software with which this license is distributed.
The software is intellectual property of Image Processing Research Group of University Federico II of Naples ('GRIP-UNINA')
and is placed under the protection of copyright laws, including Italian legislation and international treaties.
BY USING THE PROGRAM, YOU INDICATE YOUR ACCEPTANCE OF THIS LICENSE TO DO SO.
Terms and Conditions
Reproduction, modification, and usage of the software covered by this license is allowed free of charge provided that:
(i) this software should be used, reproduced and modified only for informational and nonprofit purposes; any unauthorized use of this software for industrial or profit-oriented activities is expressly prohibited; and
(ii) any reproduction or modification retains all original notices including proprietary or copyright notices; and
(iii) reference to the original authors is given whenever results, which arise from the use of this software or any modification of it, are made public.
No other use of the materials and of any information incorporated thereto is hereby authorized.
In addition, be informed that some names are protected by trademarks which are the property of GRIP-UNINA, its researchers and/or other third parties whether a specific mention in that respect is made or not.
Disclaimers
This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from the use of this software.
Transmission of user information
Any and all information or request for information you may direct to GRIP
through e-mail as may be linked to website http://www.grip.unina.it/
================================================
FILE: README.md
================================================
# Noiseprint: a CNN-based camera model fingerprint
[Noiseprint](https://ieeexplore.ieee.org/document/8713484) is a CNN-based camera model fingerprint
extracted by a fully Convolutional Neural Network (CNN).
## License
Copyright (c) 2019 Image Processing Research Group of University Federico II of Naples ('GRIP-UNINA').
All rights reserved.
This software should be used, reproduced and modified only for informational and nonprofit purposes.
By downloading and/or using any of these files, you implicitly agree to all the
terms of the license, as specified in the document LICENSE.txt
(included in this package)
## Installation
The code requires Python 3.x and Tensorflow 1.2.1 .
To install Python 3.x for Ubuntu, you can run:
```
apt-get update
apt-get install -y python3.5 python3.5-dev python3-pip python3-venv
```
We recommend to use a virtual environment:
```
python3.5 -m venv ../venv
source ../venv/bin/activate
pip install --upgrade pip
```
### Installation with GPU
Install Cuda8 and Cudnn5, more informetion on sites:
- https://developer.nvidia.com/cuda-downloads
- https://developer.nvidia.com/cudnn
Then install the requested libraries using:
```
cat noiseprint/requirements-gpu.txt | xargs -n 1 -L 1 pip install
```
### Installation without GPU
Install the requested libraries using:
```
cat noiseprint/requirements-cpu.txt | xargs -n 1 -L 1 pip install
```
## Usage
To extract the noiseprint, run:
```
python main_extraction.py <input image> <output mat/npz file>
```
The noiseprint is saved in a file with extension mat or npz.
To show the saved noiseprint, run:
```
python main_showout.py <input image> <output mat/npz file>
```
While to execute the blind localization method, run:
```
python main_blind.py <input image> <output mat/npz file>
```
The heatmap is saved in a file with extension mat or npz.
To show the result, run:
```
python main_showres.py <input image> <gt image> <output mat/npz file>
```
To convert the heatmap in a png image, run:
```
python main_map2uint8.py <output mat/npz file> <output png file>
```
### Demo
To execute the demo, run the script
```
cd ./demo
./demo_extraction.sh
./demo_heatmap.sh
```
## Reference
```js
@article{Cozzolino2019_Noiseprint,
title={Noiseprint: A CNN-Based Camera Model Fingerprint},
author={D. Cozzolino and L. Verdoliva},
journal={IEEE Transactions on Information Forensics and Security},
doi={10.1109/TIFS.2019.2916364},
pages={144-159},
year={2020},
volume={15}
}
```
================================================
FILE: demo/demo_extraction.sh
================================================
rm ./outs/*_np.mat
python ../main_extraction.py ./imgs/splicing.png ./outs/splicing_np.mat
python ../main_showout.py ./imgs/splicing.png ./outs/splicing_np.mat
python ../main_extraction.py ./imgs/faceswap.jpg ./outs/faceswap_np.mat
python ../main_showout.py ./imgs/faceswap.jpg ./outs/faceswap_np.mat
python ../main_extraction.py ./imgs/inpainting.png ./outs/inpainting_np.mat
python ../main_showout.py ./imgs/inpainting.png ./outs/inpainting_np.mat
================================================
FILE: demo/demo_heatmap.sh
================================================
rm ./outs/NC2016_2564_map.mat
python ../main_blind.py ./imgs/NC2016_2564.jpg ./outs/NC2016_2564_map.mat
python ../main_showres.py ./imgs/NC2016_2564.jpg ./refs/NC2016_2564_gt.png ./outs/NC2016_2564_map.mat
================================================
FILE: demo/outs/faceswap_np.mat
================================================
[File too large to display: 14.6 MB]
================================================
FILE: demo/outs/splicing_np.mat
================================================
[File too large to display: 12.0 MB]
================================================
FILE: docs/_config.yml
================================================
remote_theme: grip-unina/webtemplate
plugins:
- jekyll
- jekyll-seo-tag
================================================
FILE: docs/index.md
================================================
---
layout: paper
paper: Noiseprint:<br/> a CNN-based camera model fingerprint
github_url: https://github.com/grip-unina/noiseprint
authors:
- name: Davide Cozzolino
link: https://www.grip.unina.it/members/cozzolino
index: 1
- name: Luisa Verdoliva
link: https://www.grip.unina.it/members/verdoliva
index: 1
affiliations:
- name: University Federico II of Naples, Italy
index: 1
links:
paper: https://ieeexplore.ieee.org/document/8713484
arxiv: https://arxiv.org/abs/1808.08396
code: https://github.com/grip-unina/noiseprint
---
<center><img src="./header.gif" alt="header" width="50%" /></center>
Forensic analyses of digital images rely heavily on the traces of in-camera and out-camera processes left on the acquired images.
Such traces represent a sort of camera fingerprint.
If one is able to recover them, by suppressing the high-level scene content and other disturbances, a number of forensic tasks
can be easily accomplished. A notable example is the PRNU pattern, which can be regarded as a device fingerprint, and has received great attention in multimedia forensics.
In this paper we propose a method to extract a camera model fingerprint, called noiseprint, where the scene content is largely suppressed and model-related artifacts are enhanced.
This is obtained by means of a Siamese network, which is trained with pairs of image patches coming from the same (label +1) or different (label −1) cameras.
Although noiseprints can be used for a large variety of forensic tasks, here we focus on image forgery localization.
Experiments on several datasets widespread in the forensic community show noiseprint-based methods to provide state-of-the-art performance.
## News
* 2019-05-13: Paper was published in IEEE Transactions on Information Forensics and Security.
## Bibtex
```javascript
@article{Cozzolino2019_Noiseprint,
title={Noiseprint: A CNN-Based Camera Model Fingerprint},
author={D. Cozzolino and L. Verdoliva},
journal={IEEE Transactions on Information Forensics and Security},
doi={10.1109/TIFS.2019.2916364},
pages={144-159},
year={2020},
volume={15}
}
```
================================================
FILE: main_blind.py
================================================
# This code is the main of the noiseprint_blind
# python main_blind.py input.png output.mat
# python main_showout.py input.png output.mat
#
# %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
#
# Copyright (c) 2019 Image Processing Research Group of University Federico II of Naples ('GRIP-UNINA').
# All rights reserved.
# This work should only be used for nonprofit purposes.
#
# By downloading and/or using any of these files, you implicitly agree to all the
# terms of the license, as specified in the document LICENSE.txt
# (included in this package) and online at
# http://www.grip.unina.it/download/LICENSE_OPEN.txt
#
from sys import argv
import scipy.io as sio
from time import time
import io
from noiseprint.noiseprint_blind import noiseprint_blind_file
imgfilename = argv[1]
outfilename = argv[2]
with open(imgfilename,'rb') as f:
stream = io.BytesIO(f.read())
timestamp = time()
QF, mapp, valid, range0, range1, imgsize, other = noiseprint_blind_file(imgfilename)
timeApproach = time() - timestamp
if mapp is None:
print('Image is too small or too uniform')
out_dict = dict()
out_dict['QF' ] = QF
out_dict['map' ] = mapp
out_dict['valid' ] = valid
out_dict['range0' ] = range0
out_dict['range1' ] = range1
out_dict['imgsize'] = imgsize
out_dict['other' ] = other
out_dict['time' ] = timeApproach
if outfilename[-4:] == '.mat':
import scipy.io as sio
sio.savemat(outfilename, out_dict)
else:
import numpy as np
np.savez(outfilename, **out_dict)
================================================
FILE: main_extraction.py
================================================
# This is the code to extract Noiseprint
# python main_extraction.py input.png noiseprint.mat
# python main_showout.py input.png noiseprint.mat
#
# %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
#
# Copyright (c) 2019 Image Processing Research Group of University Federico II of Naples ('GRIP-UNINA').
# All rights reserved.
# This work should only be used for nonprofit purposes.
#
# By downloading and/or using any of these files, you implicitly agree to all the
# terms of the license, as specified in the document LICENSE.txt
# (included in this package) and online at
# http://www.grip.unina.it/download/LICENSE_OPEN.txt
#
from sys import argv
from time import time
from noiseprint.noiseprint import genNoiseprint
from noiseprint.utility.utilityRead import imread2f
from noiseprint.utility.utilityRead import jpeg_qtableinv
imgfilename = argv[1]
outfilename = argv[2]
timestamp = time()
img, mode = imread2f(imgfilename, channel=1)
try:
QF = jpeg_qtableinv(strimgfilenameeam)
except:
QF = 200
res = genNoiseprint(img,QF)
timeApproach = time() - timestamp
out_dict = dict()
out_dict['noiseprint'] = res
out_dict['QF'] = QF
out_dict['time'] = timeApproach
if outfilename[-4:] == '.mat':
import scipy.io as sio
sio.savemat(outfilename, out_dict)
else:
import numpy as np
np.savez(outfilename, **out_dict)
================================================
FILE: main_map2uint8.py
================================================
# This code converts the noiseprint_blind output in a PNG image
# python main_mat2uint8.py output.mat output.png
#
# %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
#
# Copyright (c) 2019 Image Processing Research Group of University Federico II of Naples ('GRIP-UNINA').
# All rights reserved.
# This work should only be used for nonprofit purposes.
#
# By downloading and/or using any of these files, you implicitly agree to all the
# terms of the license, as specified in the document LICENSE.txt
# (included in this package) and online at
# http://www.grip.unina.it/download/LICENSE_OPEN.txt
#
from sys import argv
mapfilename = argv[1]
outfilename = argv[2]
if mapfilename[-4:] == '.mat':
import scipy.io as sio
dat = sio.loadmat(mapfilename)
else:
import numpy as np
dat = np.load(mapfilename)
mapp = dat['map']
valid = dat['valid']
range0 = dat['range0'].flatten()
range1 = dat['range1'].flatten()
imgsize = dat['imgsize'].flatten()
from noiseprint.noiseprint_blind import genMappUint8
mapUint8 = genMappUint8(mapp, valid, range0, range1, imgsize)
from PIL import Image
Image.fromarray(mapUint8).save(outfilename)
================================================
FILE: main_showout.py
================================================
# This code shows the noiseprint_blind output
# python main_blind.py input.png output.mat
# python main_showout.py input.png output.mat
#
# %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
#
# Copyright (c) 2019 Image Processing Research Group of University Federico II of Naples ('GRIP-UNINA').
# All rights reserved.
# This work should only be used for nonprofit purposes.
#
# By downloading and/or using any of these files, you implicitly agree to all the
# terms of the license, as specified in the document LICENSE.txt
# (included in this package) and online at
# http://www.grip.unina.it/download/LICENSE_OPEN.txt
#
import matplotlib.pyplot as plt
import numpy as np
from sys import argv
imgfilename = argv[1]
outfilename = argv[2]
print(' %s' % imgfilename)
from noiseprint.utility.utilityRead import imread2f
img, mode = imread2f(imgfilename, channel = 3)
print('size : ', img.shape)
if outfilename[-4:] == '.mat':
import scipy.io as sio
dat = sio.loadmat(outfilename)
else:
import numpy as np
dat = np.load(outfilename)
time = dat['time'].flatten()
qf = dat['QF'].flatten()
print('time : %g' % time)
print('qf : %g' % qf)
if 'noiseprint' in dat.keys():
res = dat['noiseprint']
vmin = np.min(res[34:-34,34:-34])
vmax = np.max(res[34:-34,34:-34])
plt.figure()
plt.subplot(1,2,1)
plt.imshow(img, clim=[0,1])
plt.title('input \n image (%s, %d)' % (mode, qf))
plt.subplot(1,2,2)
plt.imshow(res.clip(vmin,vmax), clim=[vmin,vmax], cmap='gray')
plt.title('noiseprint')
plt.show()
if 'map' in dat.keys():
mapp = dat['map']
valid = dat['valid']
range0 = dat['range0'].flatten()
range1 = dat['range1'].flatten()
imgsize = dat['imgsize'].flatten()
from noiseprint.noiseprint_blind import genMappUint8
mapUint8 = genMappUint8(mapp, valid, range0,range1, imgsize)
plt.figure()
plt.subplot(1,2,1)
plt.imshow(img, clim=[0,1])
plt.title('input \n image (%s, %d)' % (mode, qf))
plt.subplot(1,2,2)
plt.imshow(mapUint8, clim=[0,255], cmap='gray')
plt.title('heatmap')
plt.show()
================================================
FILE: main_showres.py
================================================
# This code shows the result of noiseprint_blind output
# python main_blind.py input.png output.mat
# python main_showres.py input.png reference.png output.mat
#
# %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
#
# Copyright (c) 2019 Image Processing Research Group of University Federico II of Naples ('GRIP-UNINA').
# All rights reserved.
# This work should only be used for nonprofit purposes.
#
# By downloading and/or using any of these files, you implicitly agree to all the
# terms of the license, as specified in the document LICENSE.txt
# (included in this package) and online at
# http://www.grip.unina.it/download/LICENSE_OPEN.txt
#
erodeKernSize = 15
dilateKernSize = 11
import matplotlib.pyplot as plt
import matplotlib.gridspec as gridspec
import numpy as np
from sys import argv
imgfilename = argv[1]
reffilename = argv[2]
outfilename = argv[3]
print(' %s' % imgfilename)
from noiseprint.utility.utilityRead import imread2f, computeMCC
from noiseprint.noiseprint_blind import genMappFloat
from scipy.ndimage.filters import maximum_filter
from scipy.ndimage.filters import minimum_filter
from sklearn import metrics
img, mode = imread2f(imgfilename, channel = 3)
gt = imread2f(reffilename, channel = 1)[0]>0.5
print('size : ', img.shape)
assert(img.shape[0]==gt.shape[0])
assert(img.shape[1]==gt.shape[1])
gt1 = minimum_filter(gt, erodeKernSize)
gt0 = np.logical_not(maximum_filter(gt, dilateKernSize))
gtV = np.logical_or(gt0, gt1)
if outfilename[-4:] == '.mat':
import scipy.io as sio
dat = sio.loadmat(outfilename)
else:
import numpy as np
dat = np.load(outfilename)
time = dat['time'].flatten()
qf = dat['QF'].flatten()
print('time : %g' % time)
print('qf : %g' % qf)
valid = dat['valid']
range0 = dat['range0'].flatten()
range1 = dat['range1'].flatten()
imgsize = dat['imgsize'].flatten()
mapp = genMappFloat(dat['map'], valid, range0,range1, imgsize)
plt.figure(figsize=(3*5,2*5))
grid = gridspec.GridSpec(2, 3, wspace=0.2, hspace=0.2, )
plt.subplot(grid[0,0])
plt.imshow(img, clim=[0,1])
plt.title('Input image')
plt.subplot(grid[0,1])
plt.imshow(gt, clim=[0,1], cmap='gray')
plt.title('Ground truth')
plt.subplot(grid[0,2])
plt.imshow(mapp, clim=[np.nanmin(mapp),np.nanmax(mapp)], cmap='jet')
plt.title('Heatmap')
mcc, ths = computeMCC(mapp, gt0, gt1)
plt.subplot(grid[1,:2])
plt.plot(ths,mcc)
plt.grid()
plt.xlabel('threshold'); plt.ylabel('|MCC|')
plt.legend(['max |MCC|=%5.3f'%np.max(mcc)])
plt.title('Matthews Correlation Coefficient')
ap1 = metrics.average_precision_score(gt1[gtV], +mapp[gtV])
ap2 = metrics.average_precision_score(gt1[gtV], -mapp[gtV])
smapp = mapp if ap1>=ap2 else -mapp
ap = max(ap1, ap2)
prec, racall, _ = metrics.precision_recall_curve(gt1[gtV], smapp[gtV])
plt.subplot(grid[1,2])
plt.plot(racall, prec)
plt.grid();
plt.xlabel('recall '); plt.ylabel('precision')
plt.legend(['AP=%5.3f'%ap])
plt.title('precision-recall curve')
plt.show()
================================================
FILE: noiseprint/__init__.py
================================================
# %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
#
# Copyright (c) 2018 Image Processing Research Group of University Federico II of Naples ('GRIP-UNINA').
# All rights reserved.
# This work should only be used for nonprofit purposes.
#
# By downloading and/or using any of these files, you implicitly agree to all the
# terms of the license, as specified in the document LICENSE.txt
# (included in this package) and online at
# http://www.grip.unina.it/download/LICENSE_OPEN.txt
#
================================================
FILE: noiseprint/feat_spam/__init__.py
================================================
# %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
#
# Copyright (c) 2016 Image Processing Research Group of University Federico II of Naples ('GRIP-UNINA').
# All rights reserved.
# This work should only be used for nonprofit purposes.
#
# By downloading and/or using any of these files, you implicitly agree to all the
# terms of the license, as specified in the document LICENSE.txt
# (included in this package) and online at
# http://www.grip.unina.it/download/LICENSE_OPEN.txt
#
================================================
FILE: noiseprint/feat_spam/mapping.py
================================================
# %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
#
# Copyright (c) 2016 Image Processing Research Group of University Federico II of Naples ('GRIP-UNINA').
# All rights reserved.
# This work should only be used for nonprofit purposes.
#
# By downloading and/or using any of these files, you implicitly agree to all the
# terms of the license, as specified in the document LICENSE.txt
# (included in this package) and online at
# http://www.grip.unina.it/download/LICENSE_OPEN.txt
#
import numpy as np
def getIdemMapper(num):
return {'num': num,'numIn': num, 'table': np.asarray(range(num),dtype=np.int)}
def getSignSymMapper(occo, n):
#n = 2 * T + 1
numIn = n ** occo
P = getCombinations(occo, n)
V = np.ones([numIn, 1], dtype= np.bool)
table = np.zeros([numIn, 1], dtype= np.int)
indexOut = 0
for index in range(numIn):
if V[index]:
table[index] = indexOut
V[index] = False
H = P[index,:]
indexS = getPos(n-1-H, n, occo)
table[indexS] = indexOut
V[indexS] = False
H = np.flipud(H)
indexS = getPos(H, n, occo)
table[indexS] = indexOut
V[indexS] = False
indexS = getPos(n-1-H, n, occo)
table[indexS] = indexOut
V[indexS] = False
indexOut = indexOut + 1
return {'num': indexOut, 'numIn': numIn, 'table': table}
def getSignMapper(occo, n):
#n = 2 * T + 1
numIn = n ** occo
numOut = (numIn-1)/2 + 1
P = getCombinations(occo, n)
V = np.ones([numIn, 1], dtype= np.bool)
table = np.zeros([numIn, 1], dtype= np.int)
indexOut = 0
for index in range(numIn):
if V[index]:
table[index] = indexOut
V[index] = False
H = n-1-P[index,:]
indexS = getPos(H, n, occo)
table[indexS] = indexOut
V[indexS] = False
indexOut = indexOut + 1
return {'num': numOut, 'numIn': numIn, 'table': table}
def getPos(P, n, occo):
return np.matmul(P, np.power(n, range(0, occo)))
def getCombinations(occo, n):
num = n ** occo
P = np.zeros([num, occo], dtype=np.int)
P[0, :] = 0
for indexI in range(1 ,num):
P[indexI ,:] = P[indexI - 1 ,:]
for indexJ in range(occo):
P[indexI, indexJ] = P[indexI, indexJ] + 1
if P[indexI, indexJ] >= n:
P[indexI, indexJ] = 0
else:
break
return P
def mapper2filter(mapper, dtype=np.float32):
table = mapper['table']
W = np.zeros([1, 1, len(table), mapper['num']], dtype=dtype)
for index in range(mapper['num']):
W[0,0,:,index] = (np.equal(table,index)).squeeze().astype(dtype)
return W
================================================
FILE: noiseprint/feat_spam/residue.py
================================================
# %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
#
# Copyright (c) 2016 Image Processing Research Group of University Federico II of Naples ('GRIP-UNINA').
# All rights reserved.
# This work should only be used for nonprofit purposes.
#
# By downloading and/or using any of these files, you implicitly agree to all the
# terms of the license, as specified in the document LICENSE.txt
# (included in this package) and online at
# http://www.grip.unina.it/download/LICENSE_OPEN.txt
#
import numpy as np
from .mapping import getCombinations
def getFiltersResidue(res):
try:
if not(isinstance(res,basestring)): res = str(res)
except:
if not(isinstance(res,str)): res = str(res)
resTranspose = False
if res == '0':
# zero order
W = np.zeros([3,3,1,1],dtype=np.float32)
W[1, 1, 0, 0] = 1.0
F = 1.0
elif res == '1':
# 1st order
W = np.zeros([3,3,1,1],dtype=np.float32)
W[1, :, 0, 0] = [-1.0, 1.0, 0]
resTranspose = True
F = 1.0
elif res == '2':
# 2nd order
W = np.zeros([3, 3, 1, 1], dtype=np.float32)
W[1, :, 0, 0] = [-1.0, 2.0, -1.0]
resTranspose = True
F = 2.0
elif res == '3':
# 3rd order
W = np.zeros([5, 5, 1, 1], dtype=np.float32)
W[2, :, 0, 0] = [ 0.0, +1.0, -3.0, +3.0, -1.0]
resTranspose = True
F = 3.0
elif res == '5x5':
# 5x5
W = np.zeros([5, 5, 1, 1], dtype=np.float32)
W[0, :, 0, 0] = [-1.0, +2.0, -2.0, +2.0, -1.0]
W[1, :, 0, 0] = [+2.0, -6.0, +8.0, -6.0, +2.0]
W[2, :, 0, 0] = [-2.0, +8.0, -12.0, +8.0, -2.0]
W[3, :, 0, 0] = [+2.0, -6.0, +8.0, -6.0, +2.0]
W[4, :, 0, 0] = [-1.0, +2.0, -2.0, +2.0, -1.0]
F = 12.0
else:
W = np.zeros([1, 1, 1, 1], dtype=np.float32)
F = 0
# W = [1, -4, 6, -4, 1;] / 6;
# W = [- 1, 5, -10, 10, -5, 1;] / 10;
# W = [- 1, 6, -15, 20, -15, 6, -1;] / 20;
return W, F, resTranspose
def getFilterOcco(occo, values):
dim = int(occo + 1 - (occo%2))
values = np.asarray(values).astype(np.float32)
M = np.zeros([occo, dim * dim], dtype=np.float32)
f = int((dim-1)/2)
for index in range(occo):
R = np.zeros([dim, dim], dtype=np.float32)
R[index, f] = 1.0
M[index, :] = R.flatten()
P = getCombinations(occo, len(values))
V = values[P]
n = V.shape[0]
W = np.matmul(V, M)
B = -0.5 * np.sum(np.square(V), axis=1)
W = np.reshape(W, [n, dim, dim, 1])
W = np.transpose(W, [1, 2, 3, 0])
return W, B
================================================
FILE: noiseprint/feat_spam/spam_np_opt.py
================================================
# %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
#
# Copyright (c) 2016 Image Processing Research Group of University Federico II of Naples ('GRIP-UNINA').
# All rights reserved.
# This work should only be used for nonprofit purposes.
#
# By downloading and/or using any of these files, you implicitly agree to all the
# terms of the license, as specified in the document LICENSE.txt
# (included in this package) and online at
# http://www.grip.unina.it/download/LICENSE_OPEN.txt
#
import numpy as np
from .residue import getFiltersResidue
from . import mapping as spam_m
from scipy.ndimage.filters import uniform_filter
def quantizerScalarEncoder(x, values):
y = np.zeros(x.shape, dtype = np.int64)
th = (values[1:]+values[:-1]) / 2
for index in range(th.size):
y += x>th[index]
return y
def getParams(ordResid, symTranspose, q, T, ordCooc, mapper, strides):
Wres, Fres, resTranspose = getFiltersResidue(ordResid)
radius = (np.asarray(Wres.shape[0:2]) - 1) / 2
n = 2*T + 1
values = (float(q) * Fres / 256.0) * np.asarray(range(-T,T+1)).astype(np.float)
radius = radius + (ordCooc - (ordCooc % 2)) / 2
radius = radius.astype(int)
if isinstance(mapper,dict):
numFeat = mapper['num']
elif mapper is 'SignSym':
mapper = spam_m.getSignSymMapper(ordCooc, n)
numFeat = mapper['num']
elif mapper is 'Sign':
mapper = spam_m.getSignMapper(ordCooc,n)
numFeat = mapper['num']
elif mapper is 'Idem':
mapper = []
numFeat = (n ** ordCooc)
else:
mapper = spam_m.getSignSymMapper(ordCooc, n)
numFeat = mapper['num']
if isinstance(strides, (list, tuple)):
strides = strides[0:2]
else:
strides = [strides, strides]
return {'Wres': Wres, 'resTranspose': resTranspose, 'uniformQuant': True, 'values': values, 'ordCooc': ordCooc, 'mapper': mapper,
'strides': strides, 'numFeat': numFeat, 'radius': radius,
'symTranspose': symTranspose}
def computeSpamRes(res, params, weights = list(), normalize = True):
## Quantization & Truncation
values = params['values']
resQ = quantizerScalarEncoder(res, values)
## Coocorance
ordCooc = params['ordCooc']
n = (params['values']).size
dim = int(ordCooc + 1 - (ordCooc % 2))
indexL = int((dim - 1) / 2)
shapeR = np.asarray(resQ.shape[:2]) - dim + 1
resH = np.zeros(shapeR, dtype = np.int)
resV = np.zeros(shapeR, dtype = np.int)
for indexP in range(ordCooc):
nn = (n ** indexP)
resH += resQ[indexL:(shapeR[0] + indexL), indexP:(shapeR[1] + indexP)] * nn
resV += resQ[indexP:(shapeR[0] + indexP), indexL:(shapeR[1] + indexL)] * nn
## Mappeing
mapper = params['mapper']
if len(mapper) > 0:
resH = mapper['table'][resH].squeeze()
resV = mapper['table'][resV].squeeze()
## Hist
strides = params['strides']
numFeat = max(max(np.max(resH), np.max(resV))+1,params['numFeat'])
shapeR = resH.shape
range0 = np.arange(0, shapeR[0]-strides[0]+1, strides[0], dtype=np.uint16)
range1 = np.arange(0, shapeR[1]-strides[1]+1, strides[1], dtype=np.uint16)
rangeH = np.arange(0, numFeat+2, dtype = resH.dtype) # range(0, numFeat+1)
if normalize:
out_dtype = np.float32
else:
out_dtype = np.uint32
spamH = np.zeros([range0.size, range1.size, numFeat+1], dtype = out_dtype)
spamV = np.zeros([range0.size, range1.size, numFeat+1], dtype = out_dtype)
if len(weights) > 0:
weights = weights[indexL:(shapeR[0] + indexL), indexL:(shapeR[1] + indexL)] ## clip weights
resH[np.logical_not(weights)] = numFeat
resV[np.logical_not(weights)] = numFeat
weights = weights.astype(dtype=out_dtype)
else:
weights = np.ones(resH.shape, dtype=out_dtype)
for index0 in range(range0.size):
for index1 in range(range1.size):
pos0 = range0[index0]
end0 = strides[0] + pos0
pos1 = range1[index1]
end1 = strides[1] + pos1
spamH[index0, index1, :], _ = np.histogram(resH[pos0:end0, pos1:end1], rangeH, density=False)
spamV[index0, index1, :], _ = np.histogram(resV[pos0:end0, pos1:end1], rangeH, density=False)
spamW = (strides[0]*strides[1]) - spamH[:,:,-1]
spamH = spamH[:,:,:-1]
spamV = spamV[:,:,:-1]
if normalize:
spamH = spamH / np.maximum(spamW[:,:,np.newaxis],1e-20)
spamV = spamV / np.maximum(spamW[:,:,np.newaxis],1e-20)
spamW = spamW / (strides[0]*strides[1])
spam = np.concatenate([spamH, spamV], 2)
## Border
range0 = range0 + indexL + (strides[0] - 1.0) / 2.0
range1 = range1 + indexL + (strides[1] - 1.0) / 2.0
return spam, spamW, range0, range1
def getSpamRes(res, params, ksize, weights = list(), paddingModality = 0):
strides = params['strides']
if isinstance(ksize, (list,tuple)):
ksize = ksize[0:2]
else:
ksize = [ksize, ksize]
ksize[0] = int(ksize[0] / strides[0])
ksize[1] = int(ksize[1] / strides[1])
spam, spamW, range0, range1 = computeSpamRes(res, params, weights = weights, normalize=True)
spamW = np.maximum(uniform_filter(spamW, (ksize[0], ksize[1], ), mode='constant', cval=0.0), 0.0)
spam = np.maximum(uniform_filter(spam , (ksize[0], ksize[1], 1), mode='constant', cval=0.0), 0.0)
spam = spam / np.maximum(spamW[:,:,np.newaxis], 1e-20)
if paddingModality == 0:
ind0f = int(np.floor((ksize[0] - 1.0) / 2.0))
ind0c = int(np.ceil( (ksize[0] - 1.0) / 2.0))
ind1f = int(np.floor((ksize[1] - 1.0) / 2.0))
ind1c = int(np.ceil( (ksize[1] - 1.0) / 2.0))
range0 = (range0[ind0f:-ind0c] + range0[ind0c:-ind0f])/2.0
range1 = (range1[ind1f:-ind1c] + range1[ind1c:-ind1f])/2.0
spamW = spamW[ind0c:-ind0f,ind1c:-ind1f]
spam = spam [ind0c:-ind0f,ind1c:-ind1f,:]
return spam, spamW, range0, range1
================================================
FILE: noiseprint/network.py
================================================
#
# Copyright (c) 2019 Image Processing Research Group of University Federico II of Naples ('GRIP-UNINA').
# All rights reserved.
# This work should only be used for nonprofit purposes.
#
# By downloading and/or using any of these files, you implicitly agree to all the
# terms of the license, as specified in the document LICENSE.txt
# (included in this package) and online at
# http://www.grip.unina.it/download/LICENSE_OPEN.txt
#
import numpy as np
import tensorflow as tf
class FullConvNet(object):
"""FullConvNet model."""
def __init__(self, images, bnorm_decay, falg_train, num_levels = 17, padding = 'SAME'):
"""FullConvNet constructor."""
self._num_levels = num_levels
self._actfun = [tf.nn.relu, ] * (self._num_levels-1) + [tf.identity, ]
self._f_size = [3, ] * self._num_levels
self._f_num = [64, ] *(self._num_levels-1) + [1, ]
self._f_stride = [1, ] * self._num_levels
self._bnorm = [False, ] + [True,]*(self._num_levels-2) + [False,]
self._res = [0, ] * self._num_levels
self._bnorm_init_var = 1e-4
self._bnorm_init_gamma = np.sqrt(2.0/(9.0*64.0))
self._bnorm_epsilon = 1e-5
self._bnorm_decay = bnorm_decay
self.level = [None, ] * self._num_levels
self.input = images
self.falg_train = falg_train
self.extra_train = []
self.variables_list = []
self.trainable_list = []
self.decay_list = []
self.padding = padding
x = self.input
for i in range(self._num_levels):
with tf.variable_scope('level_%d' % i):
x = self._conv(x, self._f_size[i], self._f_num[i], self._f_stride[i], name = 'conv')
if self._bnorm[i]:
x = self._batch_norm(x, name = 'bn')
x = self._bias(x, name = 'bias')
if self._res[i]>0:
x = x + self.level[i-self._res[i]]
x = self._actfun[i](x, name = 'active')
self.level[i] = x
self.output = x
def _batch_norm(self, x, name = 'bnorm'):
"""Batch normalization."""
with tf.variable_scope(name):
params_shape = [x.get_shape()[-1]]
moving_mean = tf.get_variable(
'moving_mean', params_shape, tf.float32,
initializer=tf.constant_initializer(0.0, dtype=tf.float32),
trainable=False)
moving_variance = tf.get_variable(
'moving_variance', params_shape, tf.float32,
initializer=tf.constant_initializer(self._bnorm_init_var, dtype=tf.float32),
trainable=False)
self.variables_list.append(moving_mean)
self.variables_list.append(moving_variance)
gamma = tf.get_variable(
'gamma', params_shape, tf.float32,
initializer=tf.random_normal_initializer(stddev=self._bnorm_init_gamma, dtype=tf.float32))
self.variables_list.append(gamma)
self.trainable_list.append(gamma)
local_mean, local_variance = tf.nn.moments(x, [0, 1, 2], name='moments')
mean, variance = tf.cond(
self.falg_train, lambda: (local_mean, local_variance),
lambda: (moving_mean, moving_variance))
self.extra_train.append(moving_mean.assign_sub((1.0 - self._bnorm_decay) * (moving_mean - local_mean)))
self.extra_train.append(moving_variance.assign_sub((1.0 - self._bnorm_decay) * (moving_variance - local_variance)))
y = tf.nn.batch_normalization(
x, mean, variance, None, gamma, self._bnorm_epsilon)
y.set_shape(x.get_shape())
return y
def _bias(self, x, name = 'bias'):
"""Bias term."""
with tf.variable_scope(name):
params_shape = [x.get_shape()[-1]]
beta = tf.get_variable(
'beta', params_shape, tf.float32,
initializer=tf.constant_initializer(0.0, dtype=tf.float32))
self.variables_list.append(beta)
self.trainable_list.append(beta)
y = x + beta
return y
def _conv(self, x, filter_size, out_filters, stride, name='conv'):
"""Convolution."""
with tf.variable_scope(name):
in_filters = int(x.get_shape()[-1])
n = filter_size * filter_size * np.maximum(in_filters, out_filters)
kernel = tf.get_variable(
'weights', [filter_size, filter_size, in_filters, out_filters],
tf.float32, initializer=tf.random_normal_initializer(
stddev=np.sqrt(2.0/n), dtype=tf.float32))
self.variables_list.append(kernel)
self.trainable_list.append(kernel)
self.decay_list.append(kernel)
y = tf.nn.conv2d(x, kernel, [1, stride, stride, 1], padding=self.padding)
return y
================================================
FILE: noiseprint/noiseprint.py
================================================
#
# Copyright (c) 2019 Image Processing Research Group of University Federico II of Naples ('GRIP-UNINA').
# All rights reserved.
# This work should only be used for nonprofit purposes.
#
# By downloading and/or using any of these files, you implicitly agree to all the
# terms of the license, as specified in the document LICENSE.txt
# (included in this package) and online at
# http://www.grip.unina.it/download/LICENSE_OPEN.txt
#
"""
@author: davide.cozzolino
"""
import numpy as np
import tensorflow as tf
import os.path
from .network import FullConvNet
slide = 1024 #3072
largeLimit = 1050000 #9437184
overlap = 34
chkpt_folder = os.path.join(os.path.dirname(__file__),'./nets/%s_jpg%d/model')
tf.reset_default_graph()
x_data = tf.placeholder(tf.float32, [1, None, None, 1], name="x_data")
net = FullConvNet(x_data, 0.9, tf.constant(False), num_levels=17)
saver = tf.train.Saver(net.variables_list)
configSess = tf.ConfigProto(); configSess.gpu_options.allow_growth = True
#configSess = tf.ConfigProto(gpu_options=tf.GPUOptions(per_process_gpu_memory_fraction=0.95))
def genNoiseprint(img, QF=101, model_name='net'):
if QF>100: QF = 101
chkpt_fname = chkpt_folder % (model_name, QF)
with tf.Session(config=configSess) as sess:
saver.restore(sess, chkpt_fname)
if img.shape[0]*img.shape[1]>largeLimit:
print(' %dx%d large %3d' % (img.shape[0], img.shape[1], QF))
# for large image the network is executed windows with partial overlapping
res = np.zeros((img.shape[0],img.shape[1]), np.float32)
for index0 in range(0,img.shape[0],slide):
index0start = index0-overlap
index0end = index0+slide+overlap
for index1 in range(0,img.shape[1],slide):
index1start = index1-overlap
index1end = index1+slide+overlap
clip = img[max(index0start, 0): min(index0end, img.shape[0]), \
max(index1start, 0): min(index1end, img.shape[1])]
resB = sess.run(net.output, feed_dict={x_data: clip[np.newaxis,:,:,np.newaxis]})
resB = np.squeeze(resB)
if index0>0:
resB = resB[overlap:, :]
if index1>0:
resB = resB[:, overlap:]
resB = resB[:min(slide,resB.shape[0]), :min(slide,resB.shape[1])]
res[index0: min(index0+slide, res.shape[0]), \
index1: min(index1+slide, res.shape[1])] = resB
else:
print(' %dx%d small %3d' % (img.shape[0], img.shape[1], QF))
res = sess.run(net.output, feed_dict={x_data: img[np.newaxis,:,:,np.newaxis]})
res = np.squeeze(res)
return res
================================================
FILE: noiseprint/noiseprint_blind.py
================================================
#
# Copyright (c) 2019 Image Processing Research Group of University Federico II of Naples ('GRIP-UNINA').
# All rights reserved.
# This work should only be used for nonprofit purposes.
#
# By downloading and/or using any of these files, you implicitly agree to all the
# terms of the license, as specified in the document LICENSE.txt
# (included in this package) and online at
# http://www.grip.unina.it/download/LICENSE_OPEN.txt
#
"""
@author: davide.cozzolino
"""
import numpy as np
from .noiseprint import genNoiseprint
from .post_em import EMgu_img, getSpamFromNoiseprint
from .utility.utilityRead import resizeMapWithPadding
from .utility.utilityRead import imread2f
from .utility.utilityRead import jpeg_qtableinv
def noiseprint_blind_file(filename, model_name='net'):
try:
img, mode = imread2f(filename, channel=1)
except:
print('Error opening image')
return -1, -1, -1e10, None, None, None, None, None, None
try:
QF = jpeg_qtableinv(filename)
print('QF=', QF)
except:
QF = 200
mapp, valid, range0, range1, imgsize, other = noiseprint_blind(img, QF, model_name=model_name)
return QF, mapp, valid, range0, range1, imgsize, other
def noiseprint_blind(img, QF, model_name='net'):
res = genNoiseprint(img, QF, model_name)
assert(img.shape==res.shape)
return noiseprint_blind_post(res, img)
def noiseprint_blind_post(res, img):
spam, valid, range0, range1, imgsize = getSpamFromNoiseprint(res, img)
if np.sum(valid)<50:
#print('error too small %d' % np.sum(weights))
return None, valid, range0, range1, imgsize, dict()
mapp, other = EMgu_img(spam, valid, extFeat = range(32), seed = 0, maxIter = 100, replicates = 10, outliersNlogl = 42)
return mapp, valid, range0, range1, imgsize, other
def genMappFloat(mapp, valid, range0, range1, imgsize):
mapp_s = np.copy(mapp)
mapp_s[valid==0] = np.min(mapp_s[valid>0])
mapp_s = resizeMapWithPadding(mapp_s, range0, range1, imgsize)
return mapp_s
def genMappUint8(mapp, valid, range0, range1, imgsize, vmax=None, vmin=None):
mapp_s = np.copy(mapp)
mapp_s[valid==0] = np.min(mapp_s[valid>0])
if vmax is None:
vmax = np.nanmax(mapp_s)
if vmin is None:
vmin = np.nanmin(mapp_s)
mapUint8 = (255* (mapp_s.clip(vmin,vmax) - vmin) /(vmax-vmin)).clip(0, 255).astype(np.uint8)
mapUint8 = 255 - resizeMapWithPadding(mapUint8, range0, range1, imgsize)
return mapUint8
================================================
FILE: noiseprint/post_em.py
================================================
# %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
#
# Copyright (c) 2019 Image Processing Research Group of University Federico II of Naples ('GRIP-UNINA').
# All rights reserved.
# This work should only be used for nonprofit purposes.
#
# By downloading and/or using any of these files, you implicitly agree to all the
# terms of the license, as specified in the document LICENSE.txt
# (included in this package) and online at
# http://www.grip.unina.it/download/LICENSE_OPEN.txt
#
"""
@author: davide.cozzolino
"""
import numpy as np
import numpy.linalg as numpyl
from scipy.ndimage.filters import uniform_filter, maximum_filter
import skimage.morphology as ski
from .feat_spam.spam_np_opt import getSpamRes
from .utility.gaussianMixture import gm
paramSpam_default = {'resTranspose': False, 'uniformQuant': False, \
'values': np.asarray([-0.8,-0.28,+0.16,+0.7]), \
'ordCooc': 4, 'mapper': list(), \
'strides': [8,8], 'numFeat': 4**4, 'radius': [1, 1], \
'symTranspose': False}
ksize_default = 64
stride_default = 8
satutationProb = 0.95
win_v = 5
win_z = 35
def faetReduce(feat_list, inds, whiteningFlag = False):
cov_mtx = np.cov(feat_list, rowvar = False, bias = True)
w, v = np.linalg.eigh(cov_mtx)
w = w[::-1]
v = v[:,::-1]
v = v[:, inds]
if whiteningFlag:
v = v / np.sqrt(w[inds])
return v, w
def getWeights(img, res):
res_m = uniform_filter(res, (win_v, win_v))
res_v = uniform_filter(np.square(res), (win_v, win_v)) - np.square(res_m)
mm = res_v<0.005
mm[:1,:] = True; mm[-1:,:] = True;
mm[:,:1] = True; mm[:,-1:] = True;
th_White = 253.0 / 256; rd_White = 3
sat_mask = ski.binary_opening(img>th_White,ski.disk(rd_White))
mm = np.logical_or(mm,sat_mask)
mm = maximum_filter(mm, (win_z,win_z))
weights = np.logical_not(mm)
return weights
def getCoocValues(res, img_gray, n_clusters=4, random_state=0):
#img_gray is the image in range [0,1[
from sklearn.cluster import KMeans
weights = getWeights(img_gray, res)
kmeans = KMeans(n_clusters=n_clusters, random_state=random_state).fit(res[weights].reshape((-1,1)))
values = np.sort(kmeans.cluster_centers_.flatten(), axis=None)
return values
def getSpamFromNoiseprint(res, img_gray, ksize=ksize_default, stride=stride_default, values=None):
imgsize = img_gray.shape
paramSpam = dict(paramSpam_default)
paramSpam['strides'] = (stride,stride)
if values is not None:
paramSpam['values'] = values
weights = getWeights(img_gray, res)
spam, weights, range0, range1 = getSpamRes(res, paramSpam, ksize, weights = weights, paddingModality = 0)
valid = (weights >= satutationProb)
spam = np.sqrt(np.abs(spam))
spam = spam[2:-2,2:-2,:]
valid = valid[2:-2,2:-2]
range0 = range0[2:-2]
range1 = range1[2:-2]
return spam, valid, range0, range1, imgsize
def EMgu(feats, seed = 0, maxIter = 100, replicates = 10, outliersNlogl = 42):
randomState = np.random.RandomState(seed)
gm_data = gm(feats.shape[1], [0,], [2,], outliersProb = 0.01, outliersNlogl = outliersNlogl, dtype=list_valid.dtype)
gm_data.setRandomParams(feats, regularizer = -1.0, randomState = randomState)
avrLogl, _, _ = gm_data.EM(feats, maxIter = maxIter, regularizer = -1.0)
for index in range(1, replicates):
gm_data_1 = gm(feats.shape[1], [0,], [2,], outliersProb = 0.01, outliersNlogl = outliersNlogl, dtype = list_valid.dtype)
gm_data_1.setRandomParams(feats, regularizer = -1.0, randomState = randomState)
avrLogl_1, _, _ = gm_data_1.EM(feats, maxIter = maxIter, regularizer = -1.0)
if (avrLogl_1>avrLogl):
gm_data = gm_data_1
avrLogl = avrLogl_1
_, mahal = gm_data.getNlogl(list_spam)
mahal = mahal.reshape([shape_spam[0],shape_spam[1],])
other = dict()
other['Sigma'] = gm_data.listSigma[0]
other['mu'] = gm_data.mu
other['outliersNlogl'] = outliersNlogl
other['outliersProb'] = gm_data.outliersProb
return mahal, other
def EMgu_img(spam, valid, extFeat = range(32), seed = 0, maxIter = 100, replicates = 10, outliersNlogl = 42):
shape_spam = spam.shape
list_spam = spam.reshape([shape_spam[0]*shape_spam[1],shape_spam[2]])
list_valid = list_spam[valid.flatten(),:]
L, eigs = faetReduce(list_valid, extFeat, True)
list_spam = np.matmul(list_spam, L)
list_valid = list_spam[valid.flatten(), :]
randomState = np.random.RandomState(seed)
gm_data = gm(shape_spam[2], [0,], [2,], outliersProb = 0.01, outliersNlogl = outliersNlogl, dtype=list_valid.dtype)
gm_data.setRandomParams(list_valid, regularizer = -1.0, randomState = randomState)
avrLogl, _, _ = gm_data.EM(list_valid, maxIter = maxIter, regularizer = -1.0)
for index in range(1, replicates):
gm_data_1 = gm(shape_spam[2], [0,], [2,], outliersProb = 0.01, outliersNlogl = outliersNlogl, dtype = list_valid.dtype)
gm_data_1.setRandomParams(list_valid, regularizer = -1.0, randomState = randomState)
avrLogl_1, _, _ = gm_data_1.EM(list_valid, maxIter = maxIter, regularizer = -1.0)
if (avrLogl_1>avrLogl):
gm_data = gm_data_1
avrLogl = avrLogl_1
_, mahal = gm_data.getNlogl(list_spam)
mahal = mahal.reshape([shape_spam[0],shape_spam[1],])
other = dict()
other['Sigma'] = gm_data.listSigma[0]
other['mu'] = gm_data.mu
other['L'] = L
other['eigs'] = eigs
other['outliersNlogl'] = outliersNlogl
other['outliersProb'] = gm_data.outliersProb
return mahal, other
================================================
FILE: noiseprint/requirements-cpu.txt
================================================
pillow==4.2.1
numpy==1.16.1
pandas==0.20.3
scipy==0.19.1
scikit-image==0.13.0
scikit-learn==0.19.1
matplotlib==2.2.2
tensorflow==1.2.1
concurrent-iterator==0.2.6
================================================
FILE: noiseprint/requirements-gpu.txt
================================================
pillow==4.2.1
numpy==1.16.1
pandas==0.20.3
scipy==0.19.1
scikit-image==0.13.0
scikit-learn==0.19.1
matplotlib==2.2.2
tensorflow-gpu==1.2.1
concurrent-iterator==0.2.6
================================================
FILE: noiseprint/utility/__init__.py
================================================
# %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
#
# Copyright (c) 2016 Image Processing Research Group of University Federico II of Naples ('GRIP-UNINA').
# All rights reserved.
# This work should only be used for nonprofit purposes.
#
# By downloading and/or using any of these files, you implicitly agree to all the
# terms of the license, as specified in the document LICENSE.txt
# (included in this package) and online at
# http://www.grip.unina.it/download/LICENSE_OPEN.txt
#
================================================
FILE: noiseprint/utility/gaussianMixture.py
================================================
# %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
#
# Copyright (c) 2017 Image Processing Research Group of University Federico II of Naples ('GRIP-UNINA').
# This software is delivered with Government Purpose Rights (GPR) under agreement number FA8750-16-2-0204.
#
# By downloading and/or using any of these files, you implicitly agree to all the
# terms of the license, as specified in the document LICENSE.txt
# (included in this package)
#
import numpy as np
from scipy.linalg import eigvalsh
from numpy.linalg import cholesky
from numpy.linalg import eigh
class gm:
prioriProb = 0
outliersProb = 0
outliersNlogl = 0
mu = 0
listSigma = []
listSigmaInds = []
listSigmaType = []
# sigmaType = 0 # isotropic covariance
# sigmaType = 1 # diagonal covariance
# sigmaType = 2 # full covariance
# outliersProb < 0 # outliers are not managed
# outliersProb >= 0 # outliers are managed throught fixed nlogl (negative log likelihood)
# TODO: outliers managed throught fixed probability
def __init__(self, dim, listSigmaInds, listSigmaType, outliersProb = -1, outliersNlogl = 0, dtype = np.float32):
K = len(listSigmaInds)
S = len(listSigmaType)
self.listSigmaInds = listSigmaInds
self.listSigmaType = listSigmaType
self.outliersProb = outliersProb
self.outliersNlogl = outliersNlogl
self.prioriProb = (1.0-self.outliersProb) * np.ones((K, 1), dtype=dtype) / K
self.mu = np.zeros((K, dim), dtype=dtype)
self.listSigma = [None, ] * S
for s in range(S):
sigmaType = self.listSigmaType[s]
if sigmaType == 2: # full covariance
self.listSigma[s] = np.ones([dim, dim], dtype = dtype)
elif sigmaType == 1: # diagonal covariance
self.listSigma[s] = np.ones([1, dim], dtype = dtype)
else:
self.listSigma[s] = np.ones([], dtype = dtype)
def setRandomParams(self, X, regularizer = 0, randomState = np.random.get_state()):
[N, dim] = X.shape
K = len(self.listSigmaInds)
S = len(self.listSigmaType)
dtype = X.dtype
if self.outliersProb > 0:
self.prioriProb = (1.0-self.outliersProb) * np.ones((K, 1), dtype=dtype) / K
else:
self.prioriProb = np.ones((K, 1), dtype=dtype) / K
inds = randomState.random_integers(low=0,high=(N-1),size=(K,))
self.mu = X[inds, :]
varX = np.var(X, axis=0, keepdims=True)
if regularizer>0:
varX = varX + regularizer
elif regularizer<0:
varX = varX + np.abs(regularizer*np.spacing(np.max(varX)))
for s in range(S):
sigmaType = self.listSigmaType[s]
if sigmaType == 2: # full covariance
self.listSigma[s] = np.diag(varX.flatten())
elif sigmaType == 1: # diagonal covariance
self.listSigma[s] = varX
else:
self.listSigma[s] = np.mean(varX)
return inds
def setRandomParamsW(self, X, weights, regularizer = 0, randomState = np.random.get_state(), meanFlag = False):
[N, dim] = X.shape
K = len(self.listSigmaInds)
S = len(self.listSigmaType)
dtype = X.dtype
if self.outliersProb > 0:
self.prioriProb = (1.0-self.outliersProb) * np.ones((K, 1), dtype=dtype) / K
else:
self.prioriProb = np.ones((K, 1), dtype=dtype) / K
avrX = np.mean(X*weights, axis=0, keepdims=True)/np.mean(weights)
varX = np.mean(weights *((X - avrX) ** 2), axis=0, keepdims=True)/np.mean(weights)
indsW = np.sum(weights)*randomState.random_sample(size=(K,))
inds = [None, ] * K
weights = np.cumsum(weights.flatten())
for index in range(K):
inds[index] = np.count_nonzero(weights<=indsW[index])
self.mu = X[inds, :]
if meanFlag: self.mu[0,:] = avrX
#varX = np.var(X, axis=0, keepdims=True)
if regularizer>0:
varX = varX + regularizer
elif regularizer<0:
varX = varX + np.abs(regularizer*np.spacing(np.max(varX)))
for s in range(S):
sigmaType = self.listSigmaType[s]
if sigmaType == 2: # full covariance
self.listSigma[s] = np.diag(varX.flatten())
elif sigmaType == 1: # diagonal covariance
self.listSigma[s] = varX
else:
self.listSigma[s] = np.mean(varX)
return inds
def getNlogl(self, X):
[N, dim] = X.shape
K = len(self.listSigmaInds)
S = len(self.listSigmaType)
dtype = X.dtype
K0 = K
if self.outliersProb >= 0: K0 = K+1
nlogl = np.zeros([N, K0], dtype = dtype)
mahal = np.zeros([N, K ], dtype = dtype)
listLogDet = [None, ] * S
listLowMtx = [None, ] * S
for s in range(S):
sigmaType = self.listSigmaType[s]
sigma = self.listSigma[s]
if sigmaType == 2: # full covariance
try:
listLowMtx[s] = cholesky(sigma)
except:
# exceptional regularization
sigma_w, sigma_v = eigh(np.real(sigma))
sigma_w = np.maximum(sigma_w, np.spacing(np.max(sigma_w)))
sigma = np.matmul(np.matmul(sigma_v, np.diag(sigma_w)), (np.transpose(sigma_v,[1,0])))
try:
listLowMtx[s] = cholesky(sigma)
except:
sigma_w, sigma_v = eigh(np.real(sigma))
sigma_w = np.maximum(sigma_w, np.spacing(np.max(sigma_w)))
#print(np.min(sigma_w))
sigma = np.matmul(np.matmul(sigma_v, np.diag(sigma_w)), (np.transpose(sigma_v,[1,0])))
#print(sigma)
listLowMtx[s] = cholesky(sigma)
diagLowMtx = np.diag(listLowMtx[s])
listLogDet[s] = 2 * np.sum(np.log(diagLowMtx))
elif sigmaType == 1: # diagonal covariance
listLowMtx[s] = np.sqrt(sigma)
listLogDet[s] = np.sum(np.log(sigma))
else: # isotropic covariance
listLowMtx[s] = np.sqrt(sigma)
listLogDet[s] = dim * np.log(sigma)
constPi = dim*np.log(2*np.pi)
for k in range(K):
s = self.listSigmaInds[k]
sigmaType = self.listSigmaType[s]
lowMtx = listLowMtx[s]
logDet = listLogDet[s]
Xmu = X - self.mu[k,:]
if sigmaType == 2: # full covariance
Xmu = np.linalg.solve(lowMtx, Xmu.transpose()).transpose()
elif sigmaType == 1: # diagonal covariance
Xmu = Xmu / lowMtx
else: # isotropic covariance
Xmu = Xmu / lowMtx
mahal[:,k] = np.sum(Xmu * Xmu, axis = 1)
nlogl[:,k] = 0.5 * (mahal[:,k] + logDet + constPi)
if self.outliersProb >= 0:
nlogl[:, K] = self.outliersNlogl
return nlogl, mahal
def getLoglh(self, X):
nlogl, _ = self.getNlogl(X)
logPrb = np.log(self.prioriProb)
if self.outliersProb >= 0:
#print(self.outliersProb)
logPrb = np.append(logPrb.squeeze(), np.log(self.outliersProb))
logPrb = logPrb.reshape((-1,1))
return logPrb.transpose((1,0)) - nlogl
def getLoglhInlier(self, X):
nlogl, _ = self.getNlogl(X)
K = self.prioriProb.size
logPrb = np.log(self.prioriProb)
logit = logPrb.transpose((1, 0)) - nlogl[:, :K]
maxll = np.max(logit, axis=1, keepdims=True)
prob = np.exp(logit - maxll)
dem = np.sum(prob, axis=1, keepdims=True)
#return (np.log(dem) + maxll - np.log(np.sum(self.prioriProb)))
return (np.log(dem) + maxll - np.log(np.sum(self.outliersProb)))
def maximizationParam(self, X, post, regularizer = 0):
[N, dim] = X.shape
K = len(self.listSigmaInds)
S = len(self.listSigmaType)
dtype = X.dtype
self.prioriProb = np.sum(post[:,:K], axis=0, keepdims=True).transpose([1, 0])
self.mu = np.tensordot(post, X, (0, 0)) / self.prioriProb
for s in range(S):
sigmaType = self.listSigmaType[s]
if sigmaType == 2: # full covariance
sigma = np.zeros([dim, dim], dtype=dtype)
sigmadem = np.zeros([], dtype=dtype)
for k in range(K):
if s == self.listSigmaInds[k]:
Xmu = X - self.mu[(k,), :]
Xmu = np.sqrt(post[:, (k,)]) * Xmu
sigma = sigma + np.tensordot(Xmu, Xmu, (0, 0))
sigmadem += self.prioriProb[k, 0]
sigma = sigma / sigmadem
if regularizer > 0:
sigma = sigma + regularizer * np.eye(dim)
elif regularizer < 0:
#sigma = sigma - regularizer * np.spacing(np.max(np.linalg.eigvalsh(sigma))) * np.eye(dim)
sigma = sigma + np.abs(regularizer * np.spacing(eigvalsh(sigma, eigvals=(dim - 1, dim - 1)))) * np.eye(dim)
elif sigmaType == 1: # diagonal covariance
sigma = np.zeros([1, dim], dtype=dtype)
sigmadem = np.zeros([], dtype=dtype)
for k in range(K):
if s == self.listSigmaInds[k]:
Xmu = X - self.mu[(k,), :]
sigma = sigma + np.tensordot(post[:, (k,)], (Xmu * Xmu), (0, 0))
sigmadem += self.prioriProb[k, 0]
sigma = sigma / sigmadem
if regularizer > 0:
sigma = sigma + regularizer
elif regularizer < 0:
sigma = sigma + + np.abs(regularizer * np.spacing(np.max(sigma)))
else: # isotropic covariance
sigma = np.zeros([], dtype=dtype)
sigmadem = np.zeros([], dtype=dtype)
for k in range(K):
if s == self.listSigmaInds[k]:
Xmu = X - self.mu[(k,), :]
sigma = sigma + np.dot(post[:, k], np.mean((Xmu * Xmu), axis=1))
sigmadem += self.prioriProb[k, 0]
sigma = sigma / sigmadem
if regularizer > 0:
sigma = sigma + regularizer
elif regularizer < 0:
sigma = sigma + np.abs(regularizer * np.spacing(sigma))
self.listSigma[s] = sigma
# normalize PComponents
if self.outliersProb < 0:
self.prioriProb = self.prioriProb / np.sum(self.prioriProb)
else:
self.outliersProb = np.sum(post[:,K])
dem = self.outliersProb + np.sum(self.prioriProb)
self.prioriProb = self.prioriProb / dem
self.outliersProb = self.outliersProb / dem
def expectation(self, X):
[post, avrLogl] = softmax(self.getLoglh(X))
return post, avrLogl
def expectationWeighed(self, X, weighed):
[post, avrLogl] = softmaxWeighed(self.getLoglh(X), weighed)
return post, avrLogl
def MEstep(self, X, post, regularizer = 0):
self.maximizationParam(X, post, regularizer = regularizer)
[post, avrLogl] = self.expectation(X)
return post, avrLogl
def MEstepWeighed(self, X, weights, post, regularizer = 0):
self.maximizationParam(X, post * weights, regularizer = regularizer)
[post, avrLogl] = self.expectationWeighed(X, weights)
return post, avrLogl
def EM(self, X, regularizer, maxIter, relErr = 1e-5):
[post, avrLogl_old] = self.expectation(X)
flagExit = 1
# flagExit = 1 # max number of iteretions
# flagExit = 0 # converged
for iter in range(maxIter):
[post, avrLogl] = self.MEstep(X, post, regularizer = regularizer)
diff = avrLogl - avrLogl_old
if (diff >= 0) & (diff < relErr * np.abs(avrLogl)):
flagExit = 0
break
avrLogl_old = avrLogl
return avrLogl, flagExit, iter
def EMweighed(self, X, weights, regularizer, maxIter, relErr=1e-5):
[post, avrLogl_old] = self.expectationWeighed(X, weights)
flagExit = 1
# flagExit = 1 # max number of iteretions
# flagExit = 0 # converged
for iter in range(maxIter):
[post, avrLogl] = self.MEstepWeighed(X, weights, post, regularizer=regularizer)
diff = avrLogl - avrLogl_old
if (diff >= 0) & (diff < relErr * np.abs(avrLogl)):
flagExit = 0
break
avrLogl_old = avrLogl
return avrLogl, flagExit, iter
def softmax(logit):
maxll = np.max(logit, axis = 1, keepdims=True)
prob = np.exp(logit - maxll)
dem = np.sum(prob, axis = 1, keepdims=True)
prob = prob / dem
avrLogl = np.mean(np.log(dem) + maxll)
return prob, avrLogl
def softmaxWeighed(logit, weights):
maxll = np.max(logit, axis = 1, keepdims=True)
prob = np.exp(logit - maxll)
dem = np.sum(prob, axis = 1, keepdims=True)
prob = prob / dem
avrLogl = np.mean(weights * (np.log(dem) + maxll)) / np.mean(weights)
return prob, avrLogl
================================================
FILE: noiseprint/utility/utilityRead.py
================================================
# %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
#
# Copyright (c) 2018 Image Processing Research Group of University Federico II of Naples ('GRIP-UNINA').
# All rights reserved.
# This work should only be used for nonprofit purposes.
#
# By downloading and/or using any of these files, you implicitly agree to all the
# terms of the license, as specified in the document LICENSE.txt
# (included in this package) and online at
# http://www.grip.unina.it/download/LICENSE_OPEN.txt
#
from PIL.JpegImagePlugin import convert_dict_qtables
from PIL import Image
import numpy as np
def imread2f_pil(stream, channel = 1, dtype = np.float32):
img = Image.open(stream)
mode = img.mode
if channel == 3:
img = img.convert('RGB')
img = np.asarray(img).astype(dtype) / 256.0
elif channel == 1:
if img.mode == 'L':
img = np.asarray(img).astype(dtype) / 256.0
else:
img = img.convert('RGB')
img = np.asarray(img).astype(dtype)
img = (0.299 * img[:, :, 0] + 0.587 * img[:, :, 1] + 0.114 * img[:, :, 2])/256.0
else:
img = np.asarray(img).astype(dtype) / 256.0
return img, mode
try:
import rawpy
def imread2f_raw(stream, channel = 1, dtype = np.float32):
raw = rawpy.imread(stream)
img = raw.postprocess()
raw.close()
ori_dtype = img.dtype
img = np.asarray(img).astype(dtype)
if channel == 1:
img = (0.299 * img[:, :, 0] + 0.587 * img[:, :, 1] + 0.114 * img[:, :, 2])
if ori_dtype == np.uint8:
img = img / 256.0
elif ori_dtype == np.uint16:
img = img / (2.0 ** 16)
elif ori_dtype == np.uint32:
img = img / (2.0 ** 32)
elif ori_dtype == np.uint64:
img = img / (2.0 ** 64)
elif ori_dtype == np.uint128:
img = img / (2.0 ** 128)
return img, 'RAW'
except:
pass
def imread2f(stream, channel = 1, dtype = np.float32):
try:
return imread2f_raw(stream, channel=channel, dtype=dtype)
except:
return imread2f_pil(stream, channel=channel, dtype=dtype)
def jpeg_qtableinv(stream, tnum=0, force_baseline=None):
assert tnum == 0 or tnum == 1, 'Table number must be 0 or 1'
if force_baseline is None:
th_high = 32767
elif force_baseline == 0:
th_high = 32767
else:
th_high = 255
h = np.asarray(convert_dict_qtables(Image.open(stream).quantization)[tnum]).reshape((8, 8))
if tnum == 0:
# This is table 0 (the luminance table):
t = np.matrix(
[[16, 11, 10, 16, 24, 40, 51, 61],
[12, 12, 14, 19, 26, 58, 60, 55],
[14, 13, 16, 24, 40, 57, 69, 56],
[14, 17, 22, 29, 51, 87, 80, 62],
[18, 22, 37, 56, 68, 109, 103, 77],
[24, 35, 55, 64, 81, 104, 113, 92],
[49, 64, 78, 87, 103, 121, 120, 101],
[72, 92, 95, 98, 112, 100, 103, 99]])
elif tnum == 1:
# This is table 1 (the chrominance table):
t = np.matrix(
[[17, 18, 24, 47, 99, 99, 99, 99],
[18, 21, 26, 66, 99, 99, 99, 99],
[24, 26, 56, 99, 99, 99, 99, 99],
[47, 66, 99, 99, 99, 99, 99, 99],
[99, 99, 99, 99, 99, 99, 99, 99],
[99, 99, 99, 99, 99, 99, 99, 99],
[99, 99, 99, 99, 99, 99, 99, 99],
[99, 99, 99, 99, 99, 99, 99, 99]])
else:
raise ValueError(tnum, 'Table number must be 0 or 1')
h_down = np.divide((2 * h-1), (2 * t))
h_up = np.divide((2 * h+1), (2 * t))
if np.all(h == 1): return 100
x_down = (h_down[h > 1]).max()
x_up = (h_up[h < th_high]).min() if (h < th_high).any() else None
if x_up is None:
s = 1
elif x_down > 1 and x_up > 1:
s = np.ceil(50 / x_up)
elif x_up < 1:
s = np.ceil(50*(2 - x_up))
else:
s = 50
return s
from scipy.interpolate import interp1d
def resizeMapWithPadding(x, range0, range1, shapeOut):
range0 = range0.flatten()
range1 = range1.flatten()
xv = np.arange(shapeOut[1])
yv = np.arange(shapeOut[0])
y = interp1d(range1, x , axis=1, kind='nearest', fill_value='extrapolate', assume_sorted=True, bounds_error=False)
y = interp1d(range0, y(xv), axis=0, kind='nearest', fill_value='extrapolate', assume_sorted=True, bounds_error=False)
return y(yv).astype(x.dtype)
def computeMetricsContinue(values, gt0, gt1):
values = values.flatten().astype(np.float32)
gt0 = gt0.flatten().astype(np.float32)
gt1 = gt1.flatten().astype(np.float32)
inds = np.argsort(values)
inds = inds[(gt0[inds]+gt1[inds])>0]
vet_th = values[inds]
gt0 = gt0[inds]
gt1 = gt1[inds]
TN = np.cumsum(gt0)
FN = np.cumsum(gt1)
FP = np.sum(gt0) - TN
TP = np.sum(gt1) - FN
return FP, TP, FN, TN, vet_th
def computeMCC(values, gt0, gt1):
FP, TP, FN, TN, vet_th = computeMetricsContinue(values, gt0, gt1)
mcc = np.abs(TP*TN - FP*FN) / np.maximum(np.sqrt((TP + FP)*(TP + FN)*(TN+ FP)*(TN + FN) ), 1e-32)
return mcc, vet_th
================================================
FILE: training/LICENSE.txt
================================================
THIS DOCUMENT CONSTITUTES A LICENCE TO USE THE SOFTWARE ON THE TERMS AND CONDITIONS APPEARING BELOW.
Preamble
This License applies to the software which with this license is distributed.
Copyright (c) 2019 Image Processing Research Group of University Federico II of Naples ('GRIP-UNINA').
This software is delivered with Government Purpose Rights (GPR) under agreement number FA8750-16-2-0204.
Transmission of user information
Any and all information or request for information you may direct to GRIP
through e-mail as may be linked to website http://www.grip.unina.it/
================================================
FILE: training/README.md
================================================
# Noiseprint: a CNN-based camera model fingerprint
[Noiseprint](https://ieeexplore.ieee.org/document/8713484) is a CNN-based camera model fingerprint
extracted by a fully Convolutional Neural Network (CNN).
This folder contains the training code of Noiseprint defined in the following paper:
[A] D. Cozzolino and L. Verdoliva
''Noiseprint: A CNN-Based Camera Model Fingerprint'''
IEEE Transactions on Information Forensics and Security, 2020.
However, the provided dataset is related to the successive paper:
[B] D. Cozzolino, F. Marra, D. Gragnaniello, G. Poggi, and L. Verdoliva
''Combining PRNU and noiseprint for robust and efficient device sourceidentification''
EURASIP Journal on Information Security, 2020.
## License
Copyright (c) 2020 Image Processing Research Group of University Federico II of Naples ('GRIP-UNINA').
This software is delivered with Government Purpose Rights (GPR) under agreement number FA8750-16-2-0204.
By downloading and/or using any of these files, you implicitly agree to all the
terms of the license, as specified in the document LICENSE.txt
(included in this package)
## Usage
The provided dataset is a collection of images publicly available on "dpreviewer.com".
To download the dataset from "dpreviewer.com", run:
```
cd dataset
python download_images.py
```
To speed up the training, the dateset is converted in NPY files.
To create the NPY files, run:
```
cd ../code
python create_data.py
```
Noiseprint uses initial weights obtained training a denoiser.
The initial weights are included in the folder.
To train the noiseprint with the parameters used in [A], run:
```
python train_noiseprint.py --gpu 0 --inp_channel 1 --pretrain ../pretrain/denoiser_17_1_1 --padding SAME
```
To train the noiseprint with the parameters used in [B], run:
```
python train_noiseprint.py --gpu 0
```
The whole code is tesetd with Python 3.x and Tensorflow 1.2.1 .
## Dependencies
Our code uses Python3.5, Cuda8, Cudnn5.
The following python packages are required:
- pillow==5.4.1
- numpy==1.16.1
- pandas==0.20.3
- scipy==0.19.1
- scikit-learn==0.19.1
- scikit-image==0.14.2
- tensorflow-gpu==1.2.1
- concurrent-iterator==0.2.6
## Reference
```js
@article{Cozzolino2020_Noiseprint,
title={Noiseprint: A CNN-Based Camera Model Fingerprint},
author={D. Cozzolino and L. Verdoliva},
journal={IEEE Transactions on Information Forensics and Security},
doi={10.1109/TIFS.2019.2916364},
pages={144-159},
year={2020},
volume={15}
}
```
```js
@article{cozzolino2020_Combining,
title={Combining PRNU and noiseprint for robust and efficient device source identification},
author={D. Cozzolino and F. Marra and D. Gragnaniello and G. Poggi and L. Verdoliva},
journal={EURASIP Journal on Information Security},
volume={2020},
number={1},
pages={1--12},
year={2020},
publisher={SpringerOpen}
}
```
================================================
FILE: training/code/FCnet.py
================================================
# %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
#
# Copyright (c) 2020 Image Processing Research Group of University Federico II of Naples ('GRIP-UNINA').
# This software is delivered with Government Purpose Rights (GPR) under agreement number FA8750-16-2-0204.
#
# By downloading and/or using any of these files, you implicitly agree to all the
# terms of the license, as specified in the document LICENSE.txt
# (included in this package)
#
# %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
"""
@author: davide.cozzolino
"""
import numpy as np
import tensorflow as tf
"""FullConvNet model."""
class FullConvNet(object):
"""FullConvNet model."""
def __init__(self, bnorm_decay=0.9, num_levels=17, outchannels=1):
"""FullConvNet constructor."""
self._num_levels = num_levels
self._actfun = [tf.nn.relu, ] * (self._num_levels - 1) + [tf.identity, ]
self._f_size = [3, ] * self._num_levels
self._f_num = [64, ] * (self._num_levels - 1) + [outchannels, ]
self._f_stride = [1, ] * self._num_levels
self._bnorm = [False, ] + [True, ] * (self._num_levels - 2) + [False, ]
self._res = [0, ] * self._num_levels
self._bnorm_init_var = 1e-4
self._bnorm_init_gamma = np.sqrt(2.0 / (9.0 * 64.0))
self._bnorm_epsilon = 1e-5
self._bnorm_decay = bnorm_decay
self.extra_train = []
self.variables_list = []
self.trainable_list = []
self.decay_list = []
self.var_reuse = False
def __call__(self, x, flag_train, padding='VALID'):
level = [None, ] * self._num_levels
for i in range(self._num_levels):
with tf.variable_scope('level_%d' % i, reuse=self.var_reuse):
x = self._conv(x, self._f_size[i], self._f_num[i], self._f_stride[i], name='conv', padding = padding)
if self._bnorm[i]:
x = self._batch_norm(x, flag_train, name='bn')
x = self._bias(x, name='bias')
if self._res[i] > 0:
x = x + level[i - self._res[i]]
x = self._actfun[i](x, name='active')
level[i] = x
self.output = x
self.var_reuse = True
return x
def _batch_norm(self, x, flag_train, name='bnorm'):
"""Batch normalization."""
with tf.variable_scope(name, reuse=self.var_reuse):
params_shape = [x.get_shape()[-1]]
moving_mean = tf.get_variable(
'moving_mean', params_shape, tf.float32,
initializer=tf.constant_initializer(0.0, dtype=tf.float32),
trainable=False)
moving_variance = tf.get_variable(
'moving_variance', params_shape, tf.float32,
initializer=tf.constant_initializer(self._bnorm_init_var, dtype=tf.float32),
trainable=False)
if moving_mean not in self.variables_list:
self.variables_list.append(moving_mean)
if moving_variance not in self.variables_list:
self.variables_list.append(moving_variance)
gamma = tf.get_variable(
'gamma', params_shape, tf.float32,
initializer=tf.random_normal_initializer(stddev=self._bnorm_init_gamma, dtype=tf.float32))
if gamma not in self.variables_list:
self.variables_list.append(gamma)
self.trainable_list.append(gamma)
self.decay_list.append(gamma)
local_mean, local_variance = tf.nn.moments(x, [0, 1, 2], name='moments')
mean, variance = tf.cond(
flag_train, lambda: (local_mean, local_variance),
lambda: (moving_mean, moving_variance))
y = tf.nn.batch_normalization(
x, mean, variance, None, gamma, self._bnorm_epsilon)
y.set_shape(x.get_shape())
op1 = moving_mean.assign_sub((1.0 - self._bnorm_decay) * (moving_mean - local_mean))
op2 = moving_variance.assign_sub((1.0 - self._bnorm_decay) * (moving_variance - local_variance))
self.extra_train.append(op1)
self.extra_train.append(op2)
tf.add_to_collection(tf.GraphKeys.UPDATE_OPS, op1)
tf.add_to_collection(tf.GraphKeys.UPDATE_OPS, op2)
return y
def _bias(self, x, name='bias'):
"""Bias term."""
with tf.variable_scope(name, reuse=self.var_reuse):
params_shape = [x.get_shape()[-1]]
beta = tf.get_variable(
'beta', params_shape, tf.float32,
initializer=tf.constant_initializer(0.0, dtype=tf.float32))
if beta not in self.variables_list:
self.variables_list.append(beta)
self.trainable_list.append(beta)
y = x + beta
return y
def _conv(self, x, filter_size, out_filters, stride, name='conv', padding='VALID'):
"""Convolution."""
with tf.variable_scope(name, reuse=self.var_reuse):
in_filters = int(x.get_shape()[-1])
n = filter_size * filter_size * np.maximum(in_filters, out_filters)
kernel = tf.get_variable(
'weights', [filter_size, filter_size, in_filters, out_filters],
tf.float32, initializer=tf.random_normal_initializer(
stddev=np.sqrt(2.0 / n), dtype=tf.float32))
if kernel not in self.variables_list:
self.variables_list.append(kernel)
self.trainable_list.append(kernel)
self.decay_list.append(kernel)
y = tf.nn.conv2d(x, kernel, [1, stride, stride, 1], padding=padding)
return y
================================================
FILE: training/code/Producer2.py
================================================
class setWorkers_mock():
def __init__(self, indexer, pre_fun, app_fun, buffer_size=100, workers=1):
self._len = int(len(indexer))
self._buffer = int(buffer_size)
self._workers = int(workers)
assert(self._workers <=self._buffer)
assert(3*self._buffer<=self._len )
self._indexer = indexer
self._app_fun = app_fun
self._pre_fun = pre_fun
self._next_dict = dict()
self._next_index = 0
self._flag_reset = hasattr(self._indexer, "on_epoch_end")
if self._flag_reset:
self._indexer.on_epoch_end()
def info(self):
print('mock')
def __enter__(self):
self._next_dict = dict()
self._next_index = 0
return self
def __exit__(self, exc_type, exc_value, traceback):
pass
def __len__(self):
return self._len
def __iter__(self):
return self
def __next__(self):
if self._next_index>= self._len:
self._next_index = 0
if self._flag_reset:
self._indexer.on_epoch_end()
else:
raise StopIteration
item = self._indexer[self._next_index]
item = self._pre_fun(*item)
item = self._app_fun(*item)
self._next_index = self._next_index + 1
#print(self._next_index, end="\r")
return item
from multiprocessing import Queue as QueueProcess
from multiprocessing import Process
class setWorkers_process():
def __init__(self, indexer, pre_fun, app_fun, buffer_size=100, workers=1):
self._len = int(len(indexer))
self._buffer = int(buffer_size)
self._workers = int(workers)
self._flag_reset = hasattr(indexer, "on_epoch_end")
assert(self._workers <=self._buffer)
assert(3*self._buffer<=self._len )
self._queueIn = QueueProcess(self._buffer)
self._processIn = Process(target=self._run_in,args=(indexer, self._queueIn, pre_fun, self._flag_reset ))
self._queueOut = QueueProcess(self._buffer)
self._app_fun = app_fun
self._processes = [Process(target=self._run_fun,args=(index,)) for index in range(self._workers)]
self._next_dict = dict()
self._next_index = 0
def _run_in(self, indexer, queue, pre_fun, flag_reset):
while True:
if flag_reset:
indexer.on_epoch_end()
for index in range(len(indexer)):
try:
item = indexer[index]
item = pre_fun(*item)
except:
item = None
#print(index, queue.qsize(), self._queueOut.qsize(), end="\r")
queue.put((index, item))
def _run_fun(self, index_process):
while True:
try:
index, item = self._queueIn.get()
item = self._app_fun(*item)
self._queueOut.put((index, item))
except:
pass
def info(self):
for process in self._processes:
print(process.is_alive(), end=' ')
print()
def __enter__(self):
self._next_dict = dict()
self._next_index = 0
for process in self._processes:
process.start()
self._processIn.start()
return self
def __exit__(self, exc_type, exc_value, traceback):
for process in self._processes:
try:
process.terminate()
except:
pass
try:
self._processIn.terminate()
except:
pass
self._queueIn.close()
self._queueOut.close()
def __len__(self):
return self._len
def __iter__(self):
return self
def __next__(self):
if self._next_index >= self._len:
self._next_index = 0
if not self._flag_reset:
raise StopIteration
numWaiting = 0
#timeStamp = time()
while not(self._next_index in self._next_dict.keys()):
index, item = self._queueOut.get()
self._next_dict[index] = item
numWaiting = numWaiting+1
#if numWaiting>1:
# print('\nWaiting %d (in dict %d) %fsec\n'%(numWaiting, len(self._next_dict.keys()), time()-timeStamp))
value = self._next_dict.pop(self._next_index)
self._next_index = self._next_index+1
return value
from queue import Queue as QueueThread
from threading import Thread
class setWorkers_thread():
def __init__(self, indexer, pre_fun, app_fun, buffer_size=100, workers=1):
self._len = int(len(indexer))
self._buffer = int(buffer_size)
self._workers = int(workers)
self._flag_reset = hasattr(indexer, "on_epoch_end")
assert (self._workers <= self._buffer)
assert (3 * self._buffer <= self._len)
self._queueIn = QueueThread(self._buffer)
self._processIn = Thread(target=self._run_in, args=(indexer, self._queueIn, pre_fun, self._flag_reset))
self._queueOut = QueueThread(self._buffer)
self._app_fun = app_fun
self._processes = [Thread(target=self._run_fun, args=(index,)) for index in range(self._workers)]
self._next_dict = dict()
self._next_index = 0
def _run_in(self, indexer, queue, pre_fun, flag_reset):
while True:
if flag_reset:
indexer.on_epoch_end()
for index in range(len(indexer)):
try:
item = indexer[index]
item = pre_fun(*item)
except:
item = None
#print(index, queue.qsize(), self._queueOut.qsize(), end="\r")
queue.put((index, item))
def _run_fun(self, index_process):
while True:
try:
index, item = self._queueIn.get()
item = self._app_fun(*item)
self._queueOut.put((index, item))
except:
pass
def info(self):
for process in self._processes:
print(process.is_alive(), end=' ')
print()
def __enter__(self):
self._next_dict = dict()
self._next_index = 0
for process in self._processes:
process.start()
self._processIn.start()
return self
def __exit__(self, exc_type, exc_value, traceback):
for process in self._processes:
try:
process.terminate()
except:
pass
try:
self._processIn.terminate()
except:
pass
def __len__(self):
return self._len
def __iter__(self):
return self
def __next__(self):
if self._next_index >= self._len:
self._next_index = 0
if not self._flag_reset:
raise StopIteration
numWaiting = 0
# timeStamp = time()
while not (self._next_index in self._next_dict.keys()):
index, item = self._queueOut.get()
self._next_dict[index] = item
numWaiting = numWaiting + 1
# if numWaiting>1:
# print('\nWaiting %d (in dict %d) %fsec\n'%(numWaiting, len(self._next_dict.keys()), time()-timeStamp))
value = self._next_dict.pop(self._next_index)
self._next_index = self._next_index + 1
return value
================================================
FILE: training/code/create_data.py
================================================
# %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
#
# Copyright (c) 2020 Image Processing Research Group of University Federico II of Naples ('GRIP-UNINA').
# This software is delivered with Government Purpose Rights (GPR) under agreement number FA8750-16-2-0204.
#
# By downloading and/or using any of these files, you implicitly agree to all the
# terms of the license, as specified in the document LICENSE.txt
# (included in this package)
#
# %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
"""
@author: davide.cozzolino
"""
import os
from time import time
from PIL import Image
import numpy as np
import argparse
try:
from .db_utility import get_list_valid, get_list_train, jpeg_compression
except:
from db_utility import get_list_valid, get_list_train, jpeg_compression
parser = argparse.ArgumentParser(description="Script to generate numpy files of dataset.", formatter_class=argparse.ArgumentDefaultsHelpFormatter)
parser.add_argument('--output_dir', type=str , default='../data/ori/', help='output directory')
parser.add_argument('--width' , type=int , default=1792 , help='width of the extracted dataset')
parser.add_argument('--height' , type=int , default=1280 , help='height of the extracted dataset')
parser.add_argument('--seed' , type=int , default=3453 , help='manual seed')
parser.add_argument('--jpeg_comp' , type=bool, default=False, help='flag for JPEG compression')
parser.add_argument('--resize_img', type=int , default=None , help='size for image resizing, None for no resizing')
parser.add_argument('--low_comp' , type=int , default=90 , help='minimum JPEG compression')
parser.add_argument('--high_comp' , type=int , default=90 , help='maximum JPEG compression')
opt = parser.parse_args()
print(opt)
seed = opt.seed
outputdata = opt.output_dir
size_imgs = (opt.width, opt.height) # (W,H)
jpegComp = opt.jpeg_comp
lowComp = opt.low_comp
highComp = opt.low_comp
resizeImg = opt.resize_img
os.makedirs(outputdata, exist_ok=True)
imgs = dict()
imgs["train"] = get_list_train()
imgs["valid"] = get_list_valid()
print("train num.cam %3d; num img %d "% (len(imgs["train"]), sum([len(x) for x in imgs["train"]])))
print("valid num.cam %3d; num img %d "% (len(imgs["valid"]), sum([len(x) for x in imgs["valid"]])))
seed = np.random.RandomState(seed)
for key in ["train", "valid"]:
list_cams = imgs[key]
timestamp = time()
num_imgs = 0
for index, list_imgs in enumerate(list_cams):
lists_out = list()
for filename in list_imgs:
with Image.open(filename) as img_o:
if (resizeImg is not None) and (img_o.size[0]>resizeImg):
outsize = (resizeImg, img_o.size[1]*resizeImg//img_o.size[0])
print(img_o.size, outsize)
img = img_o.resize(outsize, resample=Image.BILINEAR)
else:
img = img_o.copy()
if jpegComp:
quality = seed.randint(lowComp, highComp + 1)
img = jpeg_compression(img, quality)
left = (img.size[0] - size_imgs[0]) // 2
upper = (img.size[1] - size_imgs[1]) // 2
left = left - left % 16
upper = upper - upper % 16
img = img.crop((left, upper, left + size_imgs[0], upper + size_imgs[1]))
lists_out.append(np.asarray(img))
num_imgs = num_imgs + 1
print(key, index, num_imgs, (time() - timestamp) / num_imgs)
np.save(os.path.join(outputdata,'%s%04d.npy'% (key, index)), lists_out)
================================================
FILE: training/code/db_utility.py
================================================
# %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
#
# Copyright (c) 2020 Image Processing Research Group of University Federico II of Naples ('GRIP-UNINA').
# This software is delivered with Government Purpose Rights (GPR) under agreement number FA8750-16-2-0204.
#
# By downloading and/or using any of these files, you implicitly agree to all the
# terms of the license, as specified in the document LICENSE.txt
# (included in this package)
#
# %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
"""
@author: davide.cozzolino
"""
import pandas
import numpy as np
import os
dataset_root = '../dataset/dpreview.com' #TODO set these variable
dataset_models = '../dataset/list_models.csv'
dataset_images = '../dataset/list_images.csv'
def get_list_valid():
tab_models = pandas.read_csv(dataset_models, sep=';', dtype={'id': str})
tab_images = pandas.read_csv(dataset_images, sep=';', dtype={'id': str, 'id_model':str})
list_models = sorted(tab_models.loc[tab_models['valid']==1]['id'].tolist())
imgs = list()
for item in list_models:
tab_one = tab_images[tab_images['id_model']==item]
list_file = tab_one['id'].tolist()
img1 = list()
for name in list_file:
filename = os.path.join(dataset_root, 'cam_'+item, name + '.jpg')
img1.append(filename)
imgs.append(img1)
return imgs
def get_list_train():
tab_models = pandas.read_csv(dataset_models,sep=';', dtype={'id': str})
tab_images = pandas.read_csv(dataset_images,sep=';', dtype={'id': str, 'id_model':str})
list_models = sorted(tab_models.loc[tab_models['train']==1]['id'].tolist())
imgs = list()
for item in list_models:
tab_one = tab_images[tab_images['id_model']==item]
list_file = tab_one['id'].tolist()
img1 = list()
for name in list_file:
filename = os.path.join(dataset_root, 'cam_'+item, name+'.jpg')
img1.append(filename)
imgs.append(img1)
return imgs
def jpeg_compression(img, quality):
from PIL import Image
from io import BytesIO
buffer = BytesIO()
img.save(buffer, format="JPEG", quality=quality, progression=False, optimize=False)
return Image.open(buffer)
def jpeg_compression_numpy(x, quality):
from PIL import Image
from io import BytesIO
with BytesIO() as buffer:
with Image.fromarray(x) as img_x:
img_x.save(buffer, format="JPEG", quality=quality, progression=False, optimize=False)
with Image.open(buffer) as img_y:
y = np.asarray(img_y).copy()
return y
if __name__ == '__main__':
from tqdm import tqdm
from PIL import Image
#list_all = sum(get_list_valid(),list())
list_all = sum(get_list_train(), list())
for item in tqdm(list_all):
try:
img = Image.open(item)
if img.mode=='RGB':
ss = img.size
img = np.copy(np.asarray(img))
if not img.dtype==np.uint8:
print('\n\nB%s\n\n\n'%item, img.dtype)
elif not len(img.shape)==3:
print('\n\nC%s\n\n\n'%item)
elif not img.shape[2]==3:
print('\n\nD%s\n\n\n'%item)
elif not img.shape[0]==ss[1]:
print('\n\nF%s\n\n\n'%item)
elif not img.shape[1]==ss[0]:
print('\n\nG%s\n\n\n'%item)
#print('\n\n%s\n\n\n'%'ok')
else:
print('\n\nA%s\n\n\n'%item)
except:
print('\n\nE%s\n\n\n'%item)
================================================
FILE: training/code/train_denoiser.py
================================================
# %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
#
# Copyright (c) 2020 Image Processing Research Group of University Federico II of Naples ('GRIP-UNINA').
# This software is delivered with Government Purpose Rights (GPR) under agreement number FA8750-16-2-0204.
#
# By downloading and/or using any of these files, you implicitly agree to all the
# terms of the license, as specified in the document LICENSE.txt
# (included in this package)
#
# %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
"""
@author: davide.cozzolino
"""
import os
import numpy as np
import tensorflow as tf
import argparse
try:
from . import train_utility as utility
#from .Producer2 import setWorkers_mock as setWorkers
#from .Producer2 import setWorkers_process as setWorkers
from .Producer2 import setWorkers_thread as setWorkers
from .FCnet import FullConvNet
except:
import train_utility as utility
#from Producer2 import setWorkers_mock as setWorkers
#from Producer2 import setWorkers_process as setWorkers
from Producer2 import setWorkers_thread as setWorkers
from FCnet import FullConvNet
parser = argparse.ArgumentParser(description="Script to train the denoiser.", formatter_class=argparse.ArgumentDefaultsHelpFormatter)
parser.add_argument('--gpu' , type=str , default='0' , help='id of GPU to use')
parser.add_argument('--workers' , type=int , default=4 , help='number of workers')
parser.add_argument('--output_dir' , type=str , default='../model/denoiser/', help='output directory')
parser.add_argument('--dataset_dir', type=str , default='../data/ori/' , help='dataset directory')
parser.add_argument('--train_model', type=int , default=600 , help='number of models of the training set')
parser.add_argument('--valid_model', type=int , default=25 , help='number of models of the validation set')
parser.add_argument('--block_size' , type=int , default=64 , help='block size')
parser.add_argument('--inp_channel', type=int , default=3 , help='number of input channels (default: %(default)s, use 1 to replicate original paper)')
parser.add_argument('--noise_std' , type=int , default=5 , help='std of noise (default: %(default)s, use 1 to replicate original paper)')
parser.add_argument('--noise_seed' , type=int , default=11 , help='seed of noise generation')
parser.add_argument('--batch_model', type=int , default=25 , help='number of models in a batch')
parser.add_argument('--epoch_imgs' , type=int , default=128 , help='number of images for model in an epoch')
parser.add_argument('--batch_imgs' , type=int , default=4 , help='number of images for model in a batch')
parser.add_argument('--img_clips' , type=int , default=2 , help='number of cuttings for image')
parser.add_argument('--net_levels' , type=int , default=17 , help='number of levels of the network architecture')
parser.add_argument('--padding' , type=str , default='VALID', help='padding (default: %(default)s, use ''SAME'' to replicate original paper)')
config = parser.parse_args()
print(config)
os.environ["CUDA_VISIBLE_DEVICES"] = config.gpu
np.set_printoptions(formatter={'float': '{: 7.3f}'.format})
block_size = config.block_size
sigma = config.noise_std/256.0
nearImg = config.batch_imgs
cliped_num = config.img_clips
batch_model = config.batch_model
batch_num = nearImg * cliped_num * batch_model
numMaxImg = config.epoch_imgs
num_levels = config.net_levels
numWorkers = config.workers
assert(numMaxImg%nearImg==0)
init_forderNET = None
list_lr = [1e-3,]*10 + [1e-4,]*20 + [1e-5,]*20 + [1e-6,]*20
forderNET = os.path.join(config.output_dir, "net%d_%d_%d" % (config.net_levels, config.inp_channel, config.noise_std))
def onlyOpenImage(img, *other):
return (img, *other)
def clipImage(img, wSize, crop0, crop1, indRot):
left = max(min(int(np.floor((img.shape[1] - wSize + 1) * crop1)), img.shape[1] - wSize), 0)
upper = max(min(int(np.floor((img.shape[0] - wSize + 1) * crop0)), img.shape[0] - wSize), 0)
right = left + wSize
lower = upper + wSize
img = img[upper:lower, left:right, :]
indRot = indRot % 8
if indRot >= 4:
img = img[::-1, :, :]
img = np.rot90(img, indRot % 4, axes=(0, 1))
img = img.astype(np.float32) / 256
return img
if __name__ == '__main__':
tf.reset_default_graph()
#make list datasets
imgs_train = [np.load(os.path.join(config.dataset_dir,'train%04d.npy'%index)) for index in range(config.train_model)]
imgs_valid = [np.load(os.path.join(config.dataset_dir,'valid%04d.npy'%index)) for index in range(config.valid_model)]
print(len(imgs_train), len(imgs_valid))
assert(len(imgs_train) % batch_model == 0)
assert(len(imgs_valid) % batch_model == 0)
numEpoch = len(list_lr)
global_step = tf.Variable(0, name="global_step", trainable=False)
x_data = tf.placeholder(tf.float32, [batch_num, block_size, block_size, config.inp_channel], name="x_data")
n_data = tf.random.normal([batch_num, block_size, block_size, config.inp_channel], mean=0.0, stddev=1.0, \
dtype=tf.float32, seed=config.noise_seed, name=None)
n_info = n_data[0,0,0,0]
learnin_rate = tf.placeholder(tf.float32, [], name="learnin_rate")
flag_train = tf.placeholder(tf.bool, [], name="flag_train")
net = FullConvNet(bnorm_decay=0.9, num_levels=num_levels)
net_output = net(x_data+sigma*n_data, flag_train, padding=config.padding)
print('output', net_output.get_shape())
tf_whitening = utility.make_whitening(net_output, net_output.get_shape()[1], 2)
if config.padding=='VALID':
n_target = tf.reduce_mean(n_data[:, num_levels:-num_levels, num_levels:-num_levels, :], -1, keepdims=True)
else:
n_target = tf.reduce_mean(n_data, -1, keepdims=True)
loss = tf.reduce_mean(np.square(net_output-n_target))
optimizer = tf.train.AdamOptimizer(learnin_rate, name="opt")
trainer_loss = optimizer.minimize(loss, var_list=net.trainable_list)
train_ops = [trainer_loss] + net.extra_train
train_op = tf.group(*train_ops)
configSess = tf.ConfigProto(); configSess.gpu_options.allow_growth = True
#configSess = tf.ConfigProto(gpu_options=tf.GPUOptions(per_process_gpu_memory_fraction=0.95))
sess = tf.Session(config=configSess)
sess.run(tf.global_variables_initializer())
if init_forderNET is not None:
init_saver = tf.train.Saver(net.variables_list)
init_chkpt_fname = init_forderNET #tf.train.latest_checkpoint(init_forderNET)
init_saver.restore(sess, init_chkpt_fname)
list_var_Saver = [global_step, ] + net.variables_list
saver = tf.train.Saver(list_var_Saver, max_to_keep=None)
test_function = lambda x_data_value: sess.run((loss, n_info, tf_whitening),
feed_dict={flag_train: False, x_data: x_data_value})
train_function = lambda x_data_value, learnin_rate_value: sess.run((loss, tf_whitening, train_op),
feed_dict={flag_train: True , x_data: x_data_value, learnin_rate: learnin_rate_value})
os.makedirs(forderNET, exist_ok=True)
chkpt_fname = tf.train.latest_checkpoint(forderNET)
print(chkpt_fname)
if not(chkpt_fname==None):
saver.restore(sess, chkpt_fname)
#sess.run(tf.assign(global_step, 1))
print('restored')
else:
saver.save(sess, os.path.join(forderNET, "model"), global_step = global_step)
with open(os.path.join(forderNET, "log.txt"),'a') as filelog:
for epoch in range(sess.run(global_step),numEpoch+1):
if epoch>=0:
list_valid = utility.genList(imgs_valid, numMaxImg, nearImg, 8)
assert(len(list_valid) % (batch_model * nearImg) == 0)
num_iter_valid = len(list_valid)//(batch_model * nearImg)
print(len(list_valid), batch_model * nearImg, num_iter_valid)
list_valid = utility.genListWithCliped(list_valid, batch_model * nearImg, \
cliped_num, block_size)
cum_whitening_value = 0
cum_loss = 0
with setWorkers(list_valid, pre_fun=onlyOpenImage, app_fun=clipImage, \
buffer_size=numWorkers*100, workers=numWorkers) as iter_valid:
iteretion = 0
for x_data_value in utility.genBatchList(batch_num, iter_valid, flag_reset=False):
x_data_value = np.asarray(x_data_value)
if config.inp_channel==1:
x_data_value = 0.299 * x_data_value[:, :, :, 0:1] + \
0.587 * x_data_value[:, :, :, 1:2] + \
0.114 * x_data_value[:, :, :, 2:3]
loss_value, info_value, whitening_value = test_function(x_data_value)
print("Valid epoch:%04d, %06d/%06d, loss:%6g (%6g), noise:%g, reg:%6g" % \
(epoch, iteretion, num_iter_valid, loss_value, \
-10*np.log10(loss_value), info_value, whitening_value))
cum_loss += loss_value
cum_whitening_value += whitening_value
iteretion = iteretion+1
cum_loss = cum_loss/num_iter_valid
cum_whitening_value = cum_whitening_value/num_iter_valid
print("Valid epoch:%04d, end, loss:%6g (%6g), reg:%6g" % (epoch, cum_loss, \
-10*np.log10(cum_loss), cum_whitening_value))
filelog.write("Valid epoch:%04d, end, loss:%6g (%6g), reg:%6g\n" % (epoch, cum_loss, \
-10*np.log10(cum_loss), cum_whitening_value))
filelog.flush()
if epoch < numEpoch:
learnin_rate_value = list_lr[epoch]
list_train = utility.genList(imgs_train, numMaxImg, nearImg, 1)
assert(len(list_train) % (batch_model * nearImg) == 0)
num_iter_train = len(list_train)//(batch_model * nearImg)
print(len(list_train), batch_model * nearImg, num_iter_train)
list_train = utility.genListWithCliped(list_train, batch_model * nearImg, \
cliped_num, block_size)
with setWorkers(list_train, pre_fun=onlyOpenImage, app_fun=clipImage, \
buffer_size=numWorkers*100, workers=numWorkers) as iter_train:
iteretion = 0
for x_data_value in utility.genBatchList(batch_num, iter_train, flag_reset=False):
x_data_value = np.asarray(x_data_value)
if config.inp_channel == 1:
x_data_value = 0.299 * x_data_value[:, :, :, 0:1] + \
0.587 * x_data_value[:, :, :, 1:2] + \
0.114 * x_data_value[:, :, :, 2:3]
loss_value, whitening_value, _ = train_function(x_data_value, learnin_rate_value)
print("Train epoch:%04d, lr:%6g, %06d/%06d, loss:%6g, (%6g), reg:%6g" % \
(epoch, learnin_rate_value, iteretion, num_iter_train, loss_value, -10*np.log10(loss_value), whitening_value))
iteretion = iteretion+1
sess.run(tf.assign(global_step, epoch + 1))
saver.save(sess, os.path.join(forderNET, "model"), global_step=global_step)
================================================
FILE: training/code/train_noiseprint.py
================================================
# %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
#
# Copyright (c) 2020 Image Processing Research Group of University Federico II of Naples ('GRIP-UNINA').
# This software is delivered with Government Purpose Rights (GPR) under agreement number FA8750-16-2-0204.
#
# By downloading and/or using any of these files, you implicitly agree to all the
# terms of the license, as specified in the document LICENSE.txt
# (included in this package)
#
# %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
"""
@author: davide.cozzolino
"""
import os
import numpy as np
import tensorflow as tf
import argparse
try:
from . import train_utility as utility
#from .Producer2 import setWorkers_mock as setWorkers
#from .Producer2 import setWorkers_process as setWorkers
from .Producer2 import setWorkers_thread as setWorkers
from .FCnet import FullConvNet
except:
import train_utility as utility
#from Producer2 import setWorkers_mock as setWorkers
#from Producer2 import setWorkers_process as setWorkers
from Producer2 import setWorkers_thread as setWorkers
from FCnet import FullConvNet
parser = argparse.ArgumentParser(description="Script to train the Noiseprint.", formatter_class=argparse.ArgumentDefaultsHelpFormatter)
parser.add_argument('--gpu' , type=str , default='0' , help='id of GPU to use')
parser.add_argument('--workers' , type=int , default=4 , help='number of workers')
parser.add_argument('--output_dir' , type=str , default='../model/noiseprint_ori/', help='output directory')
parser.add_argument('--dataset_dir', type=str , default='../data/ori/' , help='dataset directory')
parser.add_argument('--pretrain' , type=str , default='../pretrain/denoiser_17_3_5', \
help='pre-trained weight (default: %(default)s, use ''../pretrain/denoiser_17_1_1'' to replicate original paper)')
parser.add_argument('--train_model', type=int , default=600 , help='number of models of the training set')
parser.add_argument('--valid_model', type=int , default=25 , help='number of models of the validation set')
parser.add_argument('--block_size' , type=int , default=48 , help='block size')
parser.add_argument('--inp_channel', type=int , default=3 , help='number of input channels (default: %(default)s, use 1 to replicate original paper)')
parser.add_argument('--reg_type' , type=int , default=2 , help='type of regularization')
parser.add_argument('--reg_weight' , type=float,default=32.0 , help='weight of regularization')
parser.add_argument('--batch_model', type=int , default=25 , help='number of models in a batch')
parser.add_argument('--epoch_imgs' , type=int , default=128 , help='number of images for model in an epoch')
parser.add_argument('--batch_imgs' , type=int , default=4 , help='number of images for model in a batch')
parser.add_argument('--img_clips' , type=int , default=2 , help='number of cuttings for image')
parser.add_argument('--alpha' , type=float,default=1.0 , help='change it if you have the vanishing gradient problem')
parser.add_argument('--net_levels' , type=int , default=17 , help='number of levels of the network architecture')
parser.add_argument('--padding' , type=str , default='VALID', help='padding (default: %(default)s, use ''SAME'' to replicate original paper)')
config = parser.parse_args()
print(config)
os.environ["CUDA_VISIBLE_DEVICES"] = config.gpu
np.set_printoptions(formatter={'float': '{: 7.3f}'.format})
block_size = config.block_size
nearImg = config.batch_imgs
cliped_num = config.img_clips
batch_model = config.batch_model
batch_size = batch_model*nearImg
batch_num = batch_size*cliped_num
numMaxImg = config.epoch_imgs
num_levels = config.net_levels
numWorkers = config.workers
regularize_factor = config.reg_weight
regularize_type = config.reg_type
assert(numMaxImg%nearImg==0)
list_lr = [1e-3,]*20+ [1e-4,]*20 + [1e-5,]*20 + [1e-6,]*20
problem_type = 0 # 0 variant, 1 invariant position
forderNET = os.path.join(config.output_dir, "net%d_%d%d_%d%d_%d" % (num_levels, problem_type, config.inp_channel, nearImg, cliped_num, regularize_type))
init_forderNET = config.pretrain
def onlyOpenImage(img, *other):
return (img, *other)
def clipImage(img, wSize, crop0, crop1, indRot):
left = max(min(int(np.floor((img.shape[1]-wSize+1) * crop1)), img.shape[1]-wSize),0)
upper = max(min(int(np.floor((img.shape[0]-wSize+1) * crop0)), img.shape[0]-wSize),0)
right = left + wSize
lower = upper + wSize
img = img[upper:lower,left:right,:]
indRot = indRot%8
if indRot >=4:
img = img[::-1,:,:]
img = np.rot90(img, indRot%4, axes=(0,1))
img = img.astype(np.float32)/256
return img
if __name__ == '__main__':
cm = utility.defLabelClass(batch_num, nearImg, problem_type*(cliped_num-1)+1)
tf.reset_default_graph()
#make list datasets
imgs_train = [np.load(os.path.join(config.dataset_dir, 'train%04d.npy' % index)) for index in range(config.train_model)]
imgs_valid = [np.load(os.path.join(config.dataset_dir, 'valid%04d.npy' % index)) for index in range(config.valid_model)]
print(len(imgs_train), len(imgs_valid))
assert(len(imgs_train) % batch_model == 0)
assert(len(imgs_valid) % batch_model == 0)
numEpoch = len(list_lr)
global_step = tf.Variable(0, name="global_step", trainable=False)
corr_alpha = tf.Variable(config.alpha, dtype=tf.float32, name="corr_alpha", trainable=False)
x_data = tf.placeholder(tf.float32, [batch_num, block_size, block_size, config.inp_channel], name="x_data")
learnin_rate = tf.placeholder(tf.float32, [], name="learnin_rate")
flag_train = tf.placeholder(tf.bool, [], name="flag_train")
net = FullConvNet(bnorm_decay=0.9, num_levels=num_levels)
net_output = net(x_data, flag_train, padding=config.padding)
print('output', net_output.get_shape())
tf_whitening = utility.make_whitening(net_output, net_output.get_shape()[1], regularize_type)
dist = utility.distmxt(net_output)
corr = -corr_alpha*corr_alpha*dist
loss = tf.reduce_sum(utility.my_loss_paper(corr,cm))
print(dist.get_shape())
print(cm.shape)
dist_p = tf.reduce_sum(dist*(cm>0))/np.count_nonzero(cm>0)
dist_n = tf.reduce_sum(dist*(cm<0))/np.count_nonzero(cm<0)
optimizer = tf.train.AdamOptimizer(learnin_rate, name="opt")
if regularize_factor>0:
loss_and_reg = loss - regularize_factor*tf_whitening
else:
loss_and_reg = loss
trainer_loss = optimizer.minimize(loss_and_reg, var_list=net.trainable_list)
train_ops = [trainer_loss] + net.extra_train
train_op = tf.group(*train_ops)
configSess = tf.ConfigProto(); configSess.gpu_options.allow_growth = True
#configSess = tf.ConfigProto(gpu_options=tf.GPUOptions(per_process_gpu_memory_fraction=0.95))
sess = tf.Session(config=configSess)
sess.run(tf.global_variables_initializer())
if init_forderNET is not None:
init_saver = tf.train.Saver(net.variables_list)
if os.path.isdir(init_forderNET):
init_chkpt_fname = tf.train.latest_checkpoint(init_forderNET)
else:
init_chkpt_fname = init_forderNET
init_saver.restore(sess, init_chkpt_fname)
print('pretrain:', init_chkpt_fname)
list_var_Saver = [global_step, corr_alpha] + net.variables_list
saver = tf.train.Saver(list_var_Saver, max_to_keep=None)
test_function = lambda x_data_value: sess.run((loss, corr, tf_whitening),
feed_dict={flag_train: False, x_data: x_data_value})
train_function = lambda x_data_value, learnin_rate_value: sess.run((loss, tf_whitening, train_op),
feed_dict={flag_train: True , x_data: x_data_value, learnin_rate: learnin_rate_value})
os.makedirs(forderNET, exist_ok=True)
chkpt_fname = tf.train.latest_checkpoint(forderNET)
print(chkpt_fname)
if chkpt_fname is not None:
saver.restore(sess, chkpt_fname)
#sess.run(tf.assign(global_step, 1))
print('restored')
else:
saver.save(sess, os.path.join(forderNET, "model"), global_step = global_step)
with open(os.path.join(forderNET, "log.txt"),'a') as filelog:
for epoch in range(sess.run(global_step),numEpoch+1):
if epoch>=0:
list_valid = utility.genList(imgs_valid, numMaxImg, nearImg, 8)
assert(len(list_valid)%batch_size==0)
num_iter_valid = len(list_valid)//batch_size
print(len(list_valid), batch_size, num_iter_valid)
list_valid = utility.genListWithCliped(list_valid, batch_model*nearImg, \
cliped_num, block_size)
cum_whitening_value = 0
cum_loss = 0
cum_scores = np.zeros((0,), dtype=np.float32)
cum_labels = np.zeros((0,), dtype=np.float32)
with setWorkers(list_valid, pre_fun=onlyOpenImage, app_fun=clipImage, \
buffer_size=numWorkers*100, workers=numWorkers) as iter_valid:
iteretion = 0
for x_data_value in utility.genBatchList(batch_num, iter_valid, flag_reset=False):
x_data_value = np.asarray(x_data_value)
if config.inp_channel == 1:
x_data_value = 0.299 * x_data_value[:, :, :, 0:1] + \
0.587 * x_data_value[:, :, :, 1:2] + \
0.114 * x_data_value[:, :, :, 2:3]
loss_value, corr_value, whitening_value = test_function(x_data_value)
print("Valid epoch:%04d, %06d/%06d, loss:%6g, reg:%6g" % \
(epoch, iteretion, num_iter_valid, loss_value, whitening_value))
cum_scores = np.concatenate((cum_scores, corr_value.flatten()), 0)
cum_labels = np.concatenate((cum_labels, cm.flatten()), 0)
cum_loss += loss_value
cum_whitening_value += whitening_value
iteretion = iteretion+1
cum_loss = cum_loss/num_iter_valid
cum_whitening_value = cum_whitening_value/num_iter_valid
acc_th,acc_val,mcc_th,mcc_val,auc = utility.getAUC(cum_scores,cum_labels)
print("Valid epoch:%04d, end, loss:%6g, auc:%6g, reg:%6g" % (epoch, cum_loss, auc, cum_whitening_value))
print(" acc:%6g, mcc:%6g, acc_th:%6g mcc_th:%6g" % (acc_val, mcc_val, acc_th, mcc_th))
filelog.write("Valid epoch:%04d, end, loss:%6g, auc:%6g, reg:%6g\n" % (epoch, cum_loss, auc, cum_whitening_value))
filelog.write(" acc:%6g, mcc:%6g, acc_th:%6g mcc_th:%6g\n" % (acc_val, mcc_val, acc_th, mcc_th))
filelog.flush()
if epoch < numEpoch:
learnin_rate_value = list_lr[epoch]
list_train = utility.genList(imgs_train, numMaxImg, nearImg, 1)
assert(len(list_train)%batch_size==0)
num_iter_train = len(list_train)//batch_size
print(len(list_train), batch_size, num_iter_train)
list_train = utility.genListWithCliped(list_train, batch_model*nearImg, \
cliped_num, block_size)
with setWorkers(list_train, pre_fun=onlyOpenImage, app_fun=clipImage, \
buffer_size=numWorkers*100, workers=numWorkers) as iter_train:
iteretion = 0
for x_data_value in utility.genBatchList(batch_num, iter_train, flag_reset=False):
x_data_value = np.asarray(x_data_value)
if config.inp_channel == 1:
x_data_value = 0.299 * x_data_value[:, :, :, 0:1] + \
0.587 * x_data_value[:, :, :, 1:2] + \
0.114 * x_data_value[:, :, :, 2:3]
loss_value, whitening_value, _ = train_function(x_data_value, learnin_rate_value)
print("Train epoch:%04d, lr:%6g, %06d/%06d, loss:%6g, reg:%6g" % \
(epoch, learnin_rate_value, iteretion, num_iter_train, loss_value, whitening_value))
iteretion = iteretion+1
sess.run(tf.assign(global_step, epoch + 1))
saver.save(sess, os.path.join(forderNET, "model"), global_step=global_step)
================================================
FILE: training/code/train_utility.py
================================================
# %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
#
# Copyright (c) 2020 Image Processing Research Group of University Federico II of Naples ('GRIP-UNINA').
# This software is delivered with Government Purpose Rights (GPR) under agreement number FA8750-16-2-0204.
#
# By downloading and/or using any of these files, you implicitly agree to all the
# terms of the license, as specified in the document LICENSE.txt
# (included in this package)
#
# %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
"""
@author: davide.cozzolino
"""
import numpy as np
import tensorflow as tf
def distmxt(res):
#numImg = int(res.get_shape()[0])
numImg = tf.shape(res)[0]
res1 = tf.reshape(res ,(numImg, 1, -1))
res2 = tf.reshape(res1,(1, numImg, -1))
T = (res1 - res2)/np.sqrt(2)
dist = tf.reduce_sum(tf.square(T), axis=2)
return dist
def my_loss_paper(corr, cm):
ninf = np.NINF * tf.ones_like(corr)
corrp = tf.where(cm >0, corr, ninf)
corra = tf.where(cm!=0, corr, ninf)
loss = tf.reduce_logsumexp(corra, axis=0) - tf.reduce_logsumexp(corrp,axis=0)
return tf.reduce_sum(loss)
def defLabelClass(batch_size, nearImg, repMat):
atom_size = batch_size//nearImg//repMat
cm = -np.ones((atom_size,atom_size), dtype=np.float32) + 2.0 * np.eye(atom_size, dtype=np.float32)
cm = np.kron(np.ones((repMat,repMat), dtype=np.float32), cm)
cm = np.kron(cm, np.ones((nearImg,nearImg), dtype=np.float32))
cm = cm - np.eye(batch_size, dtype=np.float32)
return cm
def make_whitening(x, block_size, regularize_type):
from scipy import fft
mtxfft_real = np.real(fft(np.eye(block_size),axis=0)).astype(np.float32)
mtxfft_imag = np.imag(fft(np.eye(block_size),axis=0)).astype(np.float32)
tf_fft1_real = tf.tensordot(mtxfft_real, x, [[1,],[1,]])
tf_fft1_imag = tf.tensordot(mtxfft_imag, x, [[1,],[1,]])
tf_fft2_real = tf.tensordot(mtxfft_real, tf_fft1_real, [[1,],[2,]]) - tf.tensordot(mtxfft_imag, tf_fft1_imag, [[1,],[2,]])
tf_fft2_imag = tf.tensordot(mtxfft_real, tf_fft1_imag, [[1,],[2,]]) + tf.tensordot(mtxfft_imag, tf_fft1_real, [[1,],[2,]])
if regularize_type==2:
tf_fft2_abs2 = tf.reduce_mean(tf_fft2_real**2 + tf_fft2_imag**2, axis=2)
print('reg med')
tf_whitening = tf.reduce_mean(tf.log(tf_fft2_abs2 / tf.reduce_sum(tf_fft2_abs2, axis=(0,1,2), keep_dims=True)))
elif regularize_type==1:
tf_fft2_abs2 = (tf_fft2_real**2 + tf_fft2_imag**2)
print('reg sig')
tf_whitening = tf.reduce_mean(tf.log(tf_fft2_abs2 / tf.reduce_sum(tf_fft2_abs2, axis=(0,1,3), keep_dims=True)))
else:
tf_whitening = 0
return tf_whitening
def getAUC(scores, labels):
from sklearn import metrics
inds = np.argsort(scores)
labels = labels[inds]
scores = scores[inds]
tn = np.cumsum((labels==-1).astype(dtype=np.float32))
fp = tn[-1]-tn
fn = np.cumsum((labels==+1).astype(dtype=np.float32))
tp = fn[-1]-fn
acc = (tp/(tp+fn) + tn/(tn+fp))/2
ind_acc = np.argmax(acc)
mcc = (tp*tn-fn*fp)/np.maximum(np.sqrt((tp+fp)*(tp+fn)*(tn+fp)*(tn+fn)),0.0001)
ind_mcc = np.argmax(mcc)
#plt.plot(mcc)
#plt.show()
return scores[ind_acc], acc[ind_acc], scores[ind_mcc], mcc[ind_mcc], metrics.auc(fp/(tn+fp),tp/(fn+tp))
def getAUC_dict(scores, labels):
from sklearn import metrics
inds = np.argsort(scores)
labels = labels[inds]
scores = scores[inds]
tn = np.cumsum((labels==-1).astype(dtype=np.float32))
fp = tn[-1]-tn
fn = np.cumsum((labels==+1).astype(dtype=np.float32))
tp = fn[-1]-fn
FPR = fp/(tn+fp)
TPR = tp/(fn+tp)
auc = metrics.auc(FPR,TPR)
acc = (TPR+1.0-FPR)/2
mcc = (tp*tn-fn*fp)/np.maximum(np.sqrt((tp+fp)*(tp+fn)*(tn+fp)*(tn+fn)),0.0001)
inf_tnr10 = np.argmin(np.abs(TPR-0.9))
inf_tpr10 = np.argmin(np.abs(FPR-0.1))
ind_acc = np.argmax(acc)
ind_mcc = np.argmax(mcc)
out = dict()
out['auc'] = auc
out['TNR10_val'] = 1.0-FPR[inf_tnr10]
out['TPR10_val'] = TPR[inf_tpr10]
out['acc_val'] = acc[ind_acc]
out['mcc_val'] = mcc[ind_mcc]
out['acc_th'] = scores[ind_acc]
out['mcc_th'] = scores[ind_mcc]
out['TNR10_th'] = scores[inf_tnr10]
out['TPR10_th'] = scores[inf_tpr10]
return out
def genListWithCliped(list_input, element_num, cliped_num, wSize):
list_output = list()
for index0 in range(0, len(list_input), element_num):
indRR = np.random.random_sample([cliped_num, 2])
indRot = np.random.randint(low=0, high=8)
for indexR in range(cliped_num):
for indexE in range(index0, index0 + element_num):
list_output.append((list_input[indexE], wSize, indRR[indexR, 0], indRR[indexR, 1], indRot))
return list_output
def genList(imgs, numMaxImg, nearImg, rip):
listInd = list()
numModel = len(imgs)
ripModel = numMaxImg // nearImg
assert numMaxImg % nearImg == 0
numsImg = [len(imgs[indexC]) - (len(imgs[indexC]) % nearImg) for indexC in range(numModel)]
listModel = list(range(numModel))
listImg = [list(range(len(imgs[indexC]))) for indexC in range(numModel)]
for i in range(rip):
for indexR in range(ripModel):
np.random.shuffle(listModel)
for indexC in listModel:
for indexI in range(nearImg * indexR, nearImg * indexR + nearImg):
indexF = indexI % numsImg[indexC]
if indexF == 0:
np.random.shuffle(listImg[indexC])
listInd.append(imgs[indexC][listImg[indexC][indexF]])
return listInd
class genBatchList():
def __init__(self, batch_size, iterator, flag_reset=True):
self.batch_size = int(batch_size)
self.num_samples = len(iterator)
self.iterator = iter(iterator)
self.num_batch = int(np.ceil(self.num_samples / self.batch_size))
self.flag_reset = flag_reset
print(self.num_samples, self.batch_size, self.num_batch)
def getNumSamples(self):
return self.num_samples
def __len__(self):
return self.num_batch
def __iter__(self):
while True:
offset = 0
for b in range(self.num_batch):
data_batch = list()
for c in range(self.batch_size):
offset = offset + 1
data_batch.append(next(self.iterator))
if offset >= self.num_samples: break
yield data_batch
if offset >= self.num_samples: break
if not self.flag_reset:
break
class genBatch():
def __init__(self, batch_size, iterator, flag_reset=True):
self.batch_size = int(batch_size)
self.num_samples = len(iterator)
self.iterator = iter(iterator)
self.num_batch = int(np.ceil(self.num_samples / self.batch_size))
self.flag_reset = flag_reset
print(self.num_samples, self.batch_size, self.num_batch)
def getNumSamples(self):
return self.num_samples
def __len__(self):
return self.num_batch
def __iter__(self):
while True:
offset = 0
for b in range(self.num_batch):
data_batch = list()
for c in range(self.batch_size):
offset = offset + 1
data_batch.append(next(self.iterator))
if offset >= self.num_samples: break
data_batch = np.asarray(data_batch)
yield data_batch
if offset >= self.num_samples: break
if not self.flag_reset:
break
================================================
FILE: training/dataset/README.txt
================================================
This folder contains the list of images used for the training of Noiseprint in the following paper:
D. Cozzolino, F. Marra, D. Gragnaniello, G. Poggi, and L. Verdoliva
''Combining PRNU and noiseprint for robust and efficient device sourceidentification''
submitted, 2019.
Please cite this paper if you use the dataset.
-------------------------------------------------------------------
Dataset
-------------------------------------------------------------------
This a collection of images publicly available on dpreviewer.com
It comprises 625 camera models, with a number of images per model ranging from 8 to 173.
In this archive, there are the following files:
- list_models.csv : the list of 625 models,
- list_images.csv : the list of 21158 images,
- download_images.py: the script in Python 3.x to download the images from dpreview.com
-------------------------------------------------------------------
Feedback
-------------------------------------------------------------------
If you have any comment, suggestion, or question, please do
contact Davide Cozzolino at davide.cozzolino@unina.it
For other information: http://www.grip.unina.it/
================================================
FILE: training/dataset/download_images.py
================================================
# Script in Python 3.x to download the images from dpreview.com
db_root = './dpreview.com/' # directory where to save the downloaded images
file_images = './list_images.csv' # list of images to download from dpreview.com
import requests
import pandas
import numpy as np
import time
import json
import os
import locale
from tqdm import tqdm
from urllib.request import urlretrieve
locale.setlocale(locale.LC_ALL, 'en_US.UTF-8')
def download(url, output_dir ):
filename = os.path.basename(url).split('?')[0]
output_file = os.path.join(output_dir, filename)
trys = 0
while trys<5:
trys = trys+1
try:
urlretrieve(url, output_file)
return trys
except:
time.sleep(10)
return trys
list_images = pandas.read_csv(file_images, sep=';', dtype={'id': str,'id_model': str})
dat_models = dict()
print('Downloading images from dpreview.com ...')
for index, img in tqdm(list_images.iterrows(), total=len(list_images)):
id_model = img['id_model']
id_image = img['id']
if id_model not in dat_models:
output_dir = os.path.join(db_root, id_model)
os.makedirs(output_dir, exist_ok=True)
page0 = requests.get('https://www.dpreview.com/sample-galleries/data/get-gallery?galleryId=%s'%id_model)
dat_models[id_model] = json.loads(page0.content)['images']
info = [x for x in dat_models[id_model] if x['id']==id_image][0]
download(info['url'], output_dir)
print('Downloading is DONE.')
================================================
FILE: training/dataset/list_images.csv
================================================
id_model;id;make;model;orin;qf;size0;size1
7322051411;1728161198;Amazon;Fire;-1;95.0;4160;3120
7322051411;4324171913;Amazon;Fire;-1;95.0;4160;3120
7322051411;1827430622;Amazon;Fire;-1;95.0;4160;3120
7322051411;4206013541;Amazon;Fire;-1;95.0;4160;3120
7322051411;8879901833;Amazon;Fire;-1;95.0;4160;3120
7322051411;4544130086;Amazon;Fire;-1;95.0;4160;3120
7322051411;5073727424;Amazon;Fire;-1;95.0;4160;3120
7322051411;7877316934;Amazon;Fire;-1;95.0;4160;3120
7322051411;8216932071;Amazon;Fire;-1;95.0;4160;3120
7322051411;6569128414;Amazon;Fire;-1;95.0;4160;3120
7322051411;6749089112;Amazon;Fire;-1;95.0;4160;3120
7322051411;2738383728;Amazon;Fire;-1;95.0;4160;3120
7322051411;3830805230;Amazon;Fire;-1;95.0;4160;3120
7322051411;8080090625;Amazon;Fire;-1;95.0;4160;3120
7322051411;3338000266;Amazon;Fire;-1;95.0;4160;3120
7322051411;2910558017;Amazon;Fire;-1;95.0;4160;3120
7322051411;7601124617;Amazon;Fire;-1;95.0;4160;3120
7322051411;8024282474;Amazon;Fire;-1;95.0;4160;3120
7322051411;5283469477;Amazon;Fire;-1;95.0;4160;3120
7322051411;0256686407;Amazon;Fire;-1;95.0;4160;3120
7322051411;0858410041;Amazon;Fire;-1;95.0;4160;3120
7322051411;8002249246;Amazon;Fire;-1;95.0;4160;3120
7322051411;5309660018;Amazon;Fire;-1;95.0;4160;3120
7322051411;5807853852;Amazon;Fire;-1;95.0;4160;3120
7322051411;5053821266;Amazon;Fire;-1;95.0;4160;3120
7322051411;1968379041;Amazon;Fire;-1;95.0;4160;3120
7322051411;8879060022;Amazon;Fire;-1;95.0;4160;3120
7322051411;1044899125;Amazon;Fire;-1;95.0;4160;3120
7322051411;8631429213;Amazon;Fire;-1;95.0;4160;3120
6012702079;1146064630;Apple;iPhone 5s;1;95.0;3264;2448
6012702079;1479795559;Apple;iPhone 5s;1;95.0;3264;2448
6012702079;5017151918;Apple;iPhone 5s;1;95.0;3264;2448
6012702079;8021246536;Apple;iPhone 5s;1;95.0;3264;2448
6012702079;4327619923;Apple;iPhone 5s;1;95.0;3264;2448
6012702079;6098727214;Apple;iPhone 5s;1;95.0;3264;2448
6012702079;6549641290;Apple;iPhone 5s;1;95.0;3264;2448
6012702079;4900957642;Apple;iPhone 5s;1;95.0;3264;2448
6012702079;0585896318;Apple;iPhone 5s;1;95.0;3264;2448
6012702079;6602774612;Apple;iPhone 5s;1;95.0;3264;2448
6012702079;9231653702;Apple;iPhone 5s;1;95.0;3264;2448
6012702079;1929674338;Apple;iPhone 5s;1;95.0;3264;2448
6012702079;3576667248;Apple;iPhone 5s;1;95.0;3264;2448
6012702079;4384539110;Apple;iPhone 5s;1;95.0;3264;2448
6012702079;1175205318;Apple;iPhone 5s;1;95.0;3264;2448
6012702079;2436392761;Apple;iPhone 5s;1;95.0;3264;2448
6012702079;1463125254;Apple;iPhone 5s;1;95.0;3264;2448
6012702079;5019696964;Apple;iPhone 5s;1;95.0;3264;2448
6012702079;0016627020;Apple;iPhone 5s;1;95.0;3264;2448
6012702079;7841521354;Apple;iPhone 5s;1;95.0;3264;2448
6012702079;8729514292;Apple;iPhone 5s;1;95.0;3264;2448
6012702079;1421948253;Apple;iPhone 5s;1;95.0;3264;2448
6012702079;5527365622;Apple;iPhone 5s;1;95.0;3264;2448
6012702079;9639415394;Apple;iPhone 5s;1;95.0;3264;2448
6012702079;9711072319;Apple;iPhone 5s;1;95.0;3264;2448
6012702079;8730656267;Apple;iPhone 5s;1;97.0;3264;2448
6012702079;1471619440;Apple;iPhone 5s;1;95.0;3264;2448
6012702079;7287452319;Apple;iPhone 5s;1;95.0;3264;2448
6012702079;2971316412;Apple;iPhone 5s;1;95.0;3264;2448
6012702079;2432770824;Apple;iPhone 5s;1;95.0;3264;2448
6012702079;0792014992;Apple;iPhone 5s;1;97.0;3264;2448
6012702079;6356253514;Apple;iPhone 5s;1;97.0;3264;2448
6012702079;1514459785;Apple;iPhone 5s;1;97.0;3264;2448
6012702079;5809357400;Apple;iPhone 5s;1;95.0;3264;2448
6012702079;8527754546;Apple;iPhone 5s;1;95.0;3264;2448
6012702079;1014324237;Apple;iPhone 5s;1;95.0;3264;2448
6012702079;2575513938;Apple;iPhone 5s;1;95.0;3264;2448
6012702079;3093706747;Apple;iPhone 5s;1;97.0;3264;2448
6012702079;0595598448;Apple;iPhone 5s;1;97.0;3264;2448
6012702079;0684961571;Apple;iPhone 5s;1;95.0;3264;2448
6012702079;5126052654;Apple;iPhone 5s;1;95.0;3264;2448
6012702079;3304741344;Apple;iPhone 5s;1;95.0;3264;2448
6012702079;7514485441;Apple;iPhone 5s;1;97.0;3264;2448
6012702079;8381539895;Apple;iPhone 5s;1;97.0;3264;2448
6012702079;7747777023;Apple;iPhone 5s;1;97.0;3264;2448
6012702079;8640116592;Apple;iPhone 5s;1;97.0;3264;2448
6012702079;1226638923;Apple;iPhone 5s;1;97.0;3264;2448
6012702079;9895273545;Apple;iPhone 5s;1;97.0;3264;2448
6012702079;6706131922;Apple;iPhone 5s;1;97.0;3264;2448
6012702079;2341088824;Apple;iPhone 5s;1;97.0;3264;2448
6012702079;3465567615;Apple;iPhone 5s;1;97.0;3264;2448
6012702079;5172347400;Apple;iPhone 5s;1;97.0;3264;2448
2985242251;8068224892;Apple;iPhone 6 Plus;1;95.0;3264;2448
2985242251;6966269410;Apple;iPhone 6 Plus;1;97.0;3264;2448
2985242251;8497758798;Apple;iPhone 6 Plus;1;97.0;3264;2448
2985242251;0408919859;Apple;iPhone 6 Plus;1;97.0;3264;2448
2985242251;0422107871;Apple;iPhone 6 Plus;1;97.0;3264;2448
2985242251;9178123021;Apple;iPhone 6 Plus;1;97.0;3264;2448
2985242251;3629786676;Apple;iPhone 6 Plus;6;97.0;3264;2448
2985242251;7153866522;Apple;iPhone 6 Plus;6;97.0;3264;2448
2985242251;3004974300;Apple;iPhone 6 Plus;6;97.0;3264;2448
2985242251;2847233334;Apple;iPhone 6 Plus;1;97.0;3264;2448
2985242251;3101468981;Apple;iPhone 6 Plus;6;97.0;3264;2448
2985242251;4267333809;Apple;iPhone 6 Plus;1;97.0;3264;2448
2985242251;0507347470;Apple;iPhone 6 Plus;1;97.0;3264;2448
2985242251;2258811795;Apple;iPhone 6 Plus;1;97.0;3264;2448
2985242251;3922502823;Apple;iPhone 6 Plus;1;97.0;3264;2448
2985242251;0374521407;Apple;iPhone 6 Plus;1;97.0;3264;2448
2985242251;7468753403;Apple;iPhone 6 Plus;1;97.0;3264;2448
2985242251;1885521790;Apple;iPhone 6 Plus;6;95.0;3264;2448
2985242251;3330574676;Apple;iPhone 6 Plus;1;97.0;3264;2448
2985242251;9737338153;Apple;iPhone 6 Plus;1;97.0;3264;2448
2985242251;8245349000;Apple;iPhone 6 Plus;1;97.0;3264;2448
2985242251;8582958091;Apple;iPhone 6 Plus;6;97.0;3264;2448
2985242251;1664467551;Apple;iPhone 6 Plus;1;97.0;3264;2448
2985242251;9204605187;Apple;iPhone 6 Plus;1;97.0;3264;2448
2985242251;5254499992;Apple;iPhone 6 Plus;1;97.0;3264;2448
2985242251;5908050153;Apple;iPhone 6 Plus;1;97.0;3264;2448
2985242251;0668773348;Apple;iPhone 6 Plus;6;97.0;3264;2448
2985242251;5065137991;Apple;iPhone 6 Plus;1;97.0;3264;2448
1025395973;8739403266;Apple;iPhone 6s;1;96.0;4032;3024
1025395973;2015417173;Apple;iPhone 6s;3;96.0;4032;3024
1025395973;5879754856;Apple;iPhone 6s;3;96.0;4032;3024
1025395973;2794206692;Apple;iPhone 6s;3;95.0;4032;3024
1025395973;7039705065;Apple;iPhone 6s;3;96.0;4032;3024
1025395973;6859229612;Apple;iPhone 6s;6;96.0;4032;3024
1025395973;6628602645;Apple;iPhone 6s;3;95.0;4032;3024
1025395973;1423942353;Apple;iPhone 6s;3;95.0;4032;3024
1025395973;4723664321;Apple;iPhone 6s;6;96.0;4032;3024
1025395973;6684856296;Apple;iPhone 6s;3;96.0;4032;3024
1025395973;7860083874;Apple;iPhone 6s;6;96.0;4032;3024
1025395973;0257499107;Apple;iPhone 6s;1;96.0;4032;3024
1025395973;9834105258;Apple;iPhone 6s;3;96.0;4032;3024
1025395973;8851230733;Apple;iPhone 6s;3;96.0;4032;3024
1025395973;3031191635;Apple;iPhone 6s;3;96.0;4032;3024
1025395973;2241571437;Apple;iPhone 6s;3;96.0;4032;3024
1025395973;3463137357;Apple;iPhone 6s;3;96.0;4032;3024
1025395973;1360352153;Apple;iPhone 6s;6;96.0;4032;3024
1025395973;0067376879;Apple;iPhone 6s;1;96.0;4032;3024
1025395973;6713098526;Apple;iPhone 6s;3;96.0;4032;3024
1025395973;8286878526;Apple;iPhone 6s;3;96.0;4032;3024
1025395973;1398137688;Apple;iPhone 6s;1;98.0;4032;3024
1025395973;6651739972;Apple;iPhone 6s;3;96.0;4032;3024
1025395973;7294432244;Apple;iPhone 6s;3;96.0;4032;3024
1025395973;9197650884;Apple;iPhone 6s;3;96.0;4032;3024
1025395973;7019765667;Apple;iPhone 6s;3;96.0;4032;3024
1025395973;9075122174;Apple;iPhone 6s;3;96.0;4032;3024
1025395973;6057679569;Apple;iPhone 6s;3;95.0;4032;3024
1025395973;9616745172;Apple;iPhone 6s;3;96.0;4032;3024
1025395973;8051763678;Apple;iPhone 6s;3;96.0;4032;3024
1025395973;4618963968;Apple;iPhone 6s;3;96.0;4032;3024
1025395973;0693553939;Apple;iPhone 6s;3;96.0;4032;3024
1025395973;9978498760;Apple;iPhone 6s;3;96.0;4032;3024
1025395973;7329481847;Apple;iPhone 6s;3;96.0;4032;3024
1025395973;3747672404;Apple;iPhone 6s;3;96.0;4032;3024
1025395973;0655578783;Apple;iPhone 6s;3;96.0;4032;3024
1025395973;6846613810;Apple;iPhone 6s;6;96.0;4032;3024
1025395973;4916458964;Apple;iPhone 6s;3;95.0;4032;3024
1025395973;2308278466;Apple;iPhone 6s;3;96.0;4032;3024
1025395973;9916078315;Apple;iPhone 6s;3;96.0;4032;3024
1025395973;6141656987;Apple;iPhone 6s;6;96.0;4032;3024
1025395973;1284422028;Apple;iPhone 6s;6;96.0;4032;3024
1025395973;7613372512;Apple;iPhone 6s;3;96.0;4032;3024
1025395973;2888451247;Apple;iPhone 6s;3;96.0;4032;3024
7612056208;1674243597;Apple;iPhone 6s Plus;1;96.0;4032;3024
7612056208;3422262281;Apple;iPhone 6s Plus;1;96.0;4032;3024
7612056208;0647738028;Apple;iPhone 6s Plus;1;96.0;4032;3024
7612056208;8878026449;Apple;iPhone 6s Plus;1;96.0;4032;3024
7612056208;9325040961;Apple;iPhone 6s Plus;1;96.0;4032;3024
7612056208;6150269375;Apple;iPhone 6s Plus;1;96.0;4032;3024
7612056208;1022748815;Apple;iPhone 6s Plus;1;96.0;4032;3024
7612056208;9257350124;Apple;iPhone 6s Plus;1;96.0;4032;3024
7612056208;0046645997;Apple;iPhone 6s Plus;1;96.0;4032;3024
7612056208;5949228392;Apple;iPhone 6s Plus;1;96.0;4032;3024
7612056208;0788525096;Apple;iPhone 6s Plus;1;96.0;4032;3024
7612056208;2672456477;Apple;iPhone 6s Plus;1;96.0;4032;3024
7612056208;8900408568;Apple;iPhone 6s Plus;1;96.0;4032;3024
7612056208;8125648736;Apple;iPhone 6s Plus;1;96.0;4032;3024
7612056208;4647145318;Apple;iPhone 6s Plus;1;96.0;4032;3024
7612056208;5966253141;Apple;iPhone 6s Plus;1;96.0;4032;3024
7612056208;8814588688;Apple;iPhone 6s Plus;1;96.0;4032;3024
7612056208;5021411160;Apple;iPhone 6s Plus;1;96.0;4032;3024
7612056208;5713251851;Apple;iPhone 6s Plus;1;96.0;4032;3024
7612056208;4013476971;Apple;iPhone 6s Plus;1;96.0;4032;3024
7612056208;6188979717;Apple;iPhone 6s Plus;1;96.0;4032;3024
7612056208;6763389843;Apple;iPhone 6s Plus;1;96.0;4032;3024
7612056208;1640623630;Apple;iPhone 6s Plus;1;96.0;4032;3024
7612056208;6195160290;Apple;iPhone 6s Plus;6;96.0;4032;3024
7612056208;8685852784;Apple;iPhone 6s Plus;1;96.0;4032;3024
7612056208;1409903269;Apple;iPhone 6s Plus;1;96.0;4032;3024
7612056208;9442181425;Apple;iPhone 6s Plus;1;96.0;4032;3024
7612056208;3670176968;Apple;iPhone 6s Plus;1;96.0;4032;3024
7612056208;4296092758;Apple;iPhone 6s Plus;1;96.0;4032;3024
7612056208;9024023737;Apple;iPhone 6s Plus;1;96.0;4032;3024
7612056208;9794285535;Apple;iPhone 6s Plus;1;96.0;4032;3024
7612056208;4057705044;Apple;iPhone 6s Plus;1;96.0;4032;3024
7612056208;0540567159;Apple;iPhone 6s Plus;1;96.0;4032;3024
7612056208;8683033398;Apple;iPhone 6s Plus;1;96.0;4032;3024
7612056208;1008990064;Apple;iPhone 6s Plus;6;96.0;4032;3024
7612056208;0937937586;Apple;iPhone 6s Plus;1;96.0;4032;3024
7612056208;8677311240;Apple;iPhone 6s Plus;1;96.0;4032;3024
7612056208;2595087895;Apple;iPhone 6s Plus;1;96.0;4032;3024
7612056208;8111670762;Apple;iPhone 6s Plus;1;96.0;4032;3024
7612056208;3392226742;Apple;iPhone 6s Plus;1;96.0;4032;3024
7612056208;2198198679;Apple;iPhone 6s Plus;1;96.0;4032;3024
7612056208;0546084224;Apple;iPhone 6s Plus;6;96.0;4032;3024
7612056208;7865192067;Apple;iPhone 6s Plus;1;96.0;4032;3024
7612056208;9985853529;Apple;iPhone 6s Plus;1;96.0;4032;3024
7612056208;6686675236;Apple;iPhone 6s Plus;1;96.0;4032;3024
7612056208;2027385243;Apple;iPhone 6s Plus;1;96.0;4032;3024
7612056208;0351101926;Apple;iPhone 6s Plus;8;96.0;4032;3024
7612056208;9829096248;Apple;iPhone 6s Plus;6;96.0;4032;3024
7612056208;9145675203;Apple;iPhone 6s Plus;1;96.0;4032;3024
7612056208;4613015423;Apple;iPhone 6s Plus;6;96.0;4032;3024
7612056208;4178073786;Apple;iPhone 6s Plus;1;96.0;4032;3024
7612056208;4018536353;Apple;iPhone 6s Plus;1;96.0;4032;3024
7612056208;8370689740;Apple;iPhone 6s Plus;1;96.0;4032;3024
7612056208;3454904391;Apple;iPhone 6s Plus;1;96.0;4032;3024
7612056208;9016563850;Apple;iPhone 6s Plus;1;96.0;4032;3024
7612056208;4838185603;Apple;iPhone 6s Plus;1;96.0;4032;3024
7612056208;1329289564;Apple;iPhone 6s Plus;1;96.0;4032;3024
7612056208;4669402665;Apple;iPhone 6s Plus;1;96.0;4032;3024
7612056208;3739645629;Apple;iPhone 6s Plus;1;96.0;4032;3024
7612056208;1945009016;Apple;iPhone 6s Plus;1;96.0;4032;3024
7612056208;2284323624;Apple;iPhone 6s Plus;1;96.0;4032;3024
7612056208;7721768069;Apple;iPhone 6s Plus;1;96.0;4032;3024
7612056208;6390242510;Apple;iPhone 6s Plus;1;96.0;4032;3024
7612056208;4995202066;Apple;iPhone 6s Plus;1;96.0;4032;3024
7612056208;4222788622;Apple;iPhone 6s Plus;6;96.0;4032;3024
7612056208;5939281731;Apple;iPhone 6s Plus;1;96.0;4032;3024
6451030628;7789035884;Apple;iPhone 7;1;97.0;4032;3024
6451030628;8364308256;Apple;iPhone 7;1;96.0;4032;3024
6451030628;1679936033;Apple;iPhone 7;1;96.0;4032;3024
6451030628;4048274962;Apple;iPhone 7;1;96.0;4032;3024
6451030628;0598115673;Apple;iPhone 7;1;96.0;4032;3024
6451030628;9908499227;Apple;iPhone 7;1;97.0;4032;3024
6451030628;3096797042;Apple;iPhone 7;1;97.0;4032;3024
6451030628;6344281912;Apple;iPhone 7;1;96.0;4032;3024
6451030628;5100484136;Apple;iPhone 7;1;97.0;4032;3024
6451030628;2756643776;Apple;iPhone 7;1;97.0;4032;3024
6451030628;0910319874;Apple;iPhone 7;1;95.0;4032;3024
6451030628;0740601496;Apple;iPhone 7;1;97.0;4032;3024
6451030628;9349107992;Apple;iPhone 7;1;95.0;4032;3024
6451030628;8009212110;Apple;iPhone 7;1;95.0;4032;3024
6451030628;2144916766;Apple;iPhone 7;1;95.0;4032;3024
6451030628;9192363171;Apple;iPhone 7;6;95.0;4032;3024
6451030628;9049049087;Apple;iPhone 7;1;97.0;4032;3024
6451030628;9887803931;Apple;iPhone 7;1;95.0;4032;3024
6451030628;4018590352;Apple;iPhone 7;1;95.0;4032;3024
6451030628;0697954235;Apple;iPhone 7;1;97.0;4032;3024
6451030628;0821644370;Apple;iPhone 7;1;95.0;4032;3024
6451030628;3126751425;Apple;iPhone 7;6;95.0;4032;3024
6451030628;7133921162;Apple;iPhone 7;1;97.0;4032;3024
6451030628;0452850129;Apple;iPhone 7;1;95.0;4032;3024
6451030628;2836628527;Apple;iPhone 7;6;95.0;4032;3024
6451030628;5479940198;Apple;iPhone 7;1;97.0;4032;3024
6451030628;6255046021;Apple;iPhone 7;1;95.0;4032;3024
6451030628;4534595863;Apple;iPhone 7;6;95.0;4032;3024
6451030628;5460889483;Apple;iPhone 7;6;95.0;4032;3024
6451030628;0311075472;Apple;iPhone 7;6;95.0;4032;3024
9692509593;1104949529;Apple;iPhone 7 Plus;1;96.0;4032;3024
9692509593;4538982283;Apple;iPhone 7 Plus;1;95.0;4032;3024
9692509593;3397082627;Apple;iPhone 7 Plus;1;96.0;4032;3024
9692509593;1872734519;Apple;iPhone 7 Plus;1;96.0;4032;3024
9692509593;2054354529;Apple;iPhone 7 Plus;1;96.0;4032;3024
9692509593;2778484918;Apple;iPhone 7 Plus;1;96.0;4032;3024
9692509593;6723474292;Apple;iPhone 7 Plus;1;96.0;4032;3024
9692509593;2366343853;Apple;iPhone 7 Plus;1;96.0;4032;3024
9692509593;3698239782;Apple;iPhone 7 Plus;1;95.0;4032;3024
9692509593;3981393608;Apple;iPhone 7 Plus;6;96.0;4032;3024
9692509593;6791645367;Apple;iPhone 7 Plus;1;96.0;4032;3024
9692509593;1534905963;Apple;iPhone 7 Plus;1;95.0;4032;3024
9692509593;8608436927;Apple;iPhone 7 Plus;1;96.0;4032;3024
9692509593;4637171389;Apple;iPhone 7 Plus;1;96.0;4032;3024
9692509593;4576100038;Apple;iPhone 7 Plus;6;96.0;4032;3024
9692509593;8231168802;Apple;iPhone 7 Plus;1;96.0;4032;3024
9692509593;9018192709;Apple;iPhone 7 Plus;6;96.0;4032;3024
9692509593;5663211821;Apple;iPhone 7 Plus;1;96.0;4032;3024
9692509593;3476728495;Apple;iPhone 7 Plus;6;96.0;4032;3024
9692509593;2162914008;Apple;iPhone 7 Plus;1;95.0;4032;3024
9692509593;0457355490;Apple;iPhone 7 Plus;1;96.0;4032;3024
9692509593;9632368381;Apple;iPhone 7 Plus;1;96.0;4032;3024
9692509593;4508512069;Apple;iPhone 7 Plus;1;96.0;4032;3024
9692509593;8730136603;Apple;iPhone 7 Plus;1;96.0;4032;3024
9692509593;8005640396;Apple;iPhone 7 Plus;1;95.0;4032;3024
9692509593;4569139778;Apple;iPhone 7 Plus;1;96.0;4032;3024
9692509593;3305062938;Apple;iPhone 7 Plus;1;96.0;4032;3024
9692509593;5692276675;Apple;iPhone 7 Plus;1;96.0;4032;3024
9692509593;2828309201;Apple;iPhone 7 Plus;1;96.0;4032;3024
9692509593;3029043605;Apple;iPhone 7 Plus;1;95.0;4032;3024
9692509593;8393877071;Apple;iPhone 7 Plus;1;96.0;4032;3024
9692509593;4697692849;Apple;iPhone 7 Plus;1;96.0;4032;3024
9692509593;5351325778;Apple;iPhone 7 Plus;1;96.0;4032;3024
9692509593;9055028449;Apple;iPhone 7 Plus;1;96.0;4032;3024
9692509593;0225500485;Apple;iPhone 7 Plus;1;96.0;4032;3024
9692509593;1949369659;Apple;iPhone 7 Plus;1;96.0;4032;3024
9692509593;7101058077;Apple;iPhone 7 Plus;6;96.0;4032;3024
9692509593;1424954497;Apple;iPhone 7 Plus;6;96.0;4032;3024
9692509593;1477203479;Apple;iPhone 7 Plus;1;96.0;4032;3024
9692509593;7181978057;Apple;iPhone 7 Plus;1;96.0;4032;3024
9692509593;3975085521;Apple;iPhone 7 Plus;1;96.0;4032;3024
9692509593;9730532563;Apple;iPhone 7 Plus;1;95.0;4032;3024
9692509593;7708019705;Apple;iPhone 7 Plus;1;96.0;4032;3024
9692509593;9106404945;Apple;iPhone 7 Plus;1;96.0;4032;3024
9692509593;4621355250;Apple;iPhone 7 Plus;6;96.0;4032;3024
9692509593;1520872719;Apple;iPhone 7 Plus;1;95.0;4032;3024
9692509593;7312222762;Apple;iPhone 7 Plus;6;96.0;4032;3024
9692509593;1609291911;Apple;iPhone 7 Plus;6;96.0;4032;3024
9692509593;9164214470;Apple;iPhone 7 Plus;6;96.0;4032;3024
9692509593;7530290110;Apple;iPhone 7 Plus;1;96.0;4032;3024
9692509593;7996409789;Apple;iPhone 7 Plus;1;96.0;4032;3024
9692509593;4186930093;Apple;iPhone 7 Plus;1;96.0;4032;3024
9692509593;7576428532;Apple;iPhone 7 Plus;1;96.0;4032;3024
9692509593;0976989508;Apple;iPhone 7 Plus;1;96.0;4032;3024
9692509593;7339775735;Apple;iPhone 7 Plus;1;96.0;4032;3024
9692509593;6301116284;Apple;iPhone 7 Plus;1;96.0;4032;3024
9692509593;5924059206;Apple;iPhone 7 Plus;1;96.0;4032;3024
2637450826;6701679567;Apple;iPhone 8 Plus;1;95.0;4032;3024
2637450826;0004071346;Apple;iPhone 8 Plus;1;95.0;4032;3024
2637450826;5938356915;Apple;iPhone 8 Plus;1;95.0;4032;3024
2637450826;5810699793;Apple;iPhone 8 Plus;1;95.0;4032;3024
2637450826;4389516198;Apple;iPhone 8 Plus;1;95.0;4032;3024
2637450826;5933281920;Apple;iPhone 8 Plus;1;95.0;4032;3024
2637450826;6185866247;Apple;iPhone 8 Plus;1;95.0;4032;3024
2637450826;4025511414;Apple;iPhone 8 Plus;1;95.0;4032;3024
2637450826;7355166369;Apple;iPhone 8 Plus;1;95.0;4032;3024
2637450826;3825992391;Apple;iPhone 8 Plus;1;95.0;4032;3024
2637450826;4462495449;Apple;iPhone 8 Plus;1;95.0;4032;3024
2637450826;6191620726;Apple;iPhone 8 Plus;1;95.0;4032;3024
2637450826;3635779858;Apple;iPhone 8 Plus;1;95.0;4032;3024
2637450826;9427680508;Apple;iPhone 8 Plus;1;95.0;4032;3024
2637450826;7607094804;Apple;iPhone 8 Plus;1;95.0;4032;3024
2637450826;5749540529;Apple;iPhone 8 Plus;1;95.0;4032;3024
2637450826;5807448626;Apple;iPhone 8 Plus;1;95.0;4032;3024
2637450826;7531927075;Apple;iPhone 8 Plus;1;95.0;4032;3024
2637450826;5499528332;Apple;iPhone 8 Plus;1;95.0;4032;3024
2637450826;7512161148;Apple;iPhone 8 Plus;1;95.0;4032;3024
2637450826;0812876053;Apple;iPhone 8 Plus;1;95.0;4032;3024
2637450826;3020625419;Apple;iPhone 8 Plus;1;95.0;4032;3024
2637450826;1840194199;Apple;iPhone 8 Plus;1;95.0;4032;3024
2637450826;7173148392;Apple;iPhone 8 Plus;1;95.0;4032;3024
2637450826;8259933507;Apple;iPhone 8 Plus;1;95.0;4032;3024
2637450826;5011249274;Apple;iPhone 8 Plus;1;95.0;4032;3024
7669073668;3787582308;Apple;iPhone X;1;96.0;4032;3024
7669073668;2376490548;Apple;iPhone X;1;96.0;4032;3024
7669073668;8592581472;Apple;iPhone X;1;96.0;4032;3024
7669073668;6016203000;Apple;iPhone X;1;90.0;4032;3024
7669073668;3474325473;Apple;iPhone X;1;96.0;4032;3024
7669073668;7705494115;Apple;iPhone X;1;96.0;4032;3024
7669073668;5250397440;Apple;iPhone X;1;97.0;4032;3024
7669073668;5845793988;Apple;iPhone X;1;96.0;4032;3024
7669073668;6585290525;Apple;iPhone X;1;90.0;4032;3024
7669073668;5802391109;Apple;iPhone X;1;97.0;4032;3024
7669073668;8484224406;Apple;iPhone X;1;96.0;4032;3024
7669073668;6540858317;Apple;iPhone X;1;97.0;4032;3024
7669073668;8291417091;Apple;iPhone X;1;96.0;4032;3024
7669073668;2180927469;Apple;iPhone X;1;97.0;4032;3024
7669073668;4681601982;Apple;iPhone X;1;96.0;4032;3024
7669073668;3221249813;Apple;iPhone X;1;96.0;4032;3024
7669073668;1842205957;Apple;iPhone X;1;96.0;4032;3024
7669073668;9327691911;Apple;iPhone X;1;96.0;4032;3024
7669073668;9585425814;Apple;iPhone X;1;100.0;4032;3024
7669073668;7853814902;Apple;iPhone X;1;96.0;4032;3024
7669073668;3631135942;Apple;iPhone X;6;96.0;4032;3024
7669073668;4938815605;Apple;iPhone X;1;96.0;4032;3024
7669073668;7431447231;Apple;iPhone X;1;96.0;4032;3024
7669073668;9538405149;Apple;iPhone X;6;96.0;4032;3024
7669073668;3259441157;Apple;iPhone X;1;96.0;4032;3024
7669073668;5538052259;Apple;iPhone X;1;96.0;4032;3024
7669073668;9191380077;Apple;iPhone X;1;96.0;4032;3024
7669073668;0923156814;Apple;iPhone X;1;96.0;4032;3024
7669073668;8783865594;Apple;iPhone X;1;96.0;4032;3024
7669073668;2485412756;Apple;iPhone X;1;96.0;4032;3024
7669073668;8356795184;Apple;iPhone X;1;95.0;4032;3024
7669073668;9679626880;Apple;iPhone X;1;96.0;4032;3024
7669073668;5691784641;Apple;iPhone X;1;96.0;4032;3024
7669073668;2088996529;Apple;iPhone X;1;96.0;4032;3024
7669073668;8018851793;Apple;iPhone X;1;97.0;4032;3024
7669073668;1649791473;Apple;iPhone X;1;96.0;4032;3024
7669073668;5755574498;Apple;iPhone X;1;96.0;4032;3024
7669073668;1222583201;Apple;iPhone X;1;97.0;4032;3024
7669073668;1864872502;Apple;iPhone X;1;96.0;4032;3024
7669073668;3898841235;Apple;iPhone X;1;97.0;4032;3024
7669073668;6762612739;Apple;iPhone X;6;96.0;4032;3024
7669073668;6604796347;Apple;iPhone X;1;97.0;4032;3024
7669073668;7397771292;Apple;iPhone X;1;97.0;4032;3024
7669073668;4740921087;Apple;iPhone X;1;97.0;4032;3024
7669073668;6196456599;Apple;iPhone X;1;97.0;4032;3024
7669073668;1674200098;Apple;iPhone X;1;96.0;4032;3024
7669073668;1134963550;Apple;iPhone X;1;97.0;4032;3024
7669073668;6583946351;Apple;iPhone X;3;96.0;4032;3024
7669073668;8756763091;Apple;iPhone X;3;96.0;4032;3024
7669073668;5283316150;Apple;iPhone X;3;96.0;4032;3024
7669073668;3983687404;Apple;iPhone X;3;96.0;4032;3024
7669073668;3378196771;Apple;iPhone X;1;97.0;4032;3024
7669073668;1141860329;Apple;iPhone X;1;97.0;4032;3024
7669073668;8089559388;Apple;iPhone X;3;96.0;4032;3024
7669073668;5806532270;Apple;iPhone X;6;96.0;4032;3024
7669073668;4355156840;Apple;iPhone X;3;96.0;4032;3024
7669073668;3997365718;Apple;iPhone X;3;96.0;4032;3024
7669073668;6024770840;Apple;iPhone X;6;96.0;4032;3024
7669073668;8562839089;Apple;iPhone X;6;96.0;4032;3024
7669073668;1023484105;Apple;iPhone X;6;96.0;4032;3024
7669073668;1628589763;Apple;iPhone X;3;96.0;4032;3024
7669073668;7584956895;Apple;iPhone X;3;96.0;4032;3024
7669073668;2021583379;Apple;iPhone X;3;96.0;4032;3024
7669073668;0236473821;Apple;iPhone X;3;96.0;4032;3024
7669073668;1615723022;Apple;iPhone X;3;96.0;4032;3024
7669073668;3931353173;Apple;iPhone X;3;96.0;4032;3024
7669073668;4154681502;Apple;iPhone X;3;96.0;4032;3024
7669073668;4381244747;Apple;iPhone X;6;96.0;4032;3024
7669073668;3048256132;Apple;iPhone X;6;95.0;4032;3024
7669073668;5424622687;Apple;iPhone X;6;95.0;4032;3024
7669073668;9539656758;Apple;iPhone X;1;97.0;4032;3024
7669073668;7750885814;Apple;iPhone X;1;97.0;4032;3024
7669073668;2778427913;Apple;iPhone X;1;97.0;4032;3024
7669073668;8478696150;Apple;iPhone X;1;97.0;4032;3024
7669073668;9425463073;Apple;iPhone X;3;95.0;4032;3024
7669073668;0732873743;Apple;iPhone X;3;96.0;4032;3024
7669073668;2156406040;Apple;iPhone X;3;96.0;4032;3024
7669073668;3272068130;Apple;iPhone X;3;96.0;4032;3024
7669073668;4346426364;Apple;iPhone X;3;96.0;4032;3024
7669073668;1001820580;Apple;iPhone X;1;95.0;4032;3024
7780769194;5150728387;Apple;iPhone XS Max;3;97.0;4032;3024
7780769194;4517290713;Apple;iPhone XS Max;6;97.0;4032;3024
7780769194;8272616748;Apple;iPhone XS Max;3;97.0;4032;3024
7780769194;3819759232;Apple;iPhone XS Max;3;97.0;4032;3024
7780769194;7869600643;Apple;iPhone XS Max;6;97.0;4032;3024
7780769194;8043913411;Apple;iPhone XS Max;6;97.0;4032;3024
7780769194;8591885831;Apple;iPhone XS Max;6;95.0;4032;3024
7780769194;5947030334;Apple;iPhone XS Max;6;97.0;4032;3024
7780769194;7615902739;Apple;iPhone XS Max;3;97.0;4032;3024
7780769194;3130744730;Apple;iPhone XS Max;6;97.0;4032;3024
7780769194;7608941878;Apple;iPhone XS Max;3;97.0;4032;3024
7780769194;4162761759;Apple;iPhone XS Max;3;97.0;4032;3024
7780769194;2491303026;Apple;iPhone XS Max;6;95.0;4032;3024
7780769194;6766660552;Apple;iPhone XS Max;3;97.0;4032;3024
7780769194;9802405158;Apple;iPhone XS Max;3;95.0;4032;3024
7780769194;8224719037;Apple;iPhone XS Max;3;95.0;4032;3024
7780769194;8404198313;Apple;iPhone XS Max;3;97.0;4032;3024
7780769194;8657322263;Apple;iPhone XS Max;3;97.0;4032;3024
7780769194;3623760094;Apple;iPhone XS Max;1;97.0;4032;3024
9807802541;9622268376;Canon;Canon DIGITAL IXUS 40;1;98.0;2272;1704
9807802541;4344846572;Canon;Canon DIGITAL IXUS 40;6;96.0;2272;1704
9807802541;2987088260;Canon;Canon DIGITAL IXUS 40;6;96.0;2272;1704
9807802541;9255219780;Canon;Canon DIGITAL IXUS 40;6;96.0;2272;1704
9807802541;6397071336;Canon;Canon DIGITAL IXUS 40;6;96.0;2272;1704
9807802541;9046904438;Canon;Canon DIGITAL IXUS 40;6;96.0;2272;1704
9807802541;0532918521;Canon;Canon DIGITAL IXUS 40;6;98.0;2272;1704
9807802541;2605646856;Canon;Canon DIGITAL IXUS 40;8;96.0;2272;1704
9807802541;1911575745;Canon;Canon DIGITAL IXUS 40;1;96.0;2272;1704
9807802541;5906483165;Canon;Canon DIGITAL IXUS 40;1;96.0;2272;1704
9807802541;9940872465;Canon;Canon DIGITAL IXUS 40;6;96.0;2272;1704
9807802541;4308592150;Canon;Canon DIGITAL IXUS 40;6;96.0;2272;1704
9807802541;5941601476;Canon;Canon DIGITAL IXUS 40;6;96.0;2272;1704
9807802541;4186721865;Canon;Canon DIGITAL IXUS 40;1;96.0;2272;1704
9807802541;8848784429;Canon;Canon DIGITAL IXUS 40;6;96.0;2272;1704
9807802541;9272041229;Canon;Canon DIGITAL IXUS 40;6;96.0;2272;1704
9807802541;7657753966;Canon;Canon DIGITAL IXUS 40;6;98.0;2272;1704
9807802541;7223377787;Canon;Canon DIGITAL IXUS 40;6;98.0;2272;1704
9807802541;0165634524;Canon;Canon DIGITAL IXUS 40;1;98.0;2272;1704
9807802541;7619824993;Canon;Canon DIGITAL IXUS 40;1;98.0;2272;1704
9807802541;3143229141;Canon;Canon DIGITAL IXUS 40;6;98.0;2272;1704
9807802541;8569637944;Canon;Canon DIGITAL IXUS 40;1;98.0;2272;1704
9807802541;3357534237;Canon;Canon DIGITAL IXUS 40;1;98.0;2272;1704
9807802541;4969209382;Canon;Canon DIGITAL IXUS 40;6;98.0;2272;1704
9807802541;9556907108;Canon;Canon DIGITAL IXUS 40;1;98.0;2272;1704
9807802541;4040528036;Canon;Canon DIGITAL IXUS 40;1;98.0;2272;1704
9807802541;2739351286;Canon;Canon DIGITAL IXUS 40;6;98.0;2272;1704
9807802541;2784026682;Canon;Canon DIGITAL IXUS 40;6;98.0;2272;1704
3472971425;5116551992;Canon;Canon DIGITAL IXUS 50;6;98.0;2592;1944
3472971425;3540800478;Canon;Canon DIGITAL IXUS 50;1;98.0;2592;1944
3472971425;5140257761;Canon;Canon DIGITAL IXUS 50;1;98.0;2592;1944
3472971425;5621492369;Canon;Canon DIGITAL IXUS 50;1;98.0;2592;1944
3472971425;2375314449;Canon;Canon DIGITAL IXUS 50;1;98.0;2592;1944
3472971425;2407606017;Canon;Canon DIGITAL IXUS 50;1;98.0;2592;1944
3472971425;5887540901;Canon;Canon DIGITAL IXUS 50;1;98.0;2592;1944
3472971425;4336096995;Canon;Canon DIGITAL IXUS 50;1;98.0;2592;1944
3472971425;9799406834;Canon;Canon DIGITAL IXUS 50;1;98.0;2592;1944
3472971425;7194103486;Canon;Canon DIGITAL IXUS 50;1;98.0;2592;1944
3472971425;3864514845;Canon;Canon DIGITAL IXUS 50;1;98.0;2592;1944
3472971425;7196119931;Canon;Canon DIGITAL IXUS 50;1;98.0;2592;1944
3472971425;6503781334;Canon;Canon DIGITAL IXUS 50;1;98.0;2592;1944
3472971425;2453773025;Canon;Canon DIGITAL IXUS 50;1;98.0;2592;1944
3472971425;9559287130;Canon;Canon DIGITAL IXUS 50;1;98.0;2592;1944
3472971425;4008163601;Canon;Canon DIGITAL IXUS 50;1;98.0;2592;1944
3472971425;0271560006;Canon;Canon DIGITAL IXUS 50;1;98.0;2592;1944
3472971425;4012066011;Canon;Canon DIGITAL IXUS 50;1;98.0;2592;1944
3472971425;5364952125;Canon;Canon DIGITAL IXUS 50;1;98.0;2592;1944
3472971425;0998378484;Canon;Canon DIGITAL IXUS 50;1;98.0;2592;1944
3472971425;3476005010;Canon;Canon DIGITAL IXUS 50;1;98.0;2592;1944
3472971425;7828958562;Canon;Canon DIGITAL IXUS 50;6;98.0;2592;1944
3472971425;2728267993;Canon;Canon DIGITAL IXUS 50;6;98.0;2592;1944
3472971425;1048386287;Canon;Canon DIGITAL IXUS 50;6;98.0;2592;1944
3472971425;7953516081;Canon;Canon DIGITAL IXUS 50;1;98.0;2592;1944
3472971425;0511963937;Canon;Canon DIGITAL IXUS 50;1;98.0;2592;1944
3472971425;1636424957;Canon;Canon DIGITAL IXUS 50;1;98.0;2592;1944
3472971425;8770257249;Canon;Canon DIGITAL IXUS 50;1;96.0;2592;1944
3472971425;1335168214;Canon;Canon DIGITAL IXUS 50;1;98.0;2592;1944
3472971425;4155032707;Canon;Canon DIGITAL IXUS 50;6;98.0;2592;1944
6616772321;7839321964;Canon;Canon DIGITAL IXUS 55;1;98.0;2592;1944
6616772321;6068358403;Canon;Canon DIGITAL IXUS 55;6;98.0;2592;1944
6616772321;5367635115;Canon;Canon DIGITAL IXUS 55;8;98.0;2592;1944
6616772321;3693693214;Canon;Canon DIGITAL IXUS 55;8;98.0;2592;1944
6616772321;9634991849;Canon;Canon DIGITAL IXUS 55;6;98.0;2592;1944
6616772321;9307444861;Canon;Canon DIGITAL IXUS 55;6;98.0;2592;1944
6616772321;8581833836;Canon;Canon DIGITAL IXUS 55;1;98.0;2592;1944
6616772321;5222625984;Canon;Canon DIGITAL IXUS 55;6;98.0;2592;1944
6616772321;0549123741;Canon;Canon DIGITAL IXUS 55;6;98.0;2592;1944
6616772321;7409011566;Canon;Canon DIGITAL IXUS 55;6;98.0;2592;1944
6616772321;9847474013;Canon;Canon DIGITAL IXUS 55;6;98.0;2592;1944
6616772321;1808030542;Canon;Canon DIGITAL IXUS 55;6;98.0;2592;1944
6616772321;7043403457;Canon;Canon DIGITAL IXUS 55;6;98.0;2592;1944
6616772321;7868616154;Canon;Canon DIGITAL IXUS 55;6;98.0;2592;1944
6616772321;9507947206;Canon;Canon DIGITAL IXUS 55;6;98.0;2592;1944
6616772321;3291912790;Canon;Canon DIGITAL IXUS 55;1;98.0;2592;1944
6616772321;3409255603;Canon;Canon DIGITAL IXUS 55;6;98.0;2592;1944
6616772321;2020909034;Canon;Canon DIGITAL IXUS 55;6;98.0;2592;1944
6616772321;5665281203;Canon;Canon DIGITAL IXUS 55;6;98.0;2592;1944
6616772321;5525221307;Canon;Canon DIGITAL IXUS 55;6;98.0;2592;1944
6616772321;9709913476;Canon;Canon DIGITAL IXUS 55;6;98.0;2592;1944
6616772321;6722788782;Canon;Canon DIGITAL IXUS 55;6;98.0;2592;1944
6616772321;8763055543;Canon;Canon DIGITAL IXUS 55;1;98.0;2592;1944
6616772321;3565626031;Canon;Canon DIGITAL IXUS 55;1;98.0;2592;1944
6616772321;3335980750;Canon;Canon DIGITAL IXUS 55;6;98.0;2592;1944
6616772321;8513916244;Canon;Canon DIGITAL IXUS 55;6;98.0;2592;1944
6616772321;1942850038;Canon;Canon DIGITAL IXUS 55;6;98.0;2592;1944
6616772321;1721972078;Canon;Canon DIGITAL IXUS 55;1;98.0;2592;1944
6616772321;0596403159;Canon;Canon DIGITAL IXUS 55;6;98.0;2592;1944
6616772321;3034795475;Canon;Canon DIGITAL IXUS 55;6;98.0;2592;1944
6851479137;4802867316;Canon;Canon DIGITAL IXUS 700;1;96.0;3072;2304
6851479137;9896108329;Canon;Canon DIGITAL IXUS 700;6;96.0;3072;2304
6851479137;0597263877;Canon;Canon DIGITAL IXUS 700;1;96.0;3072;2304
6851479137;8312251469;Canon;Canon DIGITAL IXUS 700;6;96.0;3072;2304
6851479137;7955023269;Canon;Canon DIGITAL IXUS 700;6;96.0;3072;2304
6851479137;4827411603;Canon;Canon DIGITAL IXUS 700;1;98.0;3072;2304
6851479137;1886195504;Canon;Canon DIGITAL IXUS 700;1;96.0;3072;2304
6851479137;0723314630;Canon;Canon DIGITAL IXUS 700;1;96.0;3072;2304
6851479137;5555438251;Canon;Canon DIGITAL IXUS 700;1;96.0;3072;2304
6851479137;4810517414;Canon;Canon DIGITAL IXUS 700;6;96.0;3072;2304
6851479137;3111892241;Canon;Canon DIGITAL IXUS 700;6;98.0;3072;2304
6851479137;6410308084;Canon;Canon DIGITAL IXUS 700;6;98.0;3072;2304
6851479137;9499538347;Canon;Canon DIGITAL IXUS 700;1;98.0;3072;2304
6851479137;1139009916;Canon;Canon DIGITAL IXUS 700;6;98.0;3072;2304
6851479137;2461340006;Canon;Canon DIGITAL IXUS 700;1;98.0;3072;2304
6851479137;4827873520;Canon;Canon DIGITAL IXUS 700;6;98.0;3072;2304
6851479137;0884312076;Canon;Canon DIGITAL IXUS 700;6;98.0;3072;2304
6851479137;0570253378;Canon;Canon DIGITAL IXUS 700;6;98.0;3072;2304
6851479137;4376904222;Canon;Canon DIGITAL IXUS 700;1;98.0;3072;2304
6851479137;8938438970;Canon;Canon DIGITAL IXUS 700;6;98.0;3072;2304
6851479137;0004448679;Canon;Canon DIGITAL IXUS 700;6;98.0;3072;2304
6851479137;1451002268;Canon;Canon DIGITAL IXUS 700;6;98.0;3072;2304
6851479137;4127697877;Canon;Canon DIGITAL IXUS 700;1;98.0;3072;2304
6851479137;2609156681;Canon;Canon DIGITAL IXUS 700;6;98.0;3072;2304
6851479137;2448199191;Canon;Canon DIGITAL IXUS 700;6;98.0;3072;2304
6851479137;3196153640;Canon;Canon DIGITAL IXUS 700;6;98.0;3072;2304
6851479137;5577866462;Canon;Canon DIGITAL IXUS 700;6;98.0;3072;2304
6851479137;6268856198;Canon;Canon DIGITAL IXUS 700;1;98.0;3072;2304
6851479137;9802135760;Canon;Canon DIGITAL IXUS 700;1;98.0;3072;2304
6851479137;9557594808;Canon;Canon DIGITAL IXUS 700;6;98.0;3072;2304
7475900706;6866372700;Canon;Canon DIGITAL IXUS 750;8;98.0;3072;2304
7475900706;1031575518;Canon;Canon DIGITAL IXUS 750;6;98.0;3072;2304
7475900706;8369126368;Canon;Canon DIGITAL IXUS 750;1;98.0;3072;2304
7475900706;2762726942;Canon;Canon DIGITAL IXUS 750;1;98.0;3072;2304
7475900706;0182950004;Canon;Canon DIGITAL IXUS 750;1;98.0;3072;2304
7475900706;5793240496;Canon;Canon DIGITAL IXUS 750;6;98.0;3072;2304
7475900706;2689922176;Canon;Canon DIGITAL IXUS 750;6;98.0;3072;2304
7475900706;5604218599;Canon;Canon DIGITAL IXUS 750;6;98.0;3072;2304
7475900706;2962510273;Canon;Canon DIGITAL IXUS 750;6;98.0;3072;2304
7475900706;3617460960;Canon;Canon DIGITAL IXUS 750;1;98.0;3072;2304
7475900706;0676282259;Canon;Canon DIGITAL IXUS 750;1;98.0;3072;2304
7475900706;0167841069;Canon;Canon DIGITAL IXUS 750;1;98.0;3072;2304
7475900706;4836701556;Canon;Canon DIGITAL IXUS 750;6;98.0;3072;2304
7475900706;7156147698;Canon;Canon DIGITAL IXUS 750;6;98.0;3072;2304
7475900706;3549078757;Canon;Canon DIGITAL IXUS 750;1;98.0;3072;2304
7475900706;2567955648;Canon;Canon DIGITAL IXUS 750;6;98.0;3072;2304
7475900706;6001077650;Canon;Canon DIGITAL IXUS 750;6;98.0;3072;2304
7475900706;1227578545;Canon;Canon DIGITAL IXUS 750;6;98.0;3072;2304
7475900706;8913825355;Canon;Canon DIGITAL IXUS 750;6;98.0;3072;2304
7475900706;8119447302;Canon;Canon DIGITAL IXUS 750;6;98.0;3072;2304
7475900706;1509279182;Canon;Canon DIGITAL IXUS 750;6;98.0;3072;2304
7475900706;5132198930;Canon;Canon DIGITAL IXUS 750;1;98.0;3072;2304
7475900706;4557735739;Canon;Canon DIGITAL IXUS 750;6;98.0;3072;2304
7475900706;9088956420;Canon;Canon DIGITAL IXUS 750;6;98.0;3072;2304
7475900706;4154630980;Canon;Canon DIGITAL IXUS 750;6;98.0;3072;2304
7475900706;6142285555;Canon;Canon DIGITAL IXUS 750;6;98.0;3072;2304
7475900706;4651930855;Canon;Canon DIGITAL IXUS 750;6;98.0;3072;2304
7475900706;8442650570;Canon;Canon DIGITAL IXUS 750;6;98.0;3072;2304
7475900706;8609257974;Canon;Canon DIGITAL IXUS 750;1;98.0;3072;2304
7475900706;3515693551;Canon;Canon DIGITAL IXUS 750;6;98.0;3072;2304
7108473655;9705233642;Canon;Canon DIGITAL IXUS 80 IS;1;96.0;3264;2448
7108473655;1595614128;Canon;Canon DIGITAL IXUS 80 IS;1;96.0;3264;2448
7108473655;4712715610;Canon;Canon DIGITAL IXUS 80 IS;1;96.0;3264;2448
7108473655;8235295754;Canon;Canon DIGITAL IXUS 80 IS;1;96.0;3264;2448
7108473655;5792969057;Canon;Canon DIGITAL IXUS 80 IS;1;96.0;3264;2448
7108473655;5817952583;Canon;Canon DIGITAL IXUS 80 IS;1;96.0;3264;2448
7108473655;9528157524;Canon;Canon DIGITAL IXUS 80 IS;1;96.0;3264;2448
7108473655;3412819180;Canon;Canon DIGITAL IXUS 80 IS;8;96.0;3264;2448
7108473655;7734213548;Canon;Canon DIGITAL IXUS 80 IS;8;96.0;3264;2448
7108473655;6661597320;Canon;Canon DIGITAL IXUS 80 IS;1;96.0;3264;2448
7108473655;7360482912;Canon;Canon DIGITAL IXUS 80 IS;1;96.0;3264;2448
7108473655;4034732936;Canon;Canon DIGITAL IXUS 80 IS;1;96.0;3264;2448
7108473655;6719448227;Canon;Canon DIGITAL IXUS 80 IS;8;96.0;3264;2448
7108473655;5365897123;Canon;Canon DIGITAL IXUS 80 IS;1;96.0;3264;2448
7108473655;4966036204;Canon;Canon DIGITAL IXUS 80 IS;8;96.0;3264;2448
7108473655;7708615906;Canon;Canon DIGITAL IXUS 80 IS;1;96.0;3264;2448
7108473655;3417021882;Canon;Canon DIGITAL IXUS 80 IS;1;98.0;3264;2448
7108473655;0708174769;Canon;Canon DIGITAL IXUS 80 IS;8;98.0;3264;2448
7108473655;7893530541;Canon;Canon DIGITAL IXUS 80 IS;8;98.0;3264;2448
7108473655;1759890504;Canon;Canon DIGITAL IXUS 80 IS;1;98.0;3264;2448
7108473655;6934806585;Canon;Canon DIGITAL IXUS 80 IS;1;98.0;3264;2448
7108473655;3559115786;Canon;Canon DIGITAL IXUS 80 IS;1;98.0;3264;2448
7108473655;2474594706;Canon;Canon DIGITAL IXUS 80 IS;1;98.0;3264;2448
7108473655;5871199910;Canon;Canon DIGITAL IXUS 80 IS;6;98.0;3264;2448
7108473655;7872768210;Canon;Canon DIGITAL IXUS 80 IS;1;98.0;3264;2448
7108473655;9569078354;Canon;Canon DIGITAL IXUS 80 IS;1;98.0;3264;2448
7108473655;0770254368;Canon;Canon DIGITAL IXUS 80 IS;8;98.0;3264;2448
7108473655;8577730654;Canon;Canon DIGITAL IXUS 80 IS;6;98.0;3264;2448
7108473655;3466297097;Canon;Canon DIGITAL IXUS 80 IS;1;98.0;3264;2448
7108473655;5881592739;Canon;Canon DIGITAL IXUS 80 IS;8;98.0;3264;2448
7108473655;6968999630;Canon;Canon DIGITAL IXUS 80 IS;8;98.0;3264;2448
7108473655;7960380671;Canon;Canon DIGITAL IXUS 80 IS;1;98.0;3264;2448
7108473655;0643653462;Canon;Canon DIGITAL IXUS 80 IS;1;98.0;3264;2448
7108473655;9282343844;Canon;Canon DIGITAL IXUS 80 IS;1;98.0;3264;2448
7108473655;5695228245;Canon;Canon DIGITAL IXUS 80 IS;1;98.0;3264;2448
7108473655;2501820498;Canon;Canon DIGITAL IXUS 80 IS;1;98.0;3264;2448
7108473655;5138271185;Canon;Canon DIGITAL IXUS 80 IS;8;98.0;3264;2448
7108473655;2325423663;Canon;Canon DIGITAL IXUS 80 IS;1;98.0;3264;2448
7108473655;1854476935;Canon;Canon DIGITAL IXUS 80 IS;1;98.0;3264;2448
8928252022;0144230494;Canon;Canon DIGITAL IXUS 800 IS;6;98.0;2816;2112
8928252022;0303789772;Canon;Canon DIGITAL IXUS 800 IS;6;98.0;2816;2112
8928252022;5818052942;Canon;Canon DIGITAL IXUS 800 IS;6;98.0;2816;2112
8928252022;3276882049;Canon;Canon DIGITAL IXUS 800 IS;6;98.0;2816;2112
8928252022;5034609733;Canon;Canon DIGITAL IXUS 800 IS;6;98.0;2816;2112
8928252022;3244439766;Canon;Canon DIGITAL IXUS 800 IS;6;98.0;2816;2112
8928252022;8570332216;Canon;Canon DIGITAL IXUS 800 IS;1;98.0;2816;2112
8928252022;0216077451;Canon;Canon DIGITAL IXUS 800 IS;6;98.0;2816;2112
8928252022;0750556683;Canon;Canon DIGITAL IXUS 800 IS;6;98.0;2816;2112
8928252022;6860324060;Canon;Canon DIGITAL IXUS 800 IS;6;98.0;2816;2112
8928252022;1062426548;Canon;Canon DIGITAL IXUS 800 IS;6;98.0;2816;2112
8928252022;1608452253;Canon;Canon DIGITAL IXUS 800 IS;6;98.0;2816;2112
8928252022;6858648350;Canon;Canon DIGITAL IXUS 800 IS;6;98.0;2816;2112
8928252022;0300915798;Canon;Canon DIGITAL IXUS 800 IS;6;98.0;2816;2112
8928252022;7864178129;Canon;Canon DIGITAL IXUS 800 IS;1;98.0;2816;2112
8928252022;8037152711;Canon;Canon DIGITAL IXUS 800 IS;6;98.0;2816;2112
8928252022;3459250064;Canon;Canon DIGITAL IXUS 800 IS;6;98.0;2816;2112
8928252022;4090568978;Canon;Canon DIGITAL IXUS 800 IS;6;98.0;2816;2112
8928252022;5216697843;Canon;Canon DIGITAL IXUS 800 IS;6;98.0;2816;2112
8928252022;6037939369;Canon;Canon DIGITAL IXUS 800 IS;6;98.0;2816;2112
8928252022;9054177008;Canon;Canon DIGITAL IXUS 800 IS;6;98.0;2816;2112
8928252022;9314161645;Canon;Canon DIGITAL IXUS 800 IS;6;98.0;2816;2112
8928252022;6938010675;Canon;Canon DIGITAL IXUS 800 IS;6;98.0;2816;2112
8928252022;6064460013;Canon;Canon DIGITAL IXUS 800 IS;6;98.0;2816;2112
8928252022;5599275830;Canon;Canon DIGITAL IXUS 800 IS;6;98.0;2816;2112
8928252022;0043528055;Canon;Canon DIGITAL IXUS 800 IS;6;98.0;2816;2112
8928252022;1261654600;Canon;Canon DIGITAL IXUS 800 IS;6;98.0;2816;2112
8928252022;9438497224;Canon;Canon DIGITAL IXUS 800 IS;6;98.0;2816;2112
8928252022;8104759623;Canon;Canon DIGITAL IXUS 800 IS;1;98.0;2816;2112
8928252022;8145613082;Canon;Canon DIGITAL IXUS 800 IS;1;98.0;2816;2112
6018312265;6616995358;Canon;Canon DIGITAL IXUS 850 IS;1;98.0;3072;2304
6018312265;3117597728;Canon;Canon DIGITAL IXUS 850 IS;1;98.0;3072;2304
6018312265;6877725407;Canon;Canon DIGITAL IXUS 850 IS;1;98.0;3072;2304
6018312265;2716483154;Canon;Canon DIGITAL IXUS 850 IS;1;98.0;3072;2304
6018312265;4375092276;Canon;Canon DIGITAL IXUS 850 IS;1;98.0;3072;2304
6018312265;8385617491;Canon;Canon DIGITAL IXUS 850 IS;1;98.0;3072;2304
6018312265;6049973711;Canon;Canon DIGITAL IXUS 850 IS;1;98.0;3072;2304
6018312265;1725549542;Canon;Canon DIGITAL IXUS 850 IS;6;98.0;3072;2304
6018312265;7028370324;Canon;Canon DIGITAL IXUS 850 IS;6;98.0;3072;2304
6018312265;8828287287;Canon;Canon DIGITAL IXUS 850 IS;1;98.0;3072;2304
6018312265;4520892743;Canon;Canon DIGITAL IXUS 850 IS;1;98.0;3072;2304
6018312265;9745383762;Canon;Canon DIGITAL IXUS 850 IS;6;98.0;3072;2304
6018312265;5085701291;Canon;Canon DIGITAL IXUS 850 IS;1;98.0;3072;2304
6018312265;6511954728;Canon;Canon DIGITAL IXUS 850 IS;1;98.0;3072;2304
6018312265;7184935892;Canon;Canon DIGITAL IXUS 850 IS;6;98.0;3072;2304
6018312265;5300975587;Canon;Canon DIGITAL IXUS 850 IS;1;98.0;3072;2304
6018312265;0589730458;Canon;Canon DIGITAL IXUS 850 IS;6;98.0;3072;2304
6018312265;7902489162;Canon;Canon DIGITAL IXUS 850 IS;8;98.0;3072;2304
6018312265;7109678269;Canon;Canon DIGITAL IXUS 850 IS;1;98.0;3072;2304
6018312265;3973495446;Canon;Canon DIGITAL IXUS 850 IS;6;98.0;3072;2304
6018312265;0647849591;Canon;Canon DIGITAL IXUS 850 IS;6;98.0;3072;2304
6018312265;1389124253;Canon;Canon DIGITAL IXUS 850 IS;6;98.0;3072;2304
6018312265;9052186076;Canon;Canon DIGITAL IXUS 850 IS;6;98.0;3072;2304
6018312265;0795019564;Canon;Canon DIGITAL IXUS 850 IS;6;98.0;3072;2304
6018312265;6349178131;Canon;Canon DIGITAL IXUS 850 IS;6;98.0;3072;2304
6018312265;9042280105;Canon;Canon DIGITAL IXUS 850 IS;6;98.0;3072;2304
6018312265;3724639256;Canon;Canon DIGITAL IXUS 850 IS;6;98.0;3072;2304
6018312265;7618362902;Canon;Canon DIGITAL IXUS 850 IS;6;98.0;3072;2304
6018312265;8863498712;Canon;Canon DIGITAL IXUS 850 IS;1;98.0;3072;2304
6018312265;1023894520;Canon;Canon DIGITAL IXUS 850 IS;6;98.0;3072;2304
2704471712;1819569694;Canon;Canon DIGITAL IXUS 860 IS;1;98.0;3264;2448
2704471712;7487306372;Canon;Canon DIGITAL IXUS 860 IS;6;98.0;3264;2448
2704471712;8152380578;Canon;Canon DIGITAL IXUS 860 IS;6;98.0;3264;2448
2704471712;2308566035;Canon;Canon DIGITAL IXUS 860 IS;1;98.0;3264;2448
2704471712;9168098153;Canon;Canon DIGITAL IXUS 860 IS;1;98.0;3264;2448
2704471712;2021371045;Canon;Canon DIGITAL IXUS 860 IS;6;98.0;3264;2448
2704471712;7549586013;Canon;Canon DIGITAL IXUS 860 IS;6;98.0;3264;2448
2704471712;7860888600;Canon;Canon DIGITAL IXUS 860 IS;6;98.0;3264;2448
2704471712;1090933190;Canon;Canon DIGITAL IXUS 860 IS;1;98.0;3264;2448
2704471712;0900583774;Canon;Canon DIGITAL IXUS 860 IS;1;98.0;3264;2448
2704471712;5770861229;Canon;Canon DIGITAL IXUS 860 IS;6;98.0;3264;2448
2704471712;0544661551;Canon;Canon DIGITAL IXUS 860 IS;1;98.0;3264;2448
2704471712;6047524269;Canon;Canon DIGITAL IXUS 860 IS;6;98.0;3264;2448
2704471712;4571868561;Canon;Canon DIGITAL IXUS 860 IS;1;98.0;3264;2448
2704471712;2996410311;Canon;Canon DIGITAL IXUS 860 IS;6;98.0;3264;2448
2704471712;4854063754;Canon;Canon DIGITAL IXUS 860 IS;6;98.0;3264;2448
2704471712;6435183693;Canon;Canon DIGITAL IXUS 860 IS;6;98.0;3264;2448
2704471712;8287236700;Canon;Canon DIGITAL IXUS 860 IS;1;98.0;3264;2448
2704471712;3681819396;Canon;Canon DIGITAL IXUS 860 IS;6;98.0;3264;2448
2704471712;2659730460;Canon;Canon DIGITAL IXUS 860 IS;1;98.0;3264;2448
2704471712;4274837739;Canon;Canon DIGITAL IXUS 860 IS;1;98.0;3264;2448
2704471712;1479889057;Canon;Canon DIGITAL IXUS 860 IS;1;98.0;3264;2448
2704471712;5206685657;Canon;Canon DIGITAL IXUS 860 IS;6;98.0;3264;2448
2704471712;4726141500;Canon;Canon DIGITAL IXUS 860 IS;6;98.0;3264;2448
2704471712;2347726434;Canon;Canon DIGITAL IXUS 860 IS;1;98.0;3264;2448
2704471712;6065997139;Canon;Canon DIGITAL IXUS 860 IS;1;98.0;3264;2448
2704471712;7715575702;Canon;Canon DIGITAL IXUS 860 IS;6;98.0;3264;2448
2704471712;4503895038;Canon;Canon DIGITAL IXUS 860 IS;6;98.0;3264;2448
2704471712;4901068314;Canon;Canon DIGITAL IXUS 860 IS;1;98.0;3264;2448
2704471712;2442834873;Canon;Canon DIGITAL IXUS 860 IS;1;98.0;3264;2448
1480983897;1832550202;Canon;Canon DIGITAL IXUS 900Ti;1;98.0;3648;2736
1480983897;0471353771;Canon;Canon DIGITAL IXUS 900Ti;6;98.0;3648;2736
1480983897;8176725329;Canon;Canon DIGITAL IXUS 900Ti;1;98.0;3648;2736
1480983897;1258949126;Canon;Canon DIGITAL IXUS 900Ti;1;98.0;3648;2736
1480983897;9947823303;Canon;Canon DIGITAL IXUS 900Ti;6;98.0;3648;2736
1480983897;2316083862;Canon;Canon DIGITAL IXUS 900Ti;6;98.0;3648;2736
1480983897;0619307317;Canon;Canon DIGITAL IXUS 900Ti;6;98.0;3648;2736
1480983897;8477340830;Canon;Canon DIGITAL IXUS 900Ti;6;98.0;3648;2736
1480983897;0978824794;Canon;Canon DIGITAL IXUS 900Ti;6;98.0;3648;2736
1480983897;9890978571;Canon;Canon DIGITAL IXUS 900Ti;6;98.0;3648;2736
1480983897;0399784907;Canon;Canon DIGITAL IXUS 900Ti;6;98.0;3648;2736
1480983897;3898053609;Canon;Canon DIGITAL IXUS 900Ti;6;98.0;3648;2736
1480983897;3850351337;Canon;Canon DIGITAL IXUS 900Ti;6;98.0;3648;2736
1480983897;5790884036;Canon;Canon DIGITAL IXUS 900Ti;1;98.0;3648;2736
1480983897;4922089667;Canon;Canon DIGITAL IXUS 900Ti;6;98.0;3648;2736
1480983897;0007695292;Canon;Canon DIGITAL IXUS 900Ti;1;98.0;3648;2736
1480983897;8835528222;Canon;Canon DIGITAL IXUS 900Ti;6;98.0;3648;2736
1480983897;2764863749;Canon;Canon DIGITAL IXUS 900Ti;6;98.0;3648;2736
1480983897;1306616693;Canon;Canon DIGITAL IXUS 900Ti;6;98.0;3648;2736
1480983897;9082241632;Canon;Canon DIGITAL IXUS 900Ti;6;98.0;3648;2736
1480983897;9781200845;Canon;Canon DIGITAL IXUS 900Ti;6;98.0;3648;2736
1480983897;0026536867;Canon;Canon DIGITAL IXUS 900Ti;6;98.0;3648;2736
1480983897;4327105080;Canon;Canon DIGITAL IXUS 900Ti;6;98.0;3648;2736
1480983897;3116193822;Canon;Canon DIGITAL IXUS 900Ti;1;98.0;3648;2736
1480983897;7506335831;Canon;Canon DIGITAL IXUS 900Ti;1;96.0;3648;2736
1480983897;6786262450;Canon;Canon DIGITAL IXUS 900Ti;6;96.0;3648;2736
1480983897;3541466716;Canon;Canon DIGITAL IXUS 900Ti;1;96.0;3648;2736
1480983897;1123075181;Canon;Canon DIGITAL IXUS 900Ti;1;96.0;3648;2736
1480983897;9429691201;Canon;Canon DIGITAL IXUS 900Ti;6;98.0;3648;2736
1480983897;1480459147;Canon;Canon DIGITAL IXUS 900Ti;6;98.0;3648;2736
3266575943;0355560209;Canon;Canon DIGITAL IXUS 950 IS;1;98.0;3264;2448
3266575943;9101911710;Canon;Canon DIGITAL IXUS 950 IS;1;98.0;3264;2448
3266575943;7394538800;Canon;Canon DIGITAL IXUS 950 IS;1;98.0;3264;2448
3266575943;5309984572;Canon;Canon DIGITAL IXUS 950 IS;1;98.0;3264;2448
3266575943;2261708385;Canon;Canon DIGITAL IXUS 950 IS;1;98.0;3264;2448
3266575943;8318091717;Canon;Canon DIGITAL IXUS 950 IS;1;98.0;3264;2448
3266575943;0161568102;Canon;Canon DIGITAL IXUS 950 IS;1;98.0;3264;2448
3266575943;9020795551;Canon;Canon DIGITAL IXUS 950 IS;8;98.0;3264;2448
3266575943;0969454712;Canon;Canon DIGITAL IXUS 950 IS;8;98.0;3264;2448
3266575943;1369404630;Canon;Canon DIGITAL IXUS 950 IS;8;98.0;3264;2448
3266575943;4832093456;Canon;Canon DIGITAL IXUS 950 IS;1;98.0;3264;2448
3266575943;0830981240;Canon;Canon DIGITAL IXUS 950 IS;1;98.0;3264;2448
3266575943;6917216031;Canon;Canon DIGITAL IXUS 950 IS;1;98.0;3264;2448
3266575943;7094031340;Canon;Canon DIGITAL IXUS 950 IS;1;98.0;3264;2448
3266575943;1193496604;Canon;Canon DIGITAL IXUS 950 IS;6;98.0;3264;2448
3266575943;0353468850;Canon;Canon DIGITAL IXUS 950 IS;6;98.0;3264;2448
3266575943;7529208021;Canon;Canon DIGITAL IXUS 950 IS;1;98.0;3264;2448
3266575943;1719581571;Canon;Canon DIGITAL IXUS 950 IS;1;98.0;3264;2448
3266575943;8763990471;Canon;Canon DIGITAL IXUS 950 IS;1;98.0;3264;2448
3266575943;8331671182;Canon;Canon DIGITAL IXUS 950 IS;1;98.0;3264;2448
3266575943;8775196681;Canon;Canon DIGITAL IXUS 950 IS;1;98.0;3264;2448
3266575943;7965409215;Canon;Canon DIGITAL IXUS 950 IS;8;98.0;3264;2448
3266575943;1437198885;Canon;Canon DIGITAL IXUS 950 IS;1;98.0;3264;2448
3266575943;9452245215;Canon;Canon DIGITAL IXUS 950 IS;1;98.0;3264;2448
3266575943;2135526306;Canon;Canon DIGITAL IXUS 950 IS;8;98.0;3264;2448
3266575943;3563750184;Canon;Canon DIGITAL IXUS 950 IS;8;98.0;3264;2448
3266575943;7214536613;Canon;Canon DIGITAL IXUS 950 IS;8;98.0;3264;2448
3266575943;2546376200;Canon;Canon DIGITAL IXUS 950 IS;8;98.0;3264;2448
3266575943;8495177241;Canon;Canon DIGITAL IXUS 950 IS;8;98.0;3264;2448
3266575943;7451643059;Canon;Canon DIGITAL IXUS 950 IS;1;98.0;3264;2448
3266575943;0389667467;Canon;Canon DIGITAL IXUS 950 IS;1;98.0;3264;2448
3266575943;3664708779;Canon;Canon DIGITAL IXUS 950 IS;1;98.0;3264;2448
3266575943;6948661176;Canon;Canon DIGITAL IXUS 950 IS;1;98.0;3264;2448
3266575943;8066056643;Canon;Canon DIGITAL IXUS 950 IS;1;98.0;3264;2448
3266575943;9690097222;Canon;Canon DIGITAL IXUS 950 IS;8;98.0;3264;2448
3266575943;9564863078;Canon;Canon DIGITAL IXUS 950 IS;1;98.0;3264;2448
3266575943;7441668595;Canon;Canon DIGITAL IXUS 950 IS;1;98.0;3264;2448
2731853902;1645033587;Canon;Canon DIGITAL IXUS 990 IS;1;96.0;4000;3000
2731853902;7691956606;Canon;Canon DIGITAL IXUS 990 IS;1;96.0;4000;3000
2731853902;1703820715;Canon;Canon DIGITAL IXUS 990 IS;1;96.0;4000;3000
2731853902;6751292860;Canon;Canon DIGITAL IXUS 990 IS;1;96.0;4000;3000
2731853902;5844331637;Canon;Canon DIGITAL IXUS 990 IS;1;96.0;4000;3000
2731853902;9111248152;Canon;Canon DIGITAL IXUS 990 IS;1;96.0;4000;3000
2731853902;7658137531;Canon;Canon DIGITAL IXUS 990 IS;6;96.0;4000;3000
2731853902;5910770270;Canon;Canon DIGITAL IXUS 990 IS;1;96.0;4000;3000
2731853902;6284535515;Canon;Canon DIGITAL IXUS 990 IS;1;96.0;4000;3000
2731853902;2472946423;Canon;Canon DIGITAL IXUS 990 IS;1;96.0;4000;3000
2731853902;2512025973;Canon;Canon DIGITAL IXUS 990 IS;1;96.0;4000;3000
2731853902;7027864381;Canon;Canon DIGITAL IXUS 990 IS;1;96.0;4000;3000
2731853902;9678461980;Canon;Canon DIGITAL IXUS 990 IS;1;96.0;4000;3000
2731853902;8116719538;Canon;Canon DIGITAL IXUS 990 IS;8;96.0;4000;3000
2731853902;5548315808;Canon;Canon DIGITAL IXUS 990 IS;8;96.0;4000;3000
2731853902;7559190305;Canon;Canon DIGITAL IXUS 990 IS;1;96.0;4000;3000
2731853902;6155497504;Canon;Canon DIGITAL IXUS 990 IS;8;96.0;4000;3000
2731853902;1174957895;Canon;Canon DIGITAL IXUS 990 IS;1;96.0;4000;3000
2731853902;2425876199;Canon;Canon DIGITAL IXUS 990 IS;1;96.0;4000;3000
2731853902;1864453637;Canon;Canon DIGITAL IXUS 990 IS;8;96.0;4000;3000
2731853902;9690493812;Canon;Canon DIGITAL IXUS 990 IS;1;96.0;4000;3000
2731853902;4981010378;Canon;Canon DIGITAL IXUS 990 IS;1;96.0;4000;3000
2731853902;1450496538;Canon;Canon DIGITAL IXUS 990 IS;1;96.0;4000;3000
2731853902;9013615965;Canon;Canon DIGITAL IXUS 990 IS;1;96.0;4000;3000
2731853902;4409051078;Canon;Canon DIGITAL IXUS 990 IS;1;96.0;4000;3000
6810310134;6263366045;Canon;Canon EOS 1000D;1;98.0;3888;2592
6810310134;0023650682;Canon;Canon EOS 1000D;6;98.0;3888;2592
6810310134;5067618059;Canon;Canon EOS 1000D;6;98.0;3888;2592
6810310134;6912013610;Canon;Canon EOS 1000D;6;98.0;3888;2592
6810310134;6909247102;Canon;Canon EOS 1000D;6;98.0;3888;2592
6810310134;8195384285;Canon;Canon EOS 1000D;6;98.0;3888;2592
6810310134;3168761659;Canon;Canon EOS 1000D;6;98.0;3888;2592
6810310134;9535163674;Canon;Canon EOS 1000D;6;98.0;3888;2592
6810310134;7868318475;Canon;Canon EOS 1000D;6;98.0;3888;2592
6810310134;3491355698;Canon;Canon EOS 1000D;1;98.0;3888;2592
6810310134;6159587606;Canon;Canon EOS 1000D;6;98.0;3888;2592
6810310134;6846864164;Canon;Canon EOS 1000D;1;98.0;3888;2592
6810310134;3366264629;Canon;Canon EOS 1000D;8;98.0;3888;2592
6810310134;3606471648;Canon;Canon EOS 1000D;1;98.0;3888;2592
6810310134;1787792915;Canon;Canon EOS 1000D;1;98.0;3888;2592
6810310134;4824891628;Canon;Canon EOS 1000D;8;98.0;3888;2592
6810310134;5248068291;Canon;Canon EOS 1000D;8;98.0;3888;2592
6810310134;8663878919;Canon;Canon EOS 1000D;8;98.0;3888;2592
6810310134;0961754803;Canon;Canon EOS 1000D;1;98.0;3888;2592
6810310134;8919119066;Canon;Canon EOS 1000D;1;98.0;3888;2592
6810310134;3088975081;Canon;Canon EOS 1000D;1;98.0;3888;2592
6810310134;6314281648;Canon;Canon EOS 1000D;1;98.0;3888;2592
6810310134;5860255604;Canon;Canon EOS 1000D;1;98.0;3888;2592
6810310134;0028764700;Canon;Canon EOS 1000D;8;98.0;3888;2592
6810310134;3209565889;Canon;Canon EOS 1000D;8;98.0;3888;2592
6810310134;0759547882;Canon;Canon EOS 1000D;1;98.0;3888;2592
6810310134;1591365582;Canon;Canon EOS 1000D;6;98.0;3888;2592
6810310134;8706449012;Canon;Canon EOS 1000D;6;98.0;3888;2592
6810310134;9195094663;Canon;Canon EOS 1000D;6;98.0;3888;2592
6810310134;7446679528;Canon;Canon EOS 1000D;1;98.0;3888;2592
6810310134;0348076390;Canon;Canon EOS 1000D;6;98.0;3888;2592
6810310134;0838482005;Canon;Canon EOS 1000D;6;98.0;3888;2592
6810310134;0662855867;Canon;Canon EOS 1000D;6;98.0;3888;2592
6810310134;5623405585;Canon;Canon EOS 1000D;6;98.0;3888;2592
6810310134;3342522666;Canon;Canon EOS 1000D;1;98.0;3888;2592
6810310134;9900385791;Canon;Canon EOS 1000D;1;98.0;3888;2592
6810310134;8992100457;Canon;Canon EOS 1000D;6;98.0;3888;2592
6810310134;6465457652;Canon;Canon EOS 1000D;6;98.0;3888;2592
5774422920;4920723036;Canon;Canon EOS 10D;1;98.0;3072;2048
5774422920;3667733610;Canon;Canon EOS 10D;1;98.0;3072;2048
5774422920;9782504557;Canon;Canon EOS 10D;1;98.0;3072;2048
5774422920;3464859765;Canon;Canon EOS 10D;1;98.0;3072;2048
5774422920;8001592672;Canon;Canon EOS 10D;1;98.0;3072;2048
5774422920;3515096929;Canon;Canon EOS 10D;1;98.0;3072;2048
5774422920;8061231511;Canon;Canon EOS 10D;1;98.0;3072;2048
5774422920;3337148839;Canon;Canon EOS 10D;1;98.0;3072;2048
5774422920;8170709448;Canon;Canon EOS 10D;1;98.0;3072;2048
5774422920;0210994183;Canon;Canon EOS 10D;1;98.0;3072;2048
5774422920;3176616014;Canon;Canon EOS 10D;1;98.0;3072;2048
5774422920;9806975742;Canon;Canon EOS 10D;1;98.0;3072;2048
5774422920;6969353128;Canon;Canon EOS 10D;1;90.0;3072;2048
5774422920;2230197378;Canon;Canon EOS 10D;1;98.0;3072;2048
5774422920;7634626092;Canon;Canon EOS 10D;1;98.0;3072;2048
6066804462;1241050438;Canon;Canon EOS 1100D;8;98.0;4272;2848
6066804462;7274361644;Canon;Canon EOS 1100D;1;98.0;4272;2848
6066804462;9907564690;Canon;Canon EOS 1100D;1;98.0;4272;2848
6066804462;4309658606;Canon;Canon EOS 1100D;1;98.0;4272;2848
6066804462;1563265152;Canon;Canon EOS 1100D;8;98.0;4272;2848
6066804462;7753326065;Canon;Canon EOS 1100D;8;98.0;4272;2848
6066804462;0707813761;Canon;Canon EOS 1100D;1;98.0;4272;2848
6066804462;0450522400;Canon;Canon EOS 1100D;1;98.0;4272;2848
6066804462;8834665418;Canon;Canon EOS 1100D;8;98.0;4272;2848
6066804462;8866256980;Canon;Canon EOS 1100D;1;98.0;4272;2848
6066804462;7831055814;Canon;Canon EOS 1100D;1;98.0;4272;2848
6066804462;0660175847;Canon;Canon EOS 1100D;1;98.0;4272;2848
6066804462;9873394841;Canon;Canon EOS 1100D;1;98.0;4272;2848
6066804462;0734060403;Canon;Canon EOS 1100D;8;98.0;4272;2848
6066804462;2643792237;Canon;Canon EOS 1100D;8;98.0;4272;2848
6066804462;8071533227;Canon;Canon EOS 1100D;8;98.0;4272;2848
6066804462;3812440807;Canon;Canon EOS 1100D;1;98.0;4272;2848
6066804462;5005685721;Canon;Canon EOS 1100D;8;98.0;4272;2848
6066804462;2514960548;Canon;Canon EOS 1100D;1;98.0;4272;2848
6066804462;8258837662;Canon;Canon EOS 1100D;1;98.0;4272;2848
6066804462;7034690461;Canon;Canon EOS 1100D;1;98.0;4272;2848
6066804462;9482524716;Canon;Canon EOS 1100D;1;98.0;4272;2848
6066804462;2305085521;Canon;Canon EOS 1100D;8;98.0;4272;2848
6066804462;4339785015;Canon;Canon EOS 1100D;8;98.0;4272;2848
6066804462;6859783874;Canon;Canon EOS 1100D;8;98.0;4272;2848
6066804462;2446104164;Canon;Canon EOS 1100D;1;98.0;4272;2848
6066804462;5636105224;Canon;Canon EOS 1100D;8;98.0;4272;2848
6066804462;3123549108;Canon;Canon EOS 1100D;1;98.0;4272;2848
6066804462;4281855965;Canon;Canon EOS 1100D;8;98.0;4272;2848
6066804462;0414306538;Canon;Canon EOS 1100D;8;98.0;4272;2848
6066804462;9055629133;Canon;Canon EOS 1100D;1;98.0;4272;2848
6066804462;9058554933;Canon;Canon EOS 1100D;1;98.0;4272;2848
6066804462;0410680551;Canon;Canon EOS 1100D;1;98.0;4272;2848
6066804462;8980377320;Canon;Canon EOS 1100D;1;98.0;4272;2848
6066804462;4841211737;Canon;Canon EOS 1100D;8;98.0;4272;2848
6066804462;0725062404;Canon;Canon EOS 1100D;1;98.0;4272;2848
6066804462;5094597966;Canon;Canon EOS 1100D;1;98.0;4272;2848
6066804462;9769757591;Canon;Canon EOS 1100D;8;98.0;4272;2848
6066804462;9273510240;Canon;Canon EOS 1100D;8;98.0;4272;2848
6066804462;2204186395;Canon;Canon EOS 1100D;1;98.0;4272;2848
6066804462;5409884825;Canon;Canon EOS 1100D;1;98.0;4272;2848
6066804462;5738058575;Canon;Canon EOS 1100D;1;98.0;4272;2848
2635622765;0746490180;Canon;Canon EOS 20D;1;98.0;3504;2336
2635622765;2186957156;Canon;Canon EOS 20D;1;98.0;3504;2336
2635622765;5220548377;Canon;Canon EOS 20D;1;98.0;3504;2336
2635622765;2745279900;Canon;Canon EOS 20D;1;98.0;3504;2336
2635622765;4827369828;Canon;Canon EOS 20D;1;98.0;3504;2336
2635622765;7827297417;Canon;Canon EOS 20D;1;98.0;3504;2336
2635622765;2851512181;Canon;Canon EOS 20D;1;100.0;3504;2336
2635622765;0686946253;Canon;Canon EOS 20D;1;98.0;3504;2336
2635622765;4065452341;Canon;Canon EOS 20D;1;96.0;3504;2336
2635622765;2422020843;Canon;Canon EOS 20D;1;98.0;3504;2336
2635622765;3888505793;Canon;Canon EOS 20D;1;98.0;3504;2336
2635622765;5480608156;Canon;Canon EOS 20D;1;98.0;3504;2336
2635622765;7281096406;Canon;Canon EOS 20D;1;96.0;3504;2336
2635622765;1322951503;Canon;Canon EOS 20D;1;96.0;3504;2336
6590146709;2351404272;Canon;Canon EOS 300D DIGITAL;1;98.0;3072;2048
6590146709;2898751335;Canon;Canon EOS 300D DIGITAL;1;98.0;3072;2048
6590146709;1577580939;Canon;Canon EOS 300D DIGITAL;1;98.0;3072;2048
6590146709;5985768546;Canon;Canon EOS 300D DIGITAL;1;98.0;3072;2048
6590146709;5117148134;Canon;Canon EOS 300D DIGITAL;6;98.0;3072;2048
6590146709;9556463009;Canon;Canon EOS 300D DIGITAL;6;98.0;3072;2048
6590146709;7719141874;Canon;Canon EOS 300D DIGITAL;1;98.0;3072;2048
6590146709;1813038811;Canon;Canon EOS 300D DIGITAL;1;98.0;3072;2048
6590146709;4525329649;Canon;Canon EOS 300D DIGITAL;6;98.0;3072;2048
6590146709;6366904545;Canon;Canon EOS 300D DIGITAL;6;98.0;3072;2048
6590146709;4131417752;Canon;Canon EOS 300D DIGITAL;6;98.0;3072;2048
6590146709;7319254595;Canon;Canon EOS 300D DIGITAL;1;98.0;3072;2048
6590146709;3792914089;Canon;Canon EOS 300D DIGITAL;1;98.0;3072;2048
6590146709;7180757659;Canon;Canon EOS 300D DIGITAL;1;98.0;3072;2048
6590146709;1379752181;Canon;Canon EOS 300D DIGITAL;1;98.0;3072;2048
6590146709;3748933860;Canon;Canon EOS 300D DIGITAL;1;98.0;3072;2048
6590146709;2574548208;Canon;Canon EOS 300D DIGITAL;1;98.0;3072;2048
6590146709;2357531854;Canon;Canon EOS 300D DIGITAL;1;98.0;3072;2048
1562011426;2709285662;Canon;Canon EOS 30D;1;96.0;3504;2336
1562011426;7974036567;Canon;Canon EOS 30D;6;98.0;3504;2336
1562011426;7653621729;Canon;Canon EOS 30D;6;98.0;3504;2336
1562011426;1909829946;Canon;Canon EOS 30D;1;96.0;3504;2336
1562011426;2125881579;Canon;Canon EOS 30D;6;98.0;3504;2336
1562011426;7343089632;Canon;Canon EOS 30D;6;98.0;3504;2336
1562011426;8985393892;Canon;Canon EOS 30D;1;98.0;3504;2336
1562011426;9425588555;Canon;Canon EOS 30D;1;98.0;3504;2336
1562011426;5170103076;Canon;Canon EOS 30D;1;98.0;3504;2336
1562011426;0824618888;Canon;Canon EOS 30D;6;98.0;3504;2336
1562011426;4779198555;Canon;Canon EOS 30D;6;98.0;3504;2336
1562011426;2428268854;Canon;Canon EOS 30D;1;98.0;3504;2336
1562011426;2333838327;Canon;Canon EOS 30D;1;98.0;3504;2336
1562011426;0990831347;Canon;Canon EOS 30D;1;98.0;3504;2336
1562011426;8557428530;Canon;Canon EOS 30D;1;98.0;3504;2336
1562011426;1595244062;Canon;Canon EOS 30D;1;98.0;3504;2336
1562011426;7790223720;Canon;Canon EOS 30D;1;98.0;3504;2336
1562011426;4302780402;Canon;Canon EOS 30D;1;98.0;3504;2336
1562011426;9189542553;Canon;Canon EOS 30D;6;98.0;3504;2336
1562011426;2979145001;Canon;Canon EOS 30D;1;98.0;3504;2336
1562011426;6487489094;Canon;Canon EOS 30D;6;98.0;3504;2336
1562011426;8254515563;Canon;Canon EOS 30D;1;98.0;3504;2336
1562011426;4505071848;Canon;Canon EOS 30D;6;98.0;3504;2336
1562011426;3436530486;Canon;Canon EOS 30D;1;96.0;3504;2336
1562011426;0607424364;Canon;Canon EOS 30D;1;96.0;3504;2336
1562011426;7697852700;Canon;Canon EOS 30D;6;98.0;3504;2336
1562011426;8019377848;Canon;Canon EOS 30D;1;98.0;3504;2336
1562011426;9664586243;Canon;Canon EOS 30D;6;98.0;3504;2336
1562011426;0541361775;Canon;Canon EOS 30D;6;98.0;3504;2336
1562011426;6065607574;Canon;Canon EOS 30D;6;98.0;3504;2336
1562011426;5397981464;Canon;Canon EOS 30D;6;98.0;3504;2336
0518357823;7573339839;Canon;Canon EOS 350D DIGITAL;1;98.0;3456;2304
0518357823;8137108944;Canon;Canon EOS 350D DIGITAL;1;98.0;3456;2304
0518357823;4938034909;Canon;Canon EOS 350D DIGITAL;1;98.0;3456;2304
0518357823;5939949964;Canon;Canon EOS 350D DIGITAL;1;97.0;3456;2304
0518357823;8586317884;Canon;Canon EOS 350D DIGITAL;1;98.0;3456;2304
0518357823;5475402762;Canon;Canon EOS 350D DIGITAL;1;98.0;3456;2304
0518357823;2225851222;Canon;Canon EOS 350D DIGITAL;1;98.0;3456;2304
0518357823;1455580763;Canon;Canon EOS 350D DIGITAL;1;98.0;3456;2304
0518357823;6432525564;Canon;Canon EOS 350D DIGITAL;1;98.0;3456;2304
0518357823;0204512411;Canon;Canon EOS 350D DIGITAL;1;98.0;3456;2304
0518357823;3512922999;Canon;Canon EOS 350D DIGITAL;1;98.0;3456;2304
0518357823;9034594615;Canon;Canon EOS 350D DIGITAL;1;98.0;3456;2304
0518357823;8352488768;Canon;Canon EOS 350D DIGITAL;1;90.0;3456;2304
0518357823;7673467559;Canon;Canon EOS 350D DIGITAL;1;98.0;3456;2304
0518357823;1703223775;Canon;Canon EOS 350D DIGITAL;1;98.0;3456;2304
0518357823;0217578497;Canon;Canon EOS 350D DIGITAL;1;98.0;3456;2304
9025332744;3508765608;Canon;Canon EOS 400D DIGITAL;1;98.0;3888;2592
9025332744;2243526196;Canon;Canon EOS 400D DIGITAL;1;98.0;3888;2592
9025332744;7675992925;Canon;Canon EOS 400D DIGITAL;1;98.0;3888;2592
9025332744;9463441761;Canon;Canon EOS 400D DIGITAL;1;98.0;3888;2592
9025332744;0794899805;Canon;Canon EOS 400D DIGITAL;1;98.0;3888;2592
9025332744;5260872852;Canon;Canon EOS 400D DIGITAL;6;98.0;3888;2592
9025332744;6954909264;Canon;Canon EOS 400D DIGITAL;6;98.0;3888;2592
9025332744;1246309818;Canon;Canon EOS 400D DIGITAL;1;98.0;3888;2592
9025332744;7492044707;Canon;Canon EOS 400D DIGITAL;1;98.0;3888;2592
9025332744;3441598503;Canon;Canon EOS 400D DIGITAL;1;98.0;3888;2592
9025332744;0047267064;Canon;Canon EOS 400D DIGITAL;1;98.0;3888;2592
9025332744;9873567276;Canon;Canon EOS 400D DIGITAL;1;98.0;3888;2592
9025332744;2950801086;Canon;Canon EOS 400D DIGITAL;1;98.0;3888;2592
9025332744;9045851527;Canon;Canon EOS 400D DIGITAL;1;98.0;3888;2592
9025332744;8808395515;Canon;Canon EOS 400D DIGITAL;1;98.0;3888;2592
9025332744;5387359926;Canon;Canon EOS 400D DIGITAL;6;98.0;3888;2592
9025332744;7279220549;Canon;Canon EOS 400D DIGITAL;1;98.0;3888;2592
9025332744;5641502588;Canon;Canon EOS 400D DIGITAL;6;98.0;3888;2592
9025332744;4453227539;Canon;Canon EOS 400D DIGITAL;1;98.0;3888;2592
9025332744;0475195909;Canon;Canon EOS 400D DIGITAL;1;98.0;3888;2592
9025332744;7753248510;Canon;Canon EOS 400D DIGITAL;6;98.0;3888;2592
9025332744;8566382670;Canon;Canon EOS 400D DIGITAL;6;98.0;3888;2592
9025332744;1582480647;Canon;Canon EOS 400D DIGITAL;6;98.0;3888;2592
9373533410;2144314003;Canon;Canon EOS 40D;8;98.0;3888;2592
9373533410;4676744076;Canon;Canon EOS 40D;1;96.0;3888;2592
9373533410;7763593711;Canon;Canon EOS 40D;8;98.0;3888;2592
9373533410;7334253617;Canon;Canon EOS 40D;8;98.0;3888;2592
9373533410;5764255413;Canon;Canon EOS 40D;8;98.0;3888;2592
9373533410;6291837613;Canon;Canon EOS 40D;1;98.0;3888;2592
9373533410;4592407818;Canon;Canon EOS 40D;1;96.0;3888;2592
9373533410;7927164784;Canon;Canon EOS 40D;8;98.0;3888;2592
9373533410;6942447567;Canon;Canon EOS 40D;1;96.0;3888;2592
9373533410;6906003102;Canon;Canon EOS 40D;8;98.0;3888;2592
9373533410;9810919983;Canon;Canon EOS 40D;6;98.0;3888;2592
9373533410;0653640223;Canon;Canon EOS 40D;6;98.0;3888;2592
9373533410;0326313644;Canon;Canon EOS 40D;1;98.0;3888;2592
9373533410;0775571404;Canon;Canon EOS 40D;1;96.0;3888;2592
9373533410;0477312955;Canon;Canon EOS 40D;1;96.0;3888;2592
9373533410;4285003950;Canon;Canon EOS 40D;1;98.0;3888;2592
9373533410;4724691761;Canon;Canon EOS 40D;1;98.0;3888;2592
9373533410;8634641918;Canon;Canon EOS 40D;1;96.0;3888;2592
9373533410;1742318585;Canon;Canon EOS 40D;6;98.0;3888;2592
9373533410;0734382921;Canon;Canon EOS 40D;1;98.0;3888;2592
9373533410;9826757775;Canon;Canon EOS 40D;6;98.0;3888;2592
9373533410;2977736915;Canon;Canon EOS 40D;1;96.0;3888;2592
9373533410;6945521208;Canon;Canon EOS 40D;1;98.0;3888;2592
9373533410;8751999670;Canon;Canon EOS 40D;6;98.0;3888;2592
9373533410;2382604346;Canon;Canon EOS 40D;1;98.0;3888;2592
9373533410;2540776669;Canon;Canon EOS 40D;1;98.0;3888;2592
9373533410;4621334533;Canon;Canon EOS 40D;6;98.0;3888;2592
6129599320;1545520976;Canon;Canon EOS 450D;1;98.0;4272;2848
6129599320;0286987563;Canon;Canon EOS 450D;8;98.0;4272;2848
6129599320;9066421702;Canon;Canon EOS 450D;1;98.0;4272;2848
6129599320;5433613579;Canon;Canon EOS 450D;8;98.0;4272;2848
6129599320;6053408167;Canon;Canon EOS 450D;8;98.0;4272;2848
6129599320;8601200455;Canon;Canon EOS 450D;1;98.0;4272;2848
6129599320;3299407146;Canon;Canon EOS 450D;8;98.0;4272;2848
6129599320;9451594272;Canon;Canon EOS 450D;1;98.0;4272;2848
6129599320;3899293519;Canon;Canon EOS 450D;1;98.0;4272;2848
6129599320;5441040801;Canon;Canon EOS 450D;6;98.0;4272;2848
6129599320;5807809950;Canon;Canon EOS 450D;1;97.0;4272;2848
6129599320;9450549936;Canon;Canon EOS 450D;1;97.0;4272;2848
6129599320;4139143512;Canon;Canon EOS 450D;1;97.0;4272;2848
6129599320;0958599719;Canon;Canon EOS 450D;1;98.0;4272;2848
6129599320;0470082928;Canon;Canon EOS 450D;1;98.0;4272;2848
6129599320;5532781967;Canon;Canon EOS 450D;1;97.0;4272;2848
6129599320;7952613688;Canon;Canon EOS 450D;1;97.0;4272;2848
6129599320;7224740344;Canon;Canon EOS 450D;1;97.0;4272;2848
6129599320;5418547648;Canon;Canon EOS 450D;1;98.0;4272;2848
6129599320;0024529400;Canon;Canon EOS 450D;1;97.0;4272;2848
6129599320;7486879160;Canon;Canon EOS 450D;1;98.0;4272;2848
6129599320;2779264701;Canon;Canon EOS 450D;8;98.0;4272;2848
6129599320;1429767289;Canon;Canon EOS 450D;1;98.0;4272;2848
6129599320;1836690550;Canon;Canon EOS 450D;1;98.0;4272;2848
6129599320;8181842769;Canon;Canon EOS 450D;6;98.0;4272;2848
6129599320;6278054971;Canon;Canon EOS 450D;1;97.0;4272;2848
6129599320;6385175613;Canon;Canon EOS 450D;1;98.0;4272;2848
6129599320;9394607670;Canon;Canon EOS 450D;6;98.0;4272;2848
6129599320;0784332961;Canon;Canon EOS 450D;1;97.0;4272;2848
6129599320;0880192436;Canon;Canon EOS 450D;1;97.0;4272;2848
6129599320;8805317078;Canon;Canon EOS 450D;8;98.0;4272;2848
6129599320;1869858250;Canon;Canon EOS 450D;8;98.0;4272;2848
6129599320;1264749659;Canon;Canon EOS 450D;1;98.0;4272;2848
5169178038;7357875119;Canon;Canon EOS 500D;1;98.0;4752;3168
5169178038;3075781707;Canon;Canon EOS 500D;1;98.0;4752;3168
5169178038;0253044440;Canon;Canon EOS 500D;6;98.0;4752;3168
5169178038;5714143224;Canon;Canon EOS 500D;6;98.0;4752;3168
5169178038;3730647551;Canon;Canon EOS 500D;1;98.0;4752;3168
5169178038;0219319326;Canon;Canon EOS 500D;8;98.0;4752;3168
5169178038;6861465631;Canon;Canon EOS 500D;8;98.0;4752;3168
5169178038;4429986600;Canon;Canon EOS 500D;8;98.0;4752;3168
5169178038;6201577545;Canon;Canon EOS 500D;1;98.0;4752;3168
5169178038;9962209899;Canon;Canon EOS 500D;8;98.0;4752;3168
5169178038;1025886117;Canon;Canon EOS 500D;1;98.0;4752;3168
5169178038;8854051341;Canon;Canon EOS 500D;1;98.0;4752;3168
5169178038;3872167031;Canon;Canon EOS 500D;8;98.0;4752;3168
5169178038;7102630662;Canon;Canon EOS 500D;8;98.0;4752;3168
5169178038;1964081853;Canon;Canon EOS 500D;8;98.0;4752;3168
5169178038;3821419270;Canon;Canon EOS 500D;8;98.0;4752;3168
5169178038;1202114561;Canon;Canon EOS 500D;8;98.0;4752;3168
5169178038;8904472866;Canon;Canon EOS 500D;1;98.0;4752;3168
5169178038;7456129111;Canon;Canon EOS 500D;8;98.0;4752;3168
5169178038;8590125943;Canon;Canon EOS 500D;8;98.0;4752;3168
5169178038;7067757825;Canon;Canon EOS 500D;1;97.0;4752;3168
5169178038;1743525619;Canon;Canon EOS 500D;8;98.0;4752;3168
5169178038;1359198409;Canon;Canon EOS 500D;1;98.0;4752;3168
5169178038;0062518929;Canon;Canon EOS 500D;8;98.0;4752;3168
5169178038;3062689854;Canon;Canon EOS 500D;8;98.0;4752;3168
5169178038;0820864099;Canon;Canon EOS 500D;8;98.0;4752;3168
5169178038;4985501408;Canon;Canon EOS 500D;1;97.0;4752;3168
5169178038;8098810997;Canon;Canon EOS 500D;8;98.0;4752;3168
5169178038;6332699335;Canon;Canon EOS 500D;1;98.0;4752;3168
5169178038;0153662155;Canon;Canon EOS 500D;1;97.0;4752;3168
5169178038;2664675547;Canon;Canon EOS 500D;1;98.0;4752;3168
5169178038;7778753816;Canon;Canon EOS 500D;8;98.0;4752;3168
5169178038;0667253178;Canon;Canon EOS 500D;1;98.0;4752;3168
3308124008;9843803144;Canon;Canon EOS 50D;8;98.0;4752;3168
3308124008;9208265215;Canon;Canon EOS 50D;8;98.0;4752;3168
3308124008;9366594186;Canon;Canon EOS 50D;1;98.0;4752;3168
3308124008;5099559143;Canon;Canon EOS 50D;1;98.0;4752;3168
3308124008;2335938985;Canon;Canon EOS 50D;1;98.0;4752;3168
3308124008;9265737099;Canon;Canon EOS 50D;1;98.0;4752;3168
3308124008;6029668831;Canon;Canon EOS 50D;8;98.0;4752;3168
3308124008;6809449603;Canon;Canon EOS 50D;1;98.0;4752;3168
3308124008;5878711058;Canon;Canon EOS 50D;1;98.0;4752;3168
3308124008;6179013193;Canon;Canon EOS 50D;8;98.0;4752;3168
3308124008;2812924154;Canon;Canon EOS 50D;8;98.0;4752;3168
3308124008;7911839937;Canon;Canon EOS 50D;1;98.0;4752;3168
3308124008;7264428317;Canon;Canon EOS 50D;1;97.0;4752;3168
3308124008;3478816066;Canon;Canon EOS 50D;1;98.0;4752;3168
3308124008;5576124355;Canon;Canon EOS 50D;1;97.0;4752;3168
3308124008;6865406380;Canon;Canon EOS 50D;8;98.0;4752;3168
3308124008;7241515255;Canon;Canon EOS 50D;1;98.0;4752;3168
3308124008;5054499237;Canon;Canon EOS 50D;8;98.0;4752;3168
3308124008;5372960693;Canon;Canon EOS 50D;8;98.0;4752;3168
3308124008;2288084905;Canon;Canon EOS 50D;8;98.0;4752;3168
3308124008;1054952207;Canon;Canon EOS 50D;1;98.0;4752;3168
3308124008;1447095108;Canon;Canon EOS 50D;8;98.0;4752;3168
3308124008;5719988388;Canon;Canon EOS 50D;8;98.0;4752;3168
3308124008;4525170639;Canon;Canon EOS 50D;8;98.0;4752;3168
3308124008;2109829643;Canon;Canon EOS 50D;1;98.0;4752;3168
3308124008;7298769111;Canon;Canon EOS 50D;1;98.0;4752;3168
3308124008;8410058224;Canon;Canon EOS 50D;8;98.0;4752;3168
3308124008;3743463747;Canon;Canon EOS 50D;8;98.0;4752;3168
3308124008;7696140878;Canon;Canon EOS 50D;8;98.0;4752;3168
3308124008;5406711431;Canon;Canon EOS 50D;1;98.0;4752;3168
3308124008;9776089099;Canon;Canon EOS 50D;1;97.0;4752;3168
3308124008;6099848898;Canon;Canon EOS 50D;8;98.0;4752;3168
3308124008;9100281751;Canon;Canon EOS 50D;8;98.0;4752;3168
3308124008;8127377332;Canon;Canon EOS 50D;1;98.0;4752;3168
5776285652;8014399354;Canon;Canon EOS 550D;8;98.0;5184;3456
5776285652;9599256667;Canon;Canon EOS 550D;8;98.0;5184;3456
5776285652;8201134466;Canon;Canon EOS 550D;1;100.0;5184;3456
5776285652;2368027562;Canon;Canon EOS 550D;6;98.0;5184;3456
5776285652;6983195539;Canon;Canon EOS 550D;1;98.0;5184;3456
5776285652;1015917927;Canon;Canon EOS 550D;1;98.0;5184;3456
5776285652;9634289659;Canon;Canon EOS 550D;1;98.0;5184;3456
5776285652;2525867428;Canon;Canon EOS 550D;6;98.0;5184;3456
5776285652;1043517215;Canon;Canon EOS 550D;1;98.0;5184;3456
5776285652;1436250782;Canon;Can
gitextract_pvls8abb/
├── .gitignore
├── LICENSE.txt
├── README.md
├── demo/
│ ├── demo_extraction.sh
│ ├── demo_heatmap.sh
│ └── outs/
│ ├── NC2016_2564_map.mat
│ ├── faceswap_map.mat
│ ├── faceswap_np.mat
│ ├── inpainting_np.mat
│ ├── seamcarving_map.mat
│ ├── splicing_map.mat
│ └── splicing_np.mat
├── docs/
│ ├── _config.yml
│ └── index.md
├── main_blind.py
├── main_extraction.py
├── main_map2uint8.py
├── main_showout.py
├── main_showres.py
├── noiseprint/
│ ├── __init__.py
│ ├── feat_spam/
│ │ ├── __init__.py
│ │ ├── mapping.py
│ │ ├── residue.py
│ │ └── spam_np_opt.py
│ ├── nets/
│ │ ├── net_jpg100/
│ │ │ ├── model.data-00000-of-00001
│ │ │ ├── model.index
│ │ │ └── model.meta
│ │ ├── net_jpg101/
│ │ │ ├── model.data-00000-of-00001
│ │ │ ├── model.index
│ │ │ └── model.meta
│ │ ├── net_jpg51/
│ │ │ ├── model.data-00000-of-00001
│ │ │ ├── model.index
│ │ │ └── model.meta
│ │ ├── net_jpg52/
│ │ │ ├── model.data-00000-of-00001
│ │ │ ├── model.index
│ │ │ └── model.meta
│ │ ├── net_jpg53/
│ │ │ ├── model.data-00000-of-00001
│ │ │ ├── model.index
│ │ │ └── model.meta
│ │ ├── net_jpg54/
│ │ │ ├── model.data-00000-of-00001
│ │ │ ├── model.index
│ │ │ └── model.meta
│ │ ├── net_jpg55/
│ │ │ ├── model.data-00000-of-00001
│ │ │ ├── model.index
│ │ │ └── model.meta
│ │ ├── net_jpg56/
│ │ │ ├── model.data-00000-of-00001
│ │ │ ├── model.index
│ │ │ └── model.meta
│ │ ├── net_jpg57/
│ │ │ ├── model.data-00000-of-00001
│ │ │ ├── model.index
│ │ │ └── model.meta
│ │ ├── net_jpg58/
│ │ │ ├── model.data-00000-of-00001
│ │ │ ├── model.index
│ │ │ └── model.meta
│ │ ├── net_jpg59/
│ │ │ ├── model.data-00000-of-00001
│ │ │ ├── model.index
│ │ │ └── model.meta
│ │ ├── net_jpg60/
│ │ │ ├── model.data-00000-of-00001
│ │ │ ├── model.index
│ │ │ └── model.meta
│ │ ├── net_jpg61/
│ │ │ ├── model.data-00000-of-00001
│ │ │ ├── model.index
│ │ │ └── model.meta
│ │ ├── net_jpg62/
│ │ │ ├── model.data-00000-of-00001
│ │ │ ├── model.index
│ │ │ └── model.meta
│ │ ├── net_jpg63/
│ │ │ ├── model.data-00000-of-00001
│ │ │ ├── model.index
│ │ │ └── model.meta
│ │ ├── net_jpg64/
│ │ │ ├── model.data-00000-of-00001
│ │ │ ├── model.index
│ │ │ └── model.meta
│ │ ├── net_jpg65/
│ │ │ ├── model.data-00000-of-00001
│ │ │ ├── model.index
│ │ │ └── model.meta
│ │ ├── net_jpg66/
│ │ │ ├── model.data-00000-of-00001
│ │ │ ├── model.index
│ │ │ └── model.meta
│ │ ├── net_jpg67/
│ │ │ ├── model.data-00000-of-00001
│ │ │ ├── model.index
│ │ │ └── model.meta
│ │ ├── net_jpg68/
│ │ │ ├── model.data-00000-of-00001
│ │ │ ├── model.index
│ │ │ └── model.meta
│ │ ├── net_jpg69/
│ │ │ ├── model.data-00000-of-00001
│ │ │ ├── model.index
│ │ │ └── model.meta
│ │ ├── net_jpg70/
│ │ │ ├── model.data-00000-of-00001
│ │ │ ├── model.index
│ │ │ └── model.meta
│ │ ├── net_jpg71/
│ │ │ ├── model.data-00000-of-00001
│ │ │ ├── model.index
│ │ │ └── model.meta
│ │ ├── net_jpg72/
│ │ │ ├── model.data-00000-of-00001
│ │ │ ├── model.index
│ │ │ └── model.meta
│ │ ├── net_jpg73/
│ │ │ ├── model.data-00000-of-00001
│ │ │ ├── model.index
│ │ │ └── model.meta
│ │ ├── net_jpg74/
│ │ │ ├── model.data-00000-of-00001
│ │ │ ├── model.index
│ │ │ └── model.meta
│ │ ├── net_jpg75/
│ │ │ ├── model.data-00000-of-00001
│ │ │ ├── model.index
│ │ │ └── model.meta
│ │ ├── net_jpg76/
│ │ │ ├── model.data-00000-of-00001
│ │ │ ├── model.index
│ │ │ └── model.meta
│ │ ├── net_jpg77/
│ │ │ ├── model.data-00000-of-00001
│ │ │ ├── model.index
│ │ │ └── model.meta
│ │ ├── net_jpg78/
│ │ │ ├── model.data-00000-of-00001
│ │ │ ├── model.index
│ │ │ └── model.meta
│ │ ├── net_jpg79/
│ │ │ ├── model.data-00000-of-00001
│ │ │ ├── model.index
│ │ │ └── model.meta
│ │ ├── net_jpg80/
│ │ │ ├── model.data-00000-of-00001
│ │ │ ├── model.index
│ │ │ └── model.meta
│ │ ├── net_jpg81/
│ │ │ ├── model.data-00000-of-00001
│ │ │ ├── model.index
│ │ │ └── model.meta
│ │ ├── net_jpg82/
│ │ │ ├── model.data-00000-of-00001
│ │ │ ├── model.index
│ │ │ └── model.meta
│ │ ├── net_jpg83/
│ │ │ ├── model.data-00000-of-00001
│ │ │ ├── model.index
│ │ │ └── model.meta
│ │ ├── net_jpg84/
│ │ │ ├── model.data-00000-of-00001
│ │ │ ├── model.index
│ │ │ └── model.meta
│ │ ├── net_jpg85/
│ │ │ ├── model.data-00000-of-00001
│ │ │ ├── model.index
│ │ │ └── model.meta
│ │ ├── net_jpg86/
│ │ │ ├── model.data-00000-of-00001
│ │ │ ├── model.index
│ │ │ └── model.meta
│ │ ├── net_jpg87/
│ │ │ ├── model.data-00000-of-00001
│ │ │ ├── model.index
│ │ │ └── model.meta
│ │ ├── net_jpg88/
│ │ │ ├── model.data-00000-of-00001
│ │ │ ├── model.index
│ │ │ └── model.meta
│ │ ├── net_jpg89/
│ │ │ ├── model.data-00000-of-00001
│ │ │ ├── model.index
│ │ │ └── model.meta
│ │ ├── net_jpg90/
│ │ │ ├── model.data-00000-of-00001
│ │ │ ├── model.index
│ │ │ └── model.meta
│ │ ├── net_jpg91/
│ │ │ ├── model.data-00000-of-00001
│ │ │ ├── model.index
│ │ │ └── model.meta
│ │ ├── net_jpg92/
│ │ │ ├── model.data-00000-of-00001
│ │ │ ├── model.index
│ │ │ └── model.meta
│ │ ├── net_jpg93/
│ │ │ ├── model.data-00000-of-00001
│ │ │ ├── model.index
│ │ │ └── model.meta
│ │ ├── net_jpg94/
│ │ │ ├── model.data-00000-of-00001
│ │ │ ├── model.index
│ │ │ └── model.meta
│ │ ├── net_jpg95/
│ │ │ ├── model.data-00000-of-00001
│ │ │ ├── model.index
│ │ │ └── model.meta
│ │ ├── net_jpg96/
│ │ │ ├── model.data-00000-of-00001
│ │ │ ├── model.index
│ │ │ └── model.meta
│ │ ├── net_jpg97/
│ │ │ ├── model.data-00000-of-00001
│ │ │ ├── model.index
│ │ │ └── model.meta
│ │ ├── net_jpg98/
│ │ │ ├── model.data-00000-of-00001
│ │ │ ├── model.index
│ │ │ └── model.meta
│ │ └── net_jpg99/
│ │ ├── model.data-00000-of-00001
│ │ ├── model.index
│ │ └── model.meta
│ ├── network.py
│ ├── noiseprint.py
│ ├── noiseprint_blind.py
│ ├── post_em.py
│ ├── requirements-cpu.txt
│ ├── requirements-gpu.txt
│ └── utility/
│ ├── __init__.py
│ ├── gaussianMixture.py
│ └── utilityRead.py
└── training/
├── LICENSE.txt
├── README.md
├── code/
│ ├── FCnet.py
│ ├── Producer2.py
│ ├── create_data.py
│ ├── db_utility.py
│ ├── train_denoiser.py
│ ├── train_noiseprint.py
│ └── train_utility.py
└── dataset/
├── README.txt
├── download_images.py
├── list_images.csv
└── list_models.csv
SYMBOL INDEX (113 symbols across 16 files)
FILE: noiseprint/feat_spam/mapping.py
function getIdemMapper (line 15) | def getIdemMapper(num):
function getSignSymMapper (line 18) | def getSignSymMapper(occo, n):
function getSignMapper (line 45) | def getSignMapper(occo, n):
function getPos (line 66) | def getPos(P, n, occo):
function getCombinations (line 70) | def getCombinations(occo, n):
function mapper2filter (line 84) | def mapper2filter(mapper, dtype=np.float32):
FILE: noiseprint/feat_spam/residue.py
function getFiltersResidue (line 16) | def getFiltersResidue(res):
function getFilterOcco (line 65) | def getFilterOcco(occo, values):
FILE: noiseprint/feat_spam/spam_np_opt.py
function quantizerScalarEncoder (line 18) | def quantizerScalarEncoder(x, values):
function getParams (line 25) | def getParams(ordResid, symTranspose, q, T, ordCooc, mapper, strides):
function computeSpamRes (line 60) | def computeSpamRes(res, params, weights = list(), normalize = True):
function getSpamRes (line 138) | def getSpamRes(res, params, ksize, weights = list(), paddingModality = 0):
FILE: noiseprint/network.py
class FullConvNet (line 15) | class FullConvNet(object):
method __init__ (line 18) | def __init__(self, images, bnorm_decay, falg_train, num_levels = 17, p...
method _batch_norm (line 55) | def _batch_norm(self, x, name = 'bnorm'):
method _bias (line 91) | def _bias(self, x, name = 'bias'):
method _conv (line 103) | def _conv(self, x, filter_size, out_filters, stride, name='conv'):
FILE: noiseprint/noiseprint.py
function genNoiseprint (line 32) | def genNoiseprint(img, QF=101, model_name='net'):
FILE: noiseprint/noiseprint_blind.py
function noiseprint_blind_file (line 22) | def noiseprint_blind_file(filename, model_name='net'):
function noiseprint_blind (line 38) | def noiseprint_blind(img, QF, model_name='net'):
function noiseprint_blind_post (line 43) | def noiseprint_blind_post(res, img):
function genMappFloat (line 54) | def genMappFloat(mapp, valid, range0, range1, imgsize):
function genMappUint8 (line 62) | def genMappUint8(mapp, valid, range0, range1, imgsize, vmax=None, vmin=N...
FILE: noiseprint/post_em.py
function faetReduce (line 35) | def faetReduce(feat_list, inds, whiteningFlag = False):
function getWeights (line 45) | def getWeights(img, res):
function getCoocValues (line 59) | def getCoocValues(res, img_gray, n_clusters=4, random_state=0):
function getSpamFromNoiseprint (line 67) | def getSpamFromNoiseprint(res, img_gray, ksize=ksize_default, stride=str...
function EMgu (line 87) | def EMgu(feats, seed = 0, maxIter = 100, replicates = 10, outliersNlogl ...
function EMgu_img (line 115) | def EMgu_img(spam, valid, extFeat = range(32), seed = 0, maxIter = 100, ...
FILE: noiseprint/utility/gaussianMixture.py
class gm (line 16) | class gm:
method __init__ (line 33) | def __init__(self, dim, listSigmaInds, listSigmaType, outliersProb = -...
method setRandomParams (line 54) | def setRandomParams(self, X, regularizer = 0, randomState = np.random....
method setRandomParamsW (line 83) | def setRandomParamsW(self, X, weights, regularizer = 0, randomState = ...
method getNlogl (line 121) | def getNlogl(self, X):
method getLoglh (line 188) | def getLoglh(self, X):
method getLoglhInlier (line 198) | def getLoglhInlier(self, X):
method maximizationParam (line 210) | def maximizationParam(self, X, post, regularizer = 0):
method expectation (line 273) | def expectation(self, X):
method expectationWeighed (line 277) | def expectationWeighed(self, X, weighed):
method MEstep (line 281) | def MEstep(self, X, post, regularizer = 0):
method MEstepWeighed (line 286) | def MEstepWeighed(self, X, weights, post, regularizer = 0):
method EM (line 291) | def EM(self, X, regularizer, maxIter, relErr = 1e-5):
method EMweighed (line 309) | def EMweighed(self, X, weights, regularizer, maxIter, relErr=1e-5):
function softmax (line 326) | def softmax(logit):
function softmaxWeighed (line 334) | def softmaxWeighed(logit, weights):
FILE: noiseprint/utility/utilityRead.py
function imread2f_pil (line 18) | def imread2f_pil(stream, channel = 1, dtype = np.float32):
function imread2f_raw (line 37) | def imread2f_raw(stream, channel = 1, dtype = np.float32):
function imread2f (line 60) | def imread2f(stream, channel = 1, dtype = np.float32):
function jpeg_qtableinv (line 67) | def jpeg_qtableinv(stream, tnum=0, force_baseline=None):
function resizeMapWithPadding (line 123) | def resizeMapWithPadding(x, range0, range1, shapeOut):
function computeMetricsContinue (line 133) | def computeMetricsContinue(values, gt0, gt1):
function computeMCC (line 150) | def computeMCC(values, gt0, gt1):
FILE: training/code/FCnet.py
class FullConvNet (line 19) | class FullConvNet(object):
method __init__ (line 22) | def __init__(self, bnorm_decay=0.9, num_levels=17, outchannels=1):
method __call__ (line 43) | def __call__(self, x, flag_train, padding='VALID'):
method _batch_norm (line 59) | def _batch_norm(self, x, flag_train, name='bnorm'):
method _bias (line 104) | def _bias(self, x, name='bias'):
method _conv (line 118) | def _conv(self, x, filter_size, out_filters, stride, name='conv', padd...
FILE: training/code/Producer2.py
class setWorkers_mock (line 2) | class setWorkers_mock():
method __init__ (line 3) | def __init__(self, indexer, pre_fun, app_fun, buffer_size=100, workers...
method info (line 20) | def info(self):
method __enter__ (line 23) | def __enter__(self):
method __exit__ (line 28) | def __exit__(self, exc_type, exc_value, traceback):
method __len__ (line 31) | def __len__(self):
method __iter__ (line 34) | def __iter__(self):
method __next__ (line 37) | def __next__(self):
class setWorkers_process (line 55) | class setWorkers_process():
method __init__ (line 56) | def __init__(self, indexer, pre_fun, app_fun, buffer_size=100, workers...
method _run_in (line 75) | def _run_in(self, indexer, queue, pre_fun, flag_reset):
method _run_fun (line 88) | def _run_fun(self, index_process):
method info (line 97) | def info(self):
method __enter__ (line 102) | def __enter__(self):
method __exit__ (line 110) | def __exit__(self, exc_type, exc_value, traceback):
method __len__ (line 124) | def __len__(self):
method __iter__ (line 127) | def __iter__(self):
method __next__ (line 130) | def __next__(self):
class setWorkers_thread (line 154) | class setWorkers_thread():
method __init__ (line 155) | def __init__(self, indexer, pre_fun, app_fun, buffer_size=100, workers...
method _run_in (line 173) | def _run_in(self, indexer, queue, pre_fun, flag_reset):
method _run_fun (line 186) | def _run_fun(self, index_process):
method info (line 195) | def info(self):
method __enter__ (line 200) | def __enter__(self):
method __exit__ (line 208) | def __exit__(self, exc_type, exc_value, traceback):
method __len__ (line 220) | def __len__(self):
method __iter__ (line 223) | def __iter__(self):
method __next__ (line 226) | def __next__(self):
FILE: training/code/db_utility.py
function get_list_valid (line 23) | def get_list_valid():
function get_list_train (line 39) | def get_list_train():
function jpeg_compression (line 56) | def jpeg_compression(img, quality):
function jpeg_compression_numpy (line 63) | def jpeg_compression_numpy(x, quality):
FILE: training/code/train_denoiser.py
function onlyOpenImage (line 72) | def onlyOpenImage(img, *other):
function clipImage (line 75) | def clipImage(img, wSize, crop0, crop1, indRot):
FILE: training/code/train_noiseprint.py
function onlyOpenImage (line 77) | def onlyOpenImage(img, *other):
function clipImage (line 80) | def clipImage(img, wSize, crop0, crop1, indRot):
FILE: training/code/train_utility.py
function distmxt (line 18) | def distmxt(res):
function my_loss_paper (line 28) | def my_loss_paper(corr, cm):
function defLabelClass (line 35) | def defLabelClass(batch_size, nearImg, repMat):
function make_whitening (line 45) | def make_whitening(x, block_size, regularize_type):
function getAUC (line 66) | def getAUC(scores, labels):
function getAUC_dict (line 83) | def getAUC_dict(scores, labels):
function genListWithCliped (line 114) | def genListWithCliped(list_input, element_num, cliped_num, wSize):
function genList (line 127) | def genList(imgs, numMaxImg, nearImg, rip):
class genBatchList (line 148) | class genBatchList():
method __init__ (line 149) | def __init__(self, batch_size, iterator, flag_reset=True):
method getNumSamples (line 157) | def getNumSamples(self):
method __len__ (line 160) | def __len__(self):
method __iter__ (line 163) | def __iter__(self):
class genBatch (line 179) | class genBatch():
method __init__ (line 180) | def __init__(self, batch_size, iterator, flag_reset=True):
method getNumSamples (line 188) | def getNumSamples(self):
method __len__ (line 191) | def __len__(self):
method __iter__ (line 194) | def __iter__(self):
FILE: training/dataset/download_images.py
function download (line 16) | def download(url, output_dir ):
Condensed preview — 199 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (1,537K chars).
[
{
"path": ".gitignore",
"chars": 1203,
"preview": "# Byte-compiled / optimized / DLL files\n__pycache__/\n*.py[cod]\n*$py.class\n\n# C extensions\n*.so\n\n# Distribution / packagi"
},
{
"path": "LICENSE.txt",
"chars": 1806,
"preview": "THIS DOCUMENT CONSTITUTES A LICENCE TO USE THE SOFTWARE ON THE TERMS AND CONDITIONS APPEARING BELOW.\n\n\nPreamble\n\nThis Li"
},
{
"path": "README.md",
"chars": 2489,
"preview": "# Noiseprint: a CNN-based camera model fingerprint\n[Noiseprint](https://ieeexplore.ieee.org/document/8713484) is a CNN-b"
},
{
"path": "demo/demo_extraction.sh",
"chars": 479,
"preview": "rm ./outs/*_np.mat\npython ../main_extraction.py ./imgs/splicing.png ./outs/splicing_np.mat\npython ../main_showout.py"
},
{
"path": "demo/demo_heatmap.sh",
"chars": 210,
"preview": "rm ./outs/NC2016_2564_map.mat\npython ../main_blind.py ./imgs/NC2016_2564.jpg ./outs/NC2016_2564_map.mat\npython ../mai"
},
{
"path": "docs/_config.yml",
"chars": 76,
"preview": "remote_theme: grip-unina/webtemplate\nplugins:\n - jekyll\n - jekyll-seo-tag\n"
},
{
"path": "docs/index.md",
"chars": 2151,
"preview": "---\nlayout: paper\npaper: Noiseprint:<br/> a CNN-based camera model fingerprint\ngithub_url: https://github.com/grip"
},
{
"path": "main_blind.py",
"chars": 1532,
"preview": "# This code is the main of the noiseprint_blind\n# python main_blind.py input.png output.mat\n# python main_showout."
},
{
"path": "main_extraction.py",
"chars": 1369,
"preview": "# This is the code to extract Noiseprint\n# python main_extraction.py input.png noiseprint.mat\n# python main_showou"
},
{
"path": "main_map2uint8.py",
"chars": 1177,
"preview": "# This code converts the noiseprint_blind output in a PNG image\n# python main_mat2uint8.py output.mat output.png\n#\n# %"
},
{
"path": "main_showout.py",
"chars": 2149,
"preview": "# This code shows the noiseprint_blind output\n# python main_blind.py input.png output.mat\n# python main_showout.py"
},
{
"path": "main_showres.py",
"chars": 2965,
"preview": "# This code shows the result of noiseprint_blind output\n# python main_blind.py input.png output.mat\n# python main_"
},
{
"path": "noiseprint/__init__.py",
"chars": 509,
"preview": "# %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n#\n# Copyright (c) 2018 Image Processing Rese"
},
{
"path": "noiseprint/feat_spam/__init__.py",
"chars": 508,
"preview": "# %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n#\n# Copyright (c) 2016 Image Processing Rese"
},
{
"path": "noiseprint/feat_spam/mapping.py",
"chars": 2817,
"preview": "# %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n#\n# Copyright (c) 2016 Image Processing Rese"
},
{
"path": "noiseprint/feat_spam/residue.py",
"chars": 2636,
"preview": "# %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n#\n# Copyright (c) 2016 Image Processing Rese"
},
{
"path": "noiseprint/feat_spam/spam_np_opt.py",
"chars": 6059,
"preview": "# %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n#\n# Copyright (c) 2016 Image Processing Rese"
},
{
"path": "noiseprint/network.py",
"chars": 4584,
"preview": "#\n# Copyright (c) 2019 Image Processing Research Group of University Federico II of Naples ('GRIP-UNINA').\n# All rights "
},
{
"path": "noiseprint/noiseprint.py",
"chars": 2868,
"preview": "#\n# Copyright (c) 2019 Image Processing Research Group of University Federico II of Naples ('GRIP-UNINA').\n# All rights "
},
{
"path": "noiseprint/noiseprint_blind.py",
"chars": 2546,
"preview": "#\n# Copyright (c) 2019 Image Processing Research Group of University Federico II of Naples ('GRIP-UNINA').\n# All rights "
},
{
"path": "noiseprint/post_em.py",
"chars": 5677,
"preview": "# %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n#\n# Copyright (c) 2019 Image Processing Rese"
},
{
"path": "noiseprint/requirements-cpu.txt",
"chars": 162,
"preview": "pillow==4.2.1\nnumpy==1.16.1\npandas==0.20.3\nscipy==0.19.1\nscikit-image==0.13.0\nscikit-learn==0.19.1\nmatplotlib==2.2.2\nten"
},
{
"path": "noiseprint/requirements-gpu.txt",
"chars": 166,
"preview": "pillow==4.2.1\nnumpy==1.16.1\npandas==0.20.3\nscipy==0.19.1\nscikit-image==0.13.0\nscikit-learn==0.19.1\nmatplotlib==2.2.2\nten"
},
{
"path": "noiseprint/utility/__init__.py",
"chars": 508,
"preview": "# %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n#\n# Copyright (c) 2016 Image Processing Rese"
},
{
"path": "noiseprint/utility/gaussianMixture.py",
"chars": 13528,
"preview": "# %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n#\n# Copyright (c) 2017 Image Processing Rese"
},
{
"path": "noiseprint/utility/utilityRead.py",
"chars": 5286,
"preview": "# %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n#\n# Copyright (c) 2018 Image Processing Rese"
},
{
"path": "training/LICENSE.txt",
"chars": 578,
"preview": "THIS DOCUMENT CONSTITUTES A LICENCE TO USE THE SOFTWARE ON THE TERMS AND CONDITIONS APPEARING BELOW.\n\n\nPreamble\n\nThis Li"
},
{
"path": "training/README.md",
"chars": 2860,
"preview": "# Noiseprint: a CNN-based camera model fingerprint\n[Noiseprint](https://ieeexplore.ieee.org/document/8713484) is a CNN-b"
},
{
"path": "training/code/FCnet.py",
"chars": 5185,
"preview": "# %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n#\n# Copyright (c) 2020 Image Processing Rese"
},
{
"path": "training/code/Producer2.py",
"chars": 7641,
"preview": "\nclass setWorkers_mock():\n def __init__(self, indexer, pre_fun, app_fun, buffer_size=100, workers=1):\n self._l"
},
{
"path": "training/code/create_data.py",
"chars": 3734,
"preview": "# %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r\n#\r\n# Copyright (c) 2020 Image Processing Re"
},
{
"path": "training/code/db_utility.py",
"chars": 3651,
"preview": "# %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n#\n# Copyright (c) 2020 Image Processing Rese"
},
{
"path": "training/code/train_denoiser.py",
"chars": 11887,
"preview": "# %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n#\n# Copyright (c) 2020 Image Processing Rese"
},
{
"path": "training/code/train_noiseprint.py",
"chars": 12853,
"preview": "# %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n#\n# Copyright (c) 2020 Image Processing Rese"
},
{
"path": "training/code/train_utility.py",
"chars": 7735,
"preview": "# %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n#\n# Copyright (c) 2020 Image Processing Rese"
},
{
"path": "training/dataset/README.txt",
"chars": 1164,
"preview": "This folder contains the list of images used for the training of Noiseprint in the following paper:\n\nD. Cozzolino, F. Ma"
},
{
"path": "training/dataset/download_images.py",
"chars": 1506,
"preview": "# Script in Python 3.x to download the images from dpreview.com\ndb_root = './dpreview.com/' # directory where to "
},
{
"path": "training/dataset/list_images.csv",
"chars": 1328503,
"preview": "id_model;id;make;model;orin;qf;size0;size1\n7322051411;1728161198;Amazon;Fire;-1;95.0;4160;3120\n7322051411;4324171913;Ama"
},
{
"path": "training/dataset/list_models.csv",
"chars": 57038,
"preview": "id;make;model;train;valid;title;numel;size0;size1;qfMin;qfMax\n7322051411;Amazon;Fire;1;0;Amazon Fire Phone Sample Galler"
}
]
// ... and 160 more files (download for full content)
About this extraction
This page contains the full source code of the grip-unina/noiseprint GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 199 files (28.1 MB), approximately 747.5k tokens, and a symbol index with 113 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.