Browse Source

initial commit

undefined
Rigel Kent 2 weeks ago
commit
39ebd9658d
No known key found for this signature in database GPG Key ID: 5E53E96A494E452F
61 changed files with 28386 additions and 0 deletions
  1. +140
    -0
      .gitignore
  2. +27
    -0
      README.md
  3. +1
    -0
      download_dataset.sh
  4. +609
    -0
      poetry.lock
  5. +25
    -0
      pyproject.toml
  6. +11
    -0
      pytest.ini
  7. +0
    -0
      pyvideohash/__init__.py
  8. +71
    -0
      pyvideohash/cli.py
  9. +6
    -0
      tests/__init__.py
  10. +3
    -0
      tests/conftest.py
  11. +812
    -0
      tests/dataset/GT/GT_1.rst
  12. +305
    -0
      tests/dataset/GT/GT_10.rst
  13. +381
    -0
      tests/dataset/GT/GT_11.rst
  14. +897
    -0
      tests/dataset/GT/GT_12.rst
  15. +419
    -0
      tests/dataset/GT/GT_13.rst
  16. +108
    -0
      tests/dataset/GT/GT_14.rst
  17. +1793
    -0
      tests/dataset/GT/GT_15.rst
  18. +208
    -0
      tests/dataset/GT/GT_16.rst
  19. +657
    -0
      tests/dataset/GT/GT_17.rst
  20. +501
    -0
      tests/dataset/GT/GT_18.rst
  21. +570
    -0
      tests/dataset/GT/GT_19.rst
  22. +594
    -0
      tests/dataset/GT/GT_2.rst
  23. +198
    -0
      tests/dataset/GT/GT_20.rst
  24. +458
    -0
      tests/dataset/GT/GT_21.rst
  25. +428
    -0
      tests/dataset/GT/GT_22.rst
  26. +1352
    -0
      tests/dataset/GT/GT_23.rst
  27. +313
    -0
      tests/dataset/GT/GT_24.rst
  28. +440
    -0
      tests/dataset/GT/GT_3.rst
  29. +353
    -0
      tests/dataset/GT/GT_4.rst
  30. +404
    -0
      tests/dataset/GT/GT_5.rst
  31. +781
    -0
      tests/dataset/GT/GT_6.rst
  32. +365
    -0
      tests/dataset/GT/GT_7.rst
  33. +552
    -0
      tests/dataset/GT/GT_8.rst
  34. +238
    -0
      tests/dataset/GT/GT_9.rst
  35. +50
    -0
      tests/dataset/GT/RANK_1.rst
  36. +50
    -0
      tests/dataset/GT/RANK_10.rst
  37. +48
    -0
      tests/dataset/GT/RANK_11.rst
  38. +51
    -0
      tests/dataset/GT/RANK_12.rst
  39. +28
    -0
      tests/dataset/GT/RANK_13.rst
  40. +28
    -0
      tests/dataset/GT/RANK_14.rst
  41. +50
    -0
      tests/dataset/GT/RANK_15.rst
  42. +51
    -0
      tests/dataset/GT/RANK_16.rst
  43. +50
    -0
      tests/dataset/GT/RANK_17.rst
  44. +55
    -0
      tests/dataset/GT/RANK_18.rst
  45. +50
    -0
      tests/dataset/GT/RANK_19.rst
  46. +51
    -0
      tests/dataset/GT/RANK_2.rst
  47. +50
    -0
      tests/dataset/GT/RANK_20.rst
  48. +50
    -0
      tests/dataset/GT/RANK_21.rst
  49. +51
    -0
      tests/dataset/GT/RANK_22.rst
  50. +50
    -0
      tests/dataset/GT/RANK_23.rst
  51. +50
    -0
      tests/dataset/GT/RANK_24.rst
  52. +49
    -0
      tests/dataset/GT/RANK_3.rst
  53. +51
    -0
      tests/dataset/GT/RANK_4.rst
  54. +50
    -0
      tests/dataset/GT/RANK_5.rst
  55. +51
    -0
      tests/dataset/GT/RANK_6.rst
  56. +51
    -0
      tests/dataset/GT/RANK_7.rst
  57. +50
    -0
      tests/dataset/GT/RANK_8.rst
  58. +50
    -0
      tests/dataset/GT/RANK_9.rst
  59. +24
    -0
      tests/dataset/Seed.txt
  60. +13129
    -0
      tests/dataset/Video_List.txt
  61. +48
    -0
      tests/test_cli.py

+ 140
- 0
.gitignore View File

@@ -0,0 +1,140 @@
tests/dataset/videos/

# 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/
share/python-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/
.nox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*.cover
*.py,cover
.hypothesis/
.pytest_cache/
cover/

# Translations
*.mo
*.pot

# Django stuff:
*.log
local_settings.py
db.sqlite3
db.sqlite3-journal

# Flask stuff:
instance/
.webassets-cache

# Scrapy stuff:
.scrapy

# Sphinx documentation
docs/_build/

# PyBuilder
.pybuilder/
target/

# Jupyter Notebook
.ipynb_checkpoints

# IPython
profile_default/
ipython_config.py

# pyenv
# For a library or package, you might want to ignore these files since the code is
# intended to run in multiple environments; otherwise, check them in:
# .python-version

# pipenv
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
# However, in case of collaboration, if having platform-specific dependencies or dependencies
# having no cross-platform support, pipenv may install dependencies that don't work, or not
# install all needed dependencies.
#Pipfile.lock

# PEP 582; used by e.g. github.com/David-OConnor/pyflow
__pypackages__/

# Celery stuff
celerybeat-schedule
celerybeat.pid

# 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/
.dmypy.json
dmypy.json

# Pyre type checker
.pyre/

# pytype static type analyzer
.pytype/

# Cython debug symbols
cython_debug/

+ 27
- 0
README.md View File

@@ -0,0 +1,27 @@
# pyVideoHash
Perceptual hashing for videos / images

### What does the code do in this state?
It reads in an hardcoded (path set in video_hash.py) media file, calculates a perceptual video-hash (which is quite robust to noise and geometric transformations) and outputs this perceptual-hash with an additional file-hash into an sqlite-database.

The perceptual-hash consists of 144bits for each frame.

### What is needed to run above functionality?
#### Requirements / External libraries to install (tested with Python 2.7.11)
- numpy: various array-stuff
- moviepy: video-reading
- skimage: image-tranformations
- scikit-learn: min-max-scaling
- deltasigma: quantization
- bitstring: bit-arrays
- peewee: database-handling
- cython: acceleration of cumulant-code (cython will compile whole frame_hash.pyx)

#### Database-setup
See peewee-docs.

#### Cython-compilation
This is done automatically when setup.py is run with argument "install"

### Speed:
The code is not very much optimized and is running on one core only. I obtain ~3fps on 720p-h264 (~ 1/10 realtime-processing) which is quite slow.

+ 1
- 0
download_dataset.sh View File

@@ -0,0 +1 @@
cut -d$'\t' -f2,4 tests/dataset/Video_List.txt | awk '{$1=$1;printf "http://vireo.cs.cityu.edu.hk/webvideo/videos/%s/%s\n", $1, $2}' | head -n 24 | wget -N --progress=bar --random-wait -P tests/dataset/videos -i -

+ 609
- 0
poetry.lock View File

@@ -0,0 +1,609 @@
[[package]]
name = "atomicwrites"
version = "1.4.0"
description = "Atomic file writes."
category = "dev"
optional = false
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"

[[package]]
name = "attrs"
version = "20.2.0"
description = "Classes Without Boilerplate"
category = "dev"
optional = false
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"

[package.extras]
dev = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "zope.interface", "sphinx", "sphinx-rtd-theme", "pre-commit"]
docs = ["sphinx", "sphinx-rtd-theme", "zope.interface"]
tests = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "zope.interface"]
tests_no_zope = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six"]

[[package]]
name = "certifi"
version = "2020.6.20"
description = "Python package for providing Mozilla's CA Bundle."
category = "main"
optional = false
python-versions = "*"

[[package]]
name = "chardet"
version = "3.0.4"
description = "Universal encoding detector for Python 2 and 3"
category = "main"
optional = false
python-versions = "*"

[[package]]
name = "click"
version = "7.1.2"
description = "Composable command line interface toolkit"
category = "main"
optional = false
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"

[[package]]
name = "colorama"
version = "0.4.3"
description = "Cross-platform colored terminal text."
category = "dev"
optional = false
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"

