Commit bb5dac66 authored by Mickaël Desfrênes's avatar Mickaël Desfrênes
Browse files

alternate deskew implementation

parent eeb82bd5
Loading
Loading
Loading
Loading
+200 −52
Original line number Diff line number Diff line
@@ -19,11 +19,11 @@ tests = ["pytest", "pytest-asyncio", "mypy (>=0.800)"]

[[package]]
name = "black"
version = "22.8.0"
version = "22.10.0"
description = "The uncompromising code formatter."
category = "dev"
optional = false
python-versions = ">=3.6.2"
python-versions = ">=3.7"

[package.dependencies]
click = ">=8.0.0"
@@ -41,7 +41,7 @@ uvloop = ["uvloop (>=0.15.2)"]

[[package]]
name = "certifi"
version = "2022.6.15"
version = "2022.9.24"
description = "Python package for providing Mozilla's CA Bundle."
category = "main"
optional = false
@@ -88,9 +88,24 @@ category = "dev"
optional = false
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"

[[package]]
name = "deskew"
version = "1.3.3"
description = "Skew detection and correction in images containing text"
category = "main"
optional = false
python-versions = ">=3.8,<3.12"

[package.dependencies]
numpy = "*"
scikit-image = "*"

[package.extras]
debug_images = ["matplotlib", "opencv-python-headless"]

[[package]]
name = "django"
version = "4.1.1"
version = "4.1.2"
description = "A high-level Python web framework that encourages rapid development and clean, pragmatic design."
category = "main"
optional = false
@@ -118,7 +133,7 @@ Django = ">=3.2"

[[package]]
name = "django-extensions"
version = "3.2.0"
version = "3.2.1"
description = "Extensions for Django"
category = "main"
optional = false
@@ -152,12 +167,41 @@ redis = ["redis (>=3.0.0)"]

[[package]]
name = "idna"
version = "3.3"
version = "3.4"
description = "Internationalized Domain Names in Applications (IDNA)"
category = "main"
optional = false
python-versions = ">=3.5"

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

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

[package.extras]
all-plugins = ["astropy", "av", "imageio-ffmpeg", "opencv-python", "psutil", "tifffile"]
all-plugins-pypy = ["av", "imageio-ffmpeg", "psutil", "tifffile"]
build = ["wheel"]
dev = ["invoke", "pytest", "pytest-cov", "fsspec", "black", "flake8"]
docs = ["sphinx", "numpydoc", "pydata-sphinx-theme"]
ffmpeg = ["imageio-ffmpeg", "psutil"]
fits = ["astropy"]
full = ["astropy", "av", "black", "flake8", "fsspec", "gdal", "imageio-ffmpeg", "invoke", "itk", "numpydoc", "opencv-python", "psutil", "pydata-sphinx-theme", "pytest", "pytest-cov", "sphinx", "tifffile", "wheel"]
gdal = ["gdal"]
itk = ["itk"]
linting = ["black", "flake8"]
opencv = ["opencv-python"]
pyav = ["av"]
test = ["invoke", "pytest", "pytest-cov", "fsspec"]
tifffile = ["tifffile"]

[[package]]
name = "jama-client-certic"
version = "0.0.24"
@@ -172,12 +216,16 @@ requests = "*"

[[package]]
name = "markdown2"
version = "2.4.3"
version = "2.4.5"
description = "A fast and complete Python implementation of Markdown"
category = "main"
optional = false
python-versions = ">=3.5, <4"

[package.extras]
all = ["pygments (>=2.7.3)"]
code_syntax_highlighting = ["pygments (>=2.7.3)"]

[[package]]
name = "mypy-extensions"
version = "0.4.3"
@@ -186,9 +234,24 @@ category = "dev"
optional = false
python-versions = "*"

[[package]]
name = "networkx"
version = "2.8.7"
description = "Python package for creating and manipulating graphs and networks"
category = "main"
optional = false
python-versions = ">=3.8"

