diff --git a/.gitignore b/.gitignore index 3545968..cd4334a 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,6 @@ .DS_Store Manifest.toml + +# Documentation +build/ +site/ diff --git a/docs/.gitignore b/docs/.gitignore deleted file mode 100644 index a303fff..0000000 --- a/docs/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -build/ -site/ diff --git a/docs/Manifest.toml b/docs/Manifest.toml deleted file mode 100644 index 6ddbe88..0000000 --- a/docs/Manifest.toml +++ /dev/null @@ -1,885 +0,0 @@ -# This file is machine-generated - editing it directly is not advised - -julia_version = "1.8.0" -manifest_format = "2.0" -project_hash = "870d18f08c532732fa46dbdb3007a301cd876e1e" - -[[deps.ANSIColoredPrinters]] -git-tree-sha1 = "574baf8110975760d391c710b6341da1afa48d8c" -uuid = "a4c015fc-c6ff-483c-b24f-f7ea428134e9" -version = "0.0.1" - -[[deps.AbstractFFTs]] -deps = ["ChainRulesCore", "LinearAlgebra"] -git-tree-sha1 = "69f7020bd72f069c219b5e8c236c1fa90d2cb409" -uuid = "621f4979-c628-5d54-868e-fcf4e3e8185c" -version = "1.2.1" - -[[deps.Adapt]] -deps = ["LinearAlgebra"] -git-tree-sha1 = "195c5505521008abea5aee4f96930717958eac6f" -uuid = "79e6a3ab-5dfb-504d-930d-738a2a938a0e" -version = "3.4.0" - -[[deps.ArgTools]] -uuid = "0dad84c5-d112-42e6-8d28-ef12dabb789f" -version = "1.1.1" - -[[deps.ArnoldiMethod]] -deps = ["LinearAlgebra", "Random", "StaticArrays"] -git-tree-sha1 = "62e51b39331de8911e4a7ff6f5aaf38a5f4cc0ae" -uuid = "ec485272-7323-5ecc-a04f-4719b315124d" -version = "0.2.0" - -[[deps.Artifacts]] -uuid = "56f22d72-fd6d-98f1-02f0-08ddc0907c33" - -[[deps.AxisAlgorithms]] -deps = ["LinearAlgebra", "Random", "SparseArrays", "WoodburyMatrices"] -git-tree-sha1 = "66771c8d21c8ff5e3a93379480a2307ac36863f7" -uuid = "13072b0f-2c55-5437-9ae7-d433b7a33950" -version = "1.0.1" - -[[deps.AxisArrays]] -deps = ["Dates", "IntervalSets", "IterTools", "RangeArrays"] -git-tree-sha1 = "1dd4d9f5beebac0c03446918741b1a03dc5e5788" -uuid = "39de3d68-74b9-583c-8d2d-e117c070f3a9" -version = "0.4.6" - -[[deps.Base64]] -uuid = "2a0f44e3-6c83-55bd-87e4-b1978d98bd5f" - -[[deps.BenchmarkTools]] -deps = ["JSON", "Logging", "Printf", "Profile", "Statistics", "UUIDs"] -git-tree-sha1 = "4c10eee4af024676200bc7752e536f858c6b8f93" -uuid = "6e4b80f9-dd63-53aa-95a3-0cdb28fa8baf" -version = "1.3.1" - -[[deps.CEnum]] -git-tree-sha1 = "eb4cb44a499229b3b8426dcfb5dd85333951ff90" -uuid = "fa961155-64e5-5f13-b03f-caf6b980ea82" -version = "0.4.2" - -[[deps.CatIndices]] -deps = ["CustomUnitRanges", "OffsetArrays"] -git-tree-sha1 = "a0f80a09780eed9b1d106a1bf62041c2efc995bc" -uuid = "aafaddc9-749c-510e-ac4f-586e18779b91" -version = "0.2.2" - -[[deps.ChainRulesCore]] -deps = ["Compat", "LinearAlgebra", "SparseArrays"] -git-tree-sha1 = "e7ff6cadf743c098e08fca25c91103ee4303c9bb" -uuid = "d360d2e6-b24c-11e9-a2a3-2a2ae2dbcce4" -version = "1.15.6" - -[[deps.ChangesOfVariables]] -deps = ["ChainRulesCore", "LinearAlgebra", "Test"] -git-tree-sha1 = "38f7a08f19d8810338d4f5085211c7dfa5d5bdd8" -uuid = "9e997f8a-9a97-42d5-a9f1-ce6bfc15e2c0" -version = "0.1.4" - -[[deps.Clustering]] -deps = ["Distances", "LinearAlgebra", "NearestNeighbors", "Printf", "Random", "SparseArrays", "Statistics", "StatsBase"] -git-tree-sha1 = "64df3da1d2a26f4de23871cd1b6482bb68092bd5" -uuid = "aaaa29a8-35af-508c-8bc3-b662a17a0fe5" -version = "0.14.3" - -[[deps.ColorTypes]] -deps = ["FixedPointNumbers", "Random"] -git-tree-sha1 = "eb7f0f8307f71fac7c606984ea5fb2817275d6e4" -uuid = "3da002f7-5984-5a60-b8a6-cbb66c0b333f" -version = "0.11.4" - -[[deps.ColorVectorSpace]] -deps = ["ColorTypes", "FixedPointNumbers", "LinearAlgebra", "SpecialFunctions", "Statistics", "TensorCore"] -git-tree-sha1 = "d08c20eef1f2cbc6e60fd3612ac4340b89fea322" -uuid = "c3611d14-8923-5661-9e6a-0046d554d3a4" -version = "0.9.9" - -[[deps.Colors]] -deps = ["ColorTypes", "FixedPointNumbers", "Reexport"] -git-tree-sha1 = "417b0ed7b8b838aa6ca0a87aadf1bb9eb111ce40" -uuid = "5ae59095-9a9b-59fe-a467-6f913c188581" -version = "0.12.8" - -[[deps.Compat]] -deps = ["Dates", "LinearAlgebra", "UUIDs"] -git-tree-sha1 = "3ca828fe1b75fa84b021a7860bd039eaea84d2f2" -uuid = "34da2185-b29b-5c13-b0c7-acf172513d20" -version = "4.3.0" - -[[deps.CompilerSupportLibraries_jll]] -deps = ["Artifacts", "Libdl"] -uuid = "e66e0078-7015-5450-92f7-15fbd957f2ae" -version = "0.5.2+0" - -[[deps.ComputationalResources]] -git-tree-sha1 = "52cb3ec90e8a8bea0e62e275ba577ad0f74821f7" -uuid = "ed09eef8-17a6-5b46-8889-db040fac31e3" -version = "0.3.2" - -[[deps.CoordinateTransformations]] -deps = ["LinearAlgebra", "StaticArrays"] -git-tree-sha1 = "681ea870b918e7cff7111da58791d7f718067a19" -uuid = "150eb455-5306-5404-9cee-2592286d6298" -version = "0.6.2" - -[[deps.CustomUnitRanges]] -git-tree-sha1 = "1a3f97f907e6dd8983b744d2642651bb162a3f7a" -uuid = "dc8bdbbb-1ca9-579f-8c36-e416f6a65cce" -version = "1.0.2" - -[[deps.DataAPI]] -git-tree-sha1 = "46d2680e618f8abd007bce0c3026cb0c4a8f2032" -uuid = "9a962f9c-6df0-11e9-0e5d-c546b8b5ee8a" -version = "1.12.0" - -[[deps.DataStructures]] -deps = ["Compat", "InteractiveUtils", "OrderedCollections"] -git-tree-sha1 = "d1fff3a548102f48987a52a2e0d114fa97d730f0" -uuid = "864edb3b-99cc-5e75-8d2d-829cb0a9cfe8" -version = "0.18.13" - -[[deps.Dates]] -deps = ["Printf"] -uuid = "ade2ca70-3891-5945-98fb-dc099432e06a" - -[[deps.Distances]] -deps = ["LinearAlgebra", "SparseArrays", "Statistics", "StatsAPI"] -git-tree-sha1 = "3258d0659f812acde79e8a74b11f17ac06d0ca04" -uuid = "b4f34e82-e78d-54a5-968a-f98e89d6e8f7" -version = "0.10.7" - -[[deps.Distributed]] -deps = ["Random", "Serialization", "Sockets"] -uuid = "8ba89e20-285c-5b6f-9357-94700520ee1b" - -[[deps.DocStringExtensions]] -deps = ["LibGit2"] -git-tree-sha1 = "5158c2b41018c5f7eb1470d558127ac274eca0c9" -uuid = "ffbed154-4ef7-542d-bbb7-c09d3a79fcae" -version = "0.9.1" - -[[deps.Documenter]] -deps = ["ANSIColoredPrinters", "Base64", "Dates", "DocStringExtensions", "IOCapture", "InteractiveUtils", "JSON", "LibGit2", "Logging", "Markdown", "REPL", "Test", "Unicode"] -git-tree-sha1 = "6030186b00a38e9d0434518627426570aac2ef95" -uuid = "e30172f5-a6a5-5a46-863b-614d45cd2de4" -version = "0.27.23" - -[[deps.Downloads]] -deps = ["ArgTools", "FileWatching", "LibCURL", "NetworkOptions"] -uuid = "f43a241f-c20a-4ad4-852c-f6b1247861c6" -version = "1.6.0" - -[[deps.FFTViews]] -deps = ["CustomUnitRanges", "FFTW"] -git-tree-sha1 = "cbdf14d1e8c7c8aacbe8b19862e0179fd08321c2" -uuid = "4f61f5a4-77b1-5117-aa51-3ab5ef4ef0cd" -version = "0.3.2" - -[[deps.FFTW]] -deps = ["AbstractFFTs", "FFTW_jll", "LinearAlgebra", "MKL_jll", "Preferences", "Reexport"] -git-tree-sha1 = "90630efff0894f8142308e334473eba54c433549" -uuid = "7a1cc6ca-52ef-59f5-83cd-3a7055c09341" -version = "1.5.0" - -[[deps.FFTW_jll]] -deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"] -git-tree-sha1 = "c6033cc3892d0ef5bb9cd29b7f2f0331ea5184ea" -uuid = "f5851436-0d7a-5f13-b9de-f02708fd171a" -version = "3.3.10+0" - -[[deps.FileIO]] -deps = ["Pkg", "Requires", "UUIDs"] -git-tree-sha1 = "7be5f99f7d15578798f338f5433b6c432ea8037b" -uuid = "5789e2e9-d7fb-5bc7-8068-2c6fae9b9549" -version = "1.16.0" - -[[deps.FileWatching]] -uuid = "7b1f6079-737a-58dc-b8bc-7a2ca5c1b5ee" - -[[deps.FixedPointNumbers]] -deps = ["Statistics"] -git-tree-sha1 = "335bfdceacc84c5cdf16aadc768aa5ddfc5383cc" -uuid = "53c48c17-4a7d-5ca2-90c5-79b7896eea93" -version = "0.8.4" - -[[deps.Ghostscript_jll]] -deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"] -git-tree-sha1 = "78e2c69783c9753a91cdae88a8d432be85a2ab5e" -uuid = "61579ee1-b43e-5ca0-a5da-69d92c66a64b" -version = "9.55.0+0" - -[[deps.Graphics]] -deps = ["Colors", "LinearAlgebra", "NaNMath"] -git-tree-sha1 = "d61890399bc535850c4bf08e4e0d3a7ad0f21cbd" -uuid = "a2bd30eb-e257-5431-a919-1863eab51364" -version = "1.1.2" - -[[deps.Graphs]] -deps = ["ArnoldiMethod", "Compat", "DataStructures", "Distributed", "Inflate", "LinearAlgebra", "Random", "SharedArrays", "SimpleTraits", "SparseArrays", "Statistics"] -git-tree-sha1 = "ba2d094a88b6b287bd25cfa86f301e7693ffae2f" -uuid = "86223c79-3864-5bf0-83f7-82e725a168b6" -version = "1.7.4" - -[[deps.IOCapture]] -deps = ["Logging", "Random"] -git-tree-sha1 = "f7be53659ab06ddc986428d3a9dcc95f6fa6705a" -uuid = "b5f81e59-6552-4d32-b1f0-c071b021bf89" -version = "0.2.2" - -[[deps.ImageAxes]] -deps = ["AxisArrays", "ImageBase", "ImageCore", "Reexport", "SimpleTraits"] -git-tree-sha1 = "c54b581a83008dc7f292e205f4c409ab5caa0f04" -uuid = "2803e5a7-5153-5ecf-9a86-9b4c37f5f5ac" -version = "0.6.10" - -[[deps.ImageBase]] -deps = ["ImageCore", "Reexport"] -git-tree-sha1 = "b51bb8cae22c66d0f6357e3bcb6363145ef20835" -uuid = "c817782e-172a-44cc-b673-b171935fbb9e" -version = "0.1.5" - -[[deps.ImageContrastAdjustment]] -deps = ["ImageCore", "ImageTransformations", "Parameters"] -git-tree-sha1 = "0d75cafa80cf22026cea21a8e6cf965295003edc" -uuid = "f332f351-ec65-5f6a-b3d1-319c6670881a" -version = "0.3.10" - -[[deps.ImageCore]] -deps = ["AbstractFFTs", "ColorVectorSpace", "Colors", "FixedPointNumbers", "Graphics", "MappedArrays", "MosaicViews", "OffsetArrays", "PaddedViews", "Reexport"] -git-tree-sha1 = "acf614720ef026d38400b3817614c45882d75500" -uuid = "a09fc81d-aa75-5fe9-8630-4744c3626534" -version = "0.9.4" - -[[deps.ImageDistances]] -deps = ["Distances", "ImageCore", "ImageMorphology", "LinearAlgebra", "Statistics"] -git-tree-sha1 = "b1798a4a6b9aafb530f8f0c4a7b2eb5501e2f2a3" -uuid = "51556ac3-7006-55f5-8cb3-34580c88182d" -version = "0.2.16" - -[[deps.ImageFiltering]] -deps = ["CatIndices", "ComputationalResources", "DataStructures", "FFTViews", "FFTW", "ImageBase", "ImageCore", "LinearAlgebra", "OffsetArrays", "Reexport", "SparseArrays", "StaticArrays", "Statistics", "TiledIteration"] -git-tree-sha1 = "8b251ec0582187eff1ee5c0220501ef30a59d2f7" -uuid = "6a3955dd-da59-5b1f-98d4-e7296123deb5" -version = "0.7.2" - -[[deps.ImageHashes]] -deps = ["BenchmarkTools", "Images", "Statistics", "TestImages"] -path = ".." -uuid = "4e842e0a-c737-477c-a320-5a4e4980a4a4" -version = "0.1.0" - -[[deps.ImageIO]] -deps = ["FileIO", "IndirectArrays", "JpegTurbo", "LazyModules", "Netpbm", "OpenEXR", "PNGFiles", "QOI", "Sixel", "TiffImages", "UUIDs"] -git-tree-sha1 = "342f789fd041a55166764c351da1710db97ce0e0" -uuid = "82e4d734-157c-48bb-816b-45c225c6df19" -version = "0.6.6" - -[[deps.ImageMagick]] -deps = ["FileIO", "ImageCore", "ImageMagick_jll", "InteractiveUtils", "Libdl", "Pkg", "Random"] -git-tree-sha1 = "5bc1cb62e0c5f1005868358db0692c994c3a13c6" -uuid = "6218d12a-5da1-5696-b52f-db25d2ecc6d1" -version = "1.2.1" - -[[deps.ImageMagick_jll]] -deps = ["Artifacts", "Ghostscript_jll", "JLLWrappers", "JpegTurbo_jll", "Libdl", "Libtiff_jll", "Pkg", "Zlib_jll", "libpng_jll"] -git-tree-sha1 = "124626988534986113cfd876e3093e4a03890f58" -uuid = "c73af94c-d91f-53ed-93a7-00f77d67a9d7" -version = "6.9.12+3" - -[[deps.ImageMetadata]] -deps = ["AxisArrays", "ImageAxes", "ImageBase", "ImageCore"] -git-tree-sha1 = "36cbaebed194b292590cba2593da27b34763804a" -uuid = "bc367c6b-8a6b-528e-b4bd-a4b897500b49" -version = "0.9.8" - -[[deps.ImageMorphology]] -deps = ["ImageCore", "LinearAlgebra", "Requires", "TiledIteration"] -git-tree-sha1 = "e7c68ab3df4a75511ba33fc5d8d9098007b579a8" -uuid = "787d08f9-d448-5407-9aad-5290dd7ab264" -version = "0.3.2" - -[[deps.ImageQualityIndexes]] -deps = ["ImageContrastAdjustment", "ImageCore", "ImageDistances", "ImageFiltering", "LazyModules", "OffsetArrays", "Statistics"] -git-tree-sha1 = "0c703732335a75e683aec7fdfc6d5d1ebd7c596f" -uuid = "2996bd0c-7a13-11e9-2da2-2f5ce47296a9" -version = "0.3.3" - -[[deps.ImageSegmentation]] -deps = ["Clustering", "DataStructures", "Distances", "Graphs", "ImageCore", "ImageFiltering", "ImageMorphology", "LinearAlgebra", "MetaGraphs", "RegionTrees", "SimpleWeightedGraphs", "StaticArrays", "Statistics"] -git-tree-sha1 = "36832067ea220818d105d718527d6ed02385bf22" -uuid = "80713f31-8817-5129-9cf8-209ff8fb23e1" -version = "1.7.0" - -[[deps.ImageShow]] -deps = ["Base64", "FileIO", "ImageBase", "ImageCore", "OffsetArrays", "StackViews"] -git-tree-sha1 = "b563cf9ae75a635592fc73d3eb78b86220e55bd8" -uuid = "4e3cecfd-b093-5904-9786-8bbb286a6a31" -version = "0.3.6" - -[[deps.ImageTransformations]] -deps = ["AxisAlgorithms", "ColorVectorSpace", "CoordinateTransformations", "ImageBase", "ImageCore", "Interpolations", "OffsetArrays", "Rotations", "StaticArrays"] -git-tree-sha1 = "8717482f4a2108c9358e5c3ca903d3a6113badc9" -uuid = "02fcd773-0e25-5acc-982a-7f6622650795" -version = "0.9.5" - -[[deps.Images]] -deps = ["Base64", "FileIO", "Graphics", "ImageAxes", "ImageBase", "ImageContrastAdjustment", "ImageCore", "ImageDistances", "ImageFiltering", "ImageIO", "ImageMagick", "ImageMetadata", "ImageMorphology", "ImageQualityIndexes", "ImageSegmentation", "ImageShow", "ImageTransformations", "IndirectArrays", "IntegralArrays", "Random", "Reexport", "SparseArrays", "StaticArrays", "Statistics", "StatsBase", "TiledIteration"] -git-tree-sha1 = "03d1301b7ec885b266c0f816f338368c6c0b81bd" -uuid = "916415d5-f1e6-5110-898d-aaa5f9f070e0" -version = "0.25.2" - -[[deps.Imath_jll]] -deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"] -git-tree-sha1 = "87f7662e03a649cffa2e05bf19c303e168732d3e" -uuid = "905a6f67-0a94-5f89-b386-d35d92009cd1" -version = "3.1.2+0" - -[[deps.IndirectArrays]] -git-tree-sha1 = "012e604e1c7458645cb8b436f8fba789a51b257f" -uuid = "9b13fd28-a010-5f03-acff-a1bbcff69959" -version = "1.0.0" - -[[deps.Inflate]] -git-tree-sha1 = "5cd07aab533df5170988219191dfad0519391428" -uuid = "d25df0c9-e2be-5dd7-82c8-3ad0b3e990b9" -version = "0.1.3" - -[[deps.IntegralArrays]] -deps = ["ColorTypes", "FixedPointNumbers", "IntervalSets"] -git-tree-sha1 = "be8e690c3973443bec584db3346ddc904d4884eb" -uuid = "1d092043-8f09-5a30-832f-7509e371ab51" -version = "0.1.5" - -[[deps.IntelOpenMP_jll]] -deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"] -git-tree-sha1 = "d979e54b71da82f3a65b62553da4fc3d18c9004c" -uuid = "1d5cc7b8-4909-519e-a0f8-d0f5ad9712d0" -version = "2018.0.3+2" - -[[deps.InteractiveUtils]] -deps = ["Markdown"] -uuid = "b77e0a4c-d291-57a0-90e8-8db25a27a240" - -[[deps.Interpolations]] -deps = ["Adapt", "AxisAlgorithms", "ChainRulesCore", "LinearAlgebra", "OffsetArrays", "Random", "Ratios", "Requires", "SharedArrays", "SparseArrays", "StaticArrays", "WoodburyMatrices"] -git-tree-sha1 = "842dd89a6cb75e02e85fdd75c760cdc43f5d6863" -uuid = "a98d9a8b-a2ab-59e6-89dd-64a1c18fca59" -version = "0.14.6" - -[[deps.IntervalSets]] -deps = ["Dates", "Random", "Statistics"] -git-tree-sha1 = "3f91cd3f56ea48d4d2a75c2a65455c5fc74fa347" -uuid = "8197267c-284f-5f27-9208-e0e47529a953" -version = "0.7.3" - -[[deps.InverseFunctions]] -deps = ["Test"] -git-tree-sha1 = "49510dfcb407e572524ba94aeae2fced1f3feb0f" -uuid = "3587e190-3f89-42d0-90ee-14403ec27112" -version = "0.1.8" - -[[deps.IrrationalConstants]] -git-tree-sha1 = "7fd44fd4ff43fc60815f8e764c0f352b83c49151" -uuid = "92d709cd-6900-40b7-9082-c6be49f344b6" -version = "0.1.1" - -[[deps.IterTools]] -git-tree-sha1 = "fa6287a4469f5e048d763df38279ee729fbd44e5" -uuid = "c8e1da08-722c-5040-9ed9-7db0dc04731e" -version = "1.4.0" - -[[deps.JLD2]] -deps = ["FileIO", "MacroTools", "Mmap", "OrderedCollections", "Pkg", "Printf", "Reexport", "TranscodingStreams", "UUIDs"] -git-tree-sha1 = "1c3ff7416cb727ebf4bab0491a56a296d7b8cf1d" -uuid = "033835bb-8acc-5ee8-8aae-3f567f8a3819" -version = "0.4.25" - -[[deps.JLLWrappers]] -deps = ["Preferences"] -git-tree-sha1 = "abc9885a7ca2052a736a600f7fa66209f96506e1" -uuid = "692b3bcd-3c85-4b1f-b108-f13ce0eb3210" -version = "1.4.1" - -[[deps.JSON]] -deps = ["Dates", "Mmap", "Parsers", "Unicode"] -git-tree-sha1 = "3c837543ddb02250ef42f4738347454f95079d4e" -uuid = "682c06a0-de6a-54ab-a142-c8b1cf79cde6" -version = "0.21.3" - -[[deps.JpegTurbo]] -deps = ["CEnum", "FileIO", "ImageCore", "JpegTurbo_jll", "TOML"] -git-tree-sha1 = "a77b273f1ddec645d1b7c4fd5fb98c8f90ad10a5" -uuid = "b835a17e-a41a-41e7-81f0-2f016b05efe0" -version = "0.1.1" - -[[deps.JpegTurbo_jll]] -deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"] -git-tree-sha1 = "b53380851c6e6664204efb2e62cd24fa5c47e4ba" -uuid = "aacddb02-875f-59d6-b918-886e6ef4fbf8" -version = "2.1.2+0" - -[[deps.LERC_jll]] -deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"] -git-tree-sha1 = "bf36f528eec6634efc60d7ec062008f171071434" -uuid = "88015f11-f218-50d7-93a8-a6af411a945d" -version = "3.0.0+1" - -[[deps.LazyArtifacts]] -deps = ["Artifacts", "Pkg"] -uuid = "4af54fe1-eca0-43a8-85a7-787d91b784e3" - -[[deps.LazyModules]] -git-tree-sha1 = "a560dd966b386ac9ae60bdd3a3d3a326062d3c3e" -uuid = "8cdb02fc-e678-4876-92c5-9defec4f444e" -version = "0.3.1" - -[[deps.LibCURL]] -deps = ["LibCURL_jll", "MozillaCACerts_jll"] -uuid = "b27032c2-a3e7-50c8-80cd-2d36dbcbfd21" -version = "0.6.3" - -[[deps.LibCURL_jll]] -deps = ["Artifacts", "LibSSH2_jll", "Libdl", "MbedTLS_jll", "Zlib_jll", "nghttp2_jll"] -uuid = "deac9b47-8bc7-5906-a0fe-35ac56dc84c0" -version = "7.84.0+0" - -[[deps.LibGit2]] -deps = ["Base64", "NetworkOptions", "Printf", "SHA"] -uuid = "76f85450-5226-5b5a-8eaa-529ad045b433" - -[[deps.LibSSH2_jll]] -deps = ["Artifacts", "Libdl", "MbedTLS_jll"] -uuid = "29816b5a-b9ab-546f-933c-edad1886dfa8" -version = "1.10.2+0" - -[[deps.Libdl]] -uuid = "8f399da3-3557-5675-b5ff-fb832c97cbdb" - -[[deps.Libtiff_jll]] -deps = ["Artifacts", "JLLWrappers", "JpegTurbo_jll", "LERC_jll", "Libdl", "Pkg", "Zlib_jll", "Zstd_jll"] -git-tree-sha1 = "3eb79b0ca5764d4799c06699573fd8f533259713" -uuid = "89763e89-9b03-5906-acba-b20f662cd828" -version = "4.4.0+0" - -[[deps.LinearAlgebra]] -deps = ["Libdl", "libblastrampoline_jll"] -uuid = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e" - -[[deps.LogExpFunctions]] -deps = ["ChainRulesCore", "ChangesOfVariables", "DocStringExtensions", "InverseFunctions", "IrrationalConstants", "LinearAlgebra"] -git-tree-sha1 = "94d9c52ca447e23eac0c0f074effbcd38830deb5" -uuid = "2ab3a3ac-af41-5b50-aa03-7779005ae688" -version = "0.3.18" - -[[deps.Logging]] -uuid = "56ddb016-857b-54e1-b83d-db4d58db5568" - -[[deps.MKL_jll]] -deps = ["Artifacts", "IntelOpenMP_jll", "JLLWrappers", "LazyArtifacts", "Libdl", "Pkg"] -git-tree-sha1 = "2ce8695e1e699b68702c03402672a69f54b8aca9" -uuid = "856f044c-d86e-5d09-b602-aeab76dc8ba7" -version = "2022.2.0+0" - -[[deps.MacroTools]] -deps = ["Markdown", "Random"] -git-tree-sha1 = "42324d08725e200c23d4dfb549e0d5d89dede2d2" -uuid = "1914dd2f-81c6-5fcd-8719-6d5c9610ff09" -version = "0.5.10" - -[[deps.MappedArrays]] -git-tree-sha1 = "e8b359ef06ec72e8c030463fe02efe5527ee5142" -uuid = "dbb5928d-eab1-5f90-85c2-b9b0edb7c900" -version = "0.4.1" - -[[deps.Markdown]] -deps = ["Base64"] -uuid = "d6f4376e-aef5-505a-96c1-9c027394607a" - -[[deps.MbedTLS_jll]] -deps = ["Artifacts", "Libdl"] -uuid = "c8ffd9c3-330d-5841-b78e-0817d7145fa1" -version = "2.28.0+0" - -[[deps.MetaGraphs]] -deps = ["Graphs", "JLD2", "Random"] -git-tree-sha1 = "2af69ff3c024d13bde52b34a2a7d6887d4e7b438" -uuid = "626554b9-1ddb-594c-aa3c-2596fe9399a5" -version = "0.7.1" - -[[deps.Missings]] -deps = ["DataAPI"] -git-tree-sha1 = "bf210ce90b6c9eed32d25dbcae1ebc565df2687f" -uuid = "e1d29d7a-bbdc-5cf2-9ac0-f12de2c33e28" -version = "1.0.2" - -[[deps.Mmap]] -uuid = "a63ad114-7e13-5084-954f-fe012c677804" - -[[deps.MosaicViews]] -deps = ["MappedArrays", "OffsetArrays", "PaddedViews", "StackViews"] -git-tree-sha1 = "b34e3bc3ca7c94914418637cb10cc4d1d80d877d" -uuid = "e94cdb99-869f-56ef-bcf0-1ae2bcbe0389" -version = "0.3.3" - -[[deps.MozillaCACerts_jll]] -uuid = "14a3606d-f60d-562e-9121-12d972cd8159" -version = "2022.2.1" - -[[deps.NaNMath]] -deps = ["OpenLibm_jll"] -git-tree-sha1 = "a7c3d1da1189a1c2fe843a3bfa04d18d20eb3211" -uuid = "77ba4419-2d1f-58cd-9bb1-8ffee604a2e3" -version = "1.0.1" - -[[deps.NearestNeighbors]] -deps = ["Distances", "StaticArrays"] -git-tree-sha1 = "440165bf08bc500b8fe4a7be2dc83271a00c0716" -uuid = "b8a86587-4115-5ab1-83bc-aa920d37bbce" -version = "0.4.12" - -[[deps.Netpbm]] -deps = ["FileIO", "ImageCore"] -git-tree-sha1 = "18efc06f6ec36a8b801b23f076e3c6ac7c3bf153" -uuid = "f09324ee-3d7c-5217-9330-fc30815ba969" -version = "1.0.2" - -[[deps.NetworkOptions]] -uuid = "ca575930-c2e3-43a9-ace4-1e988b2c1908" -version = "1.2.0" - -[[deps.OffsetArrays]] -deps = ["Adapt"] -git-tree-sha1 = "f71d8950b724e9ff6110fc948dff5a329f901d64" -uuid = "6fe1bfb0-de20-5000-8ca7-80f57d26f881" -version = "1.12.8" - -[[deps.OpenBLAS_jll]] -deps = ["Artifacts", "CompilerSupportLibraries_jll", "Libdl"] -uuid = "4536629a-c528-5b80-bd46-f80d51c5b363" -version = "0.3.20+0" - -[[deps.OpenEXR]] -deps = ["Colors", "FileIO", "OpenEXR_jll"] -git-tree-sha1 = "327f53360fdb54df7ecd01e96ef1983536d1e633" -uuid = "52e1d378-f018-4a11-a4be-720524705ac7" -version = "0.3.2" - -[[deps.OpenEXR_jll]] -deps = ["Artifacts", "Imath_jll", "JLLWrappers", "Libdl", "Pkg", "Zlib_jll"] -git-tree-sha1 = "923319661e9a22712f24596ce81c54fc0366f304" -uuid = "18a262bb-aa17-5467-a713-aee519bc75cb" -version = "3.1.1+0" - -[[deps.OpenLibm_jll]] -deps = ["Artifacts", "Libdl"] -uuid = "05823500-19ac-5b8b-9628-191a04bc5112" -version = "0.8.1+0" - -[[deps.OpenSpecFun_jll]] -deps = ["Artifacts", "CompilerSupportLibraries_jll", "JLLWrappers", "Libdl", "Pkg"] -git-tree-sha1 = "13652491f6856acfd2db29360e1bbcd4565d04f1" -uuid = "efe28fd5-8261-553b-a9e1-b2916fc3738e" -version = "0.5.5+0" - -[[deps.OrderedCollections]] -git-tree-sha1 = "85f8e6578bf1f9ee0d11e7bb1b1456435479d47c" -uuid = "bac558e1-5e72-5ebc-8fee-abe8a469f55d" -version = "1.4.1" - -[[deps.PNGFiles]] -deps = ["Base64", "CEnum", "ImageCore", "IndirectArrays", "OffsetArrays", "libpng_jll"] -git-tree-sha1 = "f809158b27eba0c18c269cf2a2be6ed751d3e81d" -uuid = "f57f5aa1-a3ce-4bc8-8ab9-96f992907883" -version = "0.3.17" - -[[deps.PaddedViews]] -deps = ["OffsetArrays"] -git-tree-sha1 = "03a7a85b76381a3d04c7a1656039197e70eda03d" -uuid = "5432bcbf-9aad-5242-b902-cca2824c8663" -version = "0.5.11" - -[[deps.Parameters]] -deps = ["OrderedCollections", "UnPack"] -git-tree-sha1 = "34c0e9ad262e5f7fc75b10a9952ca7692cfc5fbe" -uuid = "d96e819e-fc66-5662-9728-84c9c7592b0a" -version = "0.12.3" - -[[deps.Parsers]] -deps = ["Dates"] -git-tree-sha1 = "3d5bf43e3e8b412656404ed9466f1dcbf7c50269" -uuid = "69de0a69-1ddd-5017-9359-2bf0b02dc9f0" -version = "2.4.0" - -[[deps.Pkg]] -deps = ["Artifacts", "Dates", "Downloads", "LibGit2", "Libdl", "Logging", "Markdown", "Printf", "REPL", "Random", "SHA", "Serialization", "TOML", "Tar", "UUIDs", "p7zip_jll"] -uuid = "44cfe95a-1eb2-52ea-b672-e2afdf69b78f" -version = "1.8.0" - -[[deps.PkgVersion]] -deps = ["Pkg"] -git-tree-sha1 = "f6cf8e7944e50901594838951729a1861e668cb8" -uuid = "eebad327-c553-4316-9ea0-9fa01ccd7688" -version = "0.3.2" - -[[deps.Preferences]] -deps = ["TOML"] -git-tree-sha1 = "47e5f437cc0e7ef2ce8406ce1e7e24d44915f88d" -uuid = "21216c6a-2e73-6563-6e65-726566657250" -version = "1.3.0" - -[[deps.Printf]] -deps = ["Unicode"] -uuid = "de0858da-6303-5e67-8744-51eddeeeb8d7" - -[[deps.Profile]] -deps = ["Printf"] -uuid = "9abbd945-dff8-562f-b5e8-e1ebf5ef1b79" - -[[deps.ProgressMeter]] -deps = ["Distributed", "Printf"] -git-tree-sha1 = "d7a7aef8f8f2d537104f170139553b14dfe39fe9" -uuid = "92933f4c-e287-5a05-a399-4b506db050ca" -version = "1.7.2" - -[[deps.QOI]] -deps = ["ColorTypes", "FileIO", "FixedPointNumbers"] -git-tree-sha1 = "18e8f4d1426e965c7b532ddd260599e1510d26ce" -uuid = "4b34888f-f399-49d4-9bb3-47ed5cae4e65" -version = "1.0.0" - -[[deps.Quaternions]] -deps = ["LinearAlgebra", "Random"] -git-tree-sha1 = "fcebf40de9a04c58da5073ec09c1c1e95944c79b" -uuid = "94ee1d12-ae83-5a48-8b1c-48b8ff168ae0" -version = "0.6.1" - -[[deps.REPL]] -deps = ["InteractiveUtils", "Markdown", "Sockets", "Unicode"] -uuid = "3fa0cd96-eef1-5676-8a61-b3b8758bbffb" - -[[deps.Random]] -deps = ["SHA", "Serialization"] -uuid = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c" - -[[deps.RangeArrays]] -git-tree-sha1 = "b9039e93773ddcfc828f12aadf7115b4b4d225f5" -uuid = "b3c3ace0-ae52-54e7-9d0b-2c1406fd6b9d" -version = "0.3.2" - -[[deps.Ratios]] -deps = ["Requires"] -git-tree-sha1 = "dc84268fe0e3335a62e315a3a7cf2afa7178a734" -uuid = "c84ed2f1-dad5-54f0-aa8e-dbefe2724439" -version = "0.4.3" - -[[deps.Reexport]] -git-tree-sha1 = "45e428421666073eab6f2da5c9d310d99bb12f9b" -uuid = "189a3867-3050-52da-a836-e630ba90ab69" -version = "1.2.2" - -[[deps.RegionTrees]] -deps = ["IterTools", "LinearAlgebra", "StaticArrays"] -git-tree-sha1 = "4618ed0da7a251c7f92e869ae1a19c74a7d2a7f9" -uuid = "dee08c22-ab7f-5625-9660-a9af2021b33f" -version = "0.3.2" - -[[deps.Requires]] -deps = ["UUIDs"] -git-tree-sha1 = "838a3a4188e2ded87a4f9f184b4b0d78a1e91cb7" -uuid = "ae029012-a4dd-5104-9daa-d747884805df" -version = "1.3.0" - -[[deps.Rotations]] -deps = ["LinearAlgebra", "Quaternions", "Random", "StaticArrays", "Statistics"] -git-tree-sha1 = "793b6ef92f9e96167ddbbd2d9685009e200eb84f" -uuid = "6038ab10-8711-5258-84ad-4b1120ba62dc" -version = "1.3.3" - -[[deps.SHA]] -uuid = "ea8e919c-243c-51af-8825-aaa63cd721ce" -version = "0.7.0" - -[[deps.Serialization]] -uuid = "9e88b42a-f829-5b0c-bbe9-9e923198166b" - -[[deps.SharedArrays]] -deps = ["Distributed", "Mmap", "Random", "Serialization"] -uuid = "1a1011a3-84de-559e-8e89-a11a2f7dc383" - -[[deps.SimpleTraits]] -deps = ["InteractiveUtils", "MacroTools"] -git-tree-sha1 = "5d7e3f4e11935503d3ecaf7186eac40602e7d231" -uuid = "699a6c99-e7fa-54fc-8d76-47d257e15c1d" -version = "0.9.4" - -[[deps.SimpleWeightedGraphs]] -deps = ["Graphs", "LinearAlgebra", "Markdown", "SparseArrays", "Test"] -git-tree-sha1 = "a6f404cc44d3d3b28c793ec0eb59af709d827e4e" -uuid = "47aef6b3-ad0c-573a-a1e2-d07658019622" -version = "1.2.1" - -[[deps.Sixel]] -deps = ["Dates", "FileIO", "ImageCore", "IndirectArrays", "OffsetArrays", "REPL", "libsixel_jll"] -git-tree-sha1 = "8fb59825be681d451c246a795117f317ecbcaa28" -uuid = "45858cf5-a6b0-47a3-bbea-62219f50df47" -version = "0.1.2" - -[[deps.Sockets]] -uuid = "6462fe0b-24de-5631-8697-dd941f90decc" - -[[deps.SortingAlgorithms]] -deps = ["DataStructures"] -git-tree-sha1 = "b3363d7460f7d098ca0912c69b082f75625d7508" -uuid = "a2af1166-a08f-5f64-846c-94a0d3cef48c" -version = "1.0.1" - -[[deps.SparseArrays]] -deps = ["LinearAlgebra", "Random"] -uuid = "2f01184e-e22b-5df5-ae63-d93ebab69eaf" - -[[deps.SpecialFunctions]] -deps = ["ChainRulesCore", "IrrationalConstants", "LogExpFunctions", "OpenLibm_jll", "OpenSpecFun_jll"] -git-tree-sha1 = "d75bda01f8c31ebb72df80a46c88b25d1c79c56d" -uuid = "276daf66-3868-5448-9aa4-cd146d93841b" -version = "2.1.7" - -[[deps.StackViews]] -deps = ["OffsetArrays"] -git-tree-sha1 = "46e589465204cd0c08b4bd97385e4fa79a0c770c" -uuid = "cae243ae-269e-4f55-b966-ac2d0dc13c15" -version = "0.1.1" - -[[deps.StaticArrays]] -deps = ["LinearAlgebra", "Random", "StaticArraysCore", "Statistics"] -git-tree-sha1 = "f86b3a049e5d05227b10e15dbb315c5b90f14988" -uuid = "90137ffa-7385-5640-81b9-e52037218182" -version = "1.5.9" - -[[deps.StaticArraysCore]] -git-tree-sha1 = "6b7ba252635a5eff6a0b0664a41ee140a1c9e72a" -uuid = "1e83bf80-4336-4d27-bf5d-d5a4f845583c" -version = "1.4.0" - -[[deps.Statistics]] -deps = ["LinearAlgebra", "SparseArrays"] -uuid = "10745b16-79ce-11e8-11f9-7d13ad32a3b2" - -[[deps.StatsAPI]] -deps = ["LinearAlgebra"] -git-tree-sha1 = "f9af7f195fb13589dd2e2d57fdb401717d2eb1f6" -uuid = "82ae8749-77ed-4fe6-ae5f-f523153014b0" -version = "1.5.0" - -[[deps.StatsBase]] -deps = ["DataAPI", "DataStructures", "LinearAlgebra", "LogExpFunctions", "Missings", "Printf", "Random", "SortingAlgorithms", "SparseArrays", "Statistics", "StatsAPI"] -git-tree-sha1 = "d1bf48bfcc554a3761a133fe3a9bb01488e06916" -uuid = "2913bbd2-ae8a-5f71-8c99-4fb6c76f3a91" -version = "0.33.21" - -[[deps.StringDistances]] -deps = ["Distances", "StatsAPI"] -git-tree-sha1 = "ceeef74797d961aee825aabf71446d6aba898acb" -uuid = "88034a9c-02f8-509d-84a9-84ec65e18404" -version = "0.11.2" - -[[deps.TOML]] -deps = ["Dates"] -uuid = "fa267f1f-6049-4f14-aa54-33bafae1ed76" -version = "1.0.0" - -[[deps.Tar]] -deps = ["ArgTools", "SHA"] -uuid = "a4e569a6-e804-4fa4-b0f3-eef7a1d5b13e" -version = "1.10.0" - -[[deps.TensorCore]] -deps = ["LinearAlgebra"] -git-tree-sha1 = "1feb45f88d133a655e001435632f019a9a1bcdb6" -uuid = "62fd8b95-f654-4bbd-a8a5-9c27f68ccd50" -version = "0.1.1" - -[[deps.Test]] -deps = ["InteractiveUtils", "Logging", "Random", "Serialization"] -uuid = "8dfed614-e22c-5e08-85e1-65c5234f0b40" - -[[deps.TestImages]] -deps = ["AxisArrays", "ColorTypes", "FileIO", "ImageIO", "ImageMagick", "OffsetArrays", "Pkg", "StringDistances"] -git-tree-sha1 = "03492434a1bdde3026288939fc31b5660407b624" -uuid = "5e47fb64-e119-507b-a336-dd2b206d9990" -version = "1.7.1" - -[[deps.TiffImages]] -deps = ["ColorTypes", "DataStructures", "DocStringExtensions", "FileIO", "FixedPointNumbers", "IndirectArrays", "Inflate", "Mmap", "OffsetArrays", "PkgVersion", "ProgressMeter", "UUIDs"] -git-tree-sha1 = "70e6d2da9210371c927176cb7a56d41ef1260db7" -uuid = "731e570b-9d59-4bfa-96dc-6df516fadf69" -version = "0.6.1" - -[[deps.TiledIteration]] -deps = ["OffsetArrays"] -git-tree-sha1 = "5683455224ba92ef59db72d10690690f4a8dc297" -uuid = "06e1c1a7-607b-532d-9fad-de7d9aa2abac" -version = "0.3.1" - -[[deps.TranscodingStreams]] -deps = ["Random", "Test"] -git-tree-sha1 = "8a75929dcd3c38611db2f8d08546decb514fcadf" -uuid = "3bb67fe8-82b1-5028-8e26-92a6c54297fa" -version = "0.9.9" - -[[deps.UUIDs]] -deps = ["Random", "SHA"] -uuid = "cf7118a7-6976-5b1a-9a39-7adc72f591a4" - -[[deps.UnPack]] -git-tree-sha1 = "387c1f73762231e86e0c9c5443ce3b4a0a9a0c2b" -uuid = "3a884ed6-31ef-47d7-9d2a-63182c4928ed" -version = "1.0.2" - -[[deps.Unicode]] -uuid = "4ec0a83e-493e-50e2-b9ac-8f72acf5a8f5" - -[[deps.WoodburyMatrices]] -deps = ["LinearAlgebra", "SparseArrays"] -git-tree-sha1 = "de67fa59e33ad156a590055375a30b23c40299d3" -uuid = "efce3f68-66dc-5838-9240-27a6d6f5f9b6" -version = "0.5.5" - -[[deps.Zlib_jll]] -deps = ["Libdl"] -uuid = "83775a58-1f1d-513f-b197-d71354ab007a" -version = "1.2.12+3" - -[[deps.Zstd_jll]] -deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"] -git-tree-sha1 = "e45044cd873ded54b6a5bac0eb5c971392cf1927" -uuid = "3161d3a3-bdf6-5164-811a-617609db77b4" -version = "1.5.2+0" - -[[deps.libblastrampoline_jll]] -deps = ["Artifacts", "Libdl", "OpenBLAS_jll"] -uuid = "8e850b90-86db-534c-a0d3-1478176c7d93" -version = "5.1.1+0" - -[[deps.libpng_jll]] -deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg", "Zlib_jll"] -git-tree-sha1 = "94d180a6d2b5e55e447e2d27a29ed04fe79eb30c" -uuid = "b53b4c65-9356-5827-b1ea-8c7a1a84506f" -version = "1.6.38+0" - -[[deps.libsixel_jll]] -deps = ["Artifacts", "JLLWrappers", "JpegTurbo_jll", "Libdl", "Pkg", "libpng_jll"] -git-tree-sha1 = "d4f63314c8aa1e48cd22aa0c17ed76cd1ae48c3c" -uuid = "075b6546-f08a-558a-be8f-8157d0f608a5" -version = "1.10.3+0" - -[[deps.nghttp2_jll]] -deps = ["Artifacts", "Libdl"] -uuid = "8e850ede-7688-5339-a07c-302acd2aaf8d" -version = "1.48.0+0" - -[[deps.p7zip_jll]] -deps = ["Artifacts", "Libdl"] -uuid = "3f19e933-33d8-53b3-aaab-bd5110c3b7a0" -version = "17.4.0+0" diff --git a/docs/Project.toml b/docs/Project.toml index fee04e3..37832f8 100644 --- a/docs/Project.toml +++ b/docs/Project.toml @@ -1,5 +1,6 @@ [deps] +BenchmarkTools = "6e4b80f9-dd63-53aa-95a3-0cdb28fa8baf" Documenter = "e30172f5-a6a5-5a46-863b-614d45cd2de4" ImageHashes = "4e842e0a-c737-477c-a320-5a4e4980a4a4" -TestImages = "5e47fb64-e119-507b-a336-dd2b206d9990" Images = "916415d5-f1e6-5110-898d-aaa5f9f070e0" +TestImages = "5e47fb64-e119-507b-a336-dd2b206d9990" diff --git a/docs/make.jl b/docs/make.jl index 4114558..6d84fda 100644 --- a/docs/make.jl +++ b/docs/make.jl @@ -1,28 +1,21 @@ -using ImageHashes +using Pkg using Documenter +using ImageHashes -push!(LOAD_PATH,"../src/") - -DocMeta.setdocmeta!(ImageHashes, :DocTestSetup, :(using ImageHashes); recursive=true) makedocs(; + warnonly=true, modules=[ImageHashes], - authors="David Buchaca Prats and contributors", - repo="https://github.com/davidbp/ImageHashes.jl/blob/{commit}{path}#{line}", sitename="ImageHashes.jl", - format=Documenter.HTML(; - prettyurls=get(ENV, "CI", "false") == "true", - canonical="https://davidbp.github.io/ImageHashes.jl", - edit_link="main", - assets=String[], - ), + authors="David Buchaca Prats and contributors", pages=[ - "Introduction" => "index.md", - "Hashes" => [ - "average_hash.md", - "difference_hash.md", - "perceptual_hash.md" - ], + "Introduction" => "index.md", + "Hashing Algorithms" => [ + "algorithms/average_hash.md", + "algorithms/difference_hash.md", + "algorithms/perceptual_hash.md" + ], + "API Reference" => "api.md", ], ) diff --git a/docs/src/algorithms/average_hash.md b/docs/src/algorithms/average_hash.md new file mode 100644 index 0000000..6813428 --- /dev/null +++ b/docs/src/algorithms/average_hash.md @@ -0,0 +1,60 @@ +```@setup A +using ImageHashes, Images, BenchmarkTools, TestImages +``` + +# Average Hash (aHash) + +Average hashing is based on four steps: + +1. Resize an image to be a squ ared image of height and width equal to a user defined input `n_size_side`. +1. Construct an matrix `img_resized_gray` with the the gray values of the resized image. +1. Compute the mean intensity of `img_resized_gray` and store it to `mean_image_intensity`. +1. Build a matrix that contains a `1` in position `k` if `img_resized_gray[k] >. mean_image_intensity`, and a `0` otherwise. + +The average hash vector for an image would be the flattenend matrix of step (4). + +## Quickstart + +A hash (vector hash) for an image can be created with the [`average_hash`](@ref) function. + +```@repl +using TestImages, ImageHashes +img = testimage("coffee.png"); +img_hash = average_hash(img) +typeof(img_hash) +``` + +# Example + +Let us visualize the original image and hash and mathash of an image. + +```@example A +using TestImages, Images, ImageHashes +img = testimage("coffee.png") +``` + +An average mat hash (matrix hash) can be created using [`average_mathash(image, size)`](@ref), as follows: + +```@repl A +mat_hash = average_mathash(img, 8) +``` + +We can visualize the hash using `Gray.()`: + +```@example A +Gray.(mat_hash) +``` + +The bigger the matrix hash is, the higher quality it can achive. + +```@example A +mat_hash = average_mathash(img, 32) +Gray.(mat_hash) +``` + +## Performance + +```@repl A +img = testimage("coffee.png"); +@benchmark average_hash($img, 8) +``` diff --git a/docs/src/algorithms/difference_hash.md b/docs/src/algorithms/difference_hash.md new file mode 100644 index 0000000..117fbf4 --- /dev/null +++ b/docs/src/algorithms/difference_hash.md @@ -0,0 +1,56 @@ +```@setup A +using ImageHashes, Images, BenchmarkTools, TestImages +``` + +# Difference Hash (dHash) + +Difference hashing is based on four steps: + +1. Reduce size shrinking the image to 9x8 so that there are 72 total pixels. Since we ignore size and aspect ratio, the hash should match any similar picture regardless of how it is stretched. +1. Convert the image to grayscale. +1. Compute the difference between adjacent pixels, creating the relative gradient direction. When shrinked to 9x8, the 9 pixels per row create 8 differences between adjacent pixels. +1. Assign each bits depending on whether the left pixel is brighter than the right pixel. + +## Quickstart + +```@repl +using TestImages, ImageHashes +img = testimage("coffee.png"); +img_hash = difference_hash(img) +typeof(img_hash) +``` + +## Example + +Let us visualize the original image and hash and mathash of an image. + +```@example A +using TestImages, Images, ImageHashes +img = testimage("coffee.png") +``` + +An difference mat hash (matrix hash) can be created using [`difference_mathash(image, size)`](@ref), as follows: + +```@repl A +mat_hash = difference_mathash(img, 8) +``` + +We can visualize the hash using `Gray.()`. + +```@example A +Gray.(mat_hash) +``` + +The bigger the matrix hash is, the higher quality it can achive. + +```@example A +mat_hash = difference_mathash(img, 32) +Gray.(mat_hash) +``` + +## Performance + +```@repl A +img = testimage("coffee.png"); +@benchmark difference_mathash($img, 8) +``` diff --git a/docs/src/algorithms/perceptual_hash.md b/docs/src/algorithms/perceptual_hash.md new file mode 100644 index 0000000..065b7a3 --- /dev/null +++ b/docs/src/algorithms/perceptual_hash.md @@ -0,0 +1,58 @@ +```@setup A +using ImageHashes, Images, BenchmarkTools, TestImages +``` + +# Perceptual Hash (pHash) + +Perceptual hashing is based on four steps: + +1. Convert the image to grayscale and resize it to `n_size_side_preprocess=32` +1. Compute the DCT of the `32x32` image. +1. Get the top `n_hash=n_size_side*n_size_side` bits of the previous `32x32` array (usually ignoring the first value). +1. Create a hash comparing each value of the previous array with the median. + +## Quickstart + +A hash (vector hash) for an image can be created with `perceptual_hash` function. + +```@repl +using TestImages, ImageHashes +img = testimage("coffee.png"); +img_hash = perceptual_hash(img) +typeof(img_hash) +``` + +## Example + +Let us visualize the original image and hash and mathash of an image. + +```@example A +using TestImages, Images, ImageHashes +img = testimage("coffee.png") +``` + +A "perceptual mathash" (matrix hash) can be created using [`perceptual_mathash`](@ref), as follows: + +```@repl A +mat_hash = perceptual_mathash(img, 8) +``` + +We can visualize the hash using `Gray.()`: + +```@example A +Gray.(mat_hash) +``` + +The bigger the matrix hash is, the higher quality it can achive. + +```@example A +mat_hash = perceptual_mathash(img, 32) +Gray.(mat_hash) +``` + +## Performance + +```@repl A +img = testimage("coffee.png"); +@benchmark perceptual_hash($img, 8) +``` diff --git a/docs/src/api.md b/docs/src/api.md new file mode 100644 index 0000000..fc3c0b1 --- /dev/null +++ b/docs/src/api.md @@ -0,0 +1,14 @@ +# API Reference + +```@index +Modules = [ImageHashes] +Order = [:type, :function] +``` + +---------- + + +```@autodocs +Modules = [ImageHashes] +Order = [:function, :type] +``` diff --git a/docs/src/average_hash.md b/docs/src/average_hash.md deleted file mode 100644 index 06d9bcc..0000000 --- a/docs/src/average_hash.md +++ /dev/null @@ -1,66 +0,0 @@ -# Average Hash - -Average hashing is based on four steps: - -- (1) Resize an image to be a squ ared image of height and width equal to a user defined input `n_size_side`. -- (2) Construct an matrix `img_resized_gray` with the the gray values of the resized image. -- (3) Compute the mean intensity of `img_resized_gray` and store it to `mean_image_intensity`. -- (4) Build a matrix that contains a `1` in position `k` if `img_resized_gray[k] >. mean_image_intensity`, and a `0` otherwise. - -The average hash vector for an image would be the flattenend matrix of step (4). - -#### Example - -Let us visualize the original image and hash and mathash of an image. - -```@example -using TestImages -img = testimage("fabio_color_256.png"); -img -``` - -An average mat hash (matrix hash) can be created using `average_hash(image, size)`, as follows: - -```@example -using TestImages, Images, ImageHashes -img = testimage("fabio_color_256.png"); -mat_hash = average_mathash(img, 8) -mat_hash -``` - - -We can visualize the hash using `Gray.`. - -```@example -using TestImages, Images, ImageHashes -img = testimage("fabio_color_256.png"); -mat_hash = average_mathash(img, 8) -Gray.(mat_hash) -``` - -The bigger the mat hash is, the higher quality it can achive. - -```@example -using TestImages, Images, ImageHashes -img = testimage("fabio_color_256.png"); -mat_hash = average_mathash(img, 28) -Gray.(mat_hash) -``` - -A hash (vector hash) for an image can be created with the `average_hash` function. - -```@example -using TestImages, ImageHashes -img = testimage("fabio_color_256.png"); -img_hash = average_hash(img, 8) -img_hash -``` - -#### Execution time and allocations - -```@example -using TestImages, ImageHashes, BenchmarkTools -img = testimage("fabio_color_256.png"); -benchmark = @benchmark average_hash($img, 8) -benchmark -``` \ No newline at end of file diff --git a/docs/src/difference_hash.md b/docs/src/difference_hash.md deleted file mode 100644 index 3527792..0000000 --- a/docs/src/difference_hash.md +++ /dev/null @@ -1,66 +0,0 @@ -# Difference Hash - -Difference hashing is based on four steps: - -- (1) Reduce size shrinking the image to 9x8 so that there are 72 total pixels. Since we ignore size and aspect ratio, the hash should match any similar picture regardless of how it is stretched. -- (2) Convert the image to grayscale. -- (3) Compute the difference between adjacent pixels, creating the relative gradient direction. When shrinked to 9x8, the 9 pixels per row create 8 differences between adjacent pixels. -- (4) Assign each bits depending on whether the left pixel is brighter than the right pixel. - - - -#### Example - -Let us visualize the original image and hash and mathash of an image. - -```@example -using TestImages -img = testimage("fabio_color_256.png"); -img -``` - -An difference mat hash (matrix hash) can be created using `difference_mathash(image, size)`, as follows: - -```@example -using TestImages, Images, ImageHashes -img = testimage("fabio_color_256.png"); -mat_hash = difference_mathash(img, 8) -mat_hash -``` - - -We can visualize the hash using `Gray.`. - -```@example -using TestImages, Images, ImageHashes -img = testimage("fabio_color_256.png"); -mat_hash = difference_mathash(img, 8) -Gray.(mat_hash) -``` - -The bigger the mat hash is, the higher quality it can achive. - -```@example -using TestImages, Images, ImageHashes -img = testimage("fabio_color_256.png"); -mat_hash = difference_mathash(img, 28) -Gray.(mat_hash) -``` - -A hash (vector hash) for an image can be created with `difference_hash` function. - -```@example -using TestImages, ImageHashes -img = testimage("fabio_color_256.png"); -img_hash = difference_hash(img, 8) -img_hash -``` - -#### Execution time and allocations - -```@example -using TestImages, ImageHashes, BenchmarkTools -img = testimage("fabio_color_256.png"); -benchmark = @benchmark difference_hash($img, 8) -benchmark -``` diff --git a/docs/src/index.md b/docs/src/index.md index 033a062..bfb3bf4 100644 --- a/docs/src/index.md +++ b/docs/src/index.md @@ -1,18 +1,43 @@ -```@meta -CurrentModule = ImageHashes -``` +# ImageHashes.jl -# ImageHashes package +ImageHashes.jl is a Julia package for image hashing. It covers various techniques to simplify +the task of finding **exact** and **near duplicates** in an image collection, among other applications. -*ImageHashes.jl* is a Julia package for image hashing. -It covers various techniques to simplify the task of finding **exact** and **near duplicates** in an image collection, among other applications. +!!! note "Related Resources" + This Package is inspired by [JohannesBuchner's imagehash](https://github.com/JohannesBuchner/imagehash) + python package. Good related material can also be found in: + - https://www.hackerfactor.com/blog/index.php?/archives/432-Looks-Like-It.html + - https://erdogant.github.io/undouble/pages/html/hash_functions.html + - https://content-blockchain.org/research/testing-different-image-hash-functions/ +Implemented image hashing algorithms: +- [Average Hash (aHash)](./algorithms/average_hash.md) +- [Difference Hash (dHash)](./algorithms/difference_hash.md) +- [Perceptual Hash (pHash)](./algorithms/perceptual_hash.md) -### Benchmark -The package provides basic benchmarks in `benchmarks/benchmark.jl `. One can run +## Getting Started +To get started, add ImageHashes to your current environment: + +```julia +using Pkg; Pkg.add("ImageHashes") ``` + +To generate image hashes use: + +```@repl +using TestImages, ImageHashes +img = testimage("coffee.png"); +img_hash = average_hash(img) +typeof(img_hash) +``` + +## Benchmark + +The package provides basic benchmarks in `benchmarks/benchmark.jl `. One can run + +```bash julia --project=. benchmarks/benchmark.jl ``` @@ -39,28 +64,3 @@ time taken to compute a hash using dhash: 0.004 seconds Hashes per second: 250 time taken to compute 100000000 hash distances: 242.927 seconds ``` - - -### Related material to `ImageHashes` - -This Package is inspired by: - -``` -https://github.com/JohannesBuchner/imagehash -``` - -Good related material can be found in -- https://github.com/JohannesBuchner/imagehash -- https://www.hackerfactor.com/blog/index.php?/archives/432-Looks-Like-It.html -- https://erdogant.github.io/undouble/pages/html/hash_functions.html -- https://content-blockchain.org/research/testing-different-image-hash-functions/ - -```@index - -``` - -```@autodocs -Modules = [ImageHashes] -``` - - diff --git a/docs/src/perceptual_hash.md b/docs/src/perceptual_hash.md deleted file mode 100644 index c3b92ed..0000000 --- a/docs/src/perceptual_hash.md +++ /dev/null @@ -1,67 +0,0 @@ -# Perceptual Hash - -Perceptual hashing is based on four steps: - -- (1) Convert the image to grayscale and resize it to `n_size_side_preprocess=32` -- (2) Compute the DCT of the `32x32` image. -- (3) Get the top `n_hash=n_size_side*n_size_side` bits of the previous `32x32` array (usually ignoring the first value). -- (4) Create a hash comparing each value of the previous array with the median. - - -#### Example - -Let us visualize the original image and hash and mathash of an image. - -```@example -using TestImages -img = testimage("fabio_color_256.png"); -img -``` - -A "perceptual mathash" (matrix hash) can be created using `perceptual_mathash(image, n_size_side)`, as follows: - -```@example -using TestImages, Images, ImageHashes -img = testimage("fabio_color_256.png"); -mat_hash = perceptual_mathash(img, 8) -mat_hash -``` - - -We can visualize the hash using `Gray.`. - -```@example -using TestImages, Images, ImageHashes -img = testimage("fabio_color_256.png"); -mat_hash = perceptual_mathash(img, 8) -Gray.(mat_hash) -``` - -The bigger the matrix hash is, the higher quality it can achive. - -```@example -using TestImages, Images, ImageHashes -img = testimage("fabio_color_256.png"); -mat_hash = perceptual_mathash(img, 28) -Gray.(mat_hash) -``` - -A hash (vector hash) for an image can be created with `perceptual_hash` function. - -```@example -using TestImages, ImageHashes -img = testimage("fabio_color_256.png"); -img_hash = perceptual_hash(img, 8) -img_hash -``` - - -#### Execution time and allocations - -```@example -using TestImages, ImageHashes, BenchmarkTools -img = testimage("fabio_color_256.png"); -benchmark = @benchmark perceptual_hash($img, 8) -benchmark -``` - diff --git a/src/hashing/average.jl b/src/hashing/average.jl index 01ae9ae..07d024d 100644 --- a/src/hashing/average.jl +++ b/src/hashing/average.jl @@ -1,10 +1,37 @@ -function average_mathash(image, n_size_side::Int = 8) +""" + average_mathash(image, n_size_side::Int = 8) + +Compute the average hash (aHash) of an image and return its bit matrix form. + +# Arguments +- `image`: Input image +- `n_size_side`: Size of the resized square image (default = `8`). + +# Returns +A `BitMatrix` of size `n_size_side × n_size_side` representing the perceptual bit +pattern of the image. +""" +function average_mathash(image, n_size_side::Int = 8) :: BitMatrix img_resized_gray, mean_image_intensity = _preprocess_image(image, n_size_side, func=mean) bit_matrix = img_resized_gray .> mean_image_intensity return bit_matrix end +""" + average_hash(image, n_size_side::Int = 8) + +Compute the average hash (aHash) of an image and return it as an integer. + +# Arguments +- `image`: The input image, in any format supported by `_preprocess_image`. +- `n_size_side`: The side length of the resized square used for hashing + (default is `8`, producing a 64-bit hash). + +# Returns +An integer representing the average-hash bit pattern. For `n_size_side = 8`, +this will fit in a `UInt64` and can be used for fast similarity comparisons. +""" function average_hash(image, n_size_side::Int = 8) img_resized_gray, mean_image_intensity = _preprocess_image(image, n_size_side, func=mean) hash = _reinterpret_bits_as_int_average_hash(img_resized_gray, mean_image_intensity) diff --git a/src/hashing/difference.jl b/src/hashing/difference.jl index 4ce0543..9304a94 100644 --- a/src/hashing/difference.jl +++ b/src/hashing/difference.jl @@ -1,19 +1,31 @@ """ - _difference_hash_matrix(image, n_size_side::Int; orientation=:vertical) + difference_mathash(image, n_size_side::Int = 8; orientation = :horizontal) -Compute the boolean bit matrix for difference hash. +Compute a `BitMatrix` representing the adjacent–pixel intensity +comparisons used by the difference hash (dHash) algorithm. -- `orientation = :vertical`: compares columns (resize to `(n_size_side, n_size_side+1)`), result `(n_size_side, n_size_side)`. -- `orientation = :horizontal`: compares rows (resize to `(n_size_side+1, n_size_side)`), result `(n_size_side, n_size_side)`. +# Arguments +- `image`: The input image. +- `n_size_side`: The side length of the final hash matrix (default = `8`). +- `orientation`: + - `:horizontal`: compare pixels from left to right (default). + - `:vertical`: compare pixels from top to bottom. + +# Returns +A `BitMatrix` where each entry indicates whether the neighboring pixel in the comparison +direction has greater intensity than the current pixel. The `size` of the resulting matrix +depends on provided `orientation`: +- `horizontal`: `(n_size_side + 1, n_size_side)` +- `vertical`: `(n_size_side, n_size_side + 1)` """ -function _difference_hash_matrix(image, n_size_side::Int; orientation::Symbol = :horizontal) +function difference_mathash(image, n_size_side::Int = 8; orientation::Symbol = :horizontal) :: BitMatrix img_resized_gray = if orientation == :horizontal _preprocess_image(image, (n_size_side + 1, n_size_side)) elseif orientation == :vertical _preprocess_image(image, (n_size_side, n_size_side + 1)) else - throw(ArgumentError("orientation must be :vertical or :horizontal")) + throw(ArgumentError("orientation must be :vertical or :horizontal, got $orientation")) end n_rows, n_cols = size(img_resized_gray) @@ -37,23 +49,24 @@ end """ - difference_mathash(image, n_size_side::Int=8; orientation=:horizontal) - -Return the difference hash as a `BitMatrix`. + difference_hash(image, n_size_side::Int = 8; orientation::Symbol = :horizontal) -- By default, uses `orientation=:horizontal` to match test expectations. -""" -difference_mathash(image, n_size_side::Int = 8; orientation::Symbol = :horizontal) = - _difference_hash_matrix(image, n_size_side; orientation) +Compute the ifference hash (dHash) of an image and return it as a compact +integer value. +# Arguments +- `image`: Input image to hash. +- `n_size_side`: Side length of the square region used for hashing (default = `8`, producing a 64-bit hash). +- `orientation`: orientation to apply the difference hash. + - `:horizontal`: compares pixels from left to right (default). + - `:vertical`: compares pixels from top to bottom. -""" - difference_hash(image, n_size_side::Int=8; orientation=:horizontal) - -Return the difference hash as a compact integer. +# Returns +A compact integer hash value whose bit pattern corresponds to the dHash +comparison matrix. For `n_size_side = 8`, the result fits in a `UInt64`. """ function difference_hash(image, n_size_side::Int = 8; orientation::Symbol = :horizontal) - bit_matrix = _difference_hash_matrix(image, n_size_side; orientation) + bit_matrix = difference_mathash(image, n_size_side; orientation) z = init_hash_container(length(bit_matrix)) @inbounds for b in bit_matrix diff --git a/src/utils.jl b/src/utils.jl index 650331c..7331595 100644 --- a/src/utils.jl +++ b/src/utils.jl @@ -19,7 +19,6 @@ end """ init_hash_container(n_bits::Int) - Choose the proper variable type for the variable storing the resulting hash based on `n_bits` of the input.. """ @@ -52,7 +51,7 @@ Resize an image to the target `size` and convert it to grayscale. - If `func` is `nothing`: the resized grayscale image. - Otherwise: a tuple `(img_resized_gray, func(img_resized_gray))`. """ -function _preprocess_image(image, size::Union{Int, Tuple{Int, Int}}; func::Union{Function,Nothing} = nothing) +function _preprocess_image(image, size::Union{Int, Tuple{Int, Int}}; func::Union{Function, Nothing} = nothing) target_size = size isa Int ? (size, size) : size img_resized = imresize(image, target_size) img_resized_gray = Gray.(img_resized)