[[package]]
name = "decorator"
version = "4.4.2"
description = "Decorators for Humans"
category = "main"
optional = false
python-versions = ">=2.6, !=3.0.*, !=3.1.*"

[[package]]
name = "idna"
version = "2.10"
description = "Internationalized Domain Names in Applications (IDNA)"
category = "main"
optional = false
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"

[[package]]
name = "imagehash"
version = "4.1.0"
description = "Image Hashing library"
category = "main"
optional = false
python-versions = "*"

[package.dependencies]
numpy = "*"
pillow = "*"
PyWavelets = "*"
scipy = "*"
six = "*"

[[package]]
name = "imageio"
version = "2.9.0"
description = "Library for reading and writing a wide range of image, video, scientific, and volumetric data formats."
category = "main"
optional = false
python-versions = ">=3.5"

[package.dependencies]
numpy = "*"
pillow = "*"

[package.extras]
ffmpeg = ["imageio-ffmpeg"]
fits = ["astropy"]
full = ["astropy", "gdal", "imageio-ffmpeg", "itk"]
gdal = ["gdal"]
itk = ["itk"]

[[package]]
name = "imageio-ffmpeg"
version = "0.4.2"
description = "FFMPEG wrapper for Python"
category = "main"
optional = false
python-versions = ">=3.4"

[[package]]
name = "iniconfig"
version = "1.0.1"
description = "iniconfig: brain-dead simple config-ini parsing"
category = "dev"
optional = false
python-versions = "*"

[[package]]
name = "moviepy"
version = "1.0.3"
description = "Video editing with Python"
category = "main"
optional = false
python-versions = "*"

[package.dependencies]
decorator = ">=4.0.2,<5.0"
imageio = {version = ">=2.5,<3.0", markers = "python_version >= \"3.4\""}
imageio_ffmpeg = {version = ">=0.2.0", markers = "python_version >= \"3.4\""}
numpy = [
{version = ">=1.17.3", markers = "python_version != \"2.7\""},
{version = "*", markers = "python_version >= \"2.7\""},
]
proglog = "<=1.0.0"
requests = ">=2.8.1,<3.0"
tqdm = ">=4.11.2,<5.0"

[package.extras]
doc = ["numpydoc (>=0.6.0,<1.0)", "sphinx_rtd_theme (>=0.1.10b0,<1.0)", "Sphinx (>=1.5.2,<2.0)", "pygame (>=1.9.3,<2.0)"]
optional = ["youtube-dl", "opencv-python (>=3.0,<4.0)", "scipy (>=0.19.0,<1.5)", "scikit-image (>=0.13.0,<1.0)", "scikit-learn", "matplotlib (>=2.0.0,<3.0)"]
test = ["coverage (<5.0)", "coveralls (>=1.1,<2.0)", "pytest-cov (>=2.5.1,<3.0)", "pytest (>=3.0.0,<4.0)", "requests (>=2.8.1,<3.0)"]

[[package]]
name = "numpy"
version = "1.19.2"
description = "NumPy is the fundamental package for array computing with Python."
category = "main"
optional = false
python-versions = ">=3.6"

[[package]]
name = "packaging"
version = "20.4"
description = "Core utilities for Python packages"
category = "dev"
optional = false
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"

[package.dependencies]
pyparsing = ">=2.0.2"
six = "*"

[[package]]
name = "pandas"
version = "1.1.3"
description = "Powerful data structures for data analysis, time series, and statistics"
category = "dev"
optional = false
python-versions = ">=3.6.1"

[package.dependencies]
numpy = ">=1.15.4"
python-dateutil = ">=2.7.3"
pytz = ">=2017.2"

[package.extras]
test = ["pytest (>=4.0.2)", "pytest-xdist", "hypothesis (>=3.58)"]

[[package]]
name = "pillow"
version = "7.2.0"
description = "Python Imaging Library (Fork)"
category = "main"
optional = false
python-versions = ">=3.5"

[[package]]
name = "pluggy"
version = "0.13.1"
description = "plugin and hook calling mechanisms for python"
category = "dev"
optional = false
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"

[package.extras]
dev = ["pre-commit", "tox"]

[[package]]
name = "proglog"
version = "0.1.9"
description = "Log and progress bar manager for console, notebooks, web..."
category = "main"
optional = false
python-versions = "*"

[package.dependencies]
tqdm = "*"

[[package]]
name = "py"
version = "1.9.0"
description = "library with cross-python path, ini-parsing, io, code, log facilities"
category = "dev"
optional = false
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"

[[package]]
name = "pyparsing"
version = "2.4.7"
description = "Python parsing module"
category = "dev"
optional = false
python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*"

[[package]]
name = "pytest"
version = "6.1.1"
description = "pytest: simple powerful testing with Python"
category = "dev"
optional = false
python-versions = ">=3.5"

[package.dependencies]
atomicwrites = {version = ">=1.0", markers = "sys_platform == \"win32\""}
attrs = ">=17.4.0"
colorama = {version = "*", markers = "sys_platform == \"win32\""}
iniconfig = "*"
packaging = "*"
pluggy = ">=0.12,<1.0"
py = ">=1.8.2"
toml = "*"

[package.extras]
checkqa_mypy = ["mypy (0.780)"]
testing = ["argcomplete", "hypothesis (>=3.56)", "mock", "nose", "requests", "xmlschema"]

[[package]]
name = "pytest-describe"
version = "1.0.0"
description = "Describe-style plugin for pytest"
category = "dev"
optional = false
python-versions = "*"

[package.dependencies]
pytest = ">=2.6.0"

[[package]]
name = "pytest-expecter"
version = "2.2"
description = "Better testing with expecter and pytest."
category = "dev"
optional = false
python-versions = ">=3.6,<4.0"

[[package]]
name = "python-dateutil"
version = "2.8.1"
description = "Extensions to the standard Python datetime module"
category = "dev"
optional = false
python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7"

[package.dependencies]
six = ">=1.5"

[[package]]
name = "pytz"
version = "2020.1"
description = "World timezone definitions, modern and historical"
category = "dev"
optional = false
python-versions = "*"

[[package]]
name = "pywavelets"
version = "1.1.1"
description = "PyWavelets, wavelet transform module"
category = "main"
optional = false
python-versions = ">=3.5"

[package.dependencies]
numpy = ">=1.13.3"

[[package]]
name = "requests"
version = "2.24.0"
description = "Python HTTP for Humans."
category = "main"
optional = false
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"

[package.dependencies]
certifi = ">=2017.4.17"
chardet = ">=3.0.2,<4"
idna = ">=2.5,<3"
urllib3 = ">=1.21.1,<1.25.0 || >1.25.0,<1.25.1 || >1.25.1,<1.26"

[package.extras]
security = ["pyOpenSSL (>=0.14)", "cryptography (>=1.3.4)"]
socks = ["PySocks (>=1.5.6,<1.5.7 || >1.5.7)", "win-inet-pton"]

[[package]]
name = "scipy"
version = "1.5.2"
description = "SciPy: Scientific Library for Python"
category = "main"
optional = false
python-versions = ">=3.6"

[package.dependencies]
numpy = ">=1.14.5"

[[package]]
name = "six"
version = "1.15.0"
description = "Python 2 and 3 compatibility utilities"
category = "main"
optional = false
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*"

[[package]]
name = "toml"
version = "0.10.1"
description = "Python Library for Tom's Obvious, Minimal Language"
category = "dev"
optional = false
python-versions = "*"

[[package]]
name = "tqdm"
version = "4.50.2"
description = "Fast, Extensible Progress Meter"
category = "main"
optional = false
python-versions = ">=2.6, !=3.0.*, !=3.1.*"

[package.extras]
dev = ["py-make (>=0.1.0)", "twine", "argopt", "pydoc-markdown"]

[[package]]
name = "urllib3"
version = "1.25.10"
description = "HTTP library with thread-safe connection pooling, file post, and more."
category = "main"
optional = false
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, <4"

[package.extras]
brotli = ["brotlipy (>=0.6.0)"]
secure = ["certifi", "cryptography (>=1.3.4)", "idna (>=2.0.0)", "pyOpenSSL (>=0.14)", "ipaddress"]
socks = ["PySocks (>=1.5.6,<1.5.7 || >1.5.7,<2.0)"]