[package.extras]
default = ["numpy (>=1.19)", "scipy (>=1.8)", "matplotlib (>=3.4)", "pandas (>=1.3)"]
developer = ["pre-commit (>=2.20)", "mypy (>=0.981)"]
doc = ["sphinx (>=5)", "pydata-sphinx-theme (>=0.9)", "sphinx-gallery (>=0.10)", "numpydoc (>=1.4)", "pillow (>=9.1)", "nb2plots (>=0.6)", "texext (>=0.6.6)"]
extra = ["lxml (>=4.6)", "pygraphviz (>=1.9)", "pydot (>=1.4.2)", "sympy (>=1.10)"]
test = ["pytest (>=7.1)", "pytest-cov (>=3.0)", "codecov (>=2.1)"]

[[package]]
name = "numpy"
version = "1.23.2"
version = "1.23.4"
description = "NumPy is the fundamental package for array computing with Python."
category = "main"
optional = false
@@ -210,6 +273,17 @@ numpy = [
    {version = ">=1.17.3", markers = "python_version >= \"3.8\""},
]

[[package]]
name = "packaging"
version = "21.3"
description = "Core utilities for Python packages"
category = "main"
optional = false
python-versions = ">=3.6"

[package.dependencies]
pyparsing = ">=2.0.2,<3.0.5 || >3.0.5"

[[package]]
name = "pathspec"
version = "0.10.1"
@@ -218,6 +292,18 @@ category = "dev"
optional = false
python-versions = ">=3.7"

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

[package.extras]
docs = ["furo", "olefile", "sphinx (>=2.4)", "sphinx-copybutton", "sphinx-issues (>=3.0.1)", "sphinx-removed-in", "sphinxext-opengraph"]
tests = ["check-manifest", "coverage", "defusedxml", "markdown2", "olefile", "packaging", "pyroma", "pytest", "pytest-cov", "pytest-timeout"]

