Compare commits
20 Commits
b7bb145089
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
| 1de21e93e1 | |||
| 59e0f2d861 | |||
| cc2820da90 | |||
| f8d4f85858 | |||
| 76e178176d | |||
| fa1e988344 | |||
| dcf78bb88d | |||
| 481de4dfb1 | |||
| 8a364b81e6 | |||
| 97ab6a1ed1 | |||
| 405b9f7f91 | |||
| 52fe136f3f | |||
| e4516e12d9 | |||
|
|
55110d6736 | ||
| 407a103913 | |||
| 6635404cf9 | |||
| 81e8195fb7 | |||
| 6f69f508b6 | |||
| f83a98ffe0 | |||
| d10665fd67 |
5
.gitignore
vendored
@@ -1,5 +1,10 @@
|
||||
# CUSTOM
|
||||
|
||||
images-input/*
|
||||
!images-input/.gitkeep
|
||||
images-output/*
|
||||
!images-output/.gitkeep
|
||||
config.yaml
|
||||
.vscode/
|
||||
*.swp
|
||||
|
||||
|
||||
4
Makefile
@@ -10,3 +10,7 @@ dev:
|
||||
clean:
|
||||
rm -rf static/*
|
||||
touch static/.gitkeep
|
||||
|
||||
batch:
|
||||
pipenv run python3 batch-process.py
|
||||
|
||||
|
||||
5
Pipfile
@@ -10,6 +10,11 @@ flask = "*"
|
||||
gunicorn = "*"
|
||||
werkzeug = "*"
|
||||
pyyaml = "*"
|
||||
matplotlib = "*"
|
||||
plotly = "*"
|
||||
pandas = "*"
|
||||
scipy = "==1.8.1"
|
||||
scikit-image = "*"
|
||||
|
||||
[dev-packages]
|
||||
|
||||
|
||||
482
Pipfile.lock
generated
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"_meta": {
|
||||
"hash": {
|
||||
"sha256": "0cfa12a983973f0699999da1f8adcf4662998d4d37158ae1eed984cb7b773fc3"
|
||||
"sha256": "4ce52e44137325bfa984f7d78467dce4463d471bfc344ecd116c2beb2af52d60"
|
||||
},
|
||||
"pipfile-spec": 6,
|
||||
"requires": {
|
||||
@@ -24,6 +24,89 @@
|
||||
"markers": "python_version >= '3.7'",
|
||||
"version": "==8.1.3"
|
||||
},
|
||||
"contourpy": {
|
||||
"hashes": [
|
||||
"sha256:0389349875424aa8c5e61f757e894687916bc4e9616cc6afcbd8051aa2428952",
|
||||
"sha256:0395ae71164bfeb2dedd136e03c71a2718a5aa9873a46f518f4133be0d63e1d2",
|
||||
"sha256:057114f698ffb9e54657e8fda6802e2f5c8fad609845cf6afaf31590ef6a33c0",
|
||||
"sha256:061e1f066c419ffe25b615a1df031b4832ea1d7f2676937e69e8e00e24512005",
|
||||
"sha256:06c4d1dde5ee4f909a8a95ba1eb04040c6c26946b4f3b5beaf10d45f14e940ee",
|
||||
"sha256:09ed9b63f4df8a7591b7a4a26c1ad066dcaafda1f846250fdcb534074a411692",
|
||||
"sha256:0f7672148f8fca48e4efc16aba24a7455b40c22d4f8abe42475dec6a12b0bb9a",
|
||||
"sha256:0f89f0608a5aa8142ed0e53957916623791a88c7f5e5f07ae530c328beeb888f",
|
||||
"sha256:128bd7acf569f8443ad5b2227f30ac909e4f5399ed221727eeacf0c6476187e6",
|
||||
"sha256:19ea64fa0cf389d2ebc10974616acfa1fdecbd73d1fd9c72215b782f3c40f561",
|
||||
"sha256:1fb782982c42cee667b892a0b0c52a9f6c7ecf1da5c5f4345845f04eaa862f93",
|
||||
"sha256:218722a29c5c26677d37c44f5f8a372daf6f07870aad793a97d47eb6ad6b3290",
|
||||
"sha256:2b5e334330d82866923015b455260173cb3b9e3b4e297052d758abd262031289",
|
||||
"sha256:2bf5c846c257578b03d498b20f54f53551616a507d8e5463511c58bb58e9a9cf",
|
||||
"sha256:2d0ad9a85f208473b1f3613c45756c7aa6fcc288266a8c7b873f896aaf741b6b",
|
||||
"sha256:2f54dcc9bb9390fd0636301ead134d46d5229fe86da0db4d974c0fda349f560e",
|
||||
"sha256:3109fa601d2a448cec4643abd3a31f972bf05b7c2f2e83df9d3429878f8c10ae",
|
||||
"sha256:3210d93ad2af742b6a96cf39792f7181822edbb8fe11c3ef29d1583fe637a8d8",
|
||||
"sha256:3b3082ade8849130203d461b98c2a061b382c46074b43b4edd5cefd81af92b8a",
|
||||
"sha256:3c3f2f6b898a40207843ae01970e57e33d22a26b22f23c6a5e07b4716751085f",
|
||||
"sha256:3ca40d7844b391d90b864c6a6d1bb6b88b09035fb4d866d64d43c4d26fb0ab64",
|
||||
"sha256:3cfc067ddde78b76dcbc9684d82688b7d3c5158fa2254a085f9bcb9586c1e2d8",
|
||||
"sha256:434942fa2f9019b9ae525fb752dc523800c49a1a28fbd6d9240b0fa959573dcc",
|
||||
"sha256:46b8e24813e2fb5a3e598c1f8b9ae403e1438cb846a80cc2b33cddf19dddd7f2",
|
||||
"sha256:59c827e536bb5e3ef58e06da0faba61fd89a14f30b68bcfeca41f43ca83a1942",
|
||||
"sha256:60f37acd4e4227c5a29f737d9a85ca3145c529a8dd4bf70af7f0637c61b49222",
|
||||
"sha256:689d7d2a840619915d0abd1ecc6e399fee202f8ad315acda2807f4ca420d0802",
|
||||
"sha256:6c02e22cf09996194bcb3a4784099975cf527d5c29caf759abadf29ebdb2fe27",
|
||||
"sha256:79908b9d02b1d6c1c71ff3b7ad127f3f82e14a8e091ab44b3c7e34b649fea733",
|
||||
"sha256:7c9e99aac7b430f6a9f15eebf058c742097cea3369f23a2bfc5e64d374b67e3a",
|
||||
"sha256:813c2944e940ef8dccea71305bacc942d4b193a021140874b3e58933ec44f5b6",
|
||||
"sha256:87121b9428ac568fb84fae4af5e7852fc34f02eadc4e3e91f6c8989327692186",
|
||||
"sha256:896631cd40222aef3697e4e51177d14c3709fda49d30983269d584f034acc8a4",
|
||||
"sha256:970a4be7ec84ccda7c27cb4ae74930bbbd477bc8d849ed55ea798084dd5fca8c",
|
||||
"sha256:9939796abcadb2810a63dfb26ff8ca4595fe7dd70a3ceae7f607a2639b714307",
|
||||
"sha256:99a8071e351b50827ad976b92ed91845fb614ac67a3c41109b24f3d8bd3afada",
|
||||
"sha256:9c16fa267740d67883899e054cccb4279e002f3f4872873b752c1ba15045ff49",
|
||||
"sha256:a30e95274f5c0e007ccc759ec258aa5708c534ec058f153ee25ac700a2f1438b",
|
||||
"sha256:a74afd8d560eaafe0d9e3e1db8c06081282a05ca4de00ee416195085a79d7d3d",
|
||||
"sha256:b46a04588ceb7cf132568e0e564a854627ef87a1ed3bf536234540a79ced44b0",
|
||||
"sha256:b4963cf08f4320d98ae72ec7694291b8ab85cb7da3b0cd824bc32701bc992edf",
|
||||
"sha256:b50e481a4317a8efcfffcfddcd4c9b36eacba440440e70cbe0256aeb6fd6abae",
|
||||
"sha256:b85553699862c09937a7a5ea14ee6229087971a7d51ae97d5f4b407f571a2c17",
|
||||
"sha256:bcc98d397c3dea45d5b262029564b29cb8e945f2607a38bee6163694c0a8b4ef",
|
||||
"sha256:bed3a2a823a041e8d249b1a7ec132933e1505299329b5cfe1b2b5ec689ec7675",
|
||||
"sha256:bf6b4c0c723664f65c2a47c8cb6ebbf660b0b2e2d936adf2e8503d4e93359465",
|
||||
"sha256:bfd634cb9685161b2a51f73a7fc4736fd0d67a56632d52319317afaa27f08243",
|
||||
"sha256:c0d5ee865b5fd16bf62d72122aadcc90aab296c30c1adb0a32b4b66bd843163e",
|
||||
"sha256:c2b4eab7c12f9cb460509bc34a3b086f9802f0dba27c89a63df4123819ad64af",
|
||||
"sha256:c51568e94f7f232296de30002f2a50f77a7bd346673da3e4f2aaf9d2b833f2e5",
|
||||
"sha256:c5158616ab39d34b76c50f40c81552ee180598f7825dc7a66fd187d29958820f",
|
||||
"sha256:cdacddb18d55ffec42d1907079cdc04ec4fa8a990cdf5b9d9fe67d281fc0d12e",
|
||||
"sha256:ce763369e646e59e4ca2c09735cd1bdd3048d909ad5f2bc116e83166a9352f3c",
|
||||
"sha256:d45822b0a2a452327ab4f95efe368d234d5294bbf89a99968be27c7938a21108",
|
||||
"sha256:d8150579bf30cdf896906baf256aa200cd50dbe6e565c17d6fd3d678e21ff5de",
|
||||
"sha256:d88814befbd1433152c5f6dd536905149ba028d795a22555b149ae0a36024d9e",
|
||||
"sha256:dca5be83a6dfaf933a46e3bc2b9f2685e5ec61b22f6a38ad740aac9c16e9a0ff",
|
||||
"sha256:dd084459ecdb224e617e4ab3f1d5ebe4d1c48facb41f24952b76aa6ba9712bb0",
|
||||
"sha256:def9a01b73c9e27d70ea03b381fb3e7aadfac1f398dbd63751313c3a46747ef5",
|
||||
"sha256:df65f4b2b4e74977f0336bef12a88051ab24e6a16873cd9249f34d67cb3e345d",
|
||||
"sha256:dfe924e5a63861c82332a12adeeab955dc8c8009ddbbd80cc2fcca049ff89a49",
|
||||
"sha256:e67dcaa34dcd908fcccbf49194211d847c731b6ebaac661c1c889f1bf6af1e44",
|
||||
"sha256:eba62b7c21a33e72dd8adab2b92dd5610d8527f0b2ac28a8e0770e71b21a13f9",
|
||||
"sha256:ed9c91bf4ce614efed5388c3f989a7cfe08728ab871d995a486ea74ff88993db",
|
||||
"sha256:f05d311c937da03b0cd26ac3e14cb991f6ff8fc94f98b3df9713537817539795",
|
||||
"sha256:f1cc623fd6855b25da52b3275e0c9e51711b86a9dccc75f8c9ab4432fd8e42c7",
|
||||
"sha256:f670686d99c867d0f24b28ce8c6f02429c6eef5e2674aab287850d0ee2d20437",
|
||||
"sha256:f856652f9b533c6cd2b9ad6836a7fc0e43917d7ff15be46c5baf1350f8cdc5d9",
|
||||
"sha256:fb0458d74726937ead9e2effc91144aea5a58ecee9754242f8539a782bed685a"
|
||||
],
|
||||
"markers": "python_version >= '3.7'",
|
||||
"version": "==1.0.5"
|
||||
},
|
||||
"cycler": {
|
||||
"hashes": [
|
||||
"sha256:3a27e95f763a428a739d2add979fa7494c912a32c17c4c38c4d5f082cad165a3",
|
||||
"sha256:9c87405839a19696e837b3b818fed3f5f69f16f1eec1a1ad77e043dcea9c772f"
|
||||
],
|
||||
"markers": "python_version >= '3.6'",
|
||||
"version": "==0.11.0"
|
||||
},
|
||||
"flask": {
|
||||
"hashes": [
|
||||
"sha256:642c450d19c4ad482f96729bd2a8f6d32554aa1e231f4f6b4e7e5264b16cca2b",
|
||||
@@ -32,6 +115,14 @@
|
||||
"index": "pypi",
|
||||
"version": "==2.2.2"
|
||||
},
|
||||
"fonttools": {
|
||||
"hashes": [
|
||||
"sha256:2bb244009f9bf3fa100fc3ead6aeb99febe5985fa20afbfbaa2f8946c2fbdaf1",
|
||||
"sha256:820466f43c8be8c3009aef8b87e785014133508f0de64ec469e4efb643ae54fb"
|
||||
],
|
||||
"markers": "python_version >= '3.7'",
|
||||
"version": "==4.38.0"
|
||||
},
|
||||
"gunicorn": {
|
||||
"hashes": [
|
||||
"sha256:9dcc4547dbb1cb284accfb15ab5667a0e5d1881cc443e0677b4882a4067a807e",
|
||||
@@ -40,6 +131,14 @@
|
||||
"index": "pypi",
|
||||
"version": "==20.1.0"
|
||||
},
|
||||
"imageio": {
|
||||
"hashes": [
|
||||
"sha256:9bdafe9c5a3d336a187f3f554f3e30bcdbf8a1d7d46f0e4d94e4a535adfb64c7",
|
||||
"sha256:db7010cd10712518819a4187baf61b05988361ea20c23e829918727b27acb977"
|
||||
],
|
||||
"markers": "python_version >= '3.7'",
|
||||
"version": "==2.22.2"
|
||||
},
|
||||
"itsdangerous": {
|
||||
"hashes": [
|
||||
"sha256:2c2349112351b88699d8d4b6b075022c0808887cb7ad10069318a8b0bc88db44",
|
||||
@@ -56,6 +155,80 @@
|
||||
"markers": "python_version >= '3.7'",
|
||||
"version": "==3.1.2"
|
||||
},
|
||||
"kiwisolver": {
|
||||
"hashes": [
|
||||
"sha256:02f79693ec433cb4b5f51694e8477ae83b3205768a6fb48ffba60549080e295b",
|
||||
"sha256:03baab2d6b4a54ddbb43bba1a3a2d1627e82d205c5cf8f4c924dc49284b87166",
|
||||
"sha256:1041feb4cda8708ce73bb4dcb9ce1ccf49d553bf87c3954bdfa46f0c3f77252c",
|
||||
"sha256:10ee06759482c78bdb864f4109886dff7b8a56529bc1609d4f1112b93fe6423c",
|
||||
"sha256:1d1573129aa0fd901076e2bfb4275a35f5b7aa60fbfb984499d661ec950320b0",
|
||||
"sha256:283dffbf061a4ec60391d51e6155e372a1f7a4f5b15d59c8505339454f8989e4",
|
||||
"sha256:28bc5b299f48150b5f822ce68624e445040595a4ac3d59251703779836eceff9",
|
||||
"sha256:2a66fdfb34e05b705620dd567f5a03f239a088d5a3f321e7b6ac3239d22aa286",
|
||||
"sha256:2e307eb9bd99801f82789b44bb45e9f541961831c7311521b13a6c85afc09767",
|
||||
"sha256:2e407cb4bd5a13984a6c2c0fe1845e4e41e96f183e5e5cd4d77a857d9693494c",
|
||||
"sha256:2f5e60fabb7343a836360c4f0919b8cd0d6dbf08ad2ca6b9cf90bf0c76a3c4f6",
|
||||
"sha256:36dafec3d6d6088d34e2de6b85f9d8e2324eb734162fba59d2ba9ed7a2043d5b",
|
||||
"sha256:3fe20f63c9ecee44560d0e7f116b3a747a5d7203376abeea292ab3152334d004",
|
||||
"sha256:41dae968a94b1ef1897cb322b39360a0812661dba7c682aa45098eb8e193dbdf",
|
||||
"sha256:4bd472dbe5e136f96a4b18f295d159d7f26fd399136f5b17b08c4e5f498cd494",
|
||||
"sha256:4ea39b0ccc4f5d803e3337dd46bcce60b702be4d86fd0b3d7531ef10fd99a1ac",
|
||||
"sha256:5853eb494c71e267912275e5586fe281444eb5e722de4e131cddf9d442615626",
|
||||
"sha256:5bce61af018b0cb2055e0e72e7d65290d822d3feee430b7b8203d8a855e78766",
|
||||
"sha256:6295ecd49304dcf3bfbfa45d9a081c96509e95f4b9d0eb7ee4ec0530c4a96514",
|
||||
"sha256:62ac9cc684da4cf1778d07a89bf5f81b35834cb96ca523d3a7fb32509380cbf6",
|
||||
"sha256:70e7c2e7b750585569564e2e5ca9845acfaa5da56ac46df68414f29fea97be9f",
|
||||
"sha256:7577c1987baa3adc4b3c62c33bd1118c3ef5c8ddef36f0f2c950ae0b199e100d",
|
||||
"sha256:75facbe9606748f43428fc91a43edb46c7ff68889b91fa31f53b58894503a191",
|
||||
"sha256:787518a6789009c159453da4d6b683f468ef7a65bbde796bcea803ccf191058d",
|
||||
"sha256:78d6601aed50c74e0ef02f4204da1816147a6d3fbdc8b3872d263338a9052c51",
|
||||
"sha256:7c43e1e1206cd421cd92e6b3280d4385d41d7166b3ed577ac20444b6995a445f",
|
||||
"sha256:81e38381b782cc7e1e46c4e14cd997ee6040768101aefc8fa3c24a4cc58e98f8",
|
||||
"sha256:841293b17ad704d70c578f1f0013c890e219952169ce8a24ebc063eecf775454",
|
||||
"sha256:872b8ca05c40d309ed13eb2e582cab0c5a05e81e987ab9c521bf05ad1d5cf5cb",
|
||||
"sha256:877272cf6b4b7e94c9614f9b10140e198d2186363728ed0f701c6eee1baec1da",
|
||||
"sha256:8c808594c88a025d4e322d5bb549282c93c8e1ba71b790f539567932722d7bd8",
|
||||
"sha256:8ed58b8acf29798b036d347791141767ccf65eee7f26bde03a71c944449e53de",
|
||||
"sha256:91672bacaa030f92fc2f43b620d7b337fd9a5af28b0d6ed3f77afc43c4a64b5a",
|
||||
"sha256:968f44fdbf6dd757d12920d63b566eeb4d5b395fd2d00d29d7ef00a00582aac9",
|
||||
"sha256:9f85003f5dfa867e86d53fac6f7e6f30c045673fa27b603c397753bebadc3008",
|
||||
"sha256:a553dadda40fef6bfa1456dc4be49b113aa92c2a9a9e8711e955618cd69622e3",
|
||||
"sha256:a68b62a02953b9841730db7797422f983935aeefceb1679f0fc85cbfbd311c32",
|
||||
"sha256:abbe9fa13da955feb8202e215c4018f4bb57469b1b78c7a4c5c7b93001699938",
|
||||
"sha256:ad881edc7ccb9d65b0224f4e4d05a1e85cf62d73aab798943df6d48ab0cd79a1",
|
||||
"sha256:b1792d939ec70abe76f5054d3f36ed5656021dcad1322d1cc996d4e54165cef9",
|
||||
"sha256:b428ef021242344340460fa4c9185d0b1f66fbdbfecc6c63eff4b7c29fad429d",
|
||||
"sha256:b533558eae785e33e8c148a8d9921692a9fe5aa516efbdff8606e7d87b9d5824",
|
||||
"sha256:ba59c92039ec0a66103b1d5fe588fa546373587a7d68f5c96f743c3396afc04b",
|
||||
"sha256:bc8d3bd6c72b2dd9decf16ce70e20abcb3274ba01b4e1c96031e0c4067d1e7cd",
|
||||
"sha256:bc9db8a3efb3e403e4ecc6cd9489ea2bac94244f80c78e27c31dcc00d2790ac2",
|
||||
"sha256:bf7d9fce9bcc4752ca4a1b80aabd38f6d19009ea5cbda0e0856983cf6d0023f5",
|
||||
"sha256:c2dbb44c3f7e6c4d3487b31037b1bdbf424d97687c1747ce4ff2895795c9bf69",
|
||||
"sha256:c79ebe8f3676a4c6630fd3f777f3cfecf9289666c84e775a67d1d358578dc2e3",
|
||||
"sha256:c97528e64cb9ebeff9701e7938653a9951922f2a38bd847787d4a8e498cc83ae",
|
||||
"sha256:d0611a0a2a518464c05ddd5a3a1a0e856ccc10e67079bb17f265ad19ab3c7597",
|
||||
"sha256:d06adcfa62a4431d404c31216f0f8ac97397d799cd53800e9d3efc2fbb3cf14e",
|
||||
"sha256:d41997519fcba4a1e46eb4a2fe31bc12f0ff957b2b81bac28db24744f333e955",
|
||||
"sha256:d5b61785a9ce44e5a4b880272baa7cf6c8f48a5180c3e81c59553ba0cb0821ca",
|
||||
"sha256:da152d8cdcab0e56e4f45eb08b9aea6455845ec83172092f09b0e077ece2cf7a",
|
||||
"sha256:da7e547706e69e45d95e116e6939488d62174e033b763ab1496b4c29b76fabea",
|
||||
"sha256:db5283d90da4174865d520e7366801a93777201e91e79bacbac6e6927cbceede",
|
||||
"sha256:db608a6757adabb32f1cfe6066e39b3706d8c3aa69bbc353a5b61edad36a5cb4",
|
||||
"sha256:e0ea21f66820452a3f5d1655f8704a60d66ba1191359b96541eaf457710a5fc6",
|
||||
"sha256:e7da3fec7408813a7cebc9e4ec55afed2d0fd65c4754bc376bf03498d4e92686",
|
||||
"sha256:e92a513161077b53447160b9bd8f522edfbed4bd9759e4c18ab05d7ef7e49408",
|
||||
"sha256:ecb1fa0db7bf4cff9dac752abb19505a233c7f16684c5826d1f11ebd9472b871",
|
||||
"sha256:efda5fc8cc1c61e4f639b8067d118e742b812c930f708e6667a5ce0d13499e29",
|
||||
"sha256:f0a1dbdb5ecbef0d34eb77e56fcb3e95bbd7e50835d9782a45df81cc46949750",
|
||||
"sha256:f0a71d85ecdd570ded8ac3d1c0f480842f49a40beb423bb8014539a9f32a5897",
|
||||
"sha256:f4f270de01dd3e129a72efad823da90cc4d6aafb64c410c9033aba70db9f1ff0",
|
||||
"sha256:f6cb459eea32a4e2cf18ba5fcece2dbdf496384413bc1bae15583f19e567f3b2",
|
||||
"sha256:f8ad8285b01b0d4695102546b342b493b3ccc6781fc28c8c6a1bb63e95d22f09",
|
||||
"sha256:f9f39e2f049db33a908319cf46624a569b36983c7c78318e9726a4cb8923b26c"
|
||||
],
|
||||
"markers": "python_version >= '3.7'",
|
||||
"version": "==1.4.4"
|
||||
},
|
||||
"llvmlite": {
|
||||
"hashes": [
|
||||
"sha256:03aee0ccd81735696474dc4f8b6be60774892a2929d6c05d093d17392c237f32",
|
||||
@@ -136,6 +309,61 @@
|
||||
"markers": "python_version >= '3.7'",
|
||||
"version": "==2.1.1"
|
||||
},
|
||||
"matplotlib": {
|
||||
"hashes": [
|
||||
"sha256:02561141c434154f7bae8e5449909d152367cb40aa57bfb2a27f2748b9c5f95f",
|
||||
"sha256:05e86446562063d6186ff6d700118c0dbd5dccc403a6187351ee526c48878f10",
|
||||
"sha256:0bab7564aafd5902128d54b68dca04f5755413fb6b502100bb0235a545882c48",
|
||||
"sha256:12ab21d0cad122f5b23688d453a0280676e7c42f634f0dbd093d15d42d142b1f",
|
||||
"sha256:183bf3ac6a6023ee590aa4b677f391ceed65ec0d6b930901a8483c267bd12995",
|
||||
"sha256:1e2c75d5d1ff6b7ef9870360bfa23bea076b8dc0945a60d19453d7619ed9ea8f",
|
||||
"sha256:220314c2d6b9ca11570d7cd4b841c9f3137546f188336003b9fb8def4dcb804d",
|
||||
"sha256:2469f57e4c5cc0e85eddc7b30995ea9c404a78c0b1856da75d1a5887156ca350",
|
||||
"sha256:27337bcb38d5db7430c14f350924542d75416ec1546d5d9d9f39b362b71db3fb",
|
||||
"sha256:2cc5d726d4d42865f909c5208a7841109d76584950dd0587b01a77cc279d4ab7",
|
||||
"sha256:3c53486278a0629fd892783271dc994b962fba8dfe207445d039e14f1928ea46",
|
||||
"sha256:4648f0d79a87bf50ee740058305c91091ee5e1fbb71a7d2f5fe6707bfe328d1c",
|
||||
"sha256:47cb088bbce82ae9fc2edf3c25e56a5c6142ce2553fea2b781679f960a70c207",
|
||||
"sha256:4a3d903588b519b38ed085d0ae762a1dcd4b70164617292175cfd91b90d6c415",
|
||||
"sha256:4d3b0e0a4611bd22065bbf47e9b2f689ac9e575bcb850a9f0ae2bbed75cab956",
|
||||
"sha256:52935b7d4ccbf0dbc9cf454dbb10ca99c11cbe8da9467596b96e5e21fd4dfc5c",
|
||||
"sha256:563896ba269324872ace436a57775dcc8322678a9496b28a8c25cdafa5ec2b92",
|
||||
"sha256:565f514dec81a41cbed10eb6011501879695087fc2787fb89423a466508abbbd",
|
||||
"sha256:5f97141e05baf160c3ec125f06ceb2a44c9bb62f42fcb8ee1c05313c73e99432",
|
||||
"sha256:6f5788168da2661b42f7468063b725cc73fdbeeb80f2704cb2d8c415e9a57c50",
|
||||
"sha256:71eced071825005011cdc64efbae2e2c76b8209c18aa487dedf69796fe4b1e40",
|
||||
"sha256:7730e60e751cfcfe7fcb223cf03c0b979e9a064c239783ad37929d340a364cef",
|
||||
"sha256:8245e85fd793f58edf29b8a9e3be47e8ecf76ea1a1e8240545f2746181ca5787",
|
||||
"sha256:85948b303534b69fd771126764cf883fde2af9b003eb5778cb60f3b46f93d3f6",
|
||||
"sha256:87027ff7b2edeb14476900261ef04d4beae949e1dfa0a3eb3ad6a6efbf9d0e1d",
|
||||
"sha256:87bdbd37d0a41e025879863fe9b17bab15c0421313bc33e77e5e1aa54215c9c5",
|
||||
"sha256:8dc25473319afabe49150267e54648ac559c33b0fc2a80c8caecfbbc2948a820",
|
||||
"sha256:8ddd58324dc9a77e2e56d7b7aea7dbd0575b6f7cd1333c3ca9d388ac70978344",
|
||||
"sha256:9403764017d20ff570f7ce973a8b9637f08a6109118f4e0ce6c7493d8849a0d3",
|
||||
"sha256:9dd40505ccc526acaf9a5db1b3029e237c64b58f1249983b28a291c2d6a1d0fa",
|
||||
"sha256:a4de03085afb3b80fab341afaf8e60dfe06ce439b6dfed55d657cf34a7bc3c40",
|
||||
"sha256:a68b91ac7e6bb26100a540a033f54c95fe06d9c0aa51312c2a52d07d1bde78f4",
|
||||
"sha256:b53387d4e59432ff221540a4ffb5ee9669c69417805e4faf0148a00d701c61f9",
|
||||
"sha256:c1effccef0cea2d4da9feeed22079adf6786f92c800a7d0d2ef2104318a1c66c",
|
||||
"sha256:c9756a8e69f6e1f76d47eb42132175b6814da1fbeae0545304c6d0fc2aae252a",
|
||||
"sha256:d0161ebf87518ecfe0980c942d5f0d5df0e080c1746ebaab2027a969967014b7",
|
||||
"sha256:e2d1b7225666f7e1bcc94c0bc9c587a82e3e8691da4757e357e5c2515222ee37",
|
||||
"sha256:e3c116e779fbbf421a9e4d3060db259a9bb486d98f4e3c5a0877c599bd173582",
|
||||
"sha256:e4c8b5a243dd29d50289d694e931bd6cb6ae0b5bd654d12c647543d63862540c",
|
||||
"sha256:e632f66218811d4cf8b7a2a649e25ec15406c3c498f72d19e2bcf8377f38445d",
|
||||
"sha256:fad858519bd6d52dbfeebdbe04d00dd8e932ed436f1c535e61bcc970a96c11e4"
|
||||
],
|
||||
"index": "pypi",
|
||||
"version": "==3.6.1"
|
||||
},
|
||||
"networkx": {
|
||||
"hashes": [
|
||||
"sha256:15cdf7f7c157637107ea690cabbc488018f8256fa28242aed0fb24c93c03a06d",
|
||||
"sha256:815383fd52ece0a7024b5fd8408cc13a389ea350cd912178b82eed8b96f82cd3"
|
||||
],
|
||||
"markers": "python_version >= '3.8'",
|
||||
"version": "==2.8.7"
|
||||
},
|
||||
"numba": {
|
||||
"hashes": [
|
||||
"sha256:0744cf4214ed795eb2df3ed1635d77a6ffcbd990a66a06125548b5fb8ee46323",
|
||||
@@ -217,6 +445,173 @@
|
||||
"index": "pypi",
|
||||
"version": "==4.6.0.66"
|
||||
},
|
||||
"packaging": {
|
||||
"hashes": [
|
||||
"sha256:dd47c42927d89ab911e606518907cc2d3a1f38bbd026385970643f9c5b8ecfeb",
|
||||
"sha256:ef103e05f519cdc783ae24ea4e2e0f508a9c99b2d4969652eed6a2e1ea5bd522"
|
||||
],
|
||||
"markers": "python_version >= '3.6'",
|
||||
"version": "==21.3"
|
||||
},
|
||||
"pandas": {
|
||||
"hashes": [
|
||||
"sha256:04e51b01d5192499390c0015630975f57836cc95c7411415b499b599b05c0c96",
|
||||
"sha256:05c527c64ee02a47a24031c880ee0ded05af0623163494173204c5b72ddce658",
|
||||
"sha256:0a78e05ec09731c5b3bd7a9805927ea631fe6f6cb06f0e7c63191a9a778d52b4",
|
||||
"sha256:17da7035d9e6f9ea9cdc3a513161f8739b8f8489d31dc932bc5a29a27243f93d",
|
||||
"sha256:249cec5f2a5b22096440bd85c33106b6102e0672204abd2d5c014106459804ee",
|
||||
"sha256:2c25e5c16ee5c0feb6cf9d982b869eec94a22ddfda9aa2fbed00842cbb697624",
|
||||
"sha256:32e3d9f65606b3f6e76555bfd1d0b68d94aff0929d82010b791b6254bf5a4b96",
|
||||
"sha256:36aa1f8f680d7584e9b572c3203b20d22d697c31b71189322f16811d4ecfecd3",
|
||||
"sha256:5b0c970e2215572197b42f1cff58a908d734503ea54b326412c70d4692256391",
|
||||
"sha256:5cee0c74e93ed4f9d39007e439debcaadc519d7ea5c0afc3d590a3a7b2edf060",
|
||||
"sha256:669c8605dba6c798c1863157aefde959c1796671ffb342b80fcb80a4c0bc4c26",
|
||||
"sha256:66a1ad667b56e679e06ba73bb88c7309b3f48a4c279bd3afea29f65a766e9036",
|
||||
"sha256:683779e5728ac9138406c59a11e09cd98c7d2c12f0a5fc2b9c5eecdbb4a00075",
|
||||
"sha256:6bb391659a747cf4f181a227c3e64b6d197100d53da98dcd766cc158bdd9ec68",
|
||||
"sha256:81f0674fa50b38b6793cd84fae5d67f58f74c2d974d2cb4e476d26eee33343d0",
|
||||
"sha256:927e59c694e039c75d7023465d311277a1fc29ed7236b5746e9dddf180393113",
|
||||
"sha256:932d2d7d3cab44cfa275601c982f30c2d874722ef6396bb539e41e4dc4618ed4",
|
||||
"sha256:a52419d9ba5906db516109660b114faf791136c94c1a636ed6b29cbfff9187ee",
|
||||
"sha256:b156a971bc451c68c9e1f97567c94fd44155f073e3bceb1b0d195fd98ed12048",
|
||||
"sha256:bcf1a82b770b8f8c1e495b19a20d8296f875a796c4fe6e91da5ef107f18c5ecb",
|
||||
"sha256:cb2a9cf1150302d69bb99861c5cddc9c25aceacb0a4ef5299785d0f5389a3209",
|
||||
"sha256:d8c709f4700573deb2036d240d140934df7e852520f4a584b2a8d5443b71f54d",
|
||||
"sha256:db45b94885000981522fb92349e6b76f5aee0924cc5315881239c7859883117d",
|
||||
"sha256:ddf46b940ef815af4e542697eaf071f0531449407a7607dd731bf23d156e20a7",
|
||||
"sha256:e675f8fe9aa6c418dc8d3aac0087b5294c1a4527f1eacf9fe5ea671685285454",
|
||||
"sha256:eb7e8cf2cf11a2580088009b43de84cabbf6f5dae94ceb489f28dba01a17cb77",
|
||||
"sha256:f340331a3f411910adfb4bbe46c2ed5872d9e473a783d7f14ecf49bc0869c594"
|
||||
],
|
||||
"index": "pypi",
|
||||
"version": "==1.5.1"
|
||||
},
|
||||
"pillow": {
|
||||
"hashes": [
|
||||
"sha256:0030fdbd926fb85844b8b92e2f9449ba89607231d3dd597a21ae72dc7fe26927",
|
||||
"sha256:030e3460861488e249731c3e7ab59b07c7853838ff3b8e16aac9561bb345da14",
|
||||
"sha256:0ed2c4ef2451de908c90436d6e8092e13a43992f1860275b4d8082667fbb2ffc",
|
||||
"sha256:136659638f61a251e8ed3b331fc6ccd124590eeff539de57c5f80ef3a9594e58",
|
||||
"sha256:13b725463f32df1bfeacbf3dd197fb358ae8ebcd8c5548faa75126ea425ccb60",
|
||||
"sha256:1536ad017a9f789430fb6b8be8bf99d2f214c76502becc196c6f2d9a75b01b76",
|
||||
"sha256:15928f824870535c85dbf949c09d6ae7d3d6ac2d6efec80f3227f73eefba741c",
|
||||
"sha256:17d4cafe22f050b46d983b71c707162d63d796a1235cdf8b9d7a112e97b15bac",
|
||||
"sha256:1802f34298f5ba11d55e5bb09c31997dc0c6aed919658dfdf0198a2fe75d5490",
|
||||
"sha256:1cc1d2451e8a3b4bfdb9caf745b58e6c7a77d2e469159b0d527a4554d73694d1",
|
||||
"sha256:1fd6f5e3c0e4697fa7eb45b6e93996299f3feee73a3175fa451f49a74d092b9f",
|
||||
"sha256:254164c57bab4b459f14c64e93df11eff5ded575192c294a0c49270f22c5d93d",
|
||||
"sha256:2ad0d4df0f5ef2247e27fc790d5c9b5a0af8ade9ba340db4a73bb1a4a3e5fb4f",
|
||||
"sha256:2c58b24e3a63efd22554c676d81b0e57f80e0a7d3a5874a7e14ce90ec40d3069",
|
||||
"sha256:2d33a11f601213dcd5718109c09a52c2a1c893e7461f0be2d6febc2879ec2402",
|
||||
"sha256:336b9036127eab855beec9662ac3ea13a4544a523ae273cbf108b228ecac8437",
|
||||
"sha256:337a74fd2f291c607d220c793a8135273c4c2ab001b03e601c36766005f36885",
|
||||
"sha256:37ff6b522a26d0538b753f0b4e8e164fdada12db6c6f00f62145d732d8a3152e",
|
||||
"sha256:3d1f14f5f691f55e1b47f824ca4fdcb4b19b4323fe43cc7bb105988cad7496be",
|
||||
"sha256:4134d3f1ba5f15027ff5c04296f13328fecd46921424084516bdb1b2548e66ff",
|
||||
"sha256:4ad2f835e0ad81d1689f1b7e3fbac7b01bb8777d5a985c8962bedee0cc6d43da",
|
||||
"sha256:50dff9cc21826d2977ef2d2a205504034e3a4563ca6f5db739b0d1026658e004",
|
||||
"sha256:510cef4a3f401c246cfd8227b300828715dd055463cdca6176c2e4036df8bd4f",
|
||||
"sha256:5aed7dde98403cd91d86a1115c78d8145c83078e864c1de1064f52e6feb61b20",
|
||||
"sha256:69bd1a15d7ba3694631e00df8de65a8cb031911ca11f44929c97fe05eb9b6c1d",
|
||||
"sha256:6bf088c1ce160f50ea40764f825ec9b72ed9da25346216b91361eef8ad1b8f8c",
|
||||
"sha256:6e8c66f70fb539301e064f6478d7453e820d8a2c631da948a23384865cd95544",
|
||||
"sha256:74a04183e6e64930b667d321524e3c5361094bb4af9083db5c301db64cd341f3",
|
||||
"sha256:75e636fd3e0fb872693f23ccb8a5ff2cd578801251f3a4f6854c6a5d437d3c04",
|
||||
"sha256:7761afe0126d046974a01e030ae7529ed0ca6a196de3ec6937c11df0df1bc91c",
|
||||
"sha256:7888310f6214f19ab2b6df90f3f06afa3df7ef7355fc025e78a3044737fab1f5",
|
||||
"sha256:7b0554af24df2bf96618dac71ddada02420f946be943b181108cac55a7a2dcd4",
|
||||
"sha256:7c7b502bc34f6e32ba022b4a209638f9e097d7a9098104ae420eb8186217ebbb",
|
||||
"sha256:808add66ea764ed97d44dda1ac4f2cfec4c1867d9efb16a33d158be79f32b8a4",
|
||||
"sha256:831e648102c82f152e14c1a0938689dbb22480c548c8d4b8b248b3e50967b88c",
|
||||
"sha256:93689632949aff41199090eff5474f3990b6823404e45d66a5d44304e9cdc467",
|
||||
"sha256:96b5e6874431df16aee0c1ba237574cb6dff1dcb173798faa6a9d8b399a05d0e",
|
||||
"sha256:9a54614049a18a2d6fe156e68e188da02a046a4a93cf24f373bffd977e943421",
|
||||
"sha256:a138441e95562b3c078746a22f8fca8ff1c22c014f856278bdbdd89ca36cff1b",
|
||||
"sha256:a647c0d4478b995c5e54615a2e5360ccedd2f85e70ab57fbe817ca613d5e63b8",
|
||||
"sha256:a9c9bc489f8ab30906d7a85afac4b4944a572a7432e00698a7239f44a44e6efb",
|
||||
"sha256:ad2277b185ebce47a63f4dc6302e30f05762b688f8dc3de55dbae4651872cdf3",
|
||||
"sha256:adabc0bce035467fb537ef3e5e74f2847c8af217ee0be0455d4fec8adc0462fc",
|
||||
"sha256:b6d5e92df2b77665e07ddb2e4dbd6d644b78e4c0d2e9272a852627cdba0d75cf",
|
||||
"sha256:bc431b065722a5ad1dfb4df354fb9333b7a582a5ee39a90e6ffff688d72f27a1",
|
||||
"sha256:bdd0de2d64688ecae88dd8935012c4a72681e5df632af903a1dca8c5e7aa871a",
|
||||
"sha256:c79698d4cd9318d9481d89a77e2d3fcaeff5486be641e60a4b49f3d2ecca4e28",
|
||||
"sha256:cb6259196a589123d755380b65127ddc60f4c64b21fc3bb46ce3a6ea663659b0",
|
||||
"sha256:d5b87da55a08acb586bad5c3aa3b86505f559b84f39035b233d5bf844b0834b1",
|
||||
"sha256:dcd7b9c7139dc8258d164b55696ecd16c04607f1cc33ba7af86613881ffe4ac8",
|
||||
"sha256:dfe4c1fedfde4e2fbc009d5ad420647f7730d719786388b7de0999bf32c0d9fd",
|
||||
"sha256:ea98f633d45f7e815db648fd7ff0f19e328302ac36427343e4432c84432e7ff4",
|
||||
"sha256:ec52c351b35ca269cb1f8069d610fc45c5bd38c3e91f9ab4cbbf0aebc136d9c8",
|
||||
"sha256:eef7592281f7c174d3d6cbfbb7ee5984a671fcd77e3fc78e973d492e9bf0eb3f",
|
||||
"sha256:f07f1f00e22b231dd3d9b9208692042e29792d6bd4f6639415d2f23158a80013",
|
||||
"sha256:f3fac744f9b540148fa7715a435d2283b71f68bfb6d4aae24482a890aed18b59",
|
||||
"sha256:fa768eff5f9f958270b081bb33581b4b569faabf8774726b283edb06617101dc",
|
||||
"sha256:fac2d65901fb0fdf20363fbd345c01958a742f2dc62a8dd4495af66e3ff502a4"
|
||||
],
|
||||
"markers": "python_version >= '3.7'",
|
||||
"version": "==9.2.0"
|
||||
},
|
||||
"plotly": {
|
||||
"hashes": [
|
||||
"sha256:4efef479c2ec1d86dcdac8405b6ca70ca65649a77408e39a7e84a1ea2db6c787",
|
||||
"sha256:52fd74b08aa4fd5a55b9d3034a30dbb746e572d7ed84897422f927fdf687ea5f"
|
||||
],
|
||||
"index": "pypi",
|
||||
"version": "==5.11.0"
|
||||
},
|
||||
"pyparsing": {
|
||||
"hashes": [
|
||||
"sha256:2b020ecf7d21b687f219b71ecad3631f644a47f01403fa1d1036b0c6416d70fb",
|
||||
"sha256:5026bae9a10eeaefb61dab2f09052b9f4307d44aee4eda64b309723d8d206bbc"
|
||||
],
|
||||
"markers": "python_full_version >= '3.6.8'",
|
||||
"version": "==3.0.9"
|
||||
},
|
||||
"python-dateutil": {
|
||||
"hashes": [
|
||||
"sha256:0123cacc1627ae19ddf3c27a5de5bd67ee4586fbdd6440d9748f8abb483d3e86",
|
||||
"sha256:961d03dc3453ebbc59dbdea9e4e11c5651520a876d0f4db161e8674aae935da9"
|
||||
],
|
||||
"markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'",
|
||||
"version": "==2.8.2"
|
||||
},
|
||||
"pytz": {
|
||||
"hashes": [
|
||||
"sha256:335ab46900b1465e714b4fda4963d87363264eb662aab5e65da039c25f1f5b22",
|
||||
"sha256:c4d88f472f54d615e9cd582a5004d1e5f624854a6a27a6211591c251f22a6914"
|
||||
],
|
||||
"version": "==2022.5"
|
||||
},
|
||||
"pywavelets": {
|
||||
"hashes": [
|
||||
"sha256:030670a213ee8fefa56f6387b0c8e7d970c7f7ad6850dc048bd7c89364771b9b",
|
||||
"sha256:058b46434eac4c04dd89aeef6fa39e4b6496a951d78c500b6641fd5b2cc2f9f4",
|
||||
"sha256:231b0e0b1cdc1112f4af3c24eea7bf181c418d37922a67670e9bf6cfa2d544d4",
|
||||
"sha256:23bafd60350b2b868076d976bdd92f950b3944f119b4754b1d7ff22b7acbf6c6",
|
||||
"sha256:3f19327f2129fb7977bc59b966b4974dfd72879c093e44a7287500a7032695de",
|
||||
"sha256:47cac4fa25bed76a45bc781a293c26ac63e8eaae9eb8f9be961758d22b58649c",
|
||||
"sha256:578af438a02a86b70f1975b546f68aaaf38f28fb082a61ceb799816049ed18aa",
|
||||
"sha256:6437af3ddf083118c26d8f97ab43b0724b956c9f958e9ea788659f6a2834ba93",
|
||||
"sha256:64c6bac6204327321db30b775060fbe8e8642316e6bff17f06b9f34936f88875",
|
||||
"sha256:67a0d28a08909f21400cb09ff62ba94c064882ffd9e3a6b27880a111211d59bd",
|
||||
"sha256:71ab30f51ee4470741bb55fc6b197b4a2b612232e30f6ac069106f0156342356",
|
||||
"sha256:7231461d7a8eb3bdc7aa2d97d9f67ea5a9f8902522818e7e2ead9c2b3408eeb1",
|
||||
"sha256:754fa5085768227c4f4a26c1e0c78bc509a266d9ebd0eb69a278be7e3ece943c",
|
||||
"sha256:7ab8d9db0fe549ab2ee0bea61f614e658dd2df419d5b75fba47baa761e95f8f2",
|
||||
"sha256:875d4d620eee655346e3589a16a73790cf9f8917abba062234439b594e706784",
|
||||
"sha256:88aa5449e109d8f5e7f0adef85f7f73b1ab086102865be64421a3a3d02d277f4",
|
||||
"sha256:91d3d393cffa634f0e550d88c0e3f217c96cfb9e32781f2960876f1808d9b45b",
|
||||
"sha256:9cb5ca8d11d3f98e89e65796a2125be98424d22e5ada360a0dbabff659fca0fc",
|
||||
"sha256:ab7da0a17822cd2f6545626946d3b82d1a8e106afc4b50e3387719ba01c7b966",
|
||||
"sha256:ad987748f60418d5f4138db89d82ba0cb49b086e0cbb8fd5c3ed4a814cfb705e",
|
||||
"sha256:d0e56cd7a53aed3cceca91a04d62feb3a0aca6725b1912d29546c26f6ea90426",
|
||||
"sha256:d854411eb5ee9cb4bc5d0e66e3634aeb8f594210f6a1bed96dbed57ec70f181c",
|
||||
"sha256:da7b9c006171be1f9ddb12cc6e0d3d703b95f7f43cb5e2c6f5f15d3233fcf202",
|
||||
"sha256:daf0aa79842b571308d7c31a9c43bc99a30b6328e6aea3f50388cd8f69ba7dbc",
|
||||
"sha256:de7cd61a88a982edfec01ea755b0740e94766e00a1ceceeafef3ed4c85c605cd"
|
||||
],
|
||||
"markers": "python_version >= '3.8'",
|
||||
"version": "==1.4.1"
|
||||
},
|
||||
"pyyaml": {
|
||||
"hashes": [
|
||||
"sha256:01b45c0191e6d66c470b6cf1b9531a771a83c1c4208272ead47a3ae4f2f603bf",
|
||||
@@ -263,6 +658,67 @@
|
||||
"index": "pypi",
|
||||
"version": "==6.0"
|
||||
},
|
||||
"scikit-image": {
|
||||
"hashes": [
|
||||
"sha256:03779a7e1736fdf89d83c0ba67d44110496edd736a3bfce61a2b5177a1c8a099",
|
||||
"sha256:0b0a199157ce8487c77de4fde0edc0b42d6d42818881c11f459262351d678b2d",
|
||||
"sha256:19a21a101a20c587a3b611a2cf6f86c35aae9f8d9563279b987e83ee1c9a9790",
|
||||
"sha256:24b5367de1762da6ee126dd8f30cc4e7efda474e0d7d70685433f0e3aa2ec450",
|
||||
"sha256:2a02d1bd0e2b53e36b952bd5fd6118d9ccc3ee51de35705d63d8eb1f2e86adef",
|
||||
"sha256:2f50b923f8099c1045fcde7418d86b206c87e333e43da980f41d8577b9605245",
|
||||
"sha256:32fb88cc36203b99c9672fb972c9ef98635deaa5fc889fe969f3e11c44f22919",
|
||||
"sha256:33dfd463ee6cc509defa279b963829f2230c9e0639ccd3931045be055878eea6",
|
||||
"sha256:3a01372ae4bca223873304b0bff79b9d92446ac6d6177f73d89b45561e2d09d8",
|
||||
"sha256:651de1c2ce1fbee834753b46b8e7d81cb12a5594898babba63ac82b30ddad49d",
|
||||
"sha256:6b6a8f98f2ac9bb73706461fd1dec875f6a5141759ed526850a5a49e90003d19",
|
||||
"sha256:7f9f8a1387afc6c70f2bed007c3854a2d7489f9f7713c242f16f32ee05934bc2",
|
||||
"sha256:84baa3179f3ae983c3a5d81c1e404bc92dcf7daeb41bfe9369badcda3fb22b92",
|
||||
"sha256:8d8917fcf85b987b1f287f823f3a1a7dac38b70aaca759bc0200f3bc292d5ced",
|
||||
"sha256:9439e5294de3f18d6e82ec8eee2c46590231cf9c690da80545e83a0733b7a69e",
|
||||
"sha256:9fb0923a3bfa99457c5e17888f27b3b8a83a3600b4fef317992e7b7234764732",
|
||||
"sha256:a7c3985c68bfe05f7571167ee021d14f5b8d1a4a250c91f0b13be7fb07e6af34",
|
||||
"sha256:a8714348ddd671f819457a797c97d4c672166f093def66d66c3254cbd1d43f83",
|
||||
"sha256:ad5d8000207a264d1a55681a9276e6a739d3f05cf4429004ad00d61d1892235f",
|
||||
"sha256:cc24177de3fdceca5d04807ad9c87d665f0bf01032ed94a9055cd1ed2b3f33e9",
|
||||
"sha256:ce3d2207f253b8eb2c824e30d145a9f07a34a14212d57f3beca9f7e03c383cbe",
|
||||
"sha256:cfbb073f23deb48e0e60c47f8741d8089121d89cc78629ea8c5b51096efc5be7",
|
||||
"sha256:e207c6ce5ce121d7d9b9d2b61b9adca57d1abed112c902d8ffbfdc20fb42c12b",
|
||||
"sha256:fd9dd3994bb6f9f7a35f228323f3c4dc44b3cf2ff15fd72d895216e9333550c6",
|
||||
"sha256:fdf48d9b1f13af69e4e2c78e05067e322e9c8c97463c315cd0ecb47a94e259fc",
|
||||
"sha256:ff3b1025356508d41f4fe48528e509d95f9e4015e90cf158cd58c56dc63e0ac5"
|
||||
],
|
||||
"index": "pypi",
|
||||
"version": "==0.19.3"
|
||||
},
|
||||
"scipy": {
|
||||
"hashes": [
|
||||
"sha256:02b567e722d62bddd4ac253dafb01ce7ed8742cf8031aea030a41414b86c1125",
|
||||
"sha256:1166514aa3bbf04cb5941027c6e294a000bba0cf00f5cdac6c77f2dad479b434",
|
||||
"sha256:1da52b45ce1a24a4a22db6c157c38b39885a990a566748fc904ec9f03ed8c6ba",
|
||||
"sha256:23b22fbeef3807966ea42d8163322366dd89da9bebdc075da7034cee3a1441ca",
|
||||
"sha256:28d2cab0c6ac5aa131cc5071a3a1d8e1366dad82288d9ec2ca44df78fb50e649",
|
||||
"sha256:2ef0fbc8bcf102c1998c1f16f15befe7cffba90895d6e84861cd6c6a33fb54f6",
|
||||
"sha256:3b69b90c9419884efeffaac2c38376d6ef566e6e730a231e15722b0ab58f0328",
|
||||
"sha256:4b93ec6f4c3c4d041b26b5f179a6aab8f5045423117ae7a45ba9710301d7e462",
|
||||
"sha256:4e53a55f6a4f22de01ffe1d2f016e30adedb67a699a310cdcac312806807ca81",
|
||||
"sha256:6311e3ae9cc75f77c33076cb2794fb0606f14c8f1b1c9ff8ce6005ba2c283621",
|
||||
"sha256:65b77f20202599c51eb2771d11a6b899b97989159b7975e9b5259594f1d35ef4",
|
||||
"sha256:6cc6b33139eb63f30725d5f7fa175763dc2df6a8f38ddf8df971f7c345b652dc",
|
||||
"sha256:70de2f11bf64ca9921fda018864c78af7147025e467ce9f4a11bc877266900a6",
|
||||
"sha256:70ebc84134cf0c504ce6a5f12d6db92cb2a8a53a49437a6bb4edca0bc101f11c",
|
||||
"sha256:83606129247e7610b58d0e1e93d2c5133959e9cf93555d3c27e536892f1ba1f2",
|
||||
"sha256:93d07494a8900d55492401917a119948ed330b8c3f1d700e0b904a578f10ead4",
|
||||
"sha256:9c4e3ae8a716c8b3151e16c05edb1daf4cb4d866caa385e861556aff41300c14",
|
||||
"sha256:9dd4012ac599a1e7eb63c114d1eee1bcfc6dc75a29b589ff0ad0bb3d9412034f",
|
||||
"sha256:9e3fb1b0e896f14a85aa9a28d5f755daaeeb54c897b746df7a55ccb02b340f33",
|
||||
"sha256:a0aa8220b89b2e3748a2836fbfa116194378910f1a6e78e4675a095bcd2c762d",
|
||||
"sha256:d3b3c8924252caaffc54d4a99f1360aeec001e61267595561089f8b5900821bb",
|
||||
"sha256:e013aed00ed776d790be4cb32826adb72799c61e318676172495383ba4570aa4",
|
||||
"sha256:f3e7a8867f307e3359cc0ed2c63b61a1e33a19080f92fe377bc7d49f646f2ec1"
|
||||
],
|
||||
"index": "pypi",
|
||||
"version": "==1.8.1"
|
||||
},
|
||||
"setuptools": {
|
||||
"hashes": [
|
||||
"sha256:512e5536220e38146176efb833d4a62aa726b7bbff82cfbc8ba9eaa3996e0b17",
|
||||
@@ -271,6 +727,30 @@
|
||||
"markers": "python_version >= '3.7'",
|
||||
"version": "==65.5.0"
|
||||
},
|
||||
"six": {
|
||||
"hashes": [
|
||||
"sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926",
|
||||
"sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"
|
||||
],
|
||||
"markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'",
|
||||
"version": "==1.16.0"
|
||||
},
|
||||
"tenacity": {
|
||||
"hashes": [
|
||||
"sha256:35525cd47f82830069f0d6b73f7eb83bc5b73ee2fff0437952cedf98b27653ac",
|
||||
"sha256:e48c437fdf9340f5666b92cd7990e96bc5fc955e1298baf4a907e3972067a445"
|
||||
],
|
||||
"markers": "python_version >= '3.6'",
|
||||
"version": "==8.1.0"
|
||||
},
|
||||
"tifffile": {
|
||||
"hashes": [
|
||||
"sha256:50b61ba943b866d191295bc38a00191c9fdab23ece063544c7f1a264e3f6aa8e",
|
||||
"sha256:87f3aee8a0d06b74655269a105de75c1958a24653e1930d523eb516100043503"
|
||||
],
|
||||
"markers": "python_version >= '3.8'",
|
||||
"version": "==2022.10.10"
|
||||
},
|
||||
"werkzeug": {
|
||||
"hashes": [
|
||||
"sha256:7ea2d48322cc7c0f8b3a215ed73eabd7b5d75d0b50e31ab006286ccff9e00b8f",
|
||||
|
||||
39
README.md
@@ -1,18 +1,31 @@
|
||||
# Pyrometry image processing
|
||||
# Fire Lab Work
|
||||
|
||||
## Interface Screenshots
|
||||
|
||||
| Input View | Results |
|
||||
| Input View | Results | Temp. Distribution |
|
||||
| --- | --- | --- |
|
||||
|  |  | 
|
||||
|
||||
| Labeling Input | Labeling Results |
|
||||
| --- | --- |
|
||||
|  | 
|
||||
|  |  |
|
||||
|
||||
## Using the web version
|
||||
|
||||
### Ratio Pyrometry
|
||||
|
||||
1. Go to [pyro.turtlebasket.ml](https://pyro.turtlebasket.ml).
|
||||
2. Select an input image.
|
||||
3. Enter your DSLR camera settings.
|
||||
4. Click "Generate Heatmap".
|
||||
|
||||
### Projected Object Area
|
||||
|
||||
1. Go to [pyro.turtlebasket.ml](https://pyro.turtlebasket.ml).
|
||||
2. Navigate to "Object Area".
|
||||
3. Select an input image.
|
||||
4. Click "Generate Projected Sizes".
|
||||
|
||||
## Using the local (batch) version
|
||||
|
||||
Create a new config file:
|
||||
@@ -67,23 +80,3 @@ To autoreload on source file changes:
|
||||
```
|
||||
gunicorn flask_frontend:app --reload
|
||||
```
|
||||
|
||||
## Temperature maps
|
||||
|
||||
**Grayscale pyrometry:** currently basic; uses grayscale opencv import, then just applies a jet filter. Doesn't yet copy the full impl in the paper.
|
||||
|
||||
**Ratio pyrometry:** pretty damn close to what's in the paper but it's very broken atm
|
||||
|
||||
**Test image:**
|
||||
|
||||

|
||||
|
||||
**Ratio pyrometry result (with convolutional smoothing):**
|
||||
|
||||
According to general researcher consensus, ratio pyrometry is supposed to be more accurate.
|
||||
|
||||

|
||||
|
||||
**Grayscale pyrometry result:**
|
||||
|
||||

|
||||
|
||||
@@ -2,14 +2,15 @@ import yaml
|
||||
import cv2 as cv
|
||||
import numpy as np
|
||||
import os
|
||||
from matplotlib import pyplot as plt, image as mpimg
|
||||
from ratio_pyrometry import rg_ratio_normalize
|
||||
|
||||
config = {}
|
||||
with open("./config.yaml", "r") as yaml_stream:
|
||||
config = yaml.safe_load(yaml_stream)
|
||||
|
||||
img_in_dir = "./images-input"
|
||||
img_out_dir = "./images-output"
|
||||
img_input_dir = "images-input"
|
||||
img_out_dir = "images-output"
|
||||
accepted_formats = [
|
||||
".jpg",
|
||||
".jpeg",
|
||||
@@ -19,44 +20,64 @@ accepted_formats = [
|
||||
|
||||
files = []
|
||||
|
||||
for file in os.listdir(img_in_dir):
|
||||
for file in os.listdir(img_input_dir):
|
||||
filename = os.fsdecode(file)
|
||||
valid = False
|
||||
for fmt in accepted_formats:
|
||||
if filename.endswith(fmt):
|
||||
files.append(os.path.join(img_in_dir, filename))
|
||||
files.append(filename)
|
||||
valid = True
|
||||
break
|
||||
if not valid:
|
||||
if not valid and filename != ".gitkeep":
|
||||
print(f"Invalid file extension for {filename}.")
|
||||
exit
|
||||
|
||||
|
||||
for filename in files:
|
||||
with open(filename) as imgfile:
|
||||
# read image & crop
|
||||
img_orig = cv.imread(imgfile, cv.IMREAD_UNCHANGED)
|
||||
# read image & crop
|
||||
img_orig = cv.imread(f'{img_input_dir}/{filename}', cv.IMREAD_UNCHANGED)
|
||||
|
||||
img = rg_ratio_normalize(
|
||||
img_orig,
|
||||
config['i-darkcurrent'],
|
||||
config['f-stop'],
|
||||
config['exposure-time'],
|
||||
config['iso'],
|
||||
config['min-temp'],
|
||||
config['max-temp'],
|
||||
config['scaling-factor'],
|
||||
)
|
||||
img = rg_ratio_normalize(
|
||||
img_orig,
|
||||
config['i-darkcurrent'],
|
||||
config['f-stop'],
|
||||
config['exposure-time'],
|
||||
config['iso'],
|
||||
config['min-temp'],
|
||||
config['max-temp'],
|
||||
config['scaling-factor'],
|
||||
img_out=False
|
||||
)
|
||||
|
||||
# build & apply smoothing conv kernel
|
||||
k = []
|
||||
smoothing_radius = config['smoothing-radius']
|
||||
for i in range(smoothing_radius):
|
||||
k.append([1/(smoothing_radius**2) for i in range(smoothing_radius)])
|
||||
kernel = np.array(k)
|
||||
# build & apply smoothing conv kernel
|
||||
k = []
|
||||
smoothing_radius = config['smoothing-radius']
|
||||
for i in range(smoothing_radius):
|
||||
k.append([1/(smoothing_radius**2) for i in range(smoothing_radius)])
|
||||
kernel = np.array(k)
|
||||
|
||||
img = cv.filter2D(src=img, ddepth=-1, kernel=kernel)
|
||||
img = cv.filter2D(src=img, ddepth=-1, kernel=kernel)
|
||||
|
||||
# write colormapped image
|
||||
img_jet = cv.applyColorMap(img, cv.COLORMAP_JET)
|
||||
# chop off alphas & reverse bgr
|
||||
img_orig = img_orig[:,:,:3]
|
||||
img_orig = img_orig[:,:,::-1]
|
||||
|
||||
# TODO: GENERTE TEMP KEY & OUTPUT MATPLOTLIB
|
||||
fig = plt.figure()
|
||||
ax = fig.add_subplot(1, 2, 1)
|
||||
ax.set_title("Original Image")
|
||||
imgplot_orig = plt.imshow(img_orig)
|
||||
ax2 = fig.add_subplot(1, 2, 2)
|
||||
ax2.set_title("Output Heatmap")
|
||||
imgplot_final = plt.imshow(img, cmap="plasma")
|
||||
ticks = np.linspace(
|
||||
config['min-temp'],
|
||||
config['max-temp'],
|
||||
4
|
||||
).tolist()
|
||||
cbar = plt.colorbar(
|
||||
orientation="horizontal",
|
||||
)
|
||||
cbar.ax.set_xticklabels([str(t) for t in ticks])
|
||||
|
||||
name = filename.split(".")[0]
|
||||
extension = filename.split(".")[1]
|
||||
fig.savefig(f"{img_out_dir}/{name}-transformed.{extension}", dpi=120)
|
||||
|
||||
|
Before Width: | Height: | Size: 7.7 KiB |
@@ -1,21 +0,0 @@
|
||||
# MONOCHROME EDGE DETECTION
|
||||
|
||||
import cv2 as cv
|
||||
import numpy as np
|
||||
|
||||
file = '01-0001-cropped.png'
|
||||
file_name = file.split(".")[0]
|
||||
file_ext = file.split(".")[1]
|
||||
|
||||
img = cv.imread(file)
|
||||
|
||||
img = cv.cvtColor(img, cv.COLOR_BGR2GRAY)
|
||||
|
||||
kernel = np.array([
|
||||
[-1, -1, -1],
|
||||
[-1, 8, -1],
|
||||
[-1, -1, -1],
|
||||
])
|
||||
img = cv.filter2D(src=img, ddepth=-1, kernel=kernel)
|
||||
|
||||
cv.imwrite(f'{file_name}-edge-detection.{file_ext}', img)
|
||||
BIN
examples/projected-area/output.png
Normal file
|
After Width: | Height: | Size: 169 KiB |
BIN
examples/projected-area/proj-area-0.png
Normal file
|
After Width: | Height: | Size: 285 KiB |
BIN
examples/projected-area/proj-area-1-processed.jpg
Normal file
|
After Width: | Height: | Size: 215 KiB |
BIN
examples/projected-area/proj-area-1.jpg
Normal file
|
After Width: | Height: | Size: 561 KiB |
BIN
examples/projected-area/proj-area-2.jpg
Normal file
|
After Width: | Height: | Size: 539 KiB |
BIN
examples/projected-area/proj-area-3.jpg
Normal file
|
After Width: | Height: | Size: 1.8 MiB |
80
examples/projected-area/projected_area.py
Normal file
@@ -0,0 +1,80 @@
|
||||
import cv2 as cv
|
||||
import numpy as np
|
||||
from skimage import measure, morphology, color, segmentation
|
||||
import matplotlib.pyplot as plt
|
||||
|
||||
file = 'proj-area-3.jpg'
|
||||
|
||||
original = cv.imread(file)
|
||||
original = cv.cvtColor(original, cv.COLOR_BGR2RGB)
|
||||
img = original
|
||||
|
||||
img = cv.cvtColor(img, cv.COLOR_BGR2GRAY)
|
||||
|
||||
retval, thresh_gray = cv.threshold(img, 200, 255, cv.THRESH_BINARY)
|
||||
|
||||
def remove_dirt(image):
|
||||
image = morphology.area_closing(image, area_threshold=250, connectivity=1)
|
||||
# image = morphology.opening(image, morphology.square(5))
|
||||
|
||||
return image
|
||||
|
||||
def calculate_area(countour):
|
||||
c = np.expand_dims(countour.astype(np.float32), 1)
|
||||
c = cv.UMat(c)
|
||||
|
||||
return cv.contourArea(c)
|
||||
|
||||
def center_of_mass(X):
|
||||
x = X[:,0]
|
||||
y = X[:,1]
|
||||
g = (x[:-1]*y[1:] - x[1:]*y[:-1])
|
||||
A = 0.5*g.sum()
|
||||
cx = ((x[:-1] + x[1:])*g).sum()
|
||||
cy = ((y[:-1] + y[1:])*g).sum()
|
||||
|
||||
return 1./(6*A)*np.array([cx,cy])
|
||||
|
||||
img = remove_dirt(thresh_gray)
|
||||
|
||||
|
||||
# alpha = 1 # Contrast control (1.0-3.0)
|
||||
# beta = 1 # Brightness control (0-100)
|
||||
|
||||
# img = cv.convertScaleAbs(img, alpha=alpha, beta=beta)
|
||||
|
||||
# img = cv.cvtColor(img, cv.COLOR_BGR2GRAY)
|
||||
|
||||
# img = cv.medianBlur(img, 5)
|
||||
|
||||
# retval, thresh_gray = cv.threshold(img, 0, 255, cv.THRESH_BINARY_INV | cv.THRESH_OTSU)
|
||||
|
||||
|
||||
# img = cv.medianBlur(img, 5)
|
||||
|
||||
# img = cv.adaptiveThreshold(img, 255, cv.ADAPTIVE_THRESH_GAUSSIAN_C, cv.THRESH_BINARY_INV, 51, 15)
|
||||
|
||||
contours = measure.find_contours(array=img, level=100)
|
||||
|
||||
fig, ax = plt.subplots()
|
||||
ax.imshow(img, cmap=plt.cm.gray, alpha=0)
|
||||
|
||||
index = 1
|
||||
|
||||
for contour in contours:
|
||||
if calculate_area(contour) > 300:
|
||||
ax.plot(contour[:, 1], contour[:, 0], linewidth=0.5, color='orangered')
|
||||
|
||||
cX, cY = center_of_mass(contour)
|
||||
|
||||
plt.text(cY, cX, index, color='black', fontsize=6)
|
||||
|
||||
index += 1
|
||||
|
||||
ax.axis('image')
|
||||
ax.set_xticks([])
|
||||
ax.set_yticks([])
|
||||
|
||||
plt.savefig('output.png', dpi=300)
|
||||
|
||||
# cv.imwrite('proj-area-1-processed.jpg', remove_dirt(img))
|
||||
|
Before Width: | Height: | Size: 263 KiB After Width: | Height: | Size: 263 KiB |
|
Before Width: | Height: | Size: 27 KiB After Width: | Height: | Size: 27 KiB |
|
Before Width: | Height: | Size: 513 KiB After Width: | Height: | Size: 513 KiB |
|
Before Width: | Height: | Size: 986 KiB After Width: | Height: | Size: 986 KiB |
|
Before Width: | Height: | Size: 1.3 MiB After Width: | Height: | Size: 1.3 MiB |
|
Before Width: | Height: | Size: 9.9 KiB After Width: | Height: | Size: 9.9 KiB |
|
Before Width: | Height: | Size: 414 KiB After Width: | Height: | Size: 414 KiB |
|
Before Width: | Height: | Size: 1.1 MiB After Width: | Height: | Size: 1.1 MiB |
|
Before Width: | Height: | Size: 354 KiB After Width: | Height: | Size: 354 KiB |
|
Before Width: | Height: | Size: 841 KiB After Width: | Height: | Size: 841 KiB |
BIN
examples/pyrometry/_DSC1022 (1)-edge-detection.png
Normal file
|
After Width: | Height: | Size: 9.7 MiB |
|
Before Width: | Height: | Size: 15 MiB After Width: | Height: | Size: 15 MiB |
BIN
examples/pyrometry/asdf.png
Normal file
|
After Width: | Height: | Size: 8.6 KiB |
78
examples/pyrometry/edge_detection.py
Normal file
@@ -0,0 +1,78 @@
|
||||
# MONOCHROME EDGE DETECTION
|
||||
|
||||
import cv2 as cv
|
||||
import numpy as np
|
||||
from skimage import measure, morphology, color, segmentation
|
||||
import matplotlib.pyplot as plt
|
||||
|
||||
file = 'streaktest2.png'
|
||||
img = cv.imread(file)
|
||||
|
||||
# blurred = cv.GaussianBlur(img, (8, 8), 0)
|
||||
|
||||
retval, thresh_gray = cv.threshold(img, 120, 255, cv.THRESH_BINARY)
|
||||
|
||||
kernel = np.ones((7, 7), np.uint8)
|
||||
image = cv.morphologyEx(thresh_gray, cv.MORPH_CLOSE, kernel, iterations=1)
|
||||
gray = cv.cvtColor(image, cv.COLOR_BGR2GRAY)
|
||||
|
||||
retval, gray = cv.threshold(gray, 0, 255, cv.THRESH_BINARY)
|
||||
|
||||
gray = cv.copyMakeBorder(
|
||||
gray,
|
||||
20,
|
||||
20,
|
||||
20,
|
||||
20,
|
||||
cv.BORDER_CONSTANT,
|
||||
value=0
|
||||
)
|
||||
|
||||
# cv.imshow('gray', gray)
|
||||
# cv.waitKey(0)
|
||||
|
||||
# contours = measure.find_contours(array=gray, level=100)
|
||||
_img, contours = cv.findContours(gray, cv.RETR_LIST, cv.CHAIN_APPROX_NONE)[0]
|
||||
|
||||
fig, ax = plt.subplots()
|
||||
ax.imshow(gray, cmap=plt.cm.gray, alpha=1)
|
||||
|
||||
def calculate_area(countour):
|
||||
c = np.expand_dims(countour.astype(np.float32), 1)
|
||||
c = cv.UMat(c)
|
||||
|
||||
return cv.contourArea(c)
|
||||
|
||||
def center_of_mass(X):
|
||||
x = X[:,0]
|
||||
y = X[:,1]
|
||||
g = (x[:-1]*y[1:] - x[1:]*y[:-1])
|
||||
A = 0.5*g.sum()
|
||||
cx = ((x[:-1] + x[1:])*g).sum()
|
||||
cy = ((y[:-1] + y[1:])*g).sum()
|
||||
|
||||
return 1./(6*A)*np.array([cx,cy])
|
||||
|
||||
|
||||
img_new = cv.cvtColor(gray, cv.COLOR_GRAY2BGR)
|
||||
|
||||
for contour in contours:
|
||||
area = calculate_area(contour)
|
||||
|
||||
# if area > 250:
|
||||
# cnt = np.array(contour).reshape((-1, 1, 2)).astype(np.int32)
|
||||
# cv.drawContours(img_new, [cnt], -1, (0, 200, 255), thickness=10)
|
||||
|
||||
cv.drawContours(img_new, [contour], -1, (0, 200, 255), thickness=3)
|
||||
|
||||
# ax.plot(contour[:, 1], contour[:, 0], linewidth=0.5, color='orangered')
|
||||
|
||||
# cv.imshow('contours', img_new)
|
||||
# cv.waitKey(0)
|
||||
|
||||
cv.imwrite("firebrand_contours_opencv.png", img_new)
|
||||
|
||||
ax.axis('image')
|
||||
ax.set_xticks([])
|
||||
ax.set_yticks([])
|
||||
plt.savefig("edge_detection_figure.png", dpi=500)
|
||||
BIN
examples/pyrometry/edge_detection_figure.png
Normal file
|
After Width: | Height: | Size: 83 KiB |
BIN
examples/pyrometry/firebrand_contours_opencv.png
Normal file
|
After Width: | Height: | Size: 14 KiB |
BIN
examples/pyrometry/streaktest-edge-detection.png
Normal file
|
After Width: | Height: | Size: 2.6 KiB |
|
Before Width: | Height: | Size: 58 KiB After Width: | Height: | Size: 58 KiB |
BIN
examples/pyrometry/streaktest2-edge-detection.png
Normal file
|
After Width: | Height: | Size: 11 KiB |
BIN
examples/pyrometry/streaktest2.png
Normal file
|
After Width: | Height: | Size: 445 KiB |
0
firebrand_detection.py
Normal file
@@ -1,6 +1,8 @@
|
||||
from flask import Flask, render_template, request
|
||||
from flask import Flask, render_template, request, send_file
|
||||
import numpy as np
|
||||
from plotly_util import generate_plotly_temperature_pdf
|
||||
from ratio_pyrometry import ratio_pyrometry_pipeline
|
||||
from size_projection import get_projected_area
|
||||
import base64
|
||||
import cv2 as cv
|
||||
|
||||
@@ -12,13 +14,13 @@ app = Flask(
|
||||
|
||||
@app.route('/', methods=['GET'])
|
||||
def index():
|
||||
return render_template('index.jinja2')
|
||||
return render_template('index.html')
|
||||
|
||||
@app.route('/ratio_pyro', methods=['POST'])
|
||||
def ratio_pyro():
|
||||
f = request.files['file']
|
||||
f_bytes = np.fromstring(f.read(), np.uint8)
|
||||
img_orig, img_res, key = ratio_pyrometry_pipeline(
|
||||
img_orig, img_res, key, ptemps, indiv_firebrands = ratio_pyrometry_pipeline(
|
||||
f_bytes,
|
||||
ISO=float(request.form['iso']),
|
||||
I_Darkcurrent=float(request.form['i_darkcurrent']),
|
||||
@@ -28,15 +30,64 @@ def ratio_pyro():
|
||||
MIN_TEMP=float(request.form['min_temp']),
|
||||
smoothing_radius=int(request.form['smoothing_radius']),
|
||||
key_entries=int(request.form['legend_entries']),
|
||||
eqn_scaling_factor=float(request.form['equation_scaling_factor'])
|
||||
eqn_scaling_factor=float(request.form['equation_scaling_factor']),
|
||||
firebrand_min_intensity_threshold=float(request.form['intensity_threshold']),
|
||||
firebrand_min_area=float(request.form['min_area']),
|
||||
)
|
||||
|
||||
# get base64 encoded images
|
||||
img_orig_b64 = base64.b64encode(cv.imencode('.png', img_orig)[1]).decode(encoding='utf-8')
|
||||
img_res_b64 = base64.b64encode(cv.imencode('.png', img_res)[1]).decode(encoding='utf-8')
|
||||
|
||||
ptemps_list = [ptemps]
|
||||
|
||||
for i in range(len(indiv_firebrands)):
|
||||
# base64 encode image data
|
||||
brand_data = indiv_firebrands[i]
|
||||
unencoded = brand_data["img_data"]
|
||||
brand_data["img_data"] = base64.b64encode(cv.imencode('.png', unencoded)[1]).decode(encoding='utf-8')
|
||||
indiv_firebrands[i] = brand_data
|
||||
|
||||
# add ptemp data to list
|
||||
ptemps_list.append(brand_data["ptemps"])
|
||||
|
||||
freq_plot, csvstrs = generate_plotly_temperature_pdf(ptemps_list)
|
||||
|
||||
return render_template(
|
||||
'results.jinja2',
|
||||
'pyrometry-results.html',
|
||||
img_orig_b64=img_orig_b64,
|
||||
img_res_b64=img_res_b64,
|
||||
legend=key
|
||||
legend=key,
|
||||
freq_plot=freq_plot,
|
||||
csv_data=csvstrs[0],
|
||||
individual_firebrands=indiv_firebrands,
|
||||
)
|
||||
|
||||
|
||||
@app.route('/projected_area')
|
||||
def projected_area():
|
||||
return render_template('projected-area.html')
|
||||
|
||||
|
||||
@app.route('/projected_area_results', methods=['POST'])
|
||||
def projected_area_results():
|
||||
f = request.files['file']
|
||||
f_bytes = np.fromstring(f.read(), np.uint8)
|
||||
|
||||
img, dtable = get_projected_area(
|
||||
f_bytes,
|
||||
int(request.form['area_threshold']),
|
||||
int(request.form['min_display_threshold']),
|
||||
float(request.form['paper_width']),
|
||||
float(request.form['paper_width'])
|
||||
)
|
||||
|
||||
return render_template(
|
||||
'projected-area-results.html',
|
||||
img_b64=img,
|
||||
dtable=dtable
|
||||
)
|
||||
|
||||
# @app.route("/download_pyrometry_temps")
|
||||
# def download_pyrometry_temps():
|
||||
# return send_file()
|
||||
|
||||
64
plotly_util.py
Normal file
@@ -0,0 +1,64 @@
|
||||
from typing import List
|
||||
import plotly.figure_factory as ff
|
||||
import pandas as pd
|
||||
|
||||
def generate_plotly_temperature_pdf(ptemps_list: List[list]):
|
||||
"""
|
||||
Generate plotly graph HTML & raw CSV data for temperature pdf
|
||||
|
||||
ptemps: pixel temperature LIST in order of:
|
||||
|
||||
- Ptemps of firebrands "overview" image
|
||||
- Ptemps list for each individual firebrand
|
||||
|
||||
plotname: what to call the plot
|
||||
|
||||
Returns result in form (plot_html, csv_data)
|
||||
"""
|
||||
|
||||
# generate prob. distribution histogram & return embed
|
||||
labels = ["Full Image"]
|
||||
for i in range(len(ptemps_list[1:])):
|
||||
labels.append(f"Firebrand {i+1}")
|
||||
labels.reverse()
|
||||
|
||||
fig = ff.create_distplot(
|
||||
ptemps_list,
|
||||
group_labels=labels,
|
||||
show_rug=False,
|
||||
show_hist=False,
|
||||
)
|
||||
fig.update_layout(
|
||||
autosize=False,
|
||||
width=800,
|
||||
height=600,
|
||||
)
|
||||
fig.update_xaxes(
|
||||
title_text="Temperature (°C)",
|
||||
)
|
||||
fig.update_yaxes(
|
||||
title_text="Probability (1/°C)",
|
||||
)
|
||||
freq_plot = fig.to_html()
|
||||
|
||||
# create csv-formatted stuff
|
||||
csvstrs = []
|
||||
plot_data=fig.to_dict()
|
||||
for i in range(len(plot_data["data"])):
|
||||
x_data = plot_data["data"][i]["x"]
|
||||
y_data = plot_data["data"][i]["y"]
|
||||
|
||||
tdata = [["Temperature", "Frequency"]]
|
||||
for i in range(len(x_data)):
|
||||
r = []
|
||||
r.append(x_data[i])
|
||||
r.append(y_data[i])
|
||||
tdata.append(r)
|
||||
|
||||
csvstr = pd.DataFrame(tdata).to_csv(index=False, header=False)
|
||||
csvstrs.append(csvstr)
|
||||
|
||||
return (
|
||||
freq_plot,
|
||||
csvstrs
|
||||
)
|
||||
@@ -3,6 +3,7 @@ from multiprocessing.sharedctypes import Value
|
||||
import cv2 as cv
|
||||
import numpy as np
|
||||
from numba import jit
|
||||
from skimage import measure
|
||||
|
||||
@jit(nopython=True)
|
||||
def rg_ratio_normalize(
|
||||
@@ -13,11 +14,16 @@ def rg_ratio_normalize(
|
||||
ISO,
|
||||
MIN_TEMP,
|
||||
MAX_TEMP,
|
||||
eqn_scaling_factor
|
||||
eqn_scaling_factor,
|
||||
):
|
||||
"""
|
||||
Get normalized G/R -> temperature data + list of all temperatures
|
||||
"""
|
||||
# copy image into new array & chop off alpha values (if applicable)
|
||||
imgnew = imgarr.copy()[:,:,:3]
|
||||
|
||||
positive_temps = []
|
||||
|
||||
for i in range(len(imgarr)):
|
||||
for j in range(len(imgarr[i])):
|
||||
px = imgarr[i][j]
|
||||
@@ -32,12 +38,14 @@ def rg_ratio_normalize(
|
||||
# remove pixels outside calibration range
|
||||
if (MIN_TEMP != None and temp_C < MIN_TEMP) or (MAX_TEMP != None and temp_C > MAX_TEMP):
|
||||
temp_C = MIN_TEMP
|
||||
elif temp_C > MIN_TEMP:
|
||||
positive_temps.append(temp_C)
|
||||
|
||||
# scale light intensity to calculated temperature
|
||||
pix_i = scale_temp(temp_C, MIN_TEMP, MAX_TEMP)
|
||||
imgnew[i][j] = [pix_i, pix_i, pix_i]
|
||||
|
||||
return imgnew
|
||||
return imgnew, positive_temps
|
||||
|
||||
|
||||
@jit(nopython=True)
|
||||
@@ -78,12 +86,105 @@ def ratio_pyrometry_pipeline(
|
||||
smoothing_radius: int,
|
||||
key_entries: int,
|
||||
eqn_scaling_factor: float,
|
||||
# firebrand detection
|
||||
firebrand_min_intensity_threshold: float,
|
||||
firebrand_min_area: float
|
||||
):
|
||||
|
||||
# read image & crop
|
||||
img_orig = cv.imdecode(file_bytes, cv.IMREAD_UNCHANGED)
|
||||
|
||||
img = rg_ratio_normalize(
|
||||
# ---------------------------------------------------------
|
||||
# -- Firebrand detection
|
||||
# ---------------------------------------------------------
|
||||
|
||||
img = cv.copyMakeBorder(
|
||||
img_orig,
|
||||
20,
|
||||
20,
|
||||
20,
|
||||
20,
|
||||
cv.BORDER_CONSTANT,
|
||||
value=0
|
||||
)
|
||||
|
||||
retval, thresh_gray = cv.threshold(img, firebrand_min_intensity_threshold, 255, cv.THRESH_BINARY)
|
||||
|
||||
kernel = np.ones((7, 7), np.uint8)
|
||||
image = cv.morphologyEx(thresh_gray, cv.MORPH_CLOSE, kernel, iterations=1)
|
||||
gray = cv.cvtColor(image, cv.COLOR_BGR2GRAY)
|
||||
|
||||
retval, gray = cv.threshold(gray, 0, 255, cv.THRESH_BINARY)
|
||||
|
||||
contours = measure.find_contours(array=gray, level=100)
|
||||
|
||||
def calculate_area(countour):
|
||||
c = np.expand_dims(countour.astype(np.float32), 1)
|
||||
c = cv.UMat(c)
|
||||
|
||||
return cv.contourArea(c)
|
||||
|
||||
individual_firebrands = []
|
||||
|
||||
for contour in contours:
|
||||
if calculate_area(contour) > firebrand_min_area:
|
||||
mask = np.zeros(img.shape[0:2], dtype='uint8')
|
||||
cv.fillPoly(mask, pts=np.int32([np.flip(contour, 1)]), color=(255,255,255))
|
||||
|
||||
retval, mask = cv.threshold(mask, 0, 255, cv.THRESH_BINARY)
|
||||
|
||||
#apply the mask to the img
|
||||
masked = cv.bitwise_and(img, img, mask=mask)
|
||||
|
||||
masked_ratio_rg, ptemps_indiv = rg_ratio_normalize(
|
||||
masked,
|
||||
I_Darkcurrent,
|
||||
f_stop,
|
||||
exposure_time,
|
||||
ISO,
|
||||
MIN_TEMP,
|
||||
MAX_TEMP,
|
||||
eqn_scaling_factor,
|
||||
)
|
||||
|
||||
# build & apply smoothing conv kernel
|
||||
k = []
|
||||
for i in range(smoothing_radius):
|
||||
k.append([1/(smoothing_radius**2) for i in range(smoothing_radius)])
|
||||
kernel = np.array(k)
|
||||
|
||||
masked_ratio_rg = cv.filter2D(src=masked_ratio_rg, ddepth=-1, kernel=kernel)
|
||||
|
||||
# write colormapped image
|
||||
masked_ratio_rg_jet = cv.applyColorMap(masked_ratio_rg, cv.COLORMAP_JET)
|
||||
|
||||
# Generate key
|
||||
step = (MAX_TEMP - MIN_TEMP) / (key_entries-1)
|
||||
temps = []
|
||||
key_img_arr = [[]]
|
||||
|
||||
for i in range(key_entries):
|
||||
res_temp = MIN_TEMP + (i * step)
|
||||
res_color = scale_temp(res_temp, MIN_TEMP, MAX_TEMP)
|
||||
temps.append(math.floor(res_temp))
|
||||
key_img_arr[0].append([res_color, res_color, res_color])
|
||||
|
||||
key_img = np.array(key_img_arr).astype(np.uint8)
|
||||
key_img_jet = cv.applyColorMap(key_img, cv.COLORMAP_JET)
|
||||
|
||||
tempkey = {}
|
||||
|
||||
for i in range(len(temps)):
|
||||
c = key_img_jet[0][i]
|
||||
tempkey[temps[i]] = f"rgb({c[2]}, {c[1]}, {c[0]})"
|
||||
|
||||
individual_firebrands.append({
|
||||
"img_data": masked_ratio_rg_jet,
|
||||
"legend": tempkey,
|
||||
"ptemps": ptemps_indiv
|
||||
})
|
||||
|
||||
|
||||
img, ptemps = rg_ratio_normalize(
|
||||
img_orig,
|
||||
I_Darkcurrent,
|
||||
f_stop,
|
||||
@@ -91,7 +192,7 @@ def ratio_pyrometry_pipeline(
|
||||
ISO,
|
||||
MIN_TEMP,
|
||||
MAX_TEMP,
|
||||
eqn_scaling_factor
|
||||
eqn_scaling_factor,
|
||||
)
|
||||
|
||||
# build & apply smoothing conv kernel
|
||||
@@ -105,7 +206,9 @@ def ratio_pyrometry_pipeline(
|
||||
# write colormapped image
|
||||
img_jet = cv.applyColorMap(img, cv.COLORMAP_JET)
|
||||
|
||||
# --- Generate temperature key ---
|
||||
# ---------------------------------------------------------
|
||||
# -- Generate temperature key
|
||||
# ---------------------------------------------------------
|
||||
|
||||
# Generate key
|
||||
step = (MAX_TEMP - MIN_TEMP) / (key_entries-1)
|
||||
@@ -126,4 +229,4 @@ def ratio_pyrometry_pipeline(
|
||||
tempkey[temps[i]] = f"rgb({c[2]}, {c[1]}, {c[0]})"
|
||||
|
||||
# original, transformed, legend
|
||||
return img_orig, img_jet, tempkey
|
||||
return img_orig, img_jet, tempkey, ptemps, individual_firebrands
|
||||
|
||||
BIN
screenshots/projected_area_in.png
Normal file
|
After Width: | Height: | Size: 436 KiB |
BIN
screenshots/projected_area_out.png
Normal file
|
After Width: | Height: | Size: 1.8 MiB |
|
Before Width: | Height: | Size: 826 KiB After Width: | Height: | Size: 1.3 MiB |
BIN
screenshots/temp_dist_plot.png
Normal file
|
After Width: | Height: | Size: 134 KiB |
75
size_projection.py
Normal file
@@ -0,0 +1,75 @@
|
||||
# use headless backend
|
||||
import matplotlib
|
||||
matplotlib.use("Agg")
|
||||
|
||||
import base64
|
||||
import cv2 as cv
|
||||
import numpy as np
|
||||
import matplotlib.pyplot as plt
|
||||
from skimage import measure, morphology, color, segmentation
|
||||
import io
|
||||
|
||||
def get_projected_area(image, area_threshold, display_threshold, paper_width, paper_height):
|
||||
total_px = image.size
|
||||
total_mm = paper_width * paper_height * 25.4
|
||||
|
||||
output = []
|
||||
original = cv.imdecode(image, cv.IMREAD_UNCHANGED)
|
||||
original = cv.cvtColor(original, cv.COLOR_BGR2RGB)
|
||||
|
||||
img = cv.cvtColor(original, cv.COLOR_BGR2GRAY)
|
||||
_retval, thresh_gray = cv.threshold(img, 200, 255, cv.THRESH_BINARY)
|
||||
|
||||
img = morphology.area_closing(thresh_gray, area_threshold=area_threshold, connectivity=1)
|
||||
|
||||
contours = measure.find_contours(image=img, level=100)
|
||||
|
||||
fig, ax = plt.subplots()
|
||||
ax.imshow(original, cmap=plt.cm.gray, alpha=0.3)
|
||||
|
||||
index = 1
|
||||
|
||||
for contour in contours:
|
||||
area = calculate_area(contour)
|
||||
|
||||
if calculate_area(contour) > display_threshold:
|
||||
ax.plot(contour[:, 1], contour[:, 0], linewidth=0.5, color='orangered')
|
||||
|
||||
cX, cY = center_of_mass(contour)
|
||||
plt.text(cY, cX, index, color='black', fontsize=6)
|
||||
|
||||
output.append((index, round(area / total_px * total_mm, 2)))
|
||||
|
||||
# print(area, total_px)
|
||||
|
||||
|
||||
index += 1
|
||||
|
||||
ax.axis('image')
|
||||
ax.set_xticks([])
|
||||
ax.set_yticks([])
|
||||
|
||||
ax.margins(0)
|
||||
|
||||
my_stringIObytes = io.BytesIO()
|
||||
plt.savefig(my_stringIObytes, format='png', dpi=500, bbox_inches='tight')
|
||||
my_stringIObytes.seek(0)
|
||||
image_arr = base64.b64encode(my_stringIObytes.read()).decode(encoding='utf-8')
|
||||
|
||||
return image_arr, output
|
||||
|
||||
def calculate_area(countour):
|
||||
c = np.expand_dims(countour.astype(np.float32), 1)
|
||||
c = cv.UMat(c)
|
||||
|
||||
return cv.contourArea(c)
|
||||
|
||||
def center_of_mass(X):
|
||||
x = X[:,0]
|
||||
y = X[:,1]
|
||||
g = (x[:-1]*y[1:] - x[1:]*y[:-1])
|
||||
A = 0.5*g.sum()
|
||||
cx = ((x[:-1] + x[1:])*g).sum()
|
||||
cy = ((y[:-1] + y[1:])*g).sum()
|
||||
|
||||
return 1./(6*A)*np.array([cx,cy])
|
||||
77
static/app.css
Normal file
@@ -0,0 +1,77 @@
|
||||
* {
|
||||
font-family: sans-serif;
|
||||
}
|
||||
|
||||
html {
|
||||
margin: 0px;
|
||||
padding: 0px;
|
||||
}
|
||||
|
||||
.navbar {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
padding: 0px 2rem;
|
||||
background-color: #e0e0e0;
|
||||
border-radius: 0.8rem;
|
||||
}
|
||||
|
||||
.navbar-links {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
margin-left: auto;
|
||||
}
|
||||
|
||||
.navbar-link {
|
||||
display: flex;
|
||||
margin-left: 3rem;
|
||||
}
|
||||
|
||||
.content {
|
||||
display: flex;
|
||||
margin: 0rem 1rem;
|
||||
}
|
||||
|
||||
.form {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
#img-preview {
|
||||
width: 18rem;
|
||||
}
|
||||
|
||||
#pyro-eqn {
|
||||
width: 800px;
|
||||
}
|
||||
|
||||
.img-table-heading {
|
||||
padding: 4px 10px;
|
||||
}
|
||||
|
||||
.img-table-cell {
|
||||
padding: 10px 20px;
|
||||
}
|
||||
|
||||
.img-out {
|
||||
width: 32rem;
|
||||
}
|
||||
|
||||
.image-out-pa {
|
||||
width: 60rem;
|
||||
}
|
||||
|
||||
.legend {
|
||||
border-spacing: 0px;
|
||||
border-collapse: collapse;
|
||||
}
|
||||
|
||||
.legend-heading {
|
||||
padding: 4px;
|
||||
}
|
||||
|
||||
.legend-cell {
|
||||
border-width: 0px;
|
||||
padding: 0px 20px;
|
||||
}
|
||||
28
static/js/csv_download.js
Normal file
@@ -0,0 +1,28 @@
|
||||
function saveData(csvStr, filename) {
|
||||
// string rep
|
||||
// var csvStr = "";
|
||||
// for (let r = 0; r < csvData.length; r++) {
|
||||
// let row = csvData[r]
|
||||
// for (let c = 0; c < row.length; c++) {
|
||||
// let item = row[c]
|
||||
// csvStr += item;
|
||||
// if (c < row.length - 1)
|
||||
// csvStr += ",";
|
||||
// }
|
||||
// if (r < csvStr.length - 1)
|
||||
// csvStr += "\r\n";
|
||||
// }
|
||||
|
||||
// define data blob
|
||||
var data = new Blob([csvStr]);
|
||||
|
||||
// create & click temp link
|
||||
// slightly modded https://stackoverflow.com/a/15832662
|
||||
var link = document.createElement("a");
|
||||
link.download = filename;
|
||||
link.href = URL.createObjectURL(data);
|
||||
document.body.appendChild(link);
|
||||
link.click();
|
||||
document.body.removeChild(link);
|
||||
delete link;
|
||||
}
|
||||
9
static/js/img_preview.js
Normal file
@@ -0,0 +1,9 @@
|
||||
let imgPreview = document.getElementById('img-preview');
|
||||
let imgUpload = document.getElementById('img-upload');
|
||||
imgUpload.onchange = event => {
|
||||
const [file] = imgUpload.files;
|
||||
if (file) {
|
||||
console.log(file)
|
||||
imgPreview.src = URL.createObjectURL(file);
|
||||
}
|
||||
};
|
||||
@@ -1,4 +0,0 @@
|
||||
.form {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
22
templates/base.html
Normal file
@@ -0,0 +1,22 @@
|
||||
<!DOCTYPE html>
|
||||
<head>
|
||||
<title>Pyrometry Application</title>
|
||||
<link rel="stylesheet" href="{{ url_for('static', filename='app.css') }}">
|
||||
{% block head %}
|
||||
{% endblock %}
|
||||
</head>
|
||||
<body>
|
||||
<div class="navbar">
|
||||
<h3>Pyrometry Toolkit</h3>
|
||||
<div class="navbar-links">
|
||||
<a class="navbar-link" href="/">Ratio Pyrometry</a>
|
||||
<a class="navbar-link" href="/projected_area">Projected Area</a>
|
||||
</div>
|
||||
</div>
|
||||
<br>
|
||||
<div class="content">
|
||||
{% block content required %}
|
||||
{% endblock %}
|
||||
</div>
|
||||
<br><br><br>
|
||||
</body>
|
||||
@@ -1,15 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<head>
|
||||
<title>Pyrometry Application</title>
|
||||
<link rel="app.css">
|
||||
</head>
|
||||
<body>
|
||||
{% block content required %}
|
||||
{% endblock %}
|
||||
</body>
|
||||
|
||||
<style>
|
||||
* {
|
||||
font-family: sans-serif;
|
||||
}
|
||||
</style>
|
||||
@@ -1,7 +1,11 @@
|
||||
{% extends "base.jinja2" %}
|
||||
{% extends "base.html" %}
|
||||
|
||||
{% block head %}
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<form action="/ratio_pyro" method="POST" enctype="multipart/form-data">
|
||||
<h2>Simple Ratio Pyrometry Interface</h2>
|
||||
<h2>Ratio Pyrometry Interface</h2>
|
||||
|
||||
<img src="#" id="img-preview" type="file"/>
|
||||
<br>
|
||||
@@ -44,6 +48,16 @@
|
||||
<input type="number" name="equation_scaling_factor" value="0.55" step="0.001"/>
|
||||
<br>
|
||||
|
||||
<h4>Firebrand Detection Settings</h4>
|
||||
|
||||
<label for="intensity_threshold">intensity threshold (0-255)</label>
|
||||
<input type="number" name="intensity_threshold" value="250", step="0.1"/>
|
||||
<br>
|
||||
|
||||
<label for="min_area">min area (removes small particles)</label>
|
||||
<input type="number" name="min_area" value="115", step="0.1"/>
|
||||
<br>
|
||||
|
||||
<h4>Output Settings</h4>
|
||||
|
||||
<label for="smoothing_radius">Smoothing Radius (px)</label>
|
||||
@@ -58,25 +72,7 @@
|
||||
<input type="submit" value="Generate Heatmap"/>
|
||||
</form>
|
||||
|
||||
<script>
|
||||
let imgPreview = document.getElementById('img-preview');
|
||||
let imgUpload = document.getElementById('img-upload');
|
||||
imgUpload.onchange = event => {
|
||||
const [file] = imgUpload.files;
|
||||
if (file) {
|
||||
console.log(file)
|
||||
imgPreview.src = URL.createObjectURL(file);
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style>
|
||||
#img-preview {
|
||||
width: 18rem;
|
||||
}
|
||||
#pyro-eqn {
|
||||
width: 800px;
|
||||
}
|
||||
</style>
|
||||
<!-- Image Preview -->
|
||||
<script src="/s/js/img_preview.js"></script>
|
||||
|
||||
{% endblock %}
|
||||
30
templates/projected-area-results.html
Normal file
@@ -0,0 +1,30 @@
|
||||
{% extends "base.html" %}
|
||||
{% block content %}
|
||||
|
||||
<h2>Results</h2>
|
||||
<a href="/projected_area">Process another image</a>
|
||||
|
||||
<div style="display: flex; align-items: start;">
|
||||
<img class="image-out-pa" src="data:image/png;base64,{{ img_b64 }}" alt="original image">
|
||||
|
||||
<div style="overflow-y: scroll;">
|
||||
<table style="background: #f1f1f1">
|
||||
<tr>
|
||||
<th class="legend-heading">Index</th>
|
||||
<th class="legend-heading">Area (mm²)</th>
|
||||
<th class="legend-heading">Copy</th>
|
||||
</tr>
|
||||
{% for item in dtable %}
|
||||
<tr>
|
||||
<td class="legend-cell">{{ item.0 }}</td>
|
||||
<td class="legend-cell">{{ item.1 }}</td>
|
||||
<td>
|
||||
<button onclick="() => navigator.clipboard.writeText('{{ item.1 }}')">Copy</button>
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% endblock %}
|
||||
38
templates/projected-area.html
Normal file
@@ -0,0 +1,38 @@
|
||||
{% extends "base.html" %}
|
||||
{% block content %}
|
||||
|
||||
<form action="/projected_area_results" method="POST" enctype="multipart/form-data">
|
||||
<h2>Projected Area Interface</h2>
|
||||
|
||||
<img src="#" id="img-preview" type="file"/>
|
||||
<br>
|
||||
|
||||
<input id="img-upload" type="file" name="file" accept=".png,.jpg,.jpeg,.tiff" value="Choose Image"/>
|
||||
|
||||
<h4>Settings</h4>
|
||||
|
||||
<label for="area_threshold">Area threshold (to remove dust particles) in px</label>
|
||||
<input type="number" name="area_threshold" value="250"/>
|
||||
<br>
|
||||
<br>
|
||||
|
||||
<label for="min_display_threshold">Minimum display threshold (in px)</label>
|
||||
<input type="number" name="min_display_threshold" value="300"/>
|
||||
<br>
|
||||
<br>
|
||||
|
||||
<label for="min_display_threshold">Page size</label>
|
||||
<input type="number" name="paper_width" value="8.5"/>
|
||||
X
|
||||
<input type="number" name="paper_height" value="11"/> inches
|
||||
<br>
|
||||
<br>
|
||||
|
||||
<br>
|
||||
<input type="submit" value="Generate Projected Sizes"/>
|
||||
</form>
|
||||
|
||||
<!-- Image Preview -->
|
||||
<script src="/s/js/img_preview.js"></script>
|
||||
|
||||
{% endblock %}
|
||||
99
templates/pyrometry-results.html
Normal file
@@ -0,0 +1,99 @@
|
||||
{% extends "base.html" %}
|
||||
|
||||
{% block head %}
|
||||
<script src="/s/js/csv_download.js"></script>
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
|
||||
<div style="display:flex; flex-direction: column;">
|
||||
|
||||
<h2>General Results</h2>
|
||||
|
||||
<table class="img-table">
|
||||
<tr>
|
||||
<th class="img-table-heading">Input Image</th>
|
||||
<th class="img-table-heading">Output Heatmap</th>
|
||||
<th class="img-table-heading">Legend</th>
|
||||
</tr>
|
||||
<tr>
|
||||
{# Original image #}
|
||||
<td class="img-table-cell" id="orig-cell">
|
||||
<img class="img-out" src="data:image/png;base64,{{ img_orig_b64 }}" alt="original image">
|
||||
</td>
|
||||
{# Result image #}
|
||||
<td class="img-table-cell" id="res-cell">
|
||||
<img class="img-out" src="data:image/png;base64,{{ img_res_b64 }}" alt="result image">
|
||||
</td>
|
||||
{# Legend #}
|
||||
<td>
|
||||
<table class="legend" id="legend">
|
||||
<tr>
|
||||
<th class="legend-heading">Color</th>
|
||||
<th class="legend-heading">Temperature</th>
|
||||
</tr>
|
||||
{% for temp, color in legend.items() %}
|
||||
<tr>
|
||||
<td class="legend-cell"><div style="width:30px;height:20px;background-color:{{ color }};"></div></td>
|
||||
<td class="legend-cell">{{ temp }}°C</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
|
||||
<h2>Individual Firebrands</h2>
|
||||
|
||||
<table>
|
||||
<tr>
|
||||
<th>Output Heatmap</th>
|
||||
<th>Legend</th>
|
||||
</tr>
|
||||
|
||||
{% for item in individual_firebrands %}
|
||||
<tr>
|
||||
{# output heatmap #}
|
||||
<td>
|
||||
<img class="img-out" src="data:image/png;base64,{{ item['img_data'] }}" alt="result image">
|
||||
</td>
|
||||
|
||||
</td>
|
||||
{# legend #}
|
||||
<td>
|
||||
<h3>Firebrand {{ loop.index }}</h3>
|
||||
<table class="legend" id="legend">
|
||||
<tr>
|
||||
<th class="legend-heading">Color</th>
|
||||
<th class="legend-heading">Temperature</th>
|
||||
</tr>
|
||||
{% for temp, color in item["legend"].items() %}
|
||||
<tr>
|
||||
<td class="legend-cell"><div style="width:30px;height:20px;background-color:{{ color }};"></div></td>
|
||||
<td class="legend-cell">{{ temp }}°C</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
|
||||
</table>
|
||||
|
||||
<br>
|
||||
{# Temperature Frequency Plot #}
|
||||
<div style="display: flex; flex-direction: row; align-items: center;">
|
||||
<strong>Temperature Distribution</strong>
|
||||
<button
|
||||
style="width: 10rem; height: 2rem; margin-left: 1rem;"
|
||||
onclick="saveData(`{{csv_data}}`, 'temperature-data.csv')">Download Data as CSV</button>
|
||||
</div>
|
||||
{{ freq_plot | safe }}
|
||||
|
||||
|
||||
<!-- Firebrands: {{ individual_firebrands }} -->
|
||||
|
||||
</div>
|
||||
|
||||
{% endblock %}
|
||||
@@ -1,67 +0,0 @@
|
||||
{% extends "base.jinja2" %}
|
||||
{% block content %}
|
||||
|
||||
<table class="img-table">
|
||||
<tr>
|
||||
<th class="img-table-heading">Input Image</th>
|
||||
<th class="img-table-heading">Output Heatmap</th>
|
||||
</tr>
|
||||
<tr>
|
||||
{# Original image #}
|
||||
<td class="img-table-cell" id="orig-cell">
|
||||
<img class="img-out" src="data:image/png;base64,{{ img_orig_b64 }}" alt="original image">
|
||||
</td>
|
||||
{# Result image #}
|
||||
<td class="img-table-cell" id="res-cell">
|
||||
<img class="img-out" src="data:image/png;base64,{{ img_res_b64 }}" alt="result image">
|
||||
</td>
|
||||
</tr>
|
||||
{# Legend #}
|
||||
<tr>
|
||||
<td class="img-table-cell"></td>
|
||||
<td class="img-table-cell">
|
||||
<table class="legend" id="legend">
|
||||
<tr>
|
||||
<th class="legend-heading">Color</th>
|
||||
<th class="legend-heading">Temperature</th>
|
||||
</tr>
|
||||
{% for temp, color in legend.items() %}
|
||||
<tr>
|
||||
<td class="legend-cell"><div style="width:30px;height:20px;background-color:{{ color }};"></div></td>
|
||||
<td class="legend-cell">{{ temp }}°C</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<style>
|
||||
.img-table-heading {
|
||||
padding: 4px 10px;
|
||||
}
|
||||
|
||||
.img-table-cell {
|
||||
padding: 10px 20px;
|
||||
}
|
||||
|
||||
.img-out {
|
||||
width: 32rem;
|
||||
}
|
||||
|
||||
.legend {
|
||||
border-spacing: 0px;
|
||||
border-collapse: collapse;
|
||||
}
|
||||
|
||||
.legend-heading {
|
||||
padding: 4px;
|
||||
}
|
||||
|
||||
.legend-cell {
|
||||
border-width: 0px;
|
||||
padding: 0px 20px;
|
||||
}
|
||||
</style>
|
||||
|
||||
{% endblock %}
|
||||