[metadata]
lock-version = "1.1"
python-versions = "^3.8"
content-hash = "162eb926e3f5a7ac04e5efa30b805a9b618fd180039290622ac168b187842d1c"

[metadata.files]
atomicwrites = [
{file = "atomicwrites-1.4.0-py2.py3-none-any.whl", hash = "sha256:6d1784dea7c0c8d4a5172b6c620f40b6e4cbfdf96d783691f2e1302a7b88e197"},
{file = "atomicwrites-1.4.0.tar.gz", hash = "sha256:ae70396ad1a434f9c7046fd2dd196fc04b12f9e91ffb859164193be8b6168a7a"},
]
attrs = [
{file = "attrs-20.2.0-py2.py3-none-any.whl", hash = "sha256:fce7fc47dfc976152e82d53ff92fa0407700c21acd20886a13777a0d20e655dc"},
{file = "attrs-20.2.0.tar.gz", hash = "sha256:26b54ddbbb9ee1d34d5d3668dd37d6cf74990ab23c828c2888dccdceee395594"},
]
certifi = [
{file = "certifi-2020.6.20-py2.py3-none-any.whl", hash = "sha256:8fc0819f1f30ba15bdb34cceffb9ef04d99f420f68eb75d901e9560b8749fc41"},
{file = "certifi-2020.6.20.tar.gz", hash = "sha256:5930595817496dd21bb8dc35dad090f1c2cd0adfaf21204bf6732ca5d8ee34d3"},
]
chardet = [
{file = "chardet-3.0.4-py2.py3-none-any.whl", hash = "sha256:fc323ffcaeaed0e0a02bf4d117757b98aed530d9ed4531e3e15460124c106691"},
{file = "chardet-3.0.4.tar.gz", hash = "sha256:84ab92ed1c4d4f16916e05906b6b75a6c0fb5db821cc65e70cbd64a3e2a5eaae"},
]
click = [
{file = "click-7.1.2-py2.py3-none-any.whl", hash = "sha256:dacca89f4bfadd5de3d7489b7c8a566eee0d3676333fbb50030263894c38c0dc"},
{file = "click-7.1.2.tar.gz", hash = "sha256:d2b5255c7c6349bc1bd1e59e08cd12acbbd63ce649f2588755783aa94dfb6b1a"},
]
colorama = [
{file = "colorama-0.4.3-py2.py3-none-any.whl", hash = "sha256:7d73d2a99753107a36ac6b455ee49046802e59d9d076ef8e47b61499fa29afff"},
{file = "colorama-0.4.3.tar.gz", hash = "sha256:e96da0d330793e2cb9485e9ddfd918d456036c7149416295932478192f4436a1"},
]
decorator = [
{file = "decorator-4.4.2-py2.py3-none-any.whl", hash = "sha256:41fa54c2a0cc4ba648be4fd43cff00aedf5b9465c9bf18d64325bc225f08f760"},
{file = "decorator-4.4.2.tar.gz", hash = "sha256:e3a62f0520172440ca0dcc823749319382e377f37f140a0b99ef45fecb84bfe7"},
]
idna = [
{file = "idna-2.10-py2.py3-none-any.whl", hash = "sha256:b97d804b1e9b523befed77c48dacec60e6dcb0b5391d57af6a65a312a90648c0"},
{file = "idna-2.10.tar.gz", hash = "sha256:b307872f855b18632ce0c21c5e45be78c0ea7ae4c15c828c20788b26921eb3f6"},
]
imagehash = [
{file = "ImageHash-4.1.0.tar.gz", hash = "sha256:978e25d3df66ae8fa4fb24542e46cea6d0724f02c0c760b2de4931a54d5c7482"},
]
imageio = [
{file = "imageio-2.9.0-py3-none-any.whl", hash = "sha256:3604d751f03002e8e0e7650aa71d8d9148144a87daf17cb1f3228e80747f2e6b"},
{file = "imageio-2.9.0.tar.gz", hash = "sha256:52ddbaeca2dccf53ba2d6dec5676ca7bc3b2403ef8b37f7da78b7654bb3e10f0"},
]
imageio-ffmpeg = [
{file = "imageio-ffmpeg-0.4.2.tar.gz", hash = "sha256:13b05b17a941a9f4a90b16910b1ffac159448cff051a153da8ba4b4343ffa195"},
{file = "imageio_ffmpeg-0.4.2-py3-none-macosx_10_9_intel.macosx_10_9_x86_64.macosx_10_10_intel.macosx_10_10_x86_64.whl", hash = "sha256:4aaa9cbd1e536143379ae474323d80f4c4a693fff0b023bab440ea5913db00ac"},
{file = "imageio_ffmpeg-0.4.2-py3-none-manylinux2010_x86_64.whl", hash = "sha256:6ec658144ddfa0b25de5f82671729734a54cdf999ddd69a134999fe6a413f3e7"},
{file = "imageio_ffmpeg-0.4.2-py3-none-win32.whl", hash = "sha256:596f9d1516972d9723c5bc6eb1849a29e3989a8cd20834b261a8c80fd9f8f6f5"},
{file = "imageio_ffmpeg-0.4.2-py3-none-win_amd64.whl", hash = "sha256:8cd09469ae25d8a7083ee4033a43827aadacabebc47a87432222034d2c97e542"},
]
iniconfig = [
{file = "iniconfig-1.0.1-py3-none-any.whl", hash = "sha256:80cf40c597eb564e86346103f609d74efce0f6b4d4f30ec8ce9e2c26411ba437"},
{file = "iniconfig-1.0.1.tar.gz", hash = "sha256:e5f92f89355a67de0595932a6c6c02ab4afddc6fcdc0bfc5becd0d60884d3f69"},
]
moviepy = [
{file = "moviepy-1.0.3.tar.gz", hash = "sha256:2884e35d1788077db3ff89e763c5ba7bfddbd7ae9108c9bc809e7ba58fa433f5"},
]
numpy = [
{file = "numpy-1.19.2-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:b594f76771bc7fc8a044c5ba303427ee67c17a09b36e1fa32bde82f5c419d17a"},
{file = "numpy-1.19.2-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:e6ddbdc5113628f15de7e4911c02aed74a4ccff531842c583e5032f6e5a179bd"},
{file = "numpy-1.19.2-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:3733640466733441295b0d6d3dcbf8e1ffa7e897d4d82903169529fd3386919a"},
{file = "numpy-1.19.2-cp36-cp36m-manylinux2010_i686.whl", hash = "sha256:4339741994c775396e1a274dba3609c69ab0f16056c1077f18979bec2a2c2e6e"},
{file = "numpy-1.19.2-cp36-cp36m-manylinux2010_x86_64.whl", hash = "sha256:7c6646314291d8f5ea900a7ea9c4261f834b5b62159ba2abe3836f4fa6705526"},
{file = "numpy-1.19.2-cp36-cp36m-manylinux2014_aarch64.whl", hash = "sha256:7118f0a9f2f617f921ec7d278d981244ba83c85eea197be7c5a4f84af80a9c3c"},
{file = "numpy-1.19.2-cp36-cp36m-win32.whl", hash = "sha256:9a3001248b9231ed73894c773142658bab914645261275f675d86c290c37f66d"},
{file = "numpy-1.19.2-cp36-cp36m-win_amd64.whl", hash = "sha256:967c92435f0b3ba37a4257c48b8715b76741410467e2bdb1097e8391fccfae15"},
{file = "numpy-1.19.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:d526fa58ae4aead839161535d59ea9565863bb0b0bdb3cc63214613fb16aced4"},
{file = "numpy-1.19.2-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:eb25c381d168daf351147713f49c626030dcff7a393d5caa62515d415a6071d8"},
{file = "numpy-1.19.2-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:62139af94728d22350a571b7c82795b9d59be77fc162414ada6c8b6a10ef5d02"},
{file = "numpy-1.19.2-cp37-cp37m-manylinux2010_i686.whl", hash = "sha256:0c66da1d202c52051625e55a249da35b31f65a81cb56e4c69af0dfb8fb0125bf"},
{file = "numpy-1.19.2-cp37-cp37m-manylinux2010_x86_64.whl", hash = "sha256:2117536e968abb7357d34d754e3733b0d7113d4c9f1d921f21a3d96dec5ff716"},
{file = "numpy-1.19.2-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:54045b198aebf41bf6bf4088012777c1d11703bf74461d70cd350c0af2182e45"},
{file = "numpy-1.19.2-cp37-cp37m-win32.whl", hash = "sha256:aba1d5daf1144b956bc87ffb87966791f5e9f3e1f6fab3d7f581db1f5b598f7a"},
{file = "numpy-1.19.2-cp37-cp37m-win_amd64.whl", hash = "sha256:addaa551b298052c16885fc70408d3848d4e2e7352de4e7a1e13e691abc734c1"},
{file = "numpy-1.19.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:58d66a6b3b55178a1f8a5fe98df26ace76260a70de694d99577ddeab7eaa9a9d"},
{file = "numpy-1.19.2-cp38-cp38-manylinux1_i686.whl", hash = "sha256:59f3d687faea7a4f7f93bd9665e5b102f32f3fa28514f15b126f099b7997203d"},
{file = "numpy-1.19.2-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:cebd4f4e64cfe87f2039e4725781f6326a61f095bc77b3716502bed812b385a9"},
{file = "numpy-1.19.2-cp38-cp38-manylinux2010_i686.whl", hash = "sha256:c35a01777f81e7333bcf276b605f39c872e28295441c265cd0c860f4b40148c1"},
{file = "numpy-1.19.2-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:d7ac33585e1f09e7345aa902c281bd777fdb792432d27fca857f39b70e5dd31c"},
{file = "numpy-1.19.2-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:04c7d4ebc5ff93d9822075ddb1751ff392a4375e5885299445fcebf877f179d5"},
{file = "numpy-1.19.2-cp38-cp38-win32.whl", hash = "sha256:51ee93e1fac3fe08ef54ff1c7f329db64d8a9c5557e6c8e908be9497ac76374b"},
{file = "numpy-1.19.2-cp38-cp38-win_amd64.whl", hash = "sha256:1669ec8e42f169ff715a904c9b2105b6640f3f2a4c4c2cb4920ae8b2785dac65"},
{file = "numpy-1.19.2-pp36-pypy36_pp73-manylinux2010_x86_64.whl", hash = "sha256:0bfd85053d1e9f60234f28f63d4a5147ada7f432943c113a11afcf3e65d9d4c8"},
{file = "numpy-1.19.2.zip", hash = "sha256:0d310730e1e793527065ad7dde736197b705d0e4c9999775f212b03c44a8484c"},
]
packaging = [
{file = "packaging-20.4-py2.py3-none-any.whl", hash = "sha256:998416ba6962ae7fbd6596850b80e17859a5753ba17c32284f67bfff33784181"},
{file = "packaging-20.4.tar.gz", hash = "sha256:4357f74f47b9c12db93624a82154e9b120fa8293699949152b22065d556079f8"},
]
pandas = [
{file = "pandas-1.1.3-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:882012763668af54b48f1412bab95c5cc0a7ccce5a2a8221cfc3839a6e3394ef"},
{file = "pandas-1.1.3-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:206d7c3e5356dcadf082e64dc25c24bc8541718045826074f96346e9d6d05a20"},
{file = "pandas-1.1.3-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:ca31ac8578d48da354cf66a473d4d5ff99277ca71d321dc7ea4e6fad3c6bb0fd"},
{file = "pandas-1.1.3-cp36-cp36m-manylinux2014_aarch64.whl", hash = "sha256:fd6f05b6101d0e76f3e5c26a47be5be7be96ed84ef3981dc1852e76898e73594"},
{file = "pandas-1.1.3-cp36-cp36m-win32.whl", hash = "sha256:ca71a5aa9eeb3ef5b31feca7d9b6369d6b3d0b2e9c85d7a89abe3ecb013f1e86"},
{file = "pandas-1.1.3-cp36-cp36m-win_amd64.whl", hash = "sha256:54f5f564058b0280d588c3758abde82e280702c440db5faf0c686b80336096f9"},
{file = "pandas-1.1.3-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:3a038cd5da602b955d335aa80cbaa0e5774f68501ff47b9c21509906981478da"},
{file = "pandas-1.1.3-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:24f61f40febe47edac271eda45d683e42838b7db2bd0f82574d9800259d2b182"},
{file = "pandas-1.1.3-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:427be9938b2f79ab298de84f87693914cda238a27cf10580da96caf3dff64115"},
{file = "pandas-1.1.3-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:5a8a84b75ca3a29bb4263b35d5ed9fcaae2b062f014feed8c5daa897339c7d85"},
{file = "pandas-1.1.3-cp37-cp37m-win32.whl", hash = "sha256:c22e40f1b4d162ca18eb6b2c572e63eef220dbc9cc3de0241cefb77972621bb7"},
{file = "pandas-1.1.3-cp37-cp37m-win_amd64.whl", hash = "sha256:920d30fdff65a079f071db635d282b4f583c2b26f2b58d5dca218aac7c59974d"},
{file = "pandas-1.1.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:d6b1f9d506dc23da2915bcae5c5968990049c9cec44108bd9855d2c7c89d91dc"},
{file = "pandas-1.1.3-cp38-cp38-manylinux1_i686.whl", hash = "sha256:b11b496c317dbe007898de699fd59eaf687d0fe8c1b7dad109db6010155d28ae"},
{file = "pandas-1.1.3-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:d89dbc58aec1544722a8d5046f880b597c497ef8a82c5fe695b4b2effafac5ec"},
{file = "pandas-1.1.3-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:df43ea0e9fd9f9672b0de9cac26d01255ad50481994bf3cb4687c21eec2d7bbc"},
{file = "pandas-1.1.3-cp38-cp38-win32.whl", hash = "sha256:a605054fbca71ed1d08bb2aef6f73c84a579bbac956bfe8f9718d5e84cb41248"},
{file = "pandas-1.1.3-cp38-cp38-win_amd64.whl", hash = "sha256:84a4ffe668df357e31f98c829536e3a7142c3036c82f996e639f644c5d32eda1"},
{file = "pandas-1.1.3.tar.gz", hash = "sha256:babbeda2f83b0686c9ad38d93b10516e68cdcd5771007eb80a763e98aaf44613"},
]
pillow = [
{file = "Pillow-7.2.0-cp35-cp35m-macosx_10_10_intel.whl", hash = "sha256:1ca594126d3c4def54babee699c055a913efb01e106c309fa6b04405d474d5ae"},
{file = "Pillow-7.2.0-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:c92302a33138409e8f1ad16731568c55c9053eee71bb05b6b744067e1b62380f"},
{file = "Pillow-7.2.0-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:8dad18b69f710bf3a001d2bf3afab7c432785d94fcf819c16b5207b1cfd17d38"},
{file = "Pillow-7.2.0-cp35-cp35m-manylinux2014_aarch64.whl", hash = "sha256:431b15cffbf949e89df2f7b48528be18b78bfa5177cb3036284a5508159492b5"},
{file = "Pillow-7.2.0-cp35-cp35m-win32.whl", hash = "sha256:09d7f9e64289cb40c2c8d7ad674b2ed6105f55dc3b09aa8e4918e20a0311e7ad"},
{file = "Pillow-7.2.0-cp35-cp35m-win_amd64.whl", hash = "sha256:0295442429645fa16d05bd567ef5cff178482439c9aad0411d3f0ce9b88b3a6f"},
{file = "Pillow-7.2.0-cp36-cp36m-macosx_10_10_x86_64.whl", hash = "sha256:ec29604081f10f16a7aea809ad42e27764188fc258b02259a03a8ff7ded3808d"},
{file = "Pillow-7.2.0-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:612cfda94e9c8346f239bf1a4b082fdd5c8143cf82d685ba2dba76e7adeeb233"},
{file = "Pillow-7.2.0-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:0a80dd307a5d8440b0a08bd7b81617e04d870e40a3e46a32d9c246e54705e86f"},
{file = "Pillow-7.2.0-cp36-cp36m-manylinux2014_aarch64.whl", hash = "sha256:06aba4169e78c439d528fdeb34762c3b61a70813527a2c57f0540541e9f433a8"},
{file = "Pillow-7.2.0-cp36-cp36m-win32.whl", hash = "sha256:f7e30c27477dffc3e85c2463b3e649f751789e0f6c8456099eea7ddd53be4a8a"},
{file = "Pillow-7.2.0-cp36-cp36m-win_amd64.whl", hash = "sha256:ffe538682dc19cc542ae7c3e504fdf54ca7f86fb8a135e59dd6bc8627eae6cce"},
{file = "Pillow-7.2.0-cp37-cp37m-macosx_10_10_x86_64.whl", hash = "sha256:94cf49723928eb6070a892cb39d6c156f7b5a2db4e8971cb958f7b6b104fb4c4"},
{file = "Pillow-7.2.0-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:6edb5446f44d901e8683ffb25ebdfc26988ee813da3bf91e12252b57ac163727"},
{file = "Pillow-7.2.0-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:52125833b070791fcb5710fabc640fc1df07d087fc0c0f02d3661f76c23c5b8b"},
{file = "Pillow-7.2.0-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:9ad7f865eebde135d526bb3163d0b23ffff365cf87e767c649550964ad72785d"},
{file = "Pillow-7.2.0-cp37-cp37m-win32.whl", hash = "sha256:c79f9c5fb846285f943aafeafda3358992d64f0ef58566e23484132ecd8d7d63"},
{file = "Pillow-7.2.0-cp37-cp37m-win_amd64.whl", hash = "sha256:d350f0f2c2421e65fbc62690f26b59b0bcda1b614beb318c81e38647e0f673a1"},
{file = "Pillow-7.2.0-cp38-cp38-macosx_10_10_x86_64.whl", hash = "sha256:6d7741e65835716ceea0fd13a7d0192961212fd59e741a46bbed7a473c634ed6"},
{file = "Pillow-7.2.0-cp38-cp38-manylinux1_i686.whl", hash = "sha256:edf31f1150778abd4322444c393ab9c7bd2af271dd4dafb4208fb613b1f3cdc9"},
{file = "Pillow-7.2.0-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:d08b23fdb388c0715990cbc06866db554e1822c4bdcf6d4166cf30ac82df8c41"},
{file = "Pillow-7.2.0-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:5e51ee2b8114def244384eda1c82b10e307ad9778dac5c83fb0943775a653cd8"},
{file = "Pillow-7.2.0-cp38-cp38-win32.whl", hash = "sha256:725aa6cfc66ce2857d585f06e9519a1cc0ef6d13f186ff3447ab6dff0a09bc7f"},
{file = "Pillow-7.2.0-cp38-cp38-win_amd64.whl", hash = "sha256:a060cf8aa332052df2158e5a119303965be92c3da6f2d93b6878f0ebca80b2f6"},
{file = "Pillow-7.2.0-pp36-pypy36_pp73-macosx_10_10_x86_64.whl", hash = "sha256:9c87ef410a58dd54b92424ffd7e28fd2ec65d2f7fc02b76f5e9b2067e355ebf6"},
{file = "Pillow-7.2.0-pp36-pypy36_pp73-manylinux2010_x86_64.whl", hash = "sha256:e901964262a56d9ea3c2693df68bc9860b8bdda2b04768821e4c44ae797de117"},
{file = "Pillow-7.2.0-pp36-pypy36_pp73-win32.whl", hash = "sha256:25930fadde8019f374400f7986e8404c8b781ce519da27792cbe46eabec00c4d"},
{file = "Pillow-7.2.0.tar.gz", hash = "sha256:97f9e7953a77d5a70f49b9a48da7776dc51e9b738151b22dacf101641594a626"},
]
pluggy = [
{file = "pluggy-0.13.1-py2.py3-none-any.whl", hash = "sha256:966c145cd83c96502c3c3868f50408687b38434af77734af1e9ca461a4081d2d"},
{file = "pluggy-0.13.1.tar.gz", hash = "sha256:15b2acde666561e1298d71b523007ed7364de07029219b604cf808bfa1c765b0"},
]
proglog = [
{file = "proglog-0.1.9.tar.gz", hash = "sha256:d8c4ccbf2138e0c5e3f3fc0d80dc51d7e69dcfe8bfde4cacb566725092a5b18d"},
]
py = [
{file = "py-1.9.0-py2.py3-none-any.whl", hash = "sha256:366389d1db726cd2fcfc79732e75410e5fe4d31db13692115529d34069a043c2"},
{file = "py-1.9.0.tar.gz", hash = "sha256:9ca6883ce56b4e8da7e79ac18787889fa5206c79dcc67fb065376cd2fe03f342"},
]
pyparsing = [
{file = "pyparsing-2.4.7-py2.py3-none-any.whl", hash = "sha256:ef9d7589ef3c200abe66653d3f1ab1033c3c419ae9b9bdb1240a85b024efc88b"},
{file = "pyparsing-2.4.7.tar.gz", hash = "sha256:c203ec8783bf771a155b207279b9bccb8dea02d8f0c9e5f8ead507bc3246ecc1"},
]
pytest = [
{file = "pytest-6.1.1-py3-none-any.whl", hash = "sha256:7a8190790c17d79a11f847fba0b004ee9a8122582ebff4729a082c109e81a4c9"},
{file = "pytest-6.1.1.tar.gz", hash = "sha256:8f593023c1a0f916110285b6efd7f99db07d59546e3d8c36fc60e2ab05d3be92"},
]
pytest-describe = [
{file = "pytest-describe-1.0.0.tar.gz", hash = "sha256:3e2ea0e77efa09edb98cf90423bf1da21a462ed90bd3120f8f98fe7519a167d5"},
{file = "pytest_describe-1.0.0-py2-none-any.whl", hash = "sha256:cc3862662faa5a6fb721927aaef46b46cf787e4a8163e5459fc8778e650fabad"},
{file = "pytest_describe-1.0.0-py3-none-any.whl", hash = "sha256:95fe78639d4d16c4a1e7d62c70f63030b217c08d2ee6dca49559fe6e730c6696"},
]
pytest-expecter = [
{file = "pytest-expecter-2.2.tar.gz", hash = "sha256:33c5b05008cad9b95ba0deb0a5bac6a51c68ae94f09de74a19cd1384a04c85d6"},
{file = "pytest_expecter-2.2-py3-none-any.whl", hash = "sha256:15dd0485c23fd03b7a9c0f6819f0cf65c0defd0ce9796725ae51e79e56b279ab"},
]
python-dateutil = [
{file = "python-dateutil-2.8.1.tar.gz", hash = "sha256:73ebfe9dbf22e832286dafa60473e4cd239f8592f699aa5adaf10050e6e1823c"},
{file = "python_dateutil-2.8.1-py2.py3-none-any.whl", hash = "sha256:75bb3f31ea686f1197762692a9ee6a7550b59fc6ca3a1f4b5d7e32fb98e2da2a"},
]
pytz = [
{file = "pytz-2020.1-py2.py3-none-any.whl", hash = "sha256:a494d53b6d39c3c6e44c3bec237336e14305e4f29bbf800b599253057fbb79ed"},
{file = "pytz-2020.1.tar.gz", hash = "sha256:c35965d010ce31b23eeb663ed3cc8c906275d6be1a34393a1d73a41febf4a048"},
]
pywavelets = [
{file = "PyWavelets-1.1.1-cp35-cp35m-macosx_10_6_intel.whl", hash = "sha256:35959c041ec014648575085a97b498eafbbaa824f86f6e4a59bfdef8a3fe6308"},
{file = "PyWavelets-1.1.1-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:55e39ec848ceec13c9fa1598253ae9dd5c31d09dfd48059462860d2b908fb224"},
{file = "PyWavelets-1.1.1-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:c06d2e340c7bf8b9ec71da2284beab8519a3908eab031f4ea126e8ccfc3fd567"},
{file = "PyWavelets-1.1.1-cp35-cp35m-win32.whl", hash = "sha256:be105382961745f88d8196bba5a69ee2c4455d87ad2a2e5d1eed6bd7fda4d3fd"},
{file = "PyWavelets-1.1.1-cp35-cp35m-win_amd64.whl", hash = "sha256:076ca8907001fdfe4205484f719d12b4a0262dfe6652fa1cfc3c5c362d14dc84"},
{file = "PyWavelets-1.1.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:7947e51ca05489b85928af52a34fe67022ab5b81d4ae32a4109a99e883a0635e"},
{file = "PyWavelets-1.1.1-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:9e2528823ccf5a0a1d23262dfefe5034dce89cd84e4e124dc553dfcdf63ebb92"},
{file = "PyWavelets-1.1.1-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:80b924edbc012ded8aa8b91cb2fd6207fb1a9a3a377beb4049b8a07445cec6f0"},
{file = "PyWavelets-1.1.1-cp36-cp36m-manylinux2014_aarch64.whl", hash = "sha256:c2a799e79cee81a862216c47e5623c97b95f1abee8dd1f9eed736df23fb653fb"},
{file = "PyWavelets-1.1.1-cp36-cp36m-win32.whl", hash = "sha256:d510aef84d9852653d079c84f2f81a82d5d09815e625f35c95714e7364570ad4"},
{file = "PyWavelets-1.1.1-cp36-cp36m-win_amd64.whl", hash = "sha256:889d4c5c5205a9c90118c1980df526857929841df33e4cd1ff1eff77c6817a65"},
{file = "PyWavelets-1.1.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:68b5c33741d26c827074b3d8f0251de1c3019bb9567b8d303eb093c822ce28f1"},
{file = "PyWavelets-1.1.1-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:18a51b3f9416a2ae6e9a35c4af32cf520dd7895f2b69714f4aa2f4342fca47f9"},
{file = "PyWavelets-1.1.1-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:cfe79844526dd92e3ecc9490b5031fca5f8ab607e1e858feba232b1b788ff0ea"},
{file = "PyWavelets-1.1.1-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:2f7429eeb5bf9c7068002d0d7f094ed654c77a70ce5e6198737fd68ab85f8311"},
{file = "PyWavelets-1.1.1-cp37-cp37m-win32.whl", hash = "sha256:720dbcdd3d91c6dfead79c80bf8b00a1d8aa4e5d551dc528c6d5151e4efc3403"},
{file = "PyWavelets-1.1.1-cp37-cp37m-win_amd64.whl", hash = "sha256:bc5e87b72371da87c9bebc68e54882aada9c3114e640de180f62d5da95749cd3"},
{file = "PyWavelets-1.1.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:98b2669c5af842a70cfab33a7043fcb5e7535a690a00cd251b44c9be0be418e5"},
{file = "PyWavelets-1.1.1-cp38-cp38-manylinux1_i686.whl", hash = "sha256:e02a0558e0c2ac8b8bbe6a6ac18c136767ec56b96a321e0dfde2173adfa5a504"},
{file = "PyWavelets-1.1.1-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:6162dc0ae04669ea04b4b51420777b9ea2d30b0a9d02901b2a3b4d61d159c2e9"},
{file = "PyWavelets-1.1.1-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:39c74740718e420d38c78ca4498568fa57976d78d5096277358e0fa9629a7aea"},
{file = "PyWavelets-1.1.1-cp38-cp38-win32.whl", hash = "sha256:79f5b54f9dc353e5ee47f0c3f02bebd2c899d49780633aa771fed43fa20b3149"},
{file = "PyWavelets-1.1.1-cp38-cp38-win_amd64.whl", hash = "sha256:935ff247b8b78bdf77647fee962b1cc208c51a7b229db30b9ba5f6da3e675178"},
{file = "PyWavelets-1.1.1.tar.gz", hash = "sha256:1a64b40f6acb4ffbaccce0545d7fc641744f95351f62e4c6aaa40549326008c9"},
]
requests = [
{file = "requests-2.24.0-py2.py3-none-any.whl", hash = "sha256:fe75cc94a9443b9246fc7049224f75604b113c36acb93f87b80ed42c44cbb898"},
{file = "requests-2.24.0.tar.gz", hash = "sha256:b3559a131db72c33ee969480840fff4bb6dd111de7dd27c8ee1f820f4f00231b"},
]
scipy = [
{file = "scipy-1.5.2-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:cca9fce15109a36a0a9f9cfc64f870f1c140cb235ddf27fe0328e6afb44dfed0"},
{file = "scipy-1.5.2-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:1c7564a4810c1cd77fcdee7fa726d7d39d4e2695ad252d7c86c3ea9d85b7fb8f"},
{file = "scipy-1.5.2-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:07e52b316b40a4f001667d1ad4eb5f2318738de34597bd91537851365b6c61f1"},
{file = "scipy-1.5.2-cp36-cp36m-win32.whl", hash = "sha256:d56b10d8ed72ec1be76bf10508446df60954f08a41c2d40778bc29a3a9ad9bce"},
{file = "scipy-1.5.2-cp36-cp36m-win_amd64.whl", hash = "sha256:8e28e74b97fc8d6aa0454989db3b5d36fc27e69cef39a7ee5eaf8174ca1123cb"},
{file = "scipy-1.5.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:6e86c873fe1335d88b7a4bfa09d021f27a9e753758fd75f3f92d714aa4093768"},
{file = "scipy-1.5.2-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:a0afbb967fd2c98efad5f4c24439a640d39463282040a88e8e928db647d8ac3d"},
{file = "scipy-1.5.2-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:eecf40fa87eeda53e8e11d265ff2254729d04000cd40bae648e76ff268885d66"},
{file = "scipy-1.5.2-cp37-cp37m-win32.whl", hash = "sha256:315aa2165aca31375f4e26c230188db192ed901761390be908c9b21d8b07df62"},
{file = "scipy-1.5.2-cp37-cp37m-win_amd64.whl", hash = "sha256:ec5fe57e46828d034775b00cd625c4a7b5c7d2e354c3b258d820c6c72212a6ec"},
{file = "scipy-1.5.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:fc98f3eac993b9bfdd392e675dfe19850cc8c7246a8fd2b42443e506344be7d9"},
{file = "scipy-1.5.2-cp38-cp38-manylinux1_i686.whl", hash = "sha256:a785409c0fa51764766840185a34f96a0a93527a0ff0230484d33a8ed085c8f8"},
{file = "scipy-1.5.2-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:0a0e9a4e58a4734c2eba917f834b25b7e3b6dc333901ce7784fd31aefbd37b2f"},
{file = "scipy-1.5.2-cp38-cp38-win32.whl", hash = "sha256:dac09281a0eacd59974e24525a3bc90fa39b4e95177e638a31b14db60d3fa806"},
{file = "scipy-1.5.2-cp38-cp38-win_amd64.whl", hash = "sha256:92eb04041d371fea828858e4fff182453c25ae3eaa8782d9b6c32b25857d23bc"},
{file = "scipy-1.5.2.tar.gz", hash = "sha256:066c513d90eb3fd7567a9e150828d39111ebd88d3e924cdfc9f8ce19ab6f90c9"},
]
six = [
{file = "six-1.15.0-py2.py3-none-any.whl", hash = "sha256:8b74bedcbbbaca38ff6d7491d76f2b06b3592611af620f8426e82dddb04a5ced"},
{file = "six-1.15.0.tar.gz", hash = "sha256:30639c035cdb23534cd4aa2dd52c3bf48f06e5f4a941509c8bafd8ce11080259"},
]
toml = [
{file = "toml-0.10.1-py2.py3-none-any.whl", hash = "sha256:bda89d5935c2eac546d648028b9901107a595863cb36bae0c73ac804a9b4ce88"},
{file = "toml-0.10.1.tar.gz", hash = "sha256:926b612be1e5ce0634a2ca03470f95169cf16f939018233a670519cb4ac58b0f"},
]
tqdm = [
{file = "tqdm-4.50.2-py2.py3-none-any.whl", hash = "sha256:43ca183da3367578ebf2f1c2e3111d51ea161ed1dc4e6345b86e27c2a93beff7"},
{file = "tqdm-4.50.2.tar.gz", hash = "sha256:69dfa6714dee976e2425a9aab84b622675b7b1742873041e3db8a8e86132a4af"},
]
urllib3 = [
{file = "urllib3-1.25.10-py2.py3-none-any.whl", hash = "sha256:e7983572181f5e1522d9c98453462384ee92a0be7fac5f1413a1e35c56cc0461"},
{file = "urllib3-1.25.10.tar.gz", hash = "sha256:91056c15fa70756691db97756772bb1eb9678fa585d9184f24534b100dc60f4a"},
]