[[package]]
name = "pkgconfig"
version = "1.5.5"
@@ -240,7 +326,7 @@ test = ["appdirs (==1.4.4)", "pytest-cov (>=2.7)", "pytest-mock (>=3.6)", "pytes

[[package]]
name = "psycopg2"
version = "2.9.3"
version = "2.9.4"
description = "psycopg2 - Python-PostgreSQL Database Adapter"
category = "main"
optional = false
@@ -267,6 +353,17 @@ docs = ["packaging", "sphinx", "sphinx-autoapi", "sphinx-rtd-theme", "sphinx-aut
json = ["ujson"]
test = ["packaging"]

[[package]]
name = "pyparsing"
version = "3.0.9"
description = "pyparsing module - Classes and methods to define and execute parsing grammars"
category = "main"
optional = false
python-versions = ">=3.6.8"

[package.extras]
diagrams = ["railroad-diagrams", "jinja2"]

[[package]]
name = "python-dotenv"
version = "0.20.0"
@@ -294,6 +391,17 @@ pkgconfig = "*"
doc = ["sphinx", "sphinx-rtd-theme"]
test = ["cffi (>=1.0.0)", "pyperf", "pytest", "pytest-flake8", "pytest-runner"]

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

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

[[package]]
name = "requests"
version = "2.28.1"
@@ -312,14 +420,68 @@ urllib3 = ">=1.21.1,<1.27"
socks = ["PySocks (>=1.5.6,!=1.5.7)"]
use_chardet_on_py3 = ["chardet (>=3.0.2,<6)"]

[[package]]
name = "scikit-image"
version = "0.19.3"
description = "Image processing in Python"
category = "main"
optional = false
python-versions = ">=3.7"

[package.dependencies]
imageio = ">=2.4.1"
networkx = ">=2.2"
numpy = ">=1.17.0"
packaging = ">=20.0"
pillow = ">=6.1.0,<7.1.0 || >7.1.0,<7.1.1 || >7.1.1,<8.3.0 || >8.3.0"
PyWavelets = ">=1.1.1"
scipy = ">=1.4.1"
tifffile = ">=2019.7.26"

[package.extras]
data = ["pooch (>=1.3.0)"]
docs = ["sphinx (>=1.8)", "sphinx-gallery (>=0.10.1)", "numpydoc (>=1.0)", "sphinx-copybutton", "pytest-runner", "scikit-learn", "matplotlib (>=3.3)", "dask[array] (>=0.15.0,!=2.17.0)", "cloudpickle (>=0.2.1)", "pandas (>=0.23.0)", "seaborn (>=0.7.1)", "pooch (>=1.3.0)", "tifffile (>=2020.5.30)", "myst-parser", "ipywidgets", "plotly (>=4.14.0)", "kaleido"]
optional = ["simpleitk", "astropy (>=3.1.2)", "cloudpickle (>=0.2.1)", "dask[array] (>=1.0.0,!=2.17.0)", "matplotlib (>=3.0.3)", "pooch (>=1.3.0)", "pyamg", "qtpy"]
test = ["asv", "codecov", "flake8", "matplotlib (>=3.0.3)", "pooch (>=1.3.0)", "pytest (>=5.2.0)", "pytest-cov (>=2.7.0)", "pytest-localserver", "pytest-faulthandler"]

[[package]]
name = "scipy"
version = "1.9.2"
description = "Fundamental algorithms for scientific computing in Python"
category = "main"
optional = false
python-versions = ">=3.8"

[package.dependencies]
numpy = ">=1.18.5,<1.26.0"

[package.extras]
test = ["pytest", "pytest-cov", "pytest-xdist", "asv", "mpmath", "gmpy2", "threadpoolctl", "scikit-umfpack"]
doc = ["sphinx (!=4.1.0)", "pydata-sphinx-theme (==0.9.0)", "sphinx-panels (>=0.5.2)", "matplotlib (>2)", "numpydoc", "sphinx-tabs"]
dev = ["mypy", "typing-extensions", "pycodestyle", "flake8"]

[[package]]
name = "sqlparse"
version = "0.4.2"
version = "0.4.3"
description = "A non-validating SQL parser."
category = "main"
optional = false
python-versions = ">=3.5"

[[package]]
name = "tifffile"
version = "2022.10.10"
description = "Read and write TIFF files"
category = "main"
optional = false
python-versions = ">=3.8"

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

[package.extras]
all = ["imagecodecs (>=2022.2.22)", "matplotlib (>=3.3)", "lxml", "zarr", "fsspec"]

[[package]]
name = "tomli"
version = "2.0.1"
@@ -330,7 +492,7 @@ python-versions = ">=3.7"

[[package]]
name = "typing-extensions"
version = "4.3.0"
version = "4.4.0"
description = "Backported and Experimental Type Hints for Python 3.7+"
category = "dev"
optional = false
@@ -338,7 +500,7 @@ python-versions = ">=3.7"

[[package]]
name = "tzdata"
version = "2022.2"
version = "2022.5"
description = "Provider of IANA time zone data"
category = "main"
optional = false
@@ -346,7 +508,7 @@ python-versions = ">=2"

[[package]]
name = "unidecode"
version = "1.3.4"
version = "1.3.6"
description = "ASCII transliterations of Unicode text"
category = "main"
optional = false
@@ -367,8 +529,8 @@ socks = ["PySocks (>=1.5.6,!=1.5.7,<2.0)"]

[metadata]
lock-version = "1.1"
python-versions = "^3.9"
content-hash = "7f45f9771427fe44b6dec5b6080a2c4d542963e3800dd60b3efac88370e1a43e"
python-versions = ">=3.9,<3.12"
content-hash = "bdf42969b732dde9fd190d9504a90a5d67ea826213c3b1c59512bb2739003367"

[metadata.files]
argh = [
@@ -380,10 +542,7 @@ asgiref = [
    {file = "asgiref-3.5.2.tar.gz", hash = "sha256:4a29362a6acebe09bf1d6640db38c1dc3d9217c68e6f9f6204d72667fc19a424"},
]
black = []
certifi = [
    {file = "certifi-2022.6.15-py3-none-any.whl", hash = "sha256:fe86415d55e84719d75f8b69414f6438ac3547d2078ab91b67e779ef69378412"},
    {file = "certifi-2022.6.15.tar.gz", hash = "sha256:84c85a9078b11105f04f3036a9482ae10e4621616db313fe045dd24743a0820d"},
]
certifi = []
cffi = []
charset-normalizer = []
click = [
@@ -394,6 +553,7 @@ colorama = [
    {file = "colorama-0.4.5-py2.py3-none-any.whl", hash = "sha256:854bf444933e37f5824ae7bfc1e98d5bce2ebe4160d46b5edf346a89358e99da"},
    {file = "colorama-0.4.5.tar.gz", hash = "sha256:e6c6b4334fc50988a639d9b98aa429a0b57da6e17b9a44f0451f930b6967b7a4"},
]
deskew = []
django = []
django-cors-headers = [
    {file = "django-cors-headers-3.13.0.tar.gz", hash = "sha256:f9dc6b4e3f611c3199700b3e5f3398c28757dcd559c2f82932687f3d0443cfdf"},
@@ -406,21 +566,17 @@ django-ranged-fileresponse = [
huey = [
    {file = "huey-2.4.3.tar.gz", hash = "sha256:4fa2f6055d581778c3bcf93fc8c9ce87aecc2a345d5ff35bd955da152c02ef37"},
]
idna = [
    {file = "idna-3.3-py3-none-any.whl", hash = "sha256:84d9dd047ffa80596e0f246e2eab0b391788b0503584e8945f2368256d2735ff"},
    {file = "idna-3.3.tar.gz", hash = "sha256:9d643ff0a55b762d5cdb124b8eaa99c66322e2157b69160bc32796e824360e6d"},
]
idna = []
imageio = []
jama-client-certic = [
    {file = "jama-client-CERTIC-0.0.24.tar.gz", hash = "sha256:5a39d93ffc5ad4ca9e42abe4e952affe49c7afa2414fbd289f10d26f6f6b95f5"},
]
markdown2 = [
    {file = "markdown2-2.4.3-py2.py3-none-any.whl", hash = "sha256:f344d4adfba5d1de821f7850b36e3507f583468a7eb47e6fa191765ed0b9c66b"},
    {file = "markdown2-2.4.3.tar.gz", hash = "sha256:412520c7b6bba540c2c2067d6be3a523ab885703bf6a81d93963f848b55dfb9a"},
]
markdown2 = []
mypy-extensions = [
    {file = "mypy_extensions-0.4.3-py2.py3-none-any.whl", hash = "sha256:090fedd75945a69ae91ce1303b5824f428daf5a028d2f6ab8a299250a846f15d"},
    {file = "mypy_extensions-0.4.3.tar.gz", hash = "sha256:2d82818f5bb3e369420cb3c4060a7970edba416647068eb4c5343488a6c604a8"},
]
networkx = []
numpy = []
opencv-python-headless = [
    {file = "opencv-python-headless-4.6.0.66.tar.gz", hash = "sha256:d5291d7e10aa2c19cab6fd86f0d61af8617290ecd2d7ffcb051e446868d04cc5"},
@@ -431,7 +587,12 @@ opencv-python-headless = [
    {file = "opencv_python_headless-4.6.0.66-cp36-abi3-win_amd64.whl", hash = "sha256:e6c069bc963d7e8fcec21b3e33e594d35948badd63eccb2e80f88b0a12102c03"},
    {file = "opencv_python_headless-4.6.0.66-cp37-abi3-macosx_11_0_arm64.whl", hash = "sha256:ffbf26fcd697af996408440a93bc69c49c05a36845771f984156dfbeaa95d497"},
]
packaging = [
    {file = "packaging-21.3-py3-none-any.whl", hash = "sha256:ef103e05f519cdc783ae24ea4e2e0f508a9c99b2d4969652eed6a2e1ea5bd522"},
    {file = "packaging-21.3.tar.gz", hash = "sha256:dd47c42927d89ab911e606518907cc2d3a1f38bbd026385970643f9c5b8ecfeb"},
]
pathspec = []
pillow = []
pkgconfig = [
    {file = "pkgconfig-1.5.5-py3-none-any.whl", hash = "sha256:d20023bbeb42ee6d428a0fac6e0904631f545985a10cdd71a20aa58bc47a4209"},
    {file = "pkgconfig-1.5.5.tar.gz", hash = "sha256:deb4163ef11f75b520d822d9505c1f462761b4309b1bb713d08689759ea8b899"},
@@ -440,24 +601,16 @@ platformdirs = [
    {file = "platformdirs-2.5.2-py3-none-any.whl", hash = "sha256:027d8e83a2d7de06bbac4e5ef7e023c02b863d7ea5d079477e722bb41ab25788"},
    {file = "platformdirs-2.5.2.tar.gz", hash = "sha256:58c8abb07dcb441e6ee4b11d8df0ac856038f944ab98b7be6b27b2a3c7feef19"},
]
psycopg2 = [
    {file = "psycopg2-2.9.3-cp310-cp310-win32.whl", hash = "sha256:083707a696e5e1c330af2508d8fab36f9700b26621ccbcb538abe22e15485362"},
    {file = "psycopg2-2.9.3-cp310-cp310-win_amd64.whl", hash = "sha256:d3ca6421b942f60c008f81a3541e8faf6865a28d5a9b48544b0ee4f40cac7fca"},
    {file = "psycopg2-2.9.3-cp36-cp36m-win32.whl", hash = "sha256:9572e08b50aed176ef6d66f15a21d823bb6f6d23152d35e8451d7d2d18fdac56"},
    {file = "psycopg2-2.9.3-cp36-cp36m-win_amd64.whl", hash = "sha256:a81e3866f99382dfe8c15a151f1ca5fde5815fde879348fe5a9884a7c092a305"},
    {file = "psycopg2-2.9.3-cp37-cp37m-win32.whl", hash = "sha256:cb10d44e6694d763fa1078a26f7f6137d69f555a78ec85dc2ef716c37447e4b2"},
    {file = "psycopg2-2.9.3-cp37-cp37m-win_amd64.whl", hash = "sha256:4295093a6ae3434d33ec6baab4ca5512a5082cc43c0505293087b8a46d108461"},
    {file = "psycopg2-2.9.3-cp38-cp38-win32.whl", hash = "sha256:34b33e0162cfcaad151f249c2649fd1030010c16f4bbc40a604c1cb77173dcf7"},
    {file = "psycopg2-2.9.3-cp38-cp38-win_amd64.whl", hash = "sha256:0762c27d018edbcb2d34d51596e4346c983bd27c330218c56c4dc25ef7e819bf"},
    {file = "psycopg2-2.9.3-cp39-cp39-win32.whl", hash = "sha256:8cf3878353cc04b053822896bc4922b194792df9df2f1ad8da01fb3043602126"},
    {file = "psycopg2-2.9.3-cp39-cp39-win_amd64.whl", hash = "sha256:06f32425949bd5fe8f625c49f17ebb9784e1e4fe928b7cce72edc36fb68e4c0c"},
    {file = "psycopg2-2.9.3.tar.gz", hash = "sha256:8e841d1bf3434da985cc5ef13e6f75c8981ced601fd70cc6bf33351b91562981"},
]
psycopg2 = []
pycparser = [
    {file = "pycparser-2.21-py2.py3-none-any.whl", hash = "sha256:8ee45429555515e1f6b185e78100aea234072576aa43ab53aefcae078162fca9"},
    {file = "pycparser-2.21.tar.gz", hash = "sha256:e644fdec12f7872f86c58ff790da456218b10f863970249516d60a5eaca77206"},
]
pyexiftool = []
pyparsing = [
    {file = "pyparsing-3.0.9-py3-none-any.whl", hash = "sha256:5026bae9a10eeaefb61dab2f09052b9f4307d44aee4eda64b309723d8d206bbc"},
    {file = "pyparsing-3.0.9.tar.gz", hash = "sha256:2b020ecf7d21b687f219b71ecad3631f644a47f01403fa1d1036b0c6416d70fb"},
]
python-dotenv = [
    {file = "python-dotenv-0.20.0.tar.gz", hash = "sha256:b7e3b04a59693c42c36f9ab1cc2acc46fa5df8c78e178fc33a8d4cd05c8d498f"},
    {file = "python_dotenv-0.20.0-py3-none-any.whl", hash = "sha256:d92a187be61fe482e4fd675b6d52200e7be63a12b724abbf931a40ce4fa92938"},
@@ -465,25 +618,20 @@ python-dotenv = [
pyvips = [
    {file = "pyvips-2.2.1.tar.gz", hash = "sha256:b51dbb45b057a282925015d540c5597560993e2986df20a778646a6b37e7cbb5"},
]
pywavelets = []
requests = [
    {file = "requests-2.28.1-py3-none-any.whl", hash = "sha256:8fefa2a1a1365bf5520aac41836fbee479da67864514bdb821f31ce07ce65349"},
    {file = "requests-2.28.1.tar.gz", hash = "sha256:7c5599b102feddaa661c826c56ab4fee28bfd17f5abca1ebbe3e7f19d7c97983"},
]
sqlparse = [
    {file = "sqlparse-0.4.2-py3-none-any.whl", hash = "sha256:48719e356bb8b42991bdbb1e8b83223757b93789c00910a616a071910ca4a64d"},
    {file = "sqlparse-0.4.2.tar.gz", hash = "sha256:0c00730c74263a94e5a9919ade150dfc3b19c574389985446148402998287dae"},
]
scikit-image = []
scipy = []
sqlparse = []
tifffile = []
tomli = [
    {file = "tomli-2.0.1-py3-none-any.whl", hash = "sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc"},
    {file = "tomli-2.0.1.tar.gz", hash = "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f"},
]
typing-extensions = [
    {file = "typing_extensions-4.3.0-py3-none-any.whl", hash = "sha256:25642c956049920a5aa49edcdd6ab1e06d7e5d467fc00e0506c44ac86fbfca02"},
    {file = "typing_extensions-4.3.0.tar.gz", hash = "sha256:e6d2677a32f47fc7eb2795db1dd15c1f34eff616bcaf2cfb5e997f854fa1c4a6"},
]
typing-extensions = []
tzdata = []
unidecode = [
    {file = "Unidecode-1.3.4-py3-none-any.whl", hash = "sha256:afa04efcdd818a93237574791be9b2817d7077c25a068b00f8cff7baa4e59257"},
    {file = "Unidecode-1.3.4.tar.gz", hash = "sha256:8e4352fb93d5a735c788110d2e7ac8e8031eb06ccbfe8d324ab71735015f9342"},
]
unidecode = []
urllib3 = []
+2 −1
Original line number Diff line number Diff line
@@ -6,7 +6,7 @@ authors = ["Mickaël Desfrênes <mickael.desfrenes@unicaen.fr>"]
license = "Cecill"

[tool.poetry.dependencies]
python = "^3.9"
python = ">=3.9,<3.12"
Django = "^4.0.5"
django-extensions = "^3.1.5"
django-cors-headers = "^3.13.0"
@@ -21,6 +21,7 @@ pyvips = "^2.2.1"
huey = "^2.4.3"
numpy = "^1.22.4"
opencv-python-headless = "^4.6.0"
deskew = "^1.3.3"

[tool.poetry.dev-dependencies]
black = "^22.3.0"
+1 −0
Original line number Diff line number Diff line
@@ -154,3 +154,4 @@ unidecode==1.3.4; python_version >= "3.5" \
urllib3==1.26.9; python_version >= "3.7" and python_full_version < "3.0.0" and python_version < "4" or python_full_version >= "3.5.0" and python_version < "4" and python_version >= "3.7" \
    --hash=sha256:44ece4d53fb1706f667c9bd1c648f5469a2ec925fcf3a776667042d645472c14 \
    --hash=sha256:aabaf16477806a5e1dd19aa41f8c2b7950dd3c746362d7e3223dbe6de6ac448e
deskew
 No newline at end of file
+30 −10
Original line number Diff line number Diff line
@@ -36,6 +36,7 @@ import numpy
from resources.helpers import handle_local_file as _handle_local_file
from datetime import timedelta
from django.utils import timezone
from deskew import determine_skew

logger = logging.getLogger(__name__)

@@ -50,10 +51,9 @@ class ServiceException(Exception):
        self.message = args[0]


def _deskew(image_path: str, max_skew: int = 10, fast: bool = True) -> float:
def _deskew2(image_path: str) -> float:
    im = cv2.imread(image_path)
    height, width, _ = im.shape
    if fast:
    scale_factor = 1000 / max(height, width)
    height = int(height * scale_factor)
    width = int(width * scale_factor)
@@ -63,25 +63,45 @@ def _deskew(image_path: str, max_skew: int = 10, fast: bool = True) -> float:
        interpolation=cv2.INTER_LINEAR,
    )
    im_gs = cv2.cvtColor(im, cv2.COLOR_BGR2GRAY)
    angle = determine_skew(im_gs)
    if angle:
        return angle * -1
    return 0.0


def _deskew(
    image_path: str, max_skew: int = 10, fast: bool = True, scale_max: int = 1000
) -> float:
    im = cv2.imread(image_path)
    height, width, _ = im.shape
    if fast:
        scale_factor = scale_max / max(height, width)
        height = int(height * scale_factor)
        width = int(width * scale_factor)
        im = cv2.resize(
            im,
            (width, height),
            interpolation=cv2.INTER_LINEAR,
        )
    im_gs = cv2.cvtColor(im, cv2.COLOR_BGR2GRAY)
    im_gs = cv2.fastNlMeansDenoising(im_gs, h=3)
    im_bw = cv2.threshold(im_gs, 0, 255, cv2.THRESH_BINARY_INV | cv2.THRESH_OTSU)[1]
    lines = cv2.HoughLinesP(
        im_bw, 1, numpy.pi / 180, 200, minLineLength=width / 12, maxLineGap=width / 150
        im_bw, 1, numpy.pi / 180, 30, minLineLength=width / 12, maxLineGap=width / 150
    )
    if lines is None:
        return 0
        return 0.0
    if type(lines) != numpy.ndarray:
        return 0
        return 0.0
    if not lines.any():
        return 0
        return 0.0
    # Collect the angles of these lines (in radians)
    angles = []
    for line in lines:
        x1, y1, x2, y2 = line[0]
        angles.append(numpy.arctan2(y2 - y1, x2 - x1))

    angles = [angle for angle in angles if abs(angle) < numpy.deg2rad(max_skew)]

    max_skew_in_deg = numpy.deg2rad(max_skew)
    angles = [angle for angle in angles if abs(angle) < max_skew_in_deg]
    if len(angles) < 5:
        # Insufficient data to deskew
        return 0
@@ -3093,4 +3113,4 @@ def auto_find_rotate_angle(user: User, resource_id: int) -> float:
        raise ServiceException(NOT_A_FILE)
    if not resource_instance.file.should_have_iiif():
        raise ServiceException(NOT_AN_IMAGE)
    return _deskew(resource_instance.file.local_path())
    return _deskew2(resource_instance.file.local_path())