Full Code of grip-unina/noiseprint for AI

master c06034eedc92 cached
199 files
28.1 MB
747.5k tokens
113 symbols
1 requests
Download .txt
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&colon;<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
Download .txt
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
Download .txt
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&colon;<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.

Copied to clipboard!