+ 25
- 0
pyproject.toml View File

@@ -0,0 +1,25 @@
[tool.poetry]
name = "pyvideohash"
version = "0.1.0"
description = ""
authors = ["Rigel Kent <sendmemail@rigelk.eu>"]
license = "MIT"

[tool.poetry.dependencies]
python = "^3.8"
moviepy = "^1.0.3"
ImageHash = "^4.1.0"
click = "^7.1.2"

[tool.poetry.dev-dependencies]
pytest = "^6.1.1"
pytest-expecter = "^2.2"
pytest-describe = "^1.0.0"
pandas = "^1.1.3"

[tool.poetry.scripts]
pyvideohash = 'pyvideohash.cli:main'

[build-system]
requires = ["poetry-core>=1.0.0"]
build-backend = "poetry.core.masonry.api"

+ 11
- 0
pytest.ini View File

@@ -0,0 +1,11 @@
[pytest]

addopts =
--strict
--pdbcls=tests:Debugger

-r sxX

cache_dir = .cache

markers =

+ 0
- 0
pyvideohash/__init__.py View File


+ 71
- 0
pyvideohash/cli.py View File

@@ -0,0 +1,71 @@
import sys
import click
import hashlib
import imagehash
import numpy as np
from moviepy.editor import VideoFileClip
from PIL import Image
def generate_file_sha256(filename, blocksize=2**20):
m = hashlib.sha256()
with open(filename, "rb") as f:
while True:
buf = f.read(blocksize)
if not buf:
break
m.update(buf)
return m.hexdigest()
def hash_frame(frame):
pil_frame = Image.fromarray(np.uint8(frame)).convert('RGB')
return imagehash.whash(pil_frame)
@click.command()
@click.argument('original_files', nargs=-1, type=click.Path(exists=True, readable=True, file_okay=True, resolve_path=True))
@click.argument('new_file', nargs=1, type=click.Path(exists=True, readable=True, file_okay=True, resolve_path=True))
@click.option('use_stdout', '--silent', is_flag=True, default=True)
@click.option('--no-progressbar', is_flag=True, default=False)
def main(
original_files,
new_file,
use_stdout=False,
no_progressbar=False,
fps=1.0, # take one frame per second
up_to=5 / 100 # up to 5% of hash can be different btw two similar images / anything higher will prove videos to be different
):
"""Perceptual comparison of two videos, with potential resolutions"""
logger = "bar" if use_stdout and not no_progressbar else None
def hash_values_of(filepath):
clip = VideoFileClip(filepath)
return [hash_frame(f) for f in clip.iter_frames(fps, dtype=float, logger=logger)]
if generate_file_sha256(new_file) in [generate_file_sha256(f) for f in original_files]:
sys.exit(0)
new_file_hashes = hash_values_of(new_file)
differences = []
for file_hashes in [hash_values_of(f) for f in original_files]:
if len(file_hashes) is not len(new_file_hashes):
# video is not of same length, video is probably radically different
pass
#sys.exit(1)
max_diff_local = 0
for file_hash, new_file_hash in zip(file_hashes, new_file_hashes):
max_diff_local = max(file_hash - new_file_hash, max_diff_local)
differences.append(max_diff_local)
ratio = min(differences)/len(new_file_hashes[0].hash)**2
if use_stdout:
print(ratio)
sys.exit(0)
if __name__ == '__main__':
main(original_files, new_file, use_stdout=True)

+ 6
- 0
tests/__init__.py View File

@@ -0,0 +1,6 @@
"""Integration tests for the package."""

try:
from IPython.terminal.debugger import TerminalPdb as Debugger
except ImportError:
from pdb import Pdb as Debugger # type: ignore

+ 3
- 0
tests/conftest.py View File

@@ -0,0 +1,3 @@
"""Integration tests configuration file."""

# pylint: disable=unused-import

+ 812
- 0
tests/dataset/GT/GT_1.rst View File

@@ -0,0 +1,812 @@
1 E
2 S
3 L
4 S
5 X
6 E
7 L
8 X
9 X
10 S
11 S
12 S
13 X
14 V
15 X
16 S
17 S
18 X
19 E
20 X
21 X
22 S
23 S
24 X
25 L
26 E
27 X
28 E
29 S
30 X
31 X
32 X
33 -1
34 X
35 X
36 S
37 S
38 X
39 X
40 X
41 S
42 X
43 S
44 E
45 S
46 X
47 X
48 X
49 X
50 X
51 X
52 X
53 -1
54 S
55 X
56 X
57 X
58 S
59 X
60 X
61 X
62 X
63 S
64 E
65 S
66 X
67 X
68 S
69 X
70 E
71 X
72 L
73 X
74 E
75 S
76 X
77 X
78 S
79 X
80 X
81 X
82 X
83 X
84 L
85 X
86 X
87 -1
88 X
89 S
90 X
91 X
92 X
93 X
94 X
95 M
96 X
97 S
98 X
99 S
100 S
101 S
102 X
103 S
104 L
105 S
106 X
107 X
108 S
109 X
110 S
111 E
112 S
113 X
114 E
115 X
116 X
117 S
118 X
119 X
120 E
121 S
122 X
123 S
124 X
125 X
126 X
127 S
128 X
129 -1
130 X
131 X
132 L
133 X
134 X
135 E
136 X
137 E
138 X
139 S
140 S
141 X
142 E
143 X
144 X
145 X
146 S
147 X
148 S
149 X
150 -1
151 S
152 S
153 E
154 X
155 S
156 S
157 E
158 S
159 X
160 X
161 M
162 X
163 S
164 S
165 S
166 X
167 S
168 X
169 S
170 S
171 S
172 X
173 M
174 S
175 S
176 E
177 S
178 X
179 S
180 M
181 E
182 S
183 S
184 X
185 X
186 V
187 E
188 S
189 X
190 E
191 E
192 S
193 X
194 E
195 X
196 X
197 E
198 X
199 S
200 S
201 L
202 E
203 S
204 X
205 S
206 X
207 X
208 E
209 X
210 E
211 X
212 S
213 S
214 X
215 S
216 X
217 S
218 S
219 S
220 X
221 X
222 E
223 X
224 X
225 S
226 X
227 X
228 S
229 -1
230 X
231 L
232 X
233 X
234 X
235 X
236 X
237 S
238 S
239 X
240 X
241 X
242 X
243 E
244 X
245 X
246 S
247 S
248 X
249 S
250 X
251 X
252 S
253 X
254 L
255 X
256 S
257 X
258 X
259 X
260 S
261 X
262 X
263 X
264 S
265 X
266 S
267 X
268 S
269 X
270 X
271 -1
272 X
273 X
274 X
275 X
276 S
277 X
278 X
279 E
280 X
281 X
282 X
283 X
284 X
285 X
286 X
287 S
288 E
289 X
290 S
291 L
292 X
293 X
294 S
295 X
296 X
297 X
298 X
299 X
300 X
301 X
302 X
303 S
304 S
305 S
306 X
307 X
308 S
309 X
310 X
311 X
312 X
313 S
314 X
315 X
316 X
317 S
318 S
319 X
320 X
321 X
322 X
323 X
324 S
325 E
326 X
327 X
328 E
329 S
330 S
331 E
332 S
333 X
334 S
335 S
336 S
337 S
338 S
339 X
340 X
341 S
342 S
343 X
344 -1
345 -1
346 X
347 X
348 X
349 L
350 X
351 X
352 S
353 S
354 X
355 X
356 E
357 L
358 X
359 X
360 S
361 E
362 -1
363 S
364 X
365 S
366 L
367 X
368 S
369 X
370 S
371 X
372 E
373 X
374 X
375 X
376 S
377 X
378 V
379 L
380 -1
381 E
382 X
383 X
384 S
385 E
386 L
387 X
388 X
389 S
390 X
391 X
392 V
393 S
394 X
395 X
396 X
397 X
398 X
399 X
400 X
401 X
402 V
403 L
404 X
405 S
406 X
407 X
408 E
409 S
410 X
411 E
412 X
413 X
414 -1
415 X
416 L
417 S
418 X
419 S
420 X
421 X
422 X
423 X
424 X
425 X
426 X
427 X
428 X
429 X
430 X
431 X
432 X
433 S
434 S
435 X
436 X
437 S
438 X
439 S
440 X
441 X
442 -1
443 S
444 X
445 X
446 L
447 S
448 X
449 X
450 X
451 S
452 X
453 S
454 X
455 X
456 -1
457 S
458 S
459 E
460 S
461 S
462 S
463 X
464 X
465 X
466 X
467 X
468 S
469 X
470 S
471 X
472 X
473 X
474 S
475 L
476 X
477 X
478 S
479 S
480 S
481 S
482 X
483 X
484 S
485 S
486 S
487 S
488 -1
489 S
490 E
491 S
492 X
493 X
494 S
495 X
496 X
497 V
498 X
499 -1
500 X
501 S
502 X
503 X
504 X
505 X
506 X
507 X
508 S
509 S
510 X
511 E
512 S
513 E
514 S
515 S
516 X
517 X
518 S
519 V
520 L
521 S
522 S
523 S
524 S
525 S
526 S
527 L
528 X
529 S
530 L
531 E
532 E
533 E
534 X
535 S
536 X
537 E
538 X
539 S
540 S
541 X
542 X
543 S
544 S
545 S
546 X
547 X
548 -1
549 X
550 L
551 X
552 X
553 X
554 S
555 X
556 X
557 X
558 X
559 X
560 X
561 X
562 X
563 X
564 E
565 V
566 S
567 E
568 X
569 X
570 X
571 L
572 S
573 X
574 X
575 X
576 X
577 X
578 X
579 X
580 X
581 X
582 X
583 X
584 S
585 V
586 X
587 X
588 X
589 X
590 S
591 X
592 L
593 L
594 X
595 X
596 X
597 S
598 S
599 S
600 S
601 V
602 S
603 X
604 S
605 S
606 X
607 X
608 E
609 M
610 X
611 S
612 L
613 S
614 X
615 E
616 X
617 X
618 -1
619 V
620 X
621 X
622 X
623 X
624 X
625 -1
626 X
627 X
628 X
629 X
630 X
631 X
632 X
633 X
634 X
635 E
636 E
637 S
638 X
639 X
640 X
641 X
642 X
643 S
644 S
645 X
646 X
647 X
648 X
649 X
650 X
651 S
652 M
653 X
654 X
655 X
656 X
657 X
658 X
659 X
660 X
661 X
662 X
663 M
664 X
665 X
666 X
667 X
668 X
669 X
670 X
671 X
672 X
673 X
674 X
675 X
676 X
677 X
678 X
679 X
680 X
681 X
682 X
683 X
684 S
685 S
686 V
687 S
688 V
689 X
690 S
691 S
692 S
693 X
694 S
695 X
696 X
697 X
698 S
699 S
700 X
701 S
702 X
703 X
704 L
705 L
706 L
707 X
708 X
709 X
710 X
711 S
712 X
713 X
714 S
715 X
716 L
717 S
718 S
719 X
720 X
721 X
722 X
723 X
724 X
725 X
726 X
727 X
728 S
729 X
730 X
731 X
732 S
733 X
734 X
735 S
736 X
737 X
738 S
739 X
740 X
741 S
742 X
743 S
744 S
745 X
746 X
747 S
748 X
749 X
750 S
751 X
752 S
753 X
754 X
755 X
756 X
757 S
758 X
759 S
760 -1
761 S
762 X
763 L
764 L
765 S
766 S
767 S
768 X
769 X
770 X
771 X
772 X
773 E
774 S
775 X
776 S
777 S
778 S
779 S
780 X
781 S
782 S
783 X
784 E
785 X
786 S
787 E
788 S
789 S
790 S
791 X
792 S
793 S
794 X
795 X
796 X
797 X
798 X
799 X
800 X
801 X
802 X
803 X
804 X
805 X
806 X
807 S
808 X
809 X
810 X
811 X
812 X

+ 305
- 0
tests/dataset/GT/GT_10.rst View File

@@ -0,0 +1,305 @@
4542 S
4543 E
4544 X
4545 X
4546 E
4547 E
4548 S
4549 E
4550 -1
4551 X
4552 S
4553 S
4554 S
4555 S
4556 X
4557 X
4558 S
4559 S
4560 X
4561 X
4562 E
4563 S
4564 S
4565 S
4566 X
4567 S
4568 S
4569 S
4570 X
4571 V
4572 X
4573 X
4574 X
4575 X
4576 S
4577 X
4578 X
4579 S
4580 X
4581 S
4582 X
4583 X
4584 V
4585 X
4586 X
4587 X
4588 X
4589 X
4590 X
4591 S
4592 V
4593 X
4594 S
4595 X
4596 X
4597 X
4598 X
4599 S
4600 S
4601 E
4602 X
4603 X
4604 X
4605 S
4606 S
4607 X
4608 -1
4609 X
4610 X
4611 X
4612 X
4613 X
4614 X
4615 S
4616 -1
4617 S
4618 S
4619 X
4620 X
4621 X
4622 X
4623 S
4624 X
4625 X
4626 X
4627 S
4628 X
4629 M
4630 X
4631 X
4632 X
4633 S
4634 X
4635 X
4636 S
4637 -1
4638 X
4639 X
4640 X
4641 X
4642 -1
4643 V
4644 X
4645 X
4646 X
4647 X
4648 X
4649 S
4650 -1
4651 X
4652 X
4653 X
4654 M
4655 S
4656 S
4657 X
4658 X
4659 X
4660 X
4661 X
4662 X
4663 X
4664 X
4665 X
4666 X
4667 X
4668 X
4669 S
4670 S
4671 X
4672 X
4673 X
4674 S
4675 X
4676 X
4677 S
4678 X
4679 X
4680 S
4681 -1
4682 X
4683 X
4684 X
4685 X
4686 X
4687 X
4688 X
4689 X
4690 X
4691 X
4692 X
4693 X
4694 X
4695 X
4696 X
4697 X
4698 X
4699 X
4700 X
4701 X
4702 X
4703 X
4704 X
4705 X
4706 X
4707 X
4708 X
4709 X
4710 X
4711 X
4712 X
4713 X
4714 X
4715 X
4716 X
4717 X
4718 X
4719 X
4720 X
4721 X
4722 X
4723 X
4724 X
4725 X
4726 X
4727 X
4728 X
4729 X
4730 X
4731 X
4732 X
4733 X
4734 X
4735 X
4736 X
4737 X
4738 X
4739 X
4740 X
4741 X
4742 X
4743 X
4744 X
4745 X
4746 X
4747 X
4748 X
4749 X
4750 X
4751 X
4752 X
4753 X
4754 X
4755 X
4756 X
4757 X
4758 X
4759 X
4760 X
4761 X
4762 X
4763 X
4764 X
4765 X
4766 X
4767 X
4768 X
4769 X
4770 X
4771 X
4772 X
4773 X
4774 X
4775 X
4776 X
4777 X
4778 X
4779 X
4780 X
4781 X
4782 X
4783 X
4784 X
4785 X
4786 X
4787 X
4788 X
4789 X
4790 X
4791 X
4792 X
4793 X
4794 X
4795 X
4796 X
4797 X
4798 X
4799 X
4800 X
4801 X
4802 X
4803 X
4804 X
4805 X
4806 X
4807 X
4808 X
4809 X
4810 X
4811 X
4812 X
4813 X
4814 X
4815 X
4816 X
4817 X
4818 X
4819 X
4820 X
4821 X
4822 X
4823 X
4824 -1
4825 X
4826 X
4827 S
4828 X
4829 X
4830 X
4831 X
4832 X
4833 X
4834 X
4835 X
4836 X
4837 X
4838 X
4839 X
4840 X
4841 X
4842 S
4843 E
4844 S
4845 X
4846 X

+ 381
- 0
tests/dataset/GT/GT_11.rst View File

@@ -0,0 +1,381 @@
4847 S
4848 S
4849 E
4850 X
4851 X
4852 X
4853 M
4854 S
4855 S
4856 S
4857 S
4858 S
4859 S
4860 S
4861 X
4862 X
4863 S
4864 S
4865 S
4866 S
4867 X
4868 X
4869 S
4870 X
4871 X
4872 S
4873 X
4874 E
4875 X
4876 S
4877 S
4878 S
4879 S
4880 S
4881 X
4882 X
4883 S
4884 S
4885 X
4886 X
4887 S
4888 S
4889 X
4890 S
4891 X
4892 S
4893 M
4894 S
4895 S
4896 X
4897 S
4898 X
4899 X
4900 X
4901 X
4902 S
4903 X
4904 S
4905 S
4906 M
4907 S
4908 S
4909 X
4910 X
4911 X
4912 S
4913 X
4914 S
4915 X
4916 S
4917 S
4918 S
4919 X
4920 X
4921 X
4922 -1
4923 X
4924 X
4925 X
4926 X
4927 S
4928 X
4929 X
4930 S
4931 X
4932 X
4933 M
4934 X
4935 X
4936 X
4937 X
4938 X
4939 X
4940 X
4941 X
4942 X
4943 X
4944 X
4945 X
4946 X
4947 X
4948 S
4949 X
4950 X
4951 X
4952 X
4953 S
4954 X
4955 X
4956 -1
4957 X
4958 X
4959 X
4960 X
4961 S