add excercise 1 source files
This commit is contained in:
parent
fde88ed0d9
commit
32290bc8a6
|
@ -0,0 +1 @@
|
|||
__pycache__
|
|
@ -0,0 +1,18 @@
|
|||
[[source]]
|
||||
url = "https://pypi.org/simple"
|
||||
verify_ssl = true
|
||||
name = "pypi"
|
||||
|
||||
[packages]
|
||||
pyqt6 = "*"
|
||||
numpy = "*"
|
||||
matplotlib = "*"
|
||||
scikit-learn = "*"
|
||||
boto3 = "*"
|
||||
opencv-python = "*"
|
||||
black = "*"
|
||||
|
||||
[dev-packages]
|
||||
|
||||
[requires]
|
||||
python_version = "3.13"
|
|
@ -0,0 +1,716 @@
|
|||
{
|
||||
"_meta": {
|
||||
"hash": {
|
||||
"sha256": "8030168f777edcbdfd2b954998e61cd68f938e2c6484ec1ed624794d81b17499"
|
||||
},
|
||||
"pipfile-spec": 6,
|
||||
"requires": {
|
||||
"python_version": "3.13"
|
||||
},
|
||||
"sources": [
|
||||
{
|
||||
"name": "pypi",
|
||||
"url": "https://pypi.org/simple",
|
||||
"verify_ssl": true
|
||||
}
|
||||
]
|
||||
},
|
||||
"default": {
|
||||
"black": {
|
||||
"hashes": [
|
||||
"sha256:14b3502784f09ce2443830e3133dacf2c0110d45191ed470ecb04d0f5f6fcb0f",
|
||||
"sha256:17374989640fbca88b6a448129cd1745c5eb8d9547b464f281b251dd00155ccd",
|
||||
"sha256:1c536fcf674217e87b8cc3657b81809d3c085d7bf3ef262ead700da345bfa6ea",
|
||||
"sha256:1cbacacb19e922a1d75ef2b6ccaefcd6e93a2c05ede32f06a21386a04cedb981",
|
||||
"sha256:1f93102e0c5bb3907451063e08b9876dbeac810e7da5a8bfb7aeb5a9ef89066b",
|
||||
"sha256:2cd9c95431d94adc56600710f8813ee27eea544dd118d45896bb734e9d7a0dc7",
|
||||
"sha256:30d2c30dc5139211dda799758559d1b049f7f14c580c409d6ad925b74a4208a8",
|
||||
"sha256:394d4ddc64782e51153eadcaaca95144ac4c35e27ef9b0a42e121ae7e57a9175",
|
||||
"sha256:3bb2b7a1f7b685f85b11fed1ef10f8a9148bceb49853e47a294a3dd963c1dd7d",
|
||||
"sha256:4007b1393d902b48b36958a216c20c4482f601569d19ed1df294a496eb366392",
|
||||
"sha256:5a2221696a8224e335c28816a9d331a6c2ae15a2ee34ec857dcf3e45dbfa99ad",
|
||||
"sha256:63f626344343083322233f175aaf372d326de8436f5928c042639a4afbbf1d3f",
|
||||
"sha256:649fff99a20bd06c6f727d2a27f401331dc0cc861fb69cde910fe95b01b5928f",
|
||||
"sha256:680359d932801c76d2e9c9068d05c6b107f2584b2a5b88831c83962eb9984c1b",
|
||||
"sha256:846ea64c97afe3bc677b761787993be4991810ecc7a4a937816dd6bddedc4875",
|
||||
"sha256:b5e39e0fae001df40f95bd8cc36b9165c5e2ea88900167bddf258bacef9bbdc3",
|
||||
"sha256:ccfa1d0cb6200857f1923b602f978386a3a2758a65b52e0950299ea014be6800",
|
||||
"sha256:d37d422772111794b26757c5b55a3eade028aa3fde43121ab7b673d050949d65",
|
||||
"sha256:ddacb691cdcdf77b96f549cf9591701d8db36b2f19519373d60d31746068dbf2",
|
||||
"sha256:e6668650ea4b685440857138e5fe40cde4d652633b1bdffc62933d0db4ed9812",
|
||||
"sha256:f9da3333530dbcecc1be13e69c250ed8dfa67f43c4005fb537bb426e19200d50",
|
||||
"sha256:fe4d6476887de70546212c99ac9bd803d90b42fc4767f058a0baa895013fbb3e"
|
||||
],
|
||||
"index": "pypi",
|
||||
"markers": "python_version >= '3.9'",
|
||||
"version": "==24.10.0"
|
||||
},
|
||||
"boto3": {
|
||||
"hashes": [
|
||||
"sha256:6d473f0f340d02b4e9ad5b8e68786a09728101a8b950231b89ebdaf72b6dca21",
|
||||
"sha256:b36feae061dc0793cf311468956a0a9e99215ce38bc99a1a4e55a5b105f16297"
|
||||
],
|
||||
"index": "pypi",
|
||||
"markers": "python_version >= '3.8'",
|
||||
"version": "==1.36.6"
|
||||
},
|
||||
"botocore": {
|
||||
"hashes": [
|
||||
"sha256:4864c53d638da191a34daf3ede3ff1371a3719d952cc0c6bd24ce2836a38dd77",
|
||||
"sha256:f77bbbb03fb420e260174650fb5c0cc142ec20a96967734eed2b0ef24334ef34"
|
||||
],
|
||||
"markers": "python_version >= '3.8'",
|
||||
"version": "==1.36.6"
|
||||
},
|
||||
"click": {
|
||||
"hashes": [
|
||||
"sha256:63c132bbbed01578a06712a2d1f497bb62d9c1c0d329b7903a866228027263b2",
|
||||
"sha256:ed53c9d8990d83c2a27deae68e4ee337473f6330c040a31d4225c9574d16096a"
|
||||
],
|
||||
"markers": "python_version >= '3.7'",
|
||||
"version": "==8.1.8"
|
||||
},
|
||||
"contourpy": {
|
||||
"hashes": [
|
||||
"sha256:041b640d4ec01922083645a94bb3b2e777e6b626788f4095cf21abbe266413c1",
|
||||
"sha256:05e806338bfeaa006acbdeba0ad681a10be63b26e1b17317bfac3c5d98f36cda",
|
||||
"sha256:08d9d449a61cf53033612cb368f3a1b26cd7835d9b8cd326647efe43bca7568d",
|
||||
"sha256:0ffa84be8e0bd33410b17189f7164c3589c229ce5db85798076a3fa136d0e509",
|
||||
"sha256:113231fe3825ebf6f15eaa8bc1f5b0ddc19d42b733345eae0934cb291beb88b6",
|
||||
"sha256:14c102b0eab282427b662cb590f2e9340a9d91a1c297f48729431f2dcd16e14f",
|
||||
"sha256:174e758c66bbc1c8576992cec9599ce8b6672b741b5d336b5c74e35ac382b18e",
|
||||
"sha256:19c1555a6801c2f084c7ddc1c6e11f02eb6a6016ca1318dd5452ba3f613a1751",
|
||||
"sha256:19d40d37c1c3a4961b4619dd9d77b12124a453cc3d02bb31a07d58ef684d3d86",
|
||||
"sha256:1bf98051f1045b15c87868dbaea84f92408337d4f81d0e449ee41920ea121d3b",
|
||||
"sha256:20914c8c973f41456337652a6eeca26d2148aa96dd7ac323b74516988bea89fc",
|
||||
"sha256:287ccc248c9e0d0566934e7d606201abd74761b5703d804ff3df8935f523d546",
|
||||
"sha256:2ba94a401342fc0f8b948e57d977557fbf4d515f03c67682dd5c6191cb2d16ec",
|
||||
"sha256:31c1b55c1f34f80557d3830d3dd93ba722ce7e33a0b472cba0ec3b6535684d8f",
|
||||
"sha256:36987a15e8ace5f58d4d5da9dca82d498c2bbb28dff6e5d04fbfcc35a9cb3a82",
|
||||
"sha256:3a04ecd68acbd77fa2d39723ceca4c3197cb2969633836ced1bea14e219d077c",
|
||||
"sha256:3e8b974d8db2c5610fb4e76307e265de0edb655ae8169e8b21f41807ccbeec4b",
|
||||
"sha256:3ea9924d28fc5586bf0b42d15f590b10c224117e74409dd7a0be3b62b74a501c",
|
||||
"sha256:4318af1c925fb9a4fb190559ef3eec206845f63e80fb603d47f2d6d67683901c",
|
||||
"sha256:44a29502ca9c7b5ba389e620d44f2fbe792b1fb5734e8b931ad307071ec58c53",
|
||||
"sha256:47734d7073fb4590b4a40122b35917cd77be5722d80683b249dac1de266aac80",
|
||||
"sha256:4d76d5993a34ef3df5181ba3c92fabb93f1eaa5729504fb03423fcd9f3177242",
|
||||
"sha256:4dbbc03a40f916a8420e420d63e96a1258d3d1b58cbdfd8d1f07b49fcbd38e85",
|
||||
"sha256:500360b77259914f7805af7462e41f9cb7ca92ad38e9f94d6c8641b089338124",
|
||||
"sha256:523a8ee12edfa36f6d2a49407f705a6ef4c5098de4f498619787e272de93f2d5",
|
||||
"sha256:573abb30e0e05bf31ed067d2f82500ecfdaec15627a59d63ea2d95714790f5c2",
|
||||
"sha256:5b75aa69cb4d6f137b36f7eb2ace9280cfb60c55dc5f61c731fdf6f037f958a3",
|
||||
"sha256:61332c87493b00091423e747ea78200659dc09bdf7fd69edd5e98cef5d3e9a8d",
|
||||
"sha256:805617228ba7e2cbbfb6c503858e626ab528ac2a32a04a2fe88ffaf6b02c32bc",
|
||||
"sha256:841ad858cff65c2c04bf93875e384ccb82b654574a6d7f30453a04f04af71342",
|
||||
"sha256:89785bb2a1980c1bd87f0cb1517a71cde374776a5f150936b82580ae6ead44a1",
|
||||
"sha256:8eb96e79b9f3dcadbad2a3891672f81cdcab7f95b27f28f1c67d75f045b6b4f1",
|
||||
"sha256:974d8145f8ca354498005b5b981165b74a195abfae9a8129df3e56771961d595",
|
||||
"sha256:9ddeb796389dadcd884c7eb07bd14ef12408aaae358f0e2ae24114d797eede30",
|
||||
"sha256:a045f341a77b77e1c5de31e74e966537bba9f3c4099b35bf4c2e3939dd54cdab",
|
||||
"sha256:a0cffcbede75c059f535725c1680dfb17b6ba8753f0c74b14e6a9c68c29d7ea3",
|
||||
"sha256:a761d9ccfc5e2ecd1bf05534eda382aa14c3e4f9205ba5b1684ecfe400716ef2",
|
||||
"sha256:a7895f46d47671fa7ceec40f31fae721da51ad34bdca0bee83e38870b1f47ffd",
|
||||
"sha256:a9fa36448e6a3a1a9a2ba23c02012c43ed88905ec80163f2ffe2421c7192a5d7",
|
||||
"sha256:ab29962927945d89d9b293eabd0d59aea28d887d4f3be6c22deaefbb938a7277",
|
||||
"sha256:abbb49fb7dac584e5abc6636b7b2a7227111c4f771005853e7d25176daaf8453",
|
||||
"sha256:ac4578ac281983f63b400f7fe6c101bedc10651650eef012be1ccffcbacf3697",
|
||||
"sha256:adce39d67c0edf383647a3a007de0a45fd1b08dedaa5318404f1a73059c2512b",
|
||||
"sha256:ade08d343436a94e633db932e7e8407fe7de8083967962b46bdfc1b0ced39454",
|
||||
"sha256:b2bdca22a27e35f16794cf585832e542123296b4687f9fd96822db6bae17bfc9",
|
||||
"sha256:b2f926efda994cdf3c8d3fdb40b9962f86edbc4457e739277b961eced3d0b4c1",
|
||||
"sha256:b457d6430833cee8e4b8e9b6f07aa1c161e5e0d52e118dc102c8f9bd7dd060d6",
|
||||
"sha256:c414fc1ed8ee1dbd5da626cf3710c6013d3d27456651d156711fa24f24bd1291",
|
||||
"sha256:cb76c1a154b83991a3cbbf0dfeb26ec2833ad56f95540b442c73950af2013750",
|
||||
"sha256:dfd97abd83335045a913e3bcc4a09c0ceadbe66580cf573fe961f4a825efa699",
|
||||
"sha256:e914a8cb05ce5c809dd0fe350cfbb4e881bde5e2a38dc04e3afe1b3e58bd158e",
|
||||
"sha256:ece6df05e2c41bd46776fbc712e0996f7c94e0d0543af1656956d150c4ca7c81",
|
||||
"sha256:efa874e87e4a647fd2e4f514d5e91c7d493697127beb95e77d2f7561f6905bd9",
|
||||
"sha256:f611e628ef06670df83fce17805c344710ca5cde01edfdc72751311da8585375"
|
||||
],
|
||||
"markers": "python_version >= '3.10'",
|
||||
"version": "==1.3.1"
|
||||
},
|
||||
"cycler": {
|
||||
"hashes": [
|
||||
"sha256:85cef7cff222d8644161529808465972e51340599459b8ac3ccbac5a854e0d30",
|
||||
"sha256:88bb128f02ba341da8ef447245a9e138fae777f6a23943da4540077d3601eb1c"
|
||||
],
|
||||
"markers": "python_version >= '3.8'",
|
||||
"version": "==0.12.1"
|
||||
},
|
||||
"fonttools": {
|
||||
"hashes": [
|
||||
"sha256:03701e7de70c71eb5965cb200986b0c11dfa3cf8e843e4f517ee30a0f43f0a25",
|
||||
"sha256:07478132407736ee5e54f9f534e73923ae28e9bb6dba17764a35e3caf7d7fea3",
|
||||
"sha256:0879f99eabbf2171dfadd9c8c75cec2b7b3aa9cd1f3955dd799c69d60a5189ef",
|
||||
"sha256:09ed667c4753e1270994e5398cce8703e6423c41702a55b08f843b2907b1be65",
|
||||
"sha256:0ee6ed68af8d57764d69da099db163aaf37d62ba246cfd42f27590e3e6724b55",
|
||||
"sha256:1062daa0390b32bfd062ded2b450db9e9cf10e5a9919561c13f535e818b1952b",
|
||||
"sha256:127999618afe3a2490fad54bab0650c5fbeab1f8109bdc0205f6ad34306deb8b",
|
||||
"sha256:132fa22be8a99784de8cb171b30425a581f04a40ec1c05183777fb2b1fe3bac9",
|
||||
"sha256:1beb4647a0df5ceaea48015656525eb8081af226fe96554089fd3b274d239ef0",
|
||||
"sha256:2d15e02b93a46982a8513a208e8f89148bca8297640527365625be56151687d0",
|
||||
"sha256:2d419483a6295e83cabddb56f1c7b7bfdc8169de2fcb5c68d622bd11140355f9",
|
||||
"sha256:34405f1314f1e88b1877a9f9e497fe45190e8c4b29a6c7cd85ed7f666a57d702",
|
||||
"sha256:3aa6c684007723895aade9b2fe76d07008c9dc90fd1ef6c310b3ca9c8566729f",
|
||||
"sha256:3f4e88f15f5ed4d2e4bdfcc98540bb3987ae25904f9be304be9a604e7a7050a1",
|
||||
"sha256:4259159715142c10b0f4d121ef14da3fa6eafc719289d9efa4b20c15e57fef82",
|
||||
"sha256:471961af7a4b8461fac0c8ee044b4986e6fe3746d4c83a1aacbdd85b4eb53f93",
|
||||
"sha256:51120695ee13001533e50abd40eec32c01b9c6f44c5567db38a7acd3eedcd19d",
|
||||
"sha256:57d55fc965e5dd20c8a60d880e0f43bafb506be87af0b650bdc42591e41e0d0d",
|
||||
"sha256:5b7535a5ac386e549e2b00b34c59b53f805e2423000676723b6867df3c10df04",
|
||||
"sha256:61aa1997c520bee4cde14ffabe81efc4708c500c8c81dce37831551627a2be56",
|
||||
"sha256:73a4aaf672e7b2265c6354a69cbbadf71b7f3133ecb74e98fec4c67c366698a3",
|
||||
"sha256:73bdff9c44d36c57ea84766afc20517eda0c9bb1571b4a09876646264bd5ff3b",
|
||||
"sha256:76ac5a595f86892b49ba86ba2e46185adc76328ce6eff0583b30e5c3ab02a914",
|
||||
"sha256:791e0cf862cdd3a252df395f1bb5f65e3a760f1da3c7ce184d0f7998c266614d",
|
||||
"sha256:7954ea66a8d835f279c17d8474597a001ddd65a2c1ca97e223041bfbbe11f65e",
|
||||
"sha256:8398928acb8a57073606feb9a310682d4a7e2d7536f2c61719261f4c0974504c",
|
||||
"sha256:860ab9ed3f9e088d3bdb77b9074e656635f173b039e77d550b603cba052a0dca",
|
||||
"sha256:88f74bc19dbab3dee6a00ca67ca54bb4793e44ff0c4dcf1fa61d68651ae3fa0a",
|
||||
"sha256:8a8004a19195eb8a8a13de69e26ec9ed60a5bc1fde336d0021b47995b368fac9",
|
||||
"sha256:8c9de8d16d02ecc8b65e3f3d2d1e3002be2c4a3f094d580faf76d7f768bd45fe",
|
||||
"sha256:9394813cc73fa22c5413ec1c5745c0a16f68dd2b890f7c55eaba5cb40187ed55",
|
||||
"sha256:94f7f2c5c5f3a6422e954ecb6d37cc363e27d6f94050a7ed3f79f12157af6bb2",
|
||||
"sha256:9f99e7876518b2d059a9cc67c506168aebf9c71ac8d81006d75e684222f291d2",
|
||||
"sha256:9fb545f3a4ebada908fa717ec732277de18dd10161f03ee3b3144d34477804de",
|
||||
"sha256:a55489c7e9d5ea69690a2afad06723c3d0c48c6d276a25391ea97cb31a16b37c",
|
||||
"sha256:a632f85bd73e002b771bcbcdc512038fa5d2e09bb18c03a22fb8d400ea492ddf",
|
||||
"sha256:ac817559a7d245454231374e194b4e457dca6fefa5b52af466ab0516e9a09c6e",
|
||||
"sha256:acc74884afddc2656bffc50100945ff407574538c152931c402fccddc46f0abc",
|
||||
"sha256:af5469bbf555047efd8752d85faeb2a3510916ddc6c50dd6fb168edf1677408f",
|
||||
"sha256:bc6f58976ffc19fe1630119a2736153b66151d023c6f30065f31c9e8baed1303",
|
||||
"sha256:c2f78ebfdef578d4db7c44bc207ac5f9a5c1f22c9db606460dcc8ad48e183338",
|
||||
"sha256:c42009177d3690894288082d5e3dac6bdc9f5d38e25054535e341a19cf5183a4",
|
||||
"sha256:d20ab5a78d0536c26628eaadba661e7ae2427b1e5c748a0a510a44d914e1b155",
|
||||
"sha256:d3226d40cb92787e09dcc3730f54b3779dfe56bdfea624e263685ba17a6faac4",
|
||||
"sha256:d77d83ca77a4c3156a2f4cbc7f09f5a8503795da658fa255b987ad433a191266",
|
||||
"sha256:d91fce2e9a87cc0db9f8042281b6458f99854df810cfefab2baf6ab2acc0f4b4",
|
||||
"sha256:e1c06fbc2fd76b9bab03eddfd8aa9fb7c0981d314d780e763c80aa76be1c9982",
|
||||
"sha256:e82772f70b84e17aa36e9f236feb2a4f73cb686ec1e162557a36cf759d1acd58",
|
||||
"sha256:edf159a8f1e48dc4683a715b36da76dd2f82954b16bfe11a215d58e963d31cfc",
|
||||
"sha256:f66561fbfb75785d06513b8025a50be37bf970c3c413e87581cc6eff10bc78f1"
|
||||
],
|
||||
"markers": "python_version >= '3.8'",
|
||||
"version": "==4.55.6"
|
||||
},
|
||||
"jmespath": {
|
||||
"hashes": [
|
||||
"sha256:02e2e4cc71b5bcab88332eebf907519190dd9e6e82107fa7f83b1003a6252980",
|
||||
"sha256:90261b206d6defd58fdd5e85f478bf633a2901798906be2ad389150c5c60edbe"
|
||||
],
|
||||
"markers": "python_version >= '3.7'",
|
||||
"version": "==1.0.1"
|
||||
},
|
||||
"joblib": {
|
||||
"hashes": [
|
||||
"sha256:06d478d5674cbc267e7496a410ee875abd68e4340feff4490bcb7afb88060ae6",
|
||||
"sha256:2382c5816b2636fbd20a09e0f4e9dad4736765fdfb7dca582943b9c1366b3f0e"
|
||||
],
|
||||
"markers": "python_version >= '3.8'",
|
||||
"version": "==1.4.2"
|
||||
},
|
||||
"kiwisolver": {
|
||||
"hashes": [
|
||||
"sha256:01c3d31902c7db5fb6182832713d3b4122ad9317c2c5877d0539227d96bb2e50",
|
||||
"sha256:034d2c891f76bd3edbdb3ea11140d8510dca675443da7304205a2eaa45d8334c",
|
||||
"sha256:085940635c62697391baafaaeabdf3dd7a6c3643577dde337f4d66eba021b2b8",
|
||||
"sha256:08e77738ed7538f036cd1170cbed942ef749137b1311fa2bbe2a7fda2f6bf3cc",
|
||||
"sha256:111793b232842991be367ed828076b03d96202c19221b5ebab421ce8bcad016f",
|
||||
"sha256:11e1022b524bd48ae56c9b4f9296bce77e15a2e42a502cceba602f804b32bb79",
|
||||
"sha256:151dffc4865e5fe6dafce5480fab84f950d14566c480c08a53c663a0020504b6",
|
||||
"sha256:16523b40aab60426ffdebe33ac374457cf62863e330a90a0383639ce14bf44b2",
|
||||
"sha256:1732e065704b47c9afca7ffa272f845300a4eb959276bf6970dc07265e73b605",
|
||||
"sha256:1c8ceb754339793c24aee1c9fb2485b5b1f5bb1c2c214ff13368431e51fc9a09",
|
||||
"sha256:23454ff084b07ac54ca8be535f4174170c1094a4cff78fbae4f73a4bcc0d4dab",
|
||||
"sha256:23d5f023bdc8c7e54eb65f03ca5d5bb25b601eac4d7f1a042888a1f45237987e",
|
||||
"sha256:257af1622860e51b1a9d0ce387bf5c2c4f36a90594cb9514f55b074bcc787cfc",
|
||||
"sha256:286b18e86682fd2217a48fc6be6b0f20c1d0ed10958d8dc53453ad58d7be0bf8",
|
||||
"sha256:291331973c64bb9cce50bbe871fb2e675c4331dab4f31abe89f175ad7679a4d7",
|
||||
"sha256:2f0121b07b356a22fb0414cec4666bbe36fd6d0d759db3d37228f496ed67c880",
|
||||
"sha256:3452046c37c7692bd52b0e752b87954ef86ee2224e624ef7ce6cb21e8c41cc1b",
|
||||
"sha256:34d142fba9c464bc3bbfeff15c96eab0e7310343d6aefb62a79d51421fcc5f1b",
|
||||
"sha256:369b75d40abedc1da2c1f4de13f3482cb99e3237b38726710f4a793432b1c5ff",
|
||||
"sha256:36dbbfd34838500a31f52c9786990d00150860e46cd5041386f217101350f0d3",
|
||||
"sha256:370fd2df41660ed4e26b8c9d6bbcad668fbe2560462cba151a721d49e5b6628c",
|
||||
"sha256:3a96c0e790ee875d65e340ab383700e2b4891677b7fcd30a699146f9384a2bb0",
|
||||
"sha256:3b9b4d2892fefc886f30301cdd80debd8bb01ecdf165a449eb6e78f79f0fabd6",
|
||||
"sha256:3cd3bc628b25f74aedc6d374d5babf0166a92ff1317f46267f12d2ed54bc1d30",
|
||||
"sha256:3ddc373e0eef45b59197de815b1b28ef89ae3955e7722cc9710fb91cd77b7f47",
|
||||
"sha256:4191ee8dfd0be1c3666ccbac178c5a05d5f8d689bbe3fc92f3c4abec817f8fe0",
|
||||
"sha256:54a62808ac74b5e55a04a408cda6156f986cefbcf0ada13572696b507cc92fa1",
|
||||
"sha256:577facaa411c10421314598b50413aa1ebcf5126f704f1e5d72d7e4e9f020d90",
|
||||
"sha256:641f2ddf9358c80faa22e22eb4c9f54bd3f0e442e038728f500e3b978d00aa7d",
|
||||
"sha256:65ea09a5a3faadd59c2ce96dc7bf0f364986a315949dc6374f04396b0d60e09b",
|
||||
"sha256:68269e60ee4929893aad82666821aaacbd455284124817af45c11e50a4b42e3c",
|
||||
"sha256:69b5637c3f316cab1ec1c9a12b8c5f4750a4c4b71af9157645bf32830e39c03a",
|
||||
"sha256:7506488470f41169b86d8c9aeff587293f530a23a23a49d6bc64dab66bedc71e",
|
||||
"sha256:768cade2c2df13db52475bd28d3a3fac8c9eff04b0e9e2fda0f3760f20b3f7fc",
|
||||
"sha256:77e6f57a20b9bd4e1e2cedda4d0b986ebd0216236f0106e55c28aea3d3d69b16",
|
||||
"sha256:782bb86f245ec18009890e7cb8d13a5ef54dcf2ebe18ed65f795e635a96a1c6a",
|
||||
"sha256:7a3ad337add5148cf51ce0b55642dc551c0b9d6248458a757f98796ca7348712",
|
||||
"sha256:7cd2785b9391f2873ad46088ed7599a6a71e762e1ea33e87514b1a441ed1da1c",
|
||||
"sha256:7e9a60b50fe8b2ec6f448fe8d81b07e40141bfced7f896309df271a0b92f80f3",
|
||||
"sha256:84a2f830d42707de1d191b9490ac186bf7997a9495d4e9072210a1296345f7dc",
|
||||
"sha256:856b269c4d28a5c0d5e6c1955ec36ebfd1651ac00e1ce0afa3e28da95293b561",
|
||||
"sha256:858416b7fb777a53f0c59ca08190ce24e9abbd3cffa18886a5781b8e3e26f65d",
|
||||
"sha256:87b287251ad6488e95b4f0b4a79a6d04d3ea35fde6340eb38fbd1ca9cd35bbbc",
|
||||
"sha256:88c6f252f6816a73b1f8c904f7bbe02fd67c09a69f7cb8a0eecdbf5ce78e63db",
|
||||
"sha256:893f5525bb92d3d735878ec00f781b2de998333659507d29ea4466208df37bed",
|
||||
"sha256:89c107041f7b27844179ea9c85d6da275aa55ecf28413e87624d033cf1f6b751",
|
||||
"sha256:918139571133f366e8362fa4a297aeba86c7816b7ecf0bc79168080e2bd79957",
|
||||
"sha256:99cea8b9dd34ff80c521aef46a1dddb0dcc0283cf18bde6d756f1e6f31772165",
|
||||
"sha256:a17b7c4f5b2c51bb68ed379defd608a03954a1845dfed7cc0117f1cc8a9b7fd2",
|
||||
"sha256:a3c44cb68861de93f0c4a8175fbaa691f0aa22550c331fefef02b618a9dcb476",
|
||||
"sha256:a4d3601908c560bdf880f07d94f31d734afd1bb71e96585cace0e38ef44c6d84",
|
||||
"sha256:a5ce1e481a74b44dd5e92ff03ea0cb371ae7a0268318e202be06c8f04f4f1246",
|
||||
"sha256:a66f60f8d0c87ab7f59b6fb80e642ebb29fec354a4dfad687ca4092ae69d04f4",
|
||||
"sha256:b21dbe165081142b1232a240fc6383fd32cdd877ca6cc89eab93e5f5883e1c25",
|
||||
"sha256:b47a465040146981dc9db8647981b8cb96366fbc8d452b031e4f8fdffec3f26d",
|
||||
"sha256:b5773efa2be9eb9fcf5415ea3ab70fc785d598729fd6057bea38d539ead28271",
|
||||
"sha256:b83dc6769ddbc57613280118fb4ce3cd08899cc3369f7d0e0fab518a7cf37fdb",
|
||||
"sha256:bade438f86e21d91e0cf5dd7c0ed00cda0f77c8c1616bd83f9fc157fa6760d31",
|
||||
"sha256:bcb1ebc3547619c3b58a39e2448af089ea2ef44b37988caf432447374941574e",
|
||||
"sha256:be4816dc51c8a471749d664161b434912eee82f2ea66bd7628bd14583a833e85",
|
||||
"sha256:c07b29089b7ba090b6f1a669f1411f27221c3662b3a1b7010e67b59bb5a6f10b",
|
||||
"sha256:c2b9a96e0f326205af81a15718a9073328df1173a2619a68553decb7097fd5d7",
|
||||
"sha256:c5020c83e8553f770cb3b5fc13faac40f17e0b205bd237aebd21d53d733adb03",
|
||||
"sha256:c72941acb7b67138f35b879bbe85be0f6c6a70cab78fe3ef6db9c024d9223e5b",
|
||||
"sha256:c8bf637892dc6e6aad2bc6d4d69d08764166e5e3f69d469e55427b6ac001b19d",
|
||||
"sha256:cc978a80a0db3a66d25767b03688f1147a69e6237175c0f4ffffaaedf744055a",
|
||||
"sha256:ce2cf1e5688edcb727fdf7cd1bbd0b6416758996826a8be1d958f91880d0809d",
|
||||
"sha256:d47b28d1dfe0793d5e96bce90835e17edf9a499b53969b03c6c47ea5985844c3",
|
||||
"sha256:d47cfb2650f0e103d4bf68b0b5804c68da97272c84bb12850d877a95c056bd67",
|
||||
"sha256:d5536185fce131780ebd809f8e623bf4030ce1b161353166c49a3c74c287897f",
|
||||
"sha256:d561d2d8883e0819445cfe58d7ddd673e4015c3c57261d7bdcd3710d0d14005c",
|
||||
"sha256:d6af5e8815fd02997cb6ad9bbed0ee1e60014438ee1a5c2444c96f87b8843502",
|
||||
"sha256:d6d6bd87df62c27d4185de7c511c6248040afae67028a8a22012b010bc7ad062",
|
||||
"sha256:dace81d28c787956bfbfbbfd72fdcef014f37d9b48830829e488fdb32b49d954",
|
||||
"sha256:e063ef9f89885a1d68dd8b2e18f5ead48653176d10a0e324e3b0030e3a69adeb",
|
||||
"sha256:e7a019419b7b510f0f7c9dceff8c5eae2392037eae483a7f9162625233802b0a",
|
||||
"sha256:eaa973f1e05131de5ff3569bbba7f5fd07ea0595d3870ed4a526d486fe57fa1b",
|
||||
"sha256:eb158fe28ca0c29f2260cca8c43005329ad58452c36f0edf298204de32a9a3ed",
|
||||
"sha256:ed33ca2002a779a2e20eeb06aea7721b6e47f2d4b8a8ece979d8ba9e2a167e34",
|
||||
"sha256:fc2ace710ba7c1dfd1a3b42530b62b9ceed115f19a1656adefce7b1782a37794"
|
||||
],
|
||||
"markers": "python_version >= '3.10'",
|
||||
"version": "==1.4.8"
|
||||
},
|
||||
"matplotlib": {
|
||||
"hashes": [
|
||||
"sha256:01d2b19f13aeec2e759414d3bfe19ddfb16b13a1250add08d46d5ff6f9be83c6",
|
||||
"sha256:12eaf48463b472c3c0f8dbacdbf906e573013df81a0ab82f0616ea4b11281908",
|
||||
"sha256:2c5829a5a1dd5a71f0e31e6e8bb449bc0ee9dbfb05ad28fc0c6b55101b3a4be6",
|
||||
"sha256:2fbbabc82fde51391c4da5006f965e36d86d95f6ee83fb594b279564a4c5d0d2",
|
||||
"sha256:3547d153d70233a8496859097ef0312212e2689cdf8d7ed764441c77604095ae",
|
||||
"sha256:359f87baedb1f836ce307f0e850d12bb5f1936f70d035561f90d41d305fdacea",
|
||||
"sha256:3b427392354d10975c1d0f4ee18aa5844640b512d5311ef32efd4dd7db106ede",
|
||||
"sha256:4659665bc7c9b58f8c00317c3c2a299f7f258eeae5a5d56b4c64226fca2f7c59",
|
||||
"sha256:4673ff67a36152c48ddeaf1135e74ce0d4bce1bbf836ae40ed39c29edf7e2765",
|
||||
"sha256:503feb23bd8c8acc75541548a1d709c059b7184cde26314896e10a9f14df5f12",
|
||||
"sha256:5439f4c5a3e2e8eab18e2f8c3ef929772fd5641876db71f08127eed95ab64683",
|
||||
"sha256:5cdbaf909887373c3e094b0318d7ff230b2ad9dcb64da7ade654182872ab2593",
|
||||
"sha256:5e6c6461e1fc63df30bf6f80f0b93f5b6784299f721bc28530477acd51bfc3d1",
|
||||
"sha256:5fd41b0ec7ee45cd960a8e71aea7c946a28a0b8a4dcee47d2856b2af051f334c",
|
||||
"sha256:607b16c8a73943df110f99ee2e940b8a1cbf9714b65307c040d422558397dac5",
|
||||
"sha256:7e8632baebb058555ac0cde75db885c61f1212e47723d63921879806b40bec6a",
|
||||
"sha256:81713dd0d103b379de4516b861d964b1d789a144103277769238c732229d7f03",
|
||||
"sha256:845d96568ec873be63f25fa80e9e7fae4be854a66a7e2f0c8ccc99e94a8bd4ef",
|
||||
"sha256:95b710fea129c76d30be72c3b38f330269363fbc6e570a5dd43580487380b5ff",
|
||||
"sha256:96f2886f5c1e466f21cc41b70c5a0cd47bfa0015eb2d5793c88ebce658600e25",
|
||||
"sha256:994c07b9d9fe8d25951e3202a68c17900679274dadfc1248738dcfa1bd40d7f3",
|
||||
"sha256:9ade1003376731a971e398cc4ef38bb83ee8caf0aee46ac6daa4b0506db1fd06",
|
||||
"sha256:9b0558bae37f154fffda54d779a592bc97ca8b4701f1c710055b609a3bac44c8",
|
||||
"sha256:a2a43cbefe22d653ab34bb55d42384ed30f611bcbdea1f8d7f431011a2e1c62e",
|
||||
"sha256:a994f29e968ca002b50982b27168addfd65f0105610b6be7fa515ca4b5307c95",
|
||||
"sha256:ad2e15300530c1a94c63cfa546e3b7864bd18ea2901317bae8bbf06a5ade6dcf",
|
||||
"sha256:ae80dc3a4add4665cf2faa90138384a7ffe2a4e37c58d83e115b54287c4f06ef",
|
||||
"sha256:b886d02a581b96704c9d1ffe55709e49b4d2d52709ccebc4be42db856e511278",
|
||||
"sha256:c40ba2eb08b3f5de88152c2333c58cee7edcead0a2a0d60fcafa116b17117adc",
|
||||
"sha256:c55b20591ced744aa04e8c3e4b7543ea4d650b6c3c4b208c08a05b4010e8b442",
|
||||
"sha256:c58a9622d5dbeb668f407f35f4e6bfac34bb9ecdcc81680c04d0258169747997",
|
||||
"sha256:d44cb942af1693cced2604c33a9abcef6205601c445f6d0dc531d813af8a2f5a",
|
||||
"sha256:d907fddb39f923d011875452ff1eca29a9e7f21722b873e90db32e5d8ddff12e",
|
||||
"sha256:fd44fc75522f58612ec4a33958a7e5552562b7705b42ef1b4f8c0818e304a363"
|
||||
],
|
||||
"index": "pypi",
|
||||
"markers": "python_version >= '3.10'",
|
||||
"version": "==3.10.0"
|
||||
},
|
||||
"mypy-extensions": {
|
||||
"hashes": [
|
||||
"sha256:4392f6c0eb8a5668a69e23d168ffa70f0be9ccfd32b5cc2d26a34ae5b844552d",
|
||||
"sha256:75dbf8955dc00442a438fc4d0666508a9a97b6bd41aa2f0ffe9d2f2725af0782"
|
||||
],
|
||||
"markers": "python_version >= '3.5'",
|
||||
"version": "==1.0.0"
|
||||
},
|
||||
"numpy": {
|
||||
"hashes": [
|
||||
"sha256:02935e2c3c0c6cbe9c7955a8efa8908dd4221d7755644c59d1bba28b94fd334f",
|
||||
"sha256:0349b025e15ea9d05c3d63f9657707a4e1d471128a3b1d876c095f328f8ff7f0",
|
||||
"sha256:09d6a2032faf25e8d0cadde7fd6145118ac55d2740132c1d845f98721b5ebcfd",
|
||||
"sha256:0bc61b307655d1a7f9f4b043628b9f2b721e80839914ede634e3d485913e1fb2",
|
||||
"sha256:0eec19f8af947a61e968d5429f0bd92fec46d92b0008d0a6685b40d6adf8a4f4",
|
||||
"sha256:106397dbbb1896f99e044efc90360d098b3335060375c26aa89c0d8a97c5f648",
|
||||
"sha256:128c41c085cab8a85dc29e66ed88c05613dccf6bc28b3866cd16050a2f5448be",
|
||||
"sha256:149d1113ac15005652e8d0d3f6fd599360e1a708a4f98e43c9c77834a28238cb",
|
||||
"sha256:159ff6ee4c4a36a23fe01b7c3d07bd8c14cc433d9720f977fcd52c13c0098160",
|
||||
"sha256:22ea3bb552ade325530e72a0c557cdf2dea8914d3a5e1fecf58fa5dbcc6f43cd",
|
||||
"sha256:23ae9f0c2d889b7b2d88a3791f6c09e2ef827c2446f1c4a3e3e76328ee4afd9a",
|
||||
"sha256:250c16b277e3b809ac20d1f590716597481061b514223c7badb7a0f9993c7f84",
|
||||
"sha256:2ec6c689c61df613b783aeb21f945c4cbe6c51c28cb70aae8430577ab39f163e",
|
||||
"sha256:2ffbb1acd69fdf8e89dd60ef6182ca90a743620957afb7066385a7bbe88dc748",
|
||||
"sha256:3074634ea4d6df66be04f6728ee1d173cfded75d002c75fac79503a880bf3825",
|
||||
"sha256:356ca982c188acbfa6af0d694284d8cf20e95b1c3d0aefa8929376fea9146f60",
|
||||
"sha256:3fbe72d347fbc59f94124125e73fc4976a06927ebc503ec5afbfb35f193cd957",
|
||||
"sha256:40c7ff5da22cd391944a28c6a9c638a5eef77fcf71d6e3a79e1d9d9e82752715",
|
||||
"sha256:41184c416143defa34cc8eb9d070b0a5ba4f13a0fa96a709e20584638254b317",
|
||||
"sha256:451e854cfae0febe723077bd0cf0a4302a5d84ff25f0bfece8f29206c7bed02e",
|
||||
"sha256:4525b88c11906d5ab1b0ec1f290996c0020dd318af8b49acaa46f198b1ffc283",
|
||||
"sha256:463247edcee4a5537841d5350bc87fe8e92d7dd0e8c71c995d2c6eecb8208278",
|
||||
"sha256:4dbd80e453bd34bd003b16bd802fac70ad76bd463f81f0c518d1245b1c55e3d9",
|
||||
"sha256:57b4012e04cc12b78590a334907e01b3a85efb2107df2b8733ff1ed05fce71de",
|
||||
"sha256:5a8c863ceacae696aff37d1fd636121f1a512117652e5dfb86031c8d84836369",
|
||||
"sha256:5acea83b801e98541619af398cc0109ff48016955cc0818f478ee9ef1c5c3dcb",
|
||||
"sha256:642199e98af1bd2b6aeb8ecf726972d238c9877b0f6e8221ee5ab945ec8a2189",
|
||||
"sha256:64bd6e1762cd7f0986a740fee4dff927b9ec2c5e4d9a28d056eb17d332158014",
|
||||
"sha256:6d9fc9d812c81e6168b6d405bf00b8d6739a7f72ef22a9214c4241e0dc70b323",
|
||||
"sha256:7079129b64cb78bdc8d611d1fd7e8002c0a2565da6a47c4df8062349fee90e3e",
|
||||
"sha256:7dca87ca328f5ea7dafc907c5ec100d187911f94825f8700caac0b3f4c384b49",
|
||||
"sha256:860fd59990c37c3ef913c3ae390b3929d005243acca1a86facb0773e2d8d9e50",
|
||||
"sha256:8e6da5cffbbe571f93588f562ed130ea63ee206d12851b60819512dd3e1ba50d",
|
||||
"sha256:8ec0636d3f7d68520afc6ac2dc4b8341ddb725039de042faf0e311599f54eb37",
|
||||
"sha256:9491100aba630910489c1d0158034e1c9a6546f0b1340f716d522dc103788e39",
|
||||
"sha256:97b974d3ba0fb4612b77ed35d7627490e8e3dff56ab41454d9e8b23448940576",
|
||||
"sha256:995f9e8181723852ca458e22de5d9b7d3ba4da3f11cc1cb113f093b271d7965a",
|
||||
"sha256:9dd47ff0cb2a656ad69c38da850df3454da88ee9a6fde0ba79acceee0e79daba",
|
||||
"sha256:9fad446ad0bc886855ddf5909cbf8cb5d0faa637aaa6277fb4b19ade134ab3c7",
|
||||
"sha256:a972cec723e0563aa0823ee2ab1df0cb196ed0778f173b381c871a03719d4826",
|
||||
"sha256:ac9bea18d6d58a995fac1b2cb4488e17eceeac413af014b1dd26170b766d8467",
|
||||
"sha256:b0531f0b0e07643eb089df4c509d30d72c9ef40defa53e41363eca8a8cc61495",
|
||||
"sha256:b208cfd4f5fe34e1535c08983a1a6803fdbc7a1e86cf13dd0c61de0b51a0aadc",
|
||||
"sha256:b3482cb7b3325faa5f6bc179649406058253d91ceda359c104dac0ad320e1391",
|
||||
"sha256:b6fb9c32a91ec32a689ec6410def76443e3c750e7cfc3fb2206b985ffb2b85f0",
|
||||
"sha256:b78ea78450fd96a498f50ee096f69c75379af5138f7881a51355ab0e11286c97",
|
||||
"sha256:bd249bc894af67cbd8bad2c22e7cbcd46cf87ddfca1f1289d1e7e54868cc785c",
|
||||
"sha256:c7d1fd447e33ee20c1f33f2c8e6634211124a9aabde3c617687d8b739aa69eac",
|
||||
"sha256:d0bbe7dd86dca64854f4b6ce2ea5c60b51e36dfd597300057cf473d3615f2369",
|
||||
"sha256:d6d6a0910c3b4368d89dde073e630882cdb266755565155bc33520283b2d9df8",
|
||||
"sha256:da1eeb460ecce8d5b8608826595c777728cdf28ce7b5a5a8c8ac8d949beadcf2",
|
||||
"sha256:e0c8854b09bc4de7b041148d8550d3bd712b5c21ff6a8ed308085f190235d7ff",
|
||||
"sha256:e0d4142eb40ca6f94539e4db929410f2a46052a0fe7a2c1c59f6179c39938d2a",
|
||||
"sha256:e9e82dcb3f2ebbc8cb5ce1102d5f1c5ed236bf8a11730fb45ba82e2841ec21df",
|
||||
"sha256:ed6906f61834d687738d25988ae117683705636936cc605be0bb208b23df4d8f"
|
||||
],
|
||||
"index": "pypi",
|
||||
"markers": "python_version >= '3.10'",
|
||||
"version": "==2.2.2"
|
||||
},
|
||||
"opencv-python": {
|
||||
"hashes": [
|
||||
"sha256:03d60ccae62304860d232272e4a4fda93c39d595780cb40b161b310244b736a4",
|
||||
"sha256:085ad9b77c18853ea66283e98affefe2de8cc4c1f43eda4c100cf9b2721142ec",
|
||||
"sha256:1b92ae2c8852208817e6776ba1ea0d6b1e0a1b5431e971a2a0ddd2a8cc398202",
|
||||
"sha256:432f67c223f1dc2824f5e73cdfcd9db0efc8710647d4e813012195dc9122a52a",
|
||||
"sha256:6b02611523803495003bd87362db3e1d2a0454a6a63025dc6658a9830570aa0d",
|
||||
"sha256:810549cb2a4aedaa84ad9a1c92fbfdfc14090e2749cedf2c1589ad8359aa169b",
|
||||
"sha256:9d05ef13d23fe97f575153558653e2d6e87103995d54e6a35db3f282fe1f9c66"
|
||||
],
|
||||
"index": "pypi",
|
||||
"markers": "python_version >= '3.6'",
|
||||
"version": "==4.11.0.86"
|
||||
},
|
||||
"packaging": {
|
||||
"hashes": [
|
||||
"sha256:09abb1bccd265c01f4a3aa3f7a7db064b36514d2cba19a2f694fe6150451a759",
|
||||
"sha256:c228a6dc5e932d346bc5739379109d49e8853dd8223571c7c5b55260edc0b97f"
|
||||
],
|
||||
"markers": "python_version >= '3.8'",
|
||||
"version": "==24.2"
|
||||
},
|
||||
"pathspec": {
|
||||
"hashes": [
|
||||
"sha256:a0d503e138a4c123b27490a4f7beda6a01c6f288df0e4a8b79c7eb0dc7b4cc08",
|
||||
"sha256:a482d51503a1ab33b1c67a6c3813a26953dbdc71c31dacaef9a838c4e29f5712"
|
||||
],
|
||||
"markers": "python_version >= '3.8'",
|
||||
"version": "==0.12.1"
|
||||
},
|
||||
"pillow": {
|
||||
"hashes": [
|
||||
"sha256:015c6e863faa4779251436db398ae75051469f7c903b043a48f078e437656f83",
|
||||
"sha256:0a2f91f8a8b367e7a57c6e91cd25af510168091fb89ec5146003e424e1558a96",
|
||||
"sha256:11633d58b6ee5733bde153a8dafd25e505ea3d32e261accd388827ee987baf65",
|
||||
"sha256:2062ffb1d36544d42fcaa277b069c88b01bb7298f4efa06731a7fd6cc290b81a",
|
||||
"sha256:31eba6bbdd27dde97b0174ddf0297d7a9c3a507a8a1480e1e60ef914fe23d352",
|
||||
"sha256:3362c6ca227e65c54bf71a5f88b3d4565ff1bcbc63ae72c34b07bbb1cc59a43f",
|
||||
"sha256:368da70808b36d73b4b390a8ffac11069f8a5c85f29eff1f1b01bcf3ef5b2a20",
|
||||
"sha256:36ba10b9cb413e7c7dfa3e189aba252deee0602c86c309799da5a74009ac7a1c",
|
||||
"sha256:3764d53e09cdedd91bee65c2527815d315c6b90d7b8b79759cc48d7bf5d4f114",
|
||||
"sha256:3a5fe20a7b66e8135d7fd617b13272626a28278d0e578c98720d9ba4b2439d49",
|
||||
"sha256:3cdcdb0b896e981678eee140d882b70092dac83ac1cdf6b3a60e2216a73f2b91",
|
||||
"sha256:4637b88343166249fe8aa94e7c4a62a180c4b3898283bb5d3d2fd5fe10d8e4e0",
|
||||
"sha256:4db853948ce4e718f2fc775b75c37ba2efb6aaea41a1a5fc57f0af59eee774b2",
|
||||
"sha256:4dd43a78897793f60766563969442020e90eb7847463eca901e41ba186a7d4a5",
|
||||
"sha256:54251ef02a2309b5eec99d151ebf5c9904b77976c8abdcbce7891ed22df53884",
|
||||
"sha256:54ce1c9a16a9561b6d6d8cb30089ab1e5eb66918cb47d457bd996ef34182922e",
|
||||
"sha256:593c5fd6be85da83656b93ffcccc2312d2d149d251e98588b14fbc288fd8909c",
|
||||
"sha256:5bb94705aea800051a743aa4874bb1397d4695fb0583ba5e425ee0328757f196",
|
||||
"sha256:67cd427c68926108778a9005f2a04adbd5e67c442ed21d95389fe1d595458756",
|
||||
"sha256:70ca5ef3b3b1c4a0812b5c63c57c23b63e53bc38e758b37a951e5bc466449861",
|
||||
"sha256:73ddde795ee9b06257dac5ad42fcb07f3b9b813f8c1f7f870f402f4dc54b5269",
|
||||
"sha256:758e9d4ef15d3560214cddbc97b8ef3ef86ce04d62ddac17ad39ba87e89bd3b1",
|
||||
"sha256:7d33d2fae0e8b170b6a6c57400e077412240f6f5bb2a342cf1ee512a787942bb",
|
||||
"sha256:7fdadc077553621911f27ce206ffcbec7d3f8d7b50e0da39f10997e8e2bb7f6a",
|
||||
"sha256:8000376f139d4d38d6851eb149b321a52bb8893a88dae8ee7d95840431977081",
|
||||
"sha256:837060a8599b8f5d402e97197d4924f05a2e0d68756998345c829c33186217b1",
|
||||
"sha256:89dbdb3e6e9594d512780a5a1c42801879628b38e3efc7038094430844e271d8",
|
||||
"sha256:8c730dc3a83e5ac137fbc92dfcfe1511ce3b2b5d7578315b63dbbb76f7f51d90",
|
||||
"sha256:8e275ee4cb11c262bd108ab2081f750db2a1c0b8c12c1897f27b160c8bd57bbc",
|
||||
"sha256:9044b5e4f7083f209c4e35aa5dd54b1dd5b112b108648f5c902ad586d4f945c5",
|
||||
"sha256:93a18841d09bcdd774dcdc308e4537e1f867b3dec059c131fde0327899734aa1",
|
||||
"sha256:9409c080586d1f683df3f184f20e36fb647f2e0bc3988094d4fd8c9f4eb1b3b3",
|
||||
"sha256:96f82000e12f23e4f29346e42702b6ed9a2f2fea34a740dd5ffffcc8c539eb35",
|
||||
"sha256:9aa9aeddeed452b2f616ff5507459e7bab436916ccb10961c4a382cd3e03f47f",
|
||||
"sha256:9ee85f0696a17dd28fbcfceb59f9510aa71934b483d1f5601d1030c3c8304f3c",
|
||||
"sha256:a07dba04c5e22824816b2615ad7a7484432d7f540e6fa86af60d2de57b0fcee2",
|
||||
"sha256:a3cd561ded2cf2bbae44d4605837221b987c216cff94f49dfeed63488bb228d2",
|
||||
"sha256:a697cd8ba0383bba3d2d3ada02b34ed268cb548b369943cd349007730c92bddf",
|
||||
"sha256:a76da0a31da6fcae4210aa94fd779c65c75786bc9af06289cd1c184451ef7a65",
|
||||
"sha256:a85b653980faad27e88b141348707ceeef8a1186f75ecc600c395dcac19f385b",
|
||||
"sha256:a8d65b38173085f24bc07f8b6c505cbb7418009fa1a1fcb111b1f4961814a442",
|
||||
"sha256:aa8dd43daa836b9a8128dbe7d923423e5ad86f50a7a14dc688194b7be5c0dea2",
|
||||
"sha256:ab8a209b8485d3db694fa97a896d96dd6533d63c22829043fd9de627060beade",
|
||||
"sha256:abc56501c3fd148d60659aae0af6ddc149660469082859fa7b066a298bde9482",
|
||||
"sha256:ad5db5781c774ab9a9b2c4302bbf0c1014960a0a7be63278d13ae6fdf88126fe",
|
||||
"sha256:ae98e14432d458fc3de11a77ccb3ae65ddce70f730e7c76140653048c71bfcbc",
|
||||
"sha256:b20be51b37a75cc54c2c55def3fa2c65bb94ba859dde241cd0a4fd302de5ae0a",
|
||||
"sha256:b523466b1a31d0dcef7c5be1f20b942919b62fd6e9a9be199d035509cbefc0ec",
|
||||
"sha256:b5d658fbd9f0d6eea113aea286b21d3cd4d3fd978157cbf2447a6035916506d3",
|
||||
"sha256:b6123aa4a59d75f06e9dd3dac5bf8bc9aa383121bb3dd9a7a612e05eabc9961a",
|
||||
"sha256:bd165131fd51697e22421d0e467997ad31621b74bfc0b75956608cb2906dda07",
|
||||
"sha256:bf902d7413c82a1bfa08b06a070876132a5ae6b2388e2712aab3a7cbc02205c6",
|
||||
"sha256:c12fc111ef090845de2bb15009372175d76ac99969bdf31e2ce9b42e4b8cd88f",
|
||||
"sha256:c1eec9d950b6fe688edee07138993e54ee4ae634c51443cfb7c1e7613322718e",
|
||||
"sha256:c640e5a06869c75994624551f45e5506e4256562ead981cce820d5ab39ae2192",
|
||||
"sha256:cc1331b6d5a6e144aeb5e626f4375f5b7ae9934ba620c0ac6b3e43d5e683a0f0",
|
||||
"sha256:cfd5cd998c2e36a862d0e27b2df63237e67273f2fc78f47445b14e73a810e7e6",
|
||||
"sha256:d3d8da4a631471dfaf94c10c85f5277b1f8e42ac42bade1ac67da4b4a7359b73",
|
||||
"sha256:d44ff19eea13ae4acdaaab0179fa68c0c6f2f45d66a4d8ec1eda7d6cecbcc15f",
|
||||
"sha256:dd0052e9db3474df30433f83a71b9b23bd9e4ef1de13d92df21a52c0303b8ab6",
|
||||
"sha256:dd0e081319328928531df7a0e63621caf67652c8464303fd102141b785ef9547",
|
||||
"sha256:dda60aa465b861324e65a78c9f5cf0f4bc713e4309f83bc387be158b077963d9",
|
||||
"sha256:e06695e0326d05b06833b40b7ef477e475d0b1ba3a6d27da1bb48c23209bf457",
|
||||
"sha256:e1abe69aca89514737465752b4bcaf8016de61b3be1397a8fc260ba33321b3a8",
|
||||
"sha256:e267b0ed063341f3e60acd25c05200df4193e15a4a5807075cd71225a2386e26",
|
||||
"sha256:e5449ca63da169a2e6068dd0e2fcc8d91f9558aba89ff6d02121ca8ab11e79e5",
|
||||
"sha256:e63e4e5081de46517099dc30abe418122f54531a6ae2ebc8680bcd7096860eab",
|
||||
"sha256:f189805c8be5ca5add39e6f899e6ce2ed824e65fb45f3c28cb2841911da19070",
|
||||
"sha256:f7955ecf5609dee9442cbface754f2c6e541d9e6eda87fad7f7a989b0bdb9d71",
|
||||
"sha256:f86d3a7a9af5d826744fabf4afd15b9dfef44fe69a98541f666f66fbb8d3fef9",
|
||||
"sha256:fbd43429d0d7ed6533b25fc993861b8fd512c42d04514a0dd6337fb3ccf22761"
|
||||
],
|
||||
"markers": "python_version >= '3.9'",
|
||||
"version": "==11.1.0"
|
||||
},
|
||||
"platformdirs": {
|
||||
"hashes": [
|
||||
"sha256:357fb2acbc885b0419afd3ce3ed34564c13c9b95c89360cd9563f73aa5e2b907",
|
||||
"sha256:73e575e1408ab8103900836b97580d5307456908a03e92031bab39e4554cc3fb"
|
||||
],
|
||||
"markers": "python_version >= '3.8'",
|
||||
"version": "==4.3.6"
|
||||
},
|
||||
"pyparsing": {
|
||||
"hashes": [
|
||||
"sha256:506ff4f4386c4cec0590ec19e6302d3aedb992fdc02c761e90416f158dacf8e1",
|
||||
"sha256:61980854fd66de3a90028d679a954d5f2623e83144b5afe5ee86f43d762e5f0a"
|
||||
],
|
||||
"markers": "python_version >= '3.9'",
|
||||
"version": "==3.2.1"
|
||||
},
|
||||
"pyqt6": {
|
||||
"hashes": [
|
||||
"sha256:3a4354816f11e812b727206a9ea6e79ff3774f1bb7228ad4b9318442d2c64ff9",
|
||||
"sha256:452bae5840077bf0f146c798d7777f70d7bdd0c7dcfa9ee7a415c1daf2d10038",
|
||||
"sha256:48bace7b87676bba5e6114482f3a20ca20be90c7f261b5d340464313f5f2bf5e",
|
||||
"sha256:6d8628de4c2a050f0b74462e4c9cb97f839bf6ffabbca91711722ffb281570d9",
|
||||
"sha256:8c5c05f5fdff31a5887dbc29b27615b09df467631238d7b449283809ffca6228",
|
||||
"sha256:a9913d479f1ffee804bf7f232079baea4fb4b221a8f4890117588917a54ea30d",
|
||||
"sha256:cf7123caea14e7ecf10bd12cae48e8d9970ef7caf627bc7d7988b0baa209adb3"
|
||||
],
|
||||
"index": "pypi",
|
||||
"markers": "python_version >= '3.9'",
|
||||
"version": "==6.8.0"
|
||||
},
|
||||
"pyqt6-qt6": {
|
||||
"hashes": [
|
||||
"sha256:006d786693d0511fbcf184a862edbd339c6ed1bb3bd9de363d73a19ed4b23dff",
|
||||
"sha256:08065d595f1e6fc2dde9f4450eeff89082f4bad26f600a8e9b9cc5966716bfcf",
|
||||
"sha256:1eb8460a1fdb38d0b2458c2974c01d471c1e59e4eb19ea63fc447aaba3ad530e",
|
||||
"sha256:20843cb86bd94942d1cd99e39bf1aeabb875b241a35a8ab273e4bbbfa63776db",
|
||||
"sha256:2f4b8b55b1414b93f340f22e8c88d25550efcdebc4b65a3927dd947b73bd4358",
|
||||
"sha256:98aa99fe38ae68c5318284cd28f3479ba538c40bf6ece293980abae0925c1b24",
|
||||
"sha256:9f3790c4ce4dc576e48b8718d55fb8743057e6cbd53a6ca1dd253ffbac9b7287",
|
||||
"sha256:a8bc2ed4ee5e7c6ff4dd1c7db0b27705d151fee5dc232bbd1bf17618f937f515",
|
||||
"sha256:d6ca5d2b9d2ec0ee4a814b2175f641a5c4299cb80b45e0f5f8356632663f89b3"
|
||||
],
|
||||
"version": "==6.8.1"
|
||||
},
|
||||
"pyqt6-sip": {
|
||||
"hashes": [
|
||||
"sha256:14f95c6352e3b85dc26bf59cfbf77a470ecbd5fcdcf00af4b648f0e1b9eefb9e",
|
||||
"sha256:15be741d1ae8c82bb7afe9a61f3cf8c50457f7d61229a1c39c24cd6e8f4d86dc",
|
||||
"sha256:1d322ded1d1fea339cc6ac65b768e72c69c486eebb7db6ccde061b5786d74cc5",
|
||||
"sha256:1ec52e962f54137a19208b6e95b6bd9f7a403eb25d7237768a99306cd9db26d1",
|
||||
"sha256:1fb405615970e85b622b13b4cad140ff1e4182eb8334a0b27a4698e6217b89b0",
|
||||
"sha256:22d66256b800f552ade51a463510bf905f3cb318aae00ff4288fae4de5d0e600",
|
||||
"sha256:2ab85aaf155828331399c59ebdd4d3b0358e42c08250e86b43d56d9873df148a",
|
||||
"sha256:3c269052c770c09b61fce2f2f9ea934a67dfc65f443d59629b4ccc8f89751890",
|
||||
"sha256:5004514b08b045ad76425cf3618187091a668d972b017677b1b4b193379ef553",
|
||||
"sha256:552ff8fdc41f5769d3eccc661f022ed496f55f6e0a214c20aaf56e56385d61b6",
|
||||
"sha256:5643c92424fe62cb0b33378fef3d28c1525f91ada79e8a15bd9a05414a09503d",
|
||||
"sha256:56ce0afb19cd8a8c63ff93ae506dffb74f844b88adaa6673ebc0dec43af48a76",
|
||||
"sha256:57b5312ef13c1766bdf69b317041140b184eb24a51e1e23ce8fc5386ba8dffb2",
|
||||
"sha256:5d7726556d1ca7a7ed78e19ba53285b64a2a8f6ad7ff4cb18a1832efca1a3102",
|
||||
"sha256:69a879cfc94f4984d180321b76f52923861cd5bf4969aa885eef7591ee932517",
|
||||
"sha256:6e6c1e2592187934f4e790c0c099d0033e986dcef7bdd3c06e3895ffa995e9fc",
|
||||
"sha256:8b2ac36d6e04db6099614b9c1178a2f87788c7ffc3826571fb63d36ddb4c401d",
|
||||
"sha256:8c207528992d59b0801458aa6fcff118e5c099608ef0fc6ff8bccbdc23f29c04",
|
||||
"sha256:976c7758f668806d4df7a8853f390ac123d5d1f73591ed368bdb8963574ff589",
|
||||
"sha256:accab6974b2758296400120fdcc9d1f37785b2ea2591f00656e1776f058ded6c",
|
||||
"sha256:c1942e107b0243ced9e510d507e0f27aeea9d6b13e0a1b7c06fd52a62e0d41f7",
|
||||
"sha256:c800db3464481e87b1d2b84523b075df1e8fc7856c6f9623dc243f89be1cb604",
|
||||
"sha256:e996d320744ca8342cad6f9454345330d4f06bce129812d032bda3bad6967c5c",
|
||||
"sha256:fa27b51ae4c7013b3700cf0ecf46907d1333ae396fc6511311920485cbce094b"
|
||||
],
|
||||
"markers": "python_version >= '3.9'",
|
||||
"version": "==13.9.1"
|
||||
},
|
||||
"python-dateutil": {
|
||||
"hashes": [
|
||||
"sha256:37dd54208da7e1cd875388217d5e00ebd4179249f90fb72437e91a35459a0ad3",
|
||||
"sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427"
|
||||
],
|
||||
"markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2'",
|
||||
"version": "==2.9.0.post0"
|
||||
},
|
||||
"s3transfer": {
|
||||
"hashes": [
|
||||
"sha256:3b39185cb72f5acc77db1a58b6e25b977f28d20496b6e58d6813d75f464d632f",
|
||||
"sha256:be6ecb39fadd986ef1701097771f87e4d2f821f27f6071c872143884d2950fbc"
|
||||
],
|
||||
"markers": "python_version >= '3.8'",
|
||||
"version": "==0.11.2"
|
||||
},
|
||||
"scikit-learn": {
|
||||
"hashes": [
|
||||
"sha256:0650e730afb87402baa88afbf31c07b84c98272622aaba002559b614600ca691",
|
||||
"sha256:0c8d036eb937dbb568c6242fa598d551d88fb4399c0344d95c001980ec1c7d36",
|
||||
"sha256:1061b7c028a8663fb9a1a1baf9317b64a257fcb036dae5c8752b2abef31d136f",
|
||||
"sha256:25fc636bdaf1cc2f4a124a116312d837148b5e10872147bdaf4887926b8c03d8",
|
||||
"sha256:2c2cae262064e6a9b77eee1c8e768fc46aa0b8338c6a8297b9b6759720ec0ff2",
|
||||
"sha256:2e69fab4ebfc9c9b580a7a80111b43d214ab06250f8a7ef590a4edf72464dd86",
|
||||
"sha256:2ffa1e9e25b3d93990e74a4be2c2fc61ee5af85811562f1288d5d055880c4322",
|
||||
"sha256:3f59fe08dc03ea158605170eb52b22a105f238a5d512c4470ddeca71feae8e5f",
|
||||
"sha256:44a17798172df1d3c1065e8fcf9019183f06c87609b49a124ebdf57ae6cb0107",
|
||||
"sha256:6849dd3234e87f55dce1db34c89a810b489ead832aaf4d4550b7ea85628be6c1",
|
||||
"sha256:6a7aa5f9908f0f28f4edaa6963c0a6183f1911e63a69aa03782f0d924c830a35",
|
||||
"sha256:70b1d7e85b1c96383f872a519b3375f92f14731e279a7b4c6cfd650cf5dffc52",
|
||||
"sha256:72abc587c75234935e97d09aa4913a82f7b03ee0b74111dcc2881cba3c5a7b33",
|
||||
"sha256:775da975a471c4f6f467725dff0ced5c7ac7bda5e9316b260225b48475279a1b",
|
||||
"sha256:7a1c43c8ec9fde528d664d947dc4c0789be4077a3647f232869f41d9bf50e0fb",
|
||||
"sha256:7a73d457070e3318e32bdb3aa79a8d990474f19035464dfd8bede2883ab5dc3b",
|
||||
"sha256:8634c4bd21a2a813e0a7e3900464e6d593162a29dd35d25bdf0103b3fce60ed5",
|
||||
"sha256:8a600c31592bd7dab31e1c61b9bbd6dea1b3433e67d264d17ce1017dbdce8002",
|
||||
"sha256:926f207c804104677af4857b2c609940b743d04c4c35ce0ddc8ff4f053cddc1b",
|
||||
"sha256:a17c1dea1d56dcda2fac315712f3651a1fea86565b64b48fa1bc090249cbf236",
|
||||
"sha256:b3b00cdc8f1317b5f33191df1386c0befd16625f49d979fe77a8d44cae82410d",
|
||||
"sha256:b4fc2525eca2c69a59260f583c56a7557c6ccdf8deafdba6e060f94c1c59738e",
|
||||
"sha256:b8b7a3b86e411e4bce21186e1c180d792f3d99223dcfa3b4f597ecc92fa1a422",
|
||||
"sha256:c06beb2e839ecc641366000ca84f3cf6fa9faa1777e29cf0c04be6e4d096a348",
|
||||
"sha256:d056391530ccd1e501056160e3c9673b4da4805eb67eb2bdf4e983e1f9c9204e",
|
||||
"sha256:dc4765af3386811c3ca21638f63b9cf5ecf66261cc4815c1db3f1e7dc7b79db2",
|
||||
"sha256:dc5cf3d68c5a20ad6d571584c0750ec641cc46aeef1c1507be51300e6003a7e1",
|
||||
"sha256:e7be3fa5d2eb9be7d77c3734ff1d599151bb523674be9b834e8da6abe132f44e",
|
||||
"sha256:e8ca8cb270fee8f1f76fa9bfd5c3507d60c6438bbee5687f81042e2bb98e5a97",
|
||||
"sha256:fa909b1a36e000a03c382aade0bd2063fd5680ff8b8e501660c0f59f021a6415"
|
||||
],
|
||||
"index": "pypi",
|
||||
"markers": "python_version >= '3.9'",
|
||||
"version": "==1.6.1"
|
||||
},
|
||||
"scipy": {
|
||||
"hashes": [
|
||||
"sha256:033a75ddad1463970c96a88063a1df87ccfddd526437136b6ee81ff0312ebdf6",
|
||||
"sha256:0458839c9f873062db69a03de9a9765ae2e694352c76a16be44f93ea45c28d2b",
|
||||
"sha256:070d10654f0cb6abd295bc96c12656f948e623ec5f9a4eab0ddb1466c000716e",
|
||||
"sha256:09c52320c42d7f5c7748b69e9f0389266fd4f82cf34c38485c14ee976cb8cb04",
|
||||
"sha256:0ac102ce99934b162914b1e4a6b94ca7da0f4058b6d6fd65b0cef330c0f3346f",
|
||||
"sha256:0fb57b30f0017d4afa5fe5f5b150b8f807618819287c21cbe51130de7ccdaed2",
|
||||
"sha256:100193bb72fbff37dbd0bf14322314fc7cbe08b7ff3137f11a34d06dc0ee6b85",
|
||||
"sha256:14eaa373c89eaf553be73c3affb11ec6c37493b7eaaf31cf9ac5dffae700c2e0",
|
||||
"sha256:2114a08daec64980e4b4cbdf5bee90935af66d750146b1d2feb0d3ac30613692",
|
||||
"sha256:21e10b1dd56ce92fba3e786007322542361984f8463c6d37f6f25935a5a6ef52",
|
||||
"sha256:2722a021a7929d21168830790202a75dbb20b468a8133c74a2c0230c72626b6c",
|
||||
"sha256:395be70220d1189756068b3173853029a013d8c8dd5fd3d1361d505b2aa58fa7",
|
||||
"sha256:3fe1d95944f9cf6ba77aa28b82dd6bb2a5b52f2026beb39ecf05304b8392864b",
|
||||
"sha256:491d57fe89927fa1aafbe260f4cfa5ffa20ab9f1435025045a5315006a91b8f5",
|
||||
"sha256:4b17d4220df99bacb63065c76b0d1126d82bbf00167d1730019d2a30d6ae01ea",
|
||||
"sha256:4c9d8fc81d6a3b6844235e6fd175ee1d4c060163905a2becce8e74cb0d7554ce",
|
||||
"sha256:55cc79ce4085c702ac31e49b1e69b27ef41111f22beafb9b49fea67142b696c4",
|
||||
"sha256:5b190b935e7db569960b48840e5bef71dc513314cc4e79a1b7d14664f57fd4ff",
|
||||
"sha256:5bd8d27d44e2c13d0c1124e6a556454f52cd3f704742985f6b09e75e163d20d2",
|
||||
"sha256:5dff14e75cdbcf07cdaa1c7707db6017d130f0af9ac41f6ce443a93318d6c6e0",
|
||||
"sha256:5eb0ca35d4b08e95da99a9f9c400dc9f6c21c424298a0ba876fdc69c7afacedf",
|
||||
"sha256:63b9b6cd0333d0eb1a49de6f834e8aeaefe438df8f6372352084535ad095219e",
|
||||
"sha256:667f950bf8b7c3a23b4199db24cb9bf7512e27e86d0e3813f015b74ec2c6e3df",
|
||||
"sha256:6b3e71893c6687fc5e29208d518900c24ea372a862854c9888368c0b267387ab",
|
||||
"sha256:71ba9a76c2390eca6e359be81a3e879614af3a71dfdabb96d1d7ab33da6f2364",
|
||||
"sha256:74bb864ff7640dea310a1377d8567dc2cb7599c26a79ca852fc184cc851954ac",
|
||||
"sha256:82add84e8a9fb12af5c2c1a3a3f1cb51849d27a580cb9e6bd66226195142be6e",
|
||||
"sha256:837299eec3d19b7e042923448d17d95a86e43941104d33f00da7e31a0f715d3c",
|
||||
"sha256:900f3fa3db87257510f011c292a5779eb627043dd89731b9c461cd16ef76ab3d",
|
||||
"sha256:9f151e9fb60fbf8e52426132f473221a49362091ce7a5e72f8aa41f8e0da4f25",
|
||||
"sha256:af0b61c1de46d0565b4b39c6417373304c1d4f5220004058bdad3061c9fa8a95",
|
||||
"sha256:bc7136626261ac1ed988dca56cfc4ab5180f75e0ee52e58f1e6aa74b5f3eacd5",
|
||||
"sha256:be3deeb32844c27599347faa077b359584ba96664c5c79d71a354b80a0ad0ce0",
|
||||
"sha256:c09aa9d90f3500ea4c9b393ee96f96b0ccb27f2f350d09a47f533293c78ea776",
|
||||
"sha256:c352c1b6d7cac452534517e022f8f7b8d139cd9f27e6fbd9f3cbd0bfd39f5bef",
|
||||
"sha256:c64ded12dcab08afff9e805a67ff4480f5e69993310e093434b10e85dc9d43e1",
|
||||
"sha256:cdde8414154054763b42b74fe8ce89d7f3d17a7ac5dd77204f0e142cdc9239e9",
|
||||
"sha256:ce3a000cd28b4430426db2ca44d96636f701ed12e2b3ca1f2b1dd7abdd84b39a",
|
||||
"sha256:f735bc41bd1c792c96bc426dece66c8723283695f02df61dcc4d0a707a42fc54",
|
||||
"sha256:f82fcf4e5b377f819542fbc8541f7b5fbcf1c0017d0df0bc22c781bf60abc4d8"
|
||||
],
|
||||
"markers": "python_version >= '3.10'",
|
||||
"version": "==1.15.1"
|
||||
},
|
||||
"six": {
|
||||
"hashes": [
|
||||
"sha256:4721f391ed90541fddacab5acf947aa0d3dc7d27b2e1e8eda2be8970586c3274",
|
||||
"sha256:ff70335d468e7eb6ec65b95b99d3a2836546063f63acc5171de367e834932a81"
|
||||
],
|
||||
"markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2'",
|
||||
"version": "==1.17.0"
|
||||
},
|
||||
"threadpoolctl": {
|
||||
"hashes": [
|
||||
"sha256:082433502dd922bf738de0d8bcc4fdcbf0979ff44c42bd40f5af8a282f6fa107",
|
||||
"sha256:56c1e26c150397e58c4926da8eeee87533b1e32bef131bd4bf6a2f45f3185467"
|
||||
],
|
||||
"markers": "python_version >= '3.8'",
|
||||
"version": "==3.5.0"
|
||||
},
|
||||
"urllib3": {
|
||||
"hashes": [
|
||||
"sha256:1cee9ad369867bfdbbb48b7dd50374c0967a0bb7710050facf0dd6911440e3df",
|
||||
"sha256:f8c5449b3cf0861679ce7e0503c7b44b5ec981bec0d1d3795a07f1ba96f0204d"
|
||||
],
|
||||
"markers": "python_version >= '3.9'",
|
||||
"version": "==2.3.0"
|
||||
}
|
||||
},
|
||||
"develop": {}
|
||||
}
|
Binary file not shown.
After Width: | Height: | Size: 244 KiB |
|
@ -0,0 +1,6 @@
|
|||
PyQt6
|
||||
numpy
|
||||
matplotlib
|
||||
scikit-learn
|
||||
boto3
|
||||
opencv-python
|
|
@ -0,0 +1,36 @@
|
|||
import boto3
|
||||
import cv2
|
||||
|
||||
|
||||
class AWSRekognition:
|
||||
def __init__(self):
|
||||
self.rekognition_client = boto3.client(
|
||||
"rekognition", region_name="eu-central-1"
|
||||
)
|
||||
|
||||
def label_image(self, img):
|
||||
result = img.copy()
|
||||
print("Detect Labels")
|
||||
# Convert the image to bytes
|
||||
_, image_bytes = cv2.imencode(".jpg", img)
|
||||
|
||||
# Call the detect_labels method
|
||||
response = self.rekognition_client.detect_labels(
|
||||
Image={"Bytes": image_bytes.tobytes()}, MaxLabels=20, MinConfidence=90
|
||||
)
|
||||
|
||||
# Print the labels
|
||||
for label in response["Labels"]:
|
||||
print(label["Name"], label["Confidence"])
|
||||
|
||||
# Draw bounding boxes around the detected objects
|
||||
for label in response["Labels"]:
|
||||
for instance in label["Instances"]:
|
||||
bounding_box = instance["BoundingBox"]
|
||||
x = int(bounding_box["Left"] * result.shape[1])
|
||||
y = int(bounding_box["Top"] * result.shape[0])
|
||||
w = int(bounding_box["Width"] * result.shape[1])
|
||||
h = int(bounding_box["Height"] * result.shape[0])
|
||||
cv2.rectangle(result, (x, y), (x + w, y + h), (0, 255, 0), 2)
|
||||
|
||||
return result
|
|
@ -0,0 +1,80 @@
|
|||
import cv2
|
||||
import numpy as np
|
||||
import matplotlib.pyplot as plt
|
||||
from mpl_toolkits.mplot3d import Axes3D
|
||||
from sklearn.cluster import KMeans
|
||||
|
||||
|
||||
class ColorAnalysis:
|
||||
|
||||
CLUSTERS = None
|
||||
IMAGE = None
|
||||
COLORS = None
|
||||
LABELS = None
|
||||
|
||||
def __init__(self, img, clusters=3):
|
||||
self.CLUSTERS = clusters
|
||||
self.IMAGE = img
|
||||
|
||||
def show3DHistogram(self):
|
||||
# img = Utilities.resize_image(img, 100)
|
||||
|
||||
# resize image# convert from BGR to RGB
|
||||
# img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
|
||||
|
||||
# get rgb values from image to 1D array
|
||||
r, g, b = cv2.split(self.IMAGE)
|
||||
r = r.flatten()
|
||||
g = g.flatten()
|
||||
b = b.flatten()
|
||||
|
||||
# plotting
|
||||
fig = plt.figure()
|
||||
ax = Axes3D(fig)
|
||||
ax.scatter(r, g, b)
|
||||
plt.show()
|
||||
|
||||
def dominantColors(self):
|
||||
img = self.IMAGE
|
||||
# img = Utilities.resize_image(img, 100)
|
||||
# reshaping to a list of pixels
|
||||
img = img.reshape((img.shape[0] * img.shape[1], 3))
|
||||
|
||||
# using k-means to cluster pixels
|
||||
kmeans = KMeans(n_clusters=self.CLUSTERS)
|
||||
kmeans.fit(img)
|
||||
|
||||
# the cluster centers are our dominant colors.
|
||||
self.COLORS = kmeans.cluster_centers_
|
||||
|
||||
# save labels
|
||||
self.LABELS = kmeans.labels_
|
||||
|
||||
# returning after converting to integer from float
|
||||
return self.COLORS.astype(int)
|
||||
|
||||
def rgb_to_hex(self, rgb):
|
||||
return "#%02x%02x%02x" % (int(rgb[0]), int(rgb[1]), int(rgb[2]))
|
||||
|
||||
def plotClusters(self):
|
||||
# plotting
|
||||
fig = plt.figure()
|
||||
ax = Axes3D(fig)
|
||||
for label, pix in zip(self.LABELS, self.IMAGE):
|
||||
ax.scatter(
|
||||
pix[0], pix[1], pix[2], color=self.rgb_to_hex(self.COLORS[label])
|
||||
)
|
||||
plt.show()
|
||||
|
||||
|
||||
def create_visual_output(colors, width, height_max):
|
||||
n_clusters = len(colors)
|
||||
visual_output = 255 * np.ones((height_max, width, 3), np.uint8)
|
||||
height = int(width / n_clusters)
|
||||
box_width = int(width / n_clusters)
|
||||
if height < height_max:
|
||||
visual_output = 255 * np.ones((height, width, 3), np.uint8)
|
||||
|
||||
for i in range(n_clusters):
|
||||
visual_output[:, box_width * i : box_width * (i + 1)] = colors[i]
|
||||
return visual_output
|
|
@ -0,0 +1,60 @@
|
|||
import cv2
|
||||
import numpy as np
|
||||
import Utilities
|
||||
|
||||
|
||||
# Task 1
|
||||
# function to stretch an image
|
||||
def stretchHistogram(img):
|
||||
result = img.copy()
|
||||
return result
|
||||
|
||||
|
||||
# Task 2
|
||||
# function to equalize an image
|
||||
def equalizeHistogram(img):
|
||||
result = img.copy()
|
||||
return result
|
||||
|
||||
|
||||
# Hilfsfunktion
|
||||
# function to apply a look-up table onto an image
|
||||
def applyLUT(img, LUT):
|
||||
result = img.copy()
|
||||
return result
|
||||
|
||||
|
||||
# Hilfsfunktion
|
||||
# function to find the minimum an maximum in a histogram
|
||||
def findMinMaxPos(histogram):
|
||||
minPos = 0
|
||||
maxPos = 255
|
||||
return minPos, maxPos
|
||||
|
||||
|
||||
# Hilfsfunktion
|
||||
# function to create a vector containing the histogram
|
||||
def calculateHistogram(img, nrBins):
|
||||
# create histogram vector
|
||||
histogram = np.zeros([nrBins], dtype=int)
|
||||
return histogram
|
||||
|
||||
|
||||
def apply_log(img):
|
||||
result = img.copy()
|
||||
return result
|
||||
|
||||
|
||||
def apply_exp(img):
|
||||
result = img.copy()
|
||||
return result
|
||||
|
||||
|
||||
def apply_inverse(img):
|
||||
result = img.copy()
|
||||
return result
|
||||
|
||||
|
||||
def apply_threshold(img, threshold):
|
||||
result = img.copy()
|
||||
return result
|
|
@ -0,0 +1,67 @@
|
|||
import numpy as np
|
||||
import matplotlib.pyplot as plt
|
||||
import datetime as dt
|
||||
import cv2
|
||||
import Utilities
|
||||
|
||||
|
||||
# apply median filter
|
||||
def applyMedianFilter(img, kSize):
|
||||
filtered_img = img.copy()
|
||||
return filtered_img
|
||||
|
||||
|
||||
# create a moving average kernel of arbitrary size
|
||||
def createMovingAverageKernel(kSize):
|
||||
kernel = np.zeros((kSize, kSize))
|
||||
return kernel
|
||||
|
||||
|
||||
def gaussian(x, y, sigmaX, sigmaY, meanX, meanY):
|
||||
result = 1
|
||||
return result
|
||||
|
||||
|
||||
# create a gaussian kernel of arbitrary size
|
||||
def createGaussianKernel(kSize, sigma=None):
|
||||
kernel = np.zeros((kSize, kSize))
|
||||
return kernel
|
||||
|
||||
|
||||
# create a sobel kernel in x direction of size 3x3
|
||||
def createSobelXKernel():
|
||||
kernel = np.zeros((3, 3))
|
||||
return kernel
|
||||
|
||||
|
||||
# create a sobel kernel in y direction of size 3x3
|
||||
def createSobelYKernel():
|
||||
kernel = np.zeros((3, 3))
|
||||
return kernel
|
||||
|
||||
|
||||
def applyKernelInSpatialDomain(img, kernel):
|
||||
filtered_img = img.copy()
|
||||
return filtered_img
|
||||
|
||||
|
||||
# Extra: create an integral image of the given image
|
||||
def createIntegralImage(img):
|
||||
integral_image = img.copy()
|
||||
return integral_image
|
||||
|
||||
|
||||
# Extra: apply the moving average filter by using an integral image
|
||||
def applyMovingAverageFilterWithIntegralImage(img, kSize):
|
||||
filtered_img = img.copy()
|
||||
return filtered_img
|
||||
|
||||
|
||||
# Extra:
|
||||
def applyMovingAverageFilterWithSeperatedKernels(img, kSize):
|
||||
filtered_img = img.copy()
|
||||
return filtered_img
|
||||
|
||||
|
||||
def run_runtime_evaluation(img):
|
||||
pass
|
|
@ -0,0 +1,110 @@
|
|||
import numpy as np
|
||||
|
||||
|
||||
def luminanceD65(rgb: np.ndarray) -> np.float64:
|
||||
"""
|
||||
Compute the luminance value of the specified linear RGB values
|
||||
according to the D65 white point.
|
||||
|
||||
@param rgb(np.ndarray): sRGB image
|
||||
|
||||
@returns The luminance value
|
||||
"""
|
||||
return np.float64(rgb @ [0.2126, 0.7152, 0.0722])
|
||||
|
||||
|
||||
# Task 1: Implement some kind of noticeable image manipulation in this function
|
||||
# e.g. channel manipulation, filter you already know, drawings on the image etc.
|
||||
def myFirstImageManipulation(img) -> np.ndarray:
|
||||
"""
|
||||
Convert each pixel in the input image using the D65 luminance formula.
|
||||
|
||||
This function takes a NumPy array `img` as input and returns a new array with
|
||||
each pixel value replaced by its corresponding D65 luminance value. The output
|
||||
array maintains the same dimensions and data type as the input array, but each
|
||||
pixel is processed through this specific transformation.
|
||||
|
||||
Parameters:
|
||||
- img (ndarray): The input image data array of shape (height, width).
|
||||
|
||||
Returns:
|
||||
- ndarray: An array where each pixel has been replaced by its D65
|
||||
luminance value from the original image.
|
||||
"""
|
||||
result = img.copy()
|
||||
|
||||
for x in range(0, result.shape[0]):
|
||||
for y in range(0, result.shape[1]):
|
||||
|
||||
result[x][y] = luminanceD65(img[x][y])
|
||||
|
||||
return result
|
||||
|
||||
|
||||
# Task 2: Return the basic image properties to the console:
|
||||
# width, height,
|
||||
# the color of the first pixel of the image,
|
||||
# Color of the first pixel in the second row
|
||||
# Color of the first pixel in the second column
|
||||
# This function should work for images with three channels
|
||||
def imageSize(img: np.ndarray) -> list[int]:
|
||||
"""Get the height and width dimensions of an image array.
|
||||
|
||||
Args:
|
||||
img (np.ndarray): A numpy array representing the image.
|
||||
|
||||
Returns:
|
||||
list[int]: A two-element list containing [height, width] dimensions of the image.
|
||||
|
||||
Note:
|
||||
The function works for any multi-dimensional numpy array. It returns
|
||||
a list with the first two dimensions regardless of whether they are 2D or higher.
|
||||
"""
|
||||
return [img.shape[0], img.shape[1]]
|
||||
|
||||
|
||||
def getPixelColor(img):
|
||||
"""
|
||||
Retrieve color information from specific pixels in an image array.
|
||||
|
||||
This function processes an RGB image array and returns a list of color values
|
||||
based on predefined positions. It is designed to handle multi-channel images,
|
||||
extracting information such as first pixel of each row, specific channels,
|
||||
and other notable points within the image data.
|
||||
|
||||
Parameters:
|
||||
img (np.ndarray): The input image data array containing RGB or grayscale values.
|
||||
|
||||
Returns:
|
||||
list: A structured list of color values extracted from different positions
|
||||
in the image. This includes colors from specified rows, columns,
|
||||
and channels where applicable.
|
||||
"""
|
||||
return [img[0][1], img[1][0]]
|
||||
|
||||
|
||||
# Task 3: Separate the given channels of a colour image in this function and return it as separate image
|
||||
def returnChannel(img: np.ndarray, channel: int) -> np.ndarray:
|
||||
"""
|
||||
Splits an image into a separate channel or keeps only the specified color channel.
|
||||
|
||||
Parameters:
|
||||
- img: Input np.ndarray (required). This should be a color image array in RGB format.
|
||||
If it's grayscale, this method might not work correctly as it expects three channels.
|
||||
- channel: int (required). The index of the channel to keep. It can be 0 for red, 1 for green, or 2 for blue.
|
||||
|
||||
Returns:
|
||||
- np.ndarray: A new image array where only the specified color channel is non-zero,
|
||||
and other channels are zeroed out.
|
||||
"""
|
||||
result = img.copy()
|
||||
|
||||
for x in range(0, result.shape[0]):
|
||||
for y in range(0, result.shape[1]):
|
||||
for c in range(0, 3):
|
||||
if c == channel:
|
||||
continue
|
||||
|
||||
result[x][y][c] = 0
|
||||
|
||||
return result
|
|
@ -0,0 +1,262 @@
|
|||
from PyQt6.QtWidgets import QLabel, QGraphicsView, QGraphicsScene, QGraphicsPixmapItem
|
||||
from PyQt6.QtGui import QTransform
|
||||
from PyQt6.QtCore import Qt
|
||||
|
||||
|
||||
class ImagePlotter(QGraphicsView):
|
||||
def __init__(self, parent=None):
|
||||
super(ImagePlotter, self).__init__(parent)
|
||||
|
||||
self.scene = QGraphicsScene()
|
||||
# self.setAlignment(Qt.AlignCenter)
|
||||
self.zoom_level = 0
|
||||
|
||||
def show_image(self, image):
|
||||
self.scene.clear()
|
||||
item = QGraphicsPixmapItem(image)
|
||||
self.scene.addItem(item)
|
||||
self.setScene(self.scene)
|
||||
|
||||
scene_rect = self.scene.itemsBoundingRect()
|
||||
|
||||
self.fitInView(scene_rect, Qt.AspectRatioMode.KeepAspectRatio)
|
||||
print(self.scene.sceneRect().width())
|
||||
print(self.width())
|
||||
self.show()
|
||||
|
||||
def wheelEvent(self, event):
|
||||
# Get the current zoom level of the view
|
||||
self.zoom_level = self.transform().m11()
|
||||
print(self.zoom_level)
|
||||
zoom = self.transform().m11()
|
||||
|
||||
# Calculate the new zoom level based on the direction of the mouse wheel
|
||||
if event.angleDelta().y() > 0:
|
||||
zoom *= 1.2
|
||||
else:
|
||||
zoom /= 1.2
|
||||
|
||||
# Set the new zoom level of the view
|
||||
self.setTransform(QTransform().scale(zoom, zoom))
|
||||
|
||||
|
||||
class ImagePlotter2(QLabel):
|
||||
def __init__(self, parent=None):
|
||||
super(ImagePlotter2, self).__init__(parent)
|
||||
self.setMouseTracking(True)
|
||||
self.setCursor(Qt.CrossCursor)
|
||||
|
||||
# def mouseMoveEvent(self, event):
|
||||
# cursor_pos = event.pos()
|
||||
# print("Cursor position:", cursor_pos.x(), cursor_pos.y())
|
||||
|
||||
def mousePressEvent(self, event):
|
||||
cursor_pos = event.pos()
|
||||
pixmap = self.pixmap()
|
||||
label_pos = self.pos()
|
||||
pixmap_rect = pixmap.rect()
|
||||
|
||||
pixmap_pos = label_pos + pixmap_rect.topLeft()
|
||||
|
||||
pixel_color = pixmap.toImage().pixelColor(0, 0)
|
||||
red = pixel_color.red()
|
||||
green = pixel_color.green()
|
||||
blue = pixel_color.blue()
|
||||
|
||||
print("RGB value of pixel at position (10, 10):", red, green, blue)
|
||||
|
||||
print(
|
||||
"Position of pixmap top left:",
|
||||
pixmap_rect.topLeft().x(),
|
||||
pixmap_rect.topLeft().y(),
|
||||
)
|
||||
print("Position of pixmap in QLabel:", pixmap_pos.x(), pixmap_pos.y())
|
||||
print("Label pos:", label_pos.x(), label_pos.y())
|
||||
# image_pos = self.mapFrom(self., cursor_pos)
|
||||
|
||||
|
||||
# print("Mouse clicked at:", event.pos().x(), event.pos().y())
|
||||
# print("Mouse clicked at:", image_pos.x(), image_pos.y())
|
||||
|
||||
|
||||
from PyQt6.QtGui import QImage, QPixmap, QPainter
|
||||
from PyQt6 import QtCore, QtGui, QtWidgets
|
||||
|
||||
|
||||
__author__ = "Atinderpal Singh"
|
||||
__license__ = "MIT"
|
||||
__version__ = "1.0"
|
||||
__email__ = "atinderpalap@gmail.com"
|
||||
|
||||
|
||||
class ImagePlotter3(QLabel):
|
||||
"""Basic image viewer class to show an image with zoom and pan functionaities.
|
||||
Requirement: Qt's Qlabel widget name where the image will be drawn/displayed.
|
||||
"""
|
||||
|
||||
def __init__(self, parent=None):
|
||||
super(ImagePlotter3, self).__init__(parent)
|
||||
self.qlabel_image = (
|
||||
QLabel()
|
||||
) # widget/window name where image is displayed (I'm usiing qlabel)
|
||||
self.qimage_scaled = QImage() # scaled image to fit to the size of qlabel_image
|
||||
self.qpixmap = QPixmap() # qpixmap to fill the qlabel_image
|
||||
|
||||
self.zoomX = 1 # zoom factor w.r.t size of qlabel_image
|
||||
self.position = [
|
||||
0,
|
||||
0,
|
||||
] # position of top left corner of qimage_label w.r.t. qimage_scaled
|
||||
self.panFlag = False # to enable or disable pan
|
||||
|
||||
self.qlabel_image.setSizePolicy(
|
||||
QtWidgets.QSizePolicy.Ignored, QtWidgets.QSizePolicy.Ignored
|
||||
)
|
||||
self.__connectEvents()
|
||||
|
||||
def __connectEvents(self):
|
||||
# Mouse events
|
||||
self.qlabel_image.mousePressEvent = self.mousePressAction
|
||||
self.qlabel_image.mouseMoveEvent = self.mouseMoveAction
|
||||
self.qlabel_image.mouseReleaseEvent = self.mouseReleaseAction
|
||||
|
||||
def onResize(self):
|
||||
"""things to do when qlabel_image is resized"""
|
||||
self.qpixmap = QPixmap(self.qlabel_image.size())
|
||||
self.qpixmap.fill(QtCore.Qt.gray)
|
||||
self.qimage_scaled = self.qimage.scaled(
|
||||
self.qlabel_image.width() * self.zoomX,
|
||||
self.qlabel_image.height() * self.zoomX,
|
||||
QtCore.Qt.KeepAspectRatio,
|
||||
)
|
||||
self.update()
|
||||
|
||||
def loadImage(self, input_image):
|
||||
"""To load and display new image."""
|
||||
self.qimage = input_image.toImage()
|
||||
print(self.qimage.width())
|
||||
self.qpixmap = QPixmap(self.qlabel_image.size())
|
||||
if not self.qimage.isNull():
|
||||
# reset Zoom factor and Pan position
|
||||
self.zoomX = 1
|
||||
self.position = [0, 0]
|
||||
self.qimage_scaled = self.qimage.scaled(
|
||||
self.qlabel_image.width(),
|
||||
self.qlabel_image.height(),
|
||||
QtCore.Qt.KeepAspectRatio,
|
||||
)
|
||||
self.update()
|
||||
else:
|
||||
self.statusbar.showMessage("Cannot open this image! Try another one.", 5000)
|
||||
|
||||
def update(self):
|
||||
"""This function actually draws the scaled image to the qlabel_image.
|
||||
It will be repeatedly called when zooming or panning.
|
||||
So, I tried to include only the necessary operations required just for these tasks.
|
||||
"""
|
||||
if not self.qimage_scaled.isNull():
|
||||
# check if position is within limits to prevent unbounded panning.
|
||||
px, py = self.position
|
||||
px = (
|
||||
px
|
||||
if (px <= self.qimage_scaled.width() - self.qlabel_image.width())
|
||||
else (self.qimage_scaled.width() - self.qlabel_image.width())
|
||||
)
|
||||
py = (
|
||||
py
|
||||
if (py <= self.qimage_scaled.height() - self.qlabel_image.height())
|
||||
else (self.qimage_scaled.height() - self.qlabel_image.height())
|
||||
)
|
||||
px = px if (px >= 0) else 0
|
||||
py = py if (py >= 0) else 0
|
||||
self.position = (px, py)
|
||||
|
||||
if self.zoomX == 1:
|
||||
self.qpixmap.fill(QtCore.Qt.white)
|
||||
|
||||
# the act of painting the qpixamp
|
||||
painter = QPainter()
|
||||
painter.begin(self.qpixmap)
|
||||
painter.drawImage(
|
||||
QtCore.QPoint(0, 0),
|
||||
self.qimage_scaled,
|
||||
QtCore.QRect(
|
||||
self.position[0],
|
||||
self.position[1],
|
||||
self.qlabel_image.width(),
|
||||
self.qlabel_image.height(),
|
||||
),
|
||||
)
|
||||
painter.end()
|
||||
|
||||
self.qlabel_image.setPixmap(self.qpixmap)
|
||||
else:
|
||||
pass
|
||||
|
||||
def mousePressAction(self, QMouseEvent):
|
||||
x, y = QMouseEvent.pos().x(), QMouseEvent.pos().y()
|
||||
# print(x,y)
|
||||
if self.panFlag:
|
||||
self.pressed = QMouseEvent.pos() # starting point of drag vector
|
||||
self.anchor = self.position # save the pan position when panning starts
|
||||
print("Label pos:")
|
||||
|
||||
def mouseMoveAction(self, QMouseEvent):
|
||||
x, y = QMouseEvent.pos().x(), QMouseEvent.pos().y()
|
||||
if self.pressed:
|
||||
dx, dy = (
|
||||
x - self.pressed.x(),
|
||||
y - self.pressed.y(),
|
||||
) # calculate the drag vector
|
||||
self.position = (
|
||||
self.anchor[0] - dx,
|
||||
self.anchor[1] - dy,
|
||||
) # update pan position using drag vector
|
||||
self.update()
|
||||
|
||||
# show the image with udated pan position
|
||||
|
||||
print("Label pos:")
|
||||
|
||||
def mouseReleaseAction(self, QMouseEvent):
|
||||
self.pressed = None # clear the starting point of drag vector
|
||||
|
||||
def zoomPlus(self):
|
||||
self.zoomX += 1
|
||||
px, py = self.position
|
||||
px += self.qlabel_image.width() / 2
|
||||
py += self.qlabel_image.height() / 2
|
||||
self.position = (px, py)
|
||||
self.qimage_scaled = self.qimage.scaled(
|
||||
self.qlabel_image.width() * self.zoomX,
|
||||
self.qlabel_image.height() * self.zoomX,
|
||||
QtCore.Qt.KeepAspectRatio,
|
||||
)
|
||||
self.update()
|
||||
|
||||
def zoomMinus(self):
|
||||
if self.zoomX > 1:
|
||||
self.zoomX -= 1
|
||||
px, py = self.position
|
||||
px -= self.qlabel_image.width() / 2
|
||||
py -= self.qlabel_image.height() / 2
|
||||
self.position = (px, py)
|
||||
self.qimage_scaled = self.qimage.scaled(
|
||||
self.qlabel_image.width() * self.zoomX,
|
||||
self.qlabel_image.height() * self.zoomX,
|
||||
QtCore.Qt.KeepAspectRatio,
|
||||
)
|
||||
self.update()
|
||||
|
||||
def resetZoom(self):
|
||||
self.zoomX = 1
|
||||
self.position = [0, 0]
|
||||
self.qimage_scaled = self.qimage.scaled(
|
||||
self.qlabel_image.width() * self.zoomX,
|
||||
self.qlabel_image.height() * self.zoomX,
|
||||
QtCore.Qt.KeepAspectRatio,
|
||||
)
|
||||
self.update()
|
||||
|
||||
def enablePan(self, value):
|
||||
self.panFlag = value
|
|
@ -0,0 +1,60 @@
|
|||
# Imports
|
||||
from PyQt6 import QtWidgets
|
||||
from matplotlib.figure import Figure
|
||||
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as Canvas
|
||||
import matplotlib
|
||||
|
||||
# Ensure using PyQt5 backend
|
||||
matplotlib.use("QT5Agg")
|
||||
|
||||
|
||||
# Matplotlib canvas class to create figure
|
||||
class MplCanvas(Canvas):
|
||||
def __init__(self):
|
||||
self.fig = Figure(figsize=(5, 2))
|
||||
self.ax = self.fig.add_subplot(111)
|
||||
Canvas.__init__(self, self.fig)
|
||||
# Canvas.setSizePolicy(self, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding)
|
||||
Canvas.updateGeometry(self)
|
||||
|
||||
|
||||
# Matplotlib widget
|
||||
class MplWidget(QtWidgets.QWidget):
|
||||
_controller = None
|
||||
|
||||
def __init__(self, parent=None):
|
||||
QtWidgets.QWidget.__init__(self, parent) # Inherit from QWidget
|
||||
self.canvas = MplCanvas() # Create canvas object
|
||||
self.vbl = QtWidgets.QVBoxLayout() # Set box for plotting
|
||||
self.vbl.addWidget(self.canvas)
|
||||
self.setLayout(self.vbl)
|
||||
|
||||
@property
|
||||
def controller(self):
|
||||
return self._image
|
||||
|
||||
@controller.setter
|
||||
def controller(self, controller):
|
||||
self._controller = controller
|
||||
|
||||
def drawHistogram(self, img):
|
||||
self.canvas.ax.cla()
|
||||
|
||||
histogram = self._controller.calculate_histogram(img)
|
||||
color = ("b", "g", "r")
|
||||
|
||||
if len(histogram) == 1:
|
||||
color = "b"
|
||||
|
||||
for i, col in enumerate(color):
|
||||
self.canvas.ax.plot(histogram[i], color=col)
|
||||
self.canvas.ax.set_xlim([0, 256])
|
||||
# self.canvas.figure.set_size_inches(2,2)
|
||||
|
||||
self.canvas.fig.tight_layout()
|
||||
self.canvas.draw()
|
||||
|
||||
def save_histogram(self, str):
|
||||
if self.canvas.fig is not None:
|
||||
# Speichere die Figur als Bild
|
||||
self.canvas.fig.savefig(str, dpi=300)
|
|
@ -0,0 +1,779 @@
|
|||
# Form implementation generated from reading ui file 'Playground_UI.ui'
|
||||
#
|
||||
# Created by: PyQt6 UI code generator 6.6.0
|
||||
#
|
||||
# WARNING: Any manual changes made to this file will be lost when pyuic6 is
|
||||
# run again. Do not edit this file unless you know what you are doing.
|
||||
|
||||
|
||||
from PyQt6 import QtCore, QtGui, QtWidgets
|
||||
|
||||
|
||||
class Ui_MainWindow(object):
|
||||
def setupUi(self, MainWindow):
|
||||
MainWindow.setObjectName("MainWindow")
|
||||
MainWindow.resize(1259, 858)
|
||||
self.centralwidget = QtWidgets.QWidget(parent=MainWindow)
|
||||
sizePolicy = QtWidgets.QSizePolicy(
|
||||
QtWidgets.QSizePolicy.Policy.Maximum, QtWidgets.QSizePolicy.Policy.Maximum
|
||||
)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
sizePolicy.setHeightForWidth(
|
||||
self.centralwidget.sizePolicy().hasHeightForWidth()
|
||||
)
|
||||
self.centralwidget.setSizePolicy(sizePolicy)
|
||||
self.centralwidget.setObjectName("centralwidget")
|
||||
self.horizontalLayout_5 = QtWidgets.QHBoxLayout(self.centralwidget)
|
||||
self.horizontalLayout_5.setObjectName("horizontalLayout_5")
|
||||
self.horizontalLayout = QtWidgets.QHBoxLayout()
|
||||
self.horizontalLayout.setSizeConstraint(
|
||||
QtWidgets.QLayout.SizeConstraint.SetDefaultConstraint
|
||||
)
|
||||
self.horizontalLayout.setSpacing(7)
|
||||
self.horizontalLayout.setObjectName("horizontalLayout")
|
||||
self.layout_left = QtWidgets.QVBoxLayout()
|
||||
self.layout_left.setObjectName("layout_left")
|
||||
self.tab_widget_image = QtWidgets.QTabWidget(parent=self.centralwidget)
|
||||
self.tab_widget_image.setMinimumSize(QtCore.QSize(500, 500))
|
||||
self.tab_widget_image.setAutoFillBackground(True)
|
||||
self.tab_widget_image.setObjectName("tab_widget_image")
|
||||
self.tab_output_image = QtWidgets.QWidget()
|
||||
self.tab_output_image.setAutoFillBackground(False)
|
||||
self.tab_output_image.setObjectName("tab_output_image")
|
||||
self.verticalLayout_3 = QtWidgets.QVBoxLayout(self.tab_output_image)
|
||||
self.verticalLayout_3.setObjectName("verticalLayout_3")
|
||||
self.label_output_image = QtWidgets.QLabel(parent=self.tab_output_image)
|
||||
sizePolicy = QtWidgets.QSizePolicy(
|
||||
QtWidgets.QSizePolicy.Policy.MinimumExpanding,
|
||||
QtWidgets.QSizePolicy.Policy.MinimumExpanding,
|
||||
)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
sizePolicy.setHeightForWidth(
|
||||
self.label_output_image.sizePolicy().hasHeightForWidth()
|
||||
)
|
||||
self.label_output_image.setSizePolicy(sizePolicy)
|
||||
self.label_output_image.setFrameShape(QtWidgets.QFrame.Shape.Box)
|
||||
self.label_output_image.setFrameShadow(QtWidgets.QFrame.Shadow.Plain)
|
||||
self.label_output_image.setScaledContents(False)
|
||||
self.label_output_image.setAlignment(QtCore.Qt.AlignmentFlag.AlignCenter)
|
||||
self.label_output_image.setObjectName("label_output_image")
|
||||
self.verticalLayout_3.addWidget(self.label_output_image)
|
||||
self.pushButton_reset_output_image = QtWidgets.QPushButton(
|
||||
parent=self.tab_output_image
|
||||
)
|
||||
self.pushButton_reset_output_image.setObjectName(
|
||||
"pushButton_reset_output_image"
|
||||
)
|
||||
self.verticalLayout_3.addWidget(self.pushButton_reset_output_image)
|
||||
self.pushButton_overwrite_input_image = QtWidgets.QPushButton(
|
||||
parent=self.tab_output_image
|
||||
)
|
||||
self.pushButton_overwrite_input_image.setObjectName(
|
||||
"pushButton_overwrite_input_image"
|
||||
)
|
||||
self.verticalLayout_3.addWidget(self.pushButton_overwrite_input_image)
|
||||
self.tab_widget_image.addTab(self.tab_output_image, "")
|
||||
self.tab_input_image = QtWidgets.QWidget()
|
||||
self.tab_input_image.setObjectName("tab_input_image")
|
||||
self.verticalLayout_4 = QtWidgets.QVBoxLayout(self.tab_input_image)
|
||||
self.verticalLayout_4.setObjectName("verticalLayout_4")
|
||||
self.label_input_image = QtWidgets.QLabel(parent=self.tab_input_image)
|
||||
sizePolicy = QtWidgets.QSizePolicy(
|
||||
QtWidgets.QSizePolicy.Policy.MinimumExpanding,
|
||||
QtWidgets.QSizePolicy.Policy.MinimumExpanding,
|
||||
)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
sizePolicy.setHeightForWidth(
|
||||
self.label_input_image.sizePolicy().hasHeightForWidth()
|
||||
)
|
||||
self.label_input_image.setSizePolicy(sizePolicy)
|
||||
self.label_input_image.setAutoFillBackground(False)
|
||||
self.label_input_image.setFrameShape(QtWidgets.QFrame.Shape.Box)
|
||||
self.label_input_image.setScaledContents(False)
|
||||
self.label_input_image.setAlignment(QtCore.Qt.AlignmentFlag.AlignCenter)
|
||||
self.label_input_image.setObjectName("label_input_image")
|
||||
self.verticalLayout_4.addWidget(self.label_input_image)
|
||||
self.tab_widget_image.addTab(self.tab_input_image, "")
|
||||
self.layout_left.addWidget(self.tab_widget_image)
|
||||
self.line = QtWidgets.QFrame(parent=self.centralwidget)
|
||||
self.line.setFrameShape(QtWidgets.QFrame.Shape.HLine)
|
||||
self.line.setFrameShadow(QtWidgets.QFrame.Shadow.Sunken)
|
||||
self.line.setObjectName("line")
|
||||
self.layout_left.addWidget(self.line)
|
||||
self.text_output = QtWidgets.QTextBrowser(parent=self.centralwidget)
|
||||
self.text_output.setMinimumSize(QtCore.QSize(0, 150))
|
||||
self.text_output.setObjectName("text_output")
|
||||
self.layout_left.addWidget(
|
||||
self.text_output, 0, QtCore.Qt.AlignmentFlag.AlignBottom
|
||||
)
|
||||
self.horizontalLayout.addLayout(self.layout_left)
|
||||
self.vertical_line = QtWidgets.QFrame(parent=self.centralwidget)
|
||||
self.vertical_line.setFrameShape(QtWidgets.QFrame.Shape.VLine)
|
||||
self.vertical_line.setFrameShadow(QtWidgets.QFrame.Shadow.Sunken)
|
||||
self.vertical_line.setObjectName("vertical_line")
|
||||
self.horizontalLayout.addWidget(self.vertical_line)
|
||||
self.layout_right = QtWidgets.QVBoxLayout()
|
||||
self.layout_right.setObjectName("layout_right")
|
||||
self.label = QtWidgets.QLabel(parent=self.centralwidget)
|
||||
self.label.setObjectName("label")
|
||||
self.layout_right.addWidget(self.label)
|
||||
self.widget_histogram = MplWidget(parent=self.centralwidget)
|
||||
sizePolicy = QtWidgets.QSizePolicy(
|
||||
QtWidgets.QSizePolicy.Policy.Fixed, QtWidgets.QSizePolicy.Policy.Fixed
|
||||
)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
sizePolicy.setHeightForWidth(
|
||||
self.widget_histogram.sizePolicy().hasHeightForWidth()
|
||||
)
|
||||
self.widget_histogram.setSizePolicy(sizePolicy)
|
||||
self.widget_histogram.setMinimumSize(QtCore.QSize(400, 250))
|
||||
self.widget_histogram.setAutoFillBackground(True)
|
||||
self.widget_histogram.setObjectName("widget_histogram")
|
||||
self.layout_right.addWidget(self.widget_histogram)
|
||||
self.horizontal_line = QtWidgets.QFrame(parent=self.centralwidget)
|
||||
self.horizontal_line.setContextMenuPolicy(
|
||||
QtCore.Qt.ContextMenuPolicy.PreventContextMenu
|
||||
)
|
||||
self.horizontal_line.setFrameShape(QtWidgets.QFrame.Shape.HLine)
|
||||
self.horizontal_line.setFrameShadow(QtWidgets.QFrame.Shadow.Sunken)
|
||||
self.horizontal_line.setObjectName("horizontal_line")
|
||||
self.layout_right.addWidget(self.horizontal_line)
|
||||
self.tabWidget_controller = QtWidgets.QTabWidget(parent=self.centralwidget)
|
||||
sizePolicy = QtWidgets.QSizePolicy(
|
||||
QtWidgets.QSizePolicy.Policy.Maximum, QtWidgets.QSizePolicy.Policy.Expanding
|
||||
)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
sizePolicy.setHeightForWidth(
|
||||
self.tabWidget_controller.sizePolicy().hasHeightForWidth()
|
||||
)
|
||||
self.tabWidget_controller.setSizePolicy(sizePolicy)
|
||||
self.tabWidget_controller.setMinimumSize(QtCore.QSize(400, 0))
|
||||
self.tabWidget_controller.setObjectName("tabWidget_controller")
|
||||
self.tab_image_analysis = QtWidgets.QWidget()
|
||||
self.tab_image_analysis.setObjectName("tab_image_analysis")
|
||||
self.verticalLayout_7 = QtWidgets.QVBoxLayout(self.tab_image_analysis)
|
||||
self.verticalLayout_7.setObjectName("verticalLayout_7")
|
||||
self.tabWidget_analysis = QtWidgets.QTabWidget(parent=self.tab_image_analysis)
|
||||
sizePolicy = QtWidgets.QSizePolicy(
|
||||
QtWidgets.QSizePolicy.Policy.Maximum,
|
||||
QtWidgets.QSizePolicy.Policy.MinimumExpanding,
|
||||
)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
sizePolicy.setHeightForWidth(
|
||||
self.tabWidget_analysis.sizePolicy().hasHeightForWidth()
|
||||
)
|
||||
self.tabWidget_analysis.setSizePolicy(sizePolicy)
|
||||
self.tabWidget_analysis.setMinimumSize(QtCore.QSize(380, 0))
|
||||
self.tabWidget_analysis.setObjectName("tabWidget_analysis")
|
||||
self.widget_image_information = QtWidgets.QWidget()
|
||||
self.widget_image_information.setObjectName("widget_image_information")
|
||||
self.verticalLayout_8 = QtWidgets.QVBoxLayout(self.widget_image_information)
|
||||
self.verticalLayout_8.setObjectName("verticalLayout_8")
|
||||
self.widget = QtWidgets.QWidget(parent=self.widget_image_information)
|
||||
self.widget.setObjectName("widget")
|
||||
self.formLayout = QtWidgets.QFormLayout(self.widget)
|
||||
self.formLayout.setObjectName("formLayout")
|
||||
self.label_height_text = QtWidgets.QLabel(parent=self.widget)
|
||||
self.label_height_text.setObjectName("label_height_text")
|
||||
self.formLayout.setWidget(
|
||||
0, QtWidgets.QFormLayout.ItemRole.LabelRole, self.label_height_text
|
||||
)
|
||||
self.label_height_image = QtWidgets.QLabel(parent=self.widget)
|
||||
self.label_height_image.setObjectName("label_height_image")
|
||||
self.formLayout.setWidget(
|
||||
0, QtWidgets.QFormLayout.ItemRole.FieldRole, self.label_height_image
|
||||
)
|
||||
self.label_width_text = QtWidgets.QLabel(parent=self.widget)
|
||||
self.label_width_text.setObjectName("label_width_text")
|
||||
self.formLayout.setWidget(
|
||||
1, QtWidgets.QFormLayout.ItemRole.LabelRole, self.label_width_text
|
||||
)
|
||||
self.label_width_image = QtWidgets.QLabel(parent=self.widget)
|
||||
self.label_width_image.setObjectName("label_width_image")
|
||||
self.formLayout.setWidget(
|
||||
1, QtWidgets.QFormLayout.ItemRole.FieldRole, self.label_width_image
|
||||
)
|
||||
self.verticalLayout_8.addWidget(self.widget)
|
||||
self.groupBox_2 = QtWidgets.QGroupBox(parent=self.widget_image_information)
|
||||
self.groupBox_2.setObjectName("groupBox_2")
|
||||
self.formLayout_4 = QtWidgets.QFormLayout(self.groupBox_2)
|
||||
self.formLayout_4.setObjectName("formLayout_4")
|
||||
self.label_4 = QtWidgets.QLabel(parent=self.groupBox_2)
|
||||
self.label_4.setObjectName("label_4")
|
||||
self.formLayout_4.setWidget(
|
||||
0, QtWidgets.QFormLayout.ItemRole.LabelRole, self.label_4
|
||||
)
|
||||
self.label_color_pixel1 = QtWidgets.QLabel(parent=self.groupBox_2)
|
||||
self.label_color_pixel1.setObjectName("label_color_pixel1")
|
||||
self.formLayout_4.setWidget(
|
||||
0, QtWidgets.QFormLayout.ItemRole.FieldRole, self.label_color_pixel1
|
||||
)
|
||||
self.label_5 = QtWidgets.QLabel(parent=self.groupBox_2)
|
||||
self.label_5.setObjectName("label_5")
|
||||
self.formLayout_4.setWidget(
|
||||
1, QtWidgets.QFormLayout.ItemRole.LabelRole, self.label_5
|
||||
)
|
||||
self.label_color_pixel2 = QtWidgets.QLabel(parent=self.groupBox_2)
|
||||
self.label_color_pixel2.setObjectName("label_color_pixel2")
|
||||
self.formLayout_4.setWidget(
|
||||
1, QtWidgets.QFormLayout.ItemRole.FieldRole, self.label_color_pixel2
|
||||
)
|
||||
self.verticalLayout_8.addWidget(self.groupBox_2)
|
||||
self.groupBox = QtWidgets.QGroupBox(parent=self.widget_image_information)
|
||||
self.groupBox.setObjectName("groupBox")
|
||||
self.horizontalLayout_4 = QtWidgets.QHBoxLayout(self.groupBox)
|
||||
self.horizontalLayout_4.setObjectName("horizontalLayout_4")
|
||||
self.pushButton_show_channel1 = QtWidgets.QPushButton(parent=self.groupBox)
|
||||
self.pushButton_show_channel1.setObjectName("pushButton_show_channel1")
|
||||
self.horizontalLayout_4.addWidget(self.pushButton_show_channel1)
|
||||
self.pushButton_show_channel2 = QtWidgets.QPushButton(parent=self.groupBox)
|
||||
self.pushButton_show_channel2.setObjectName("pushButton_show_channel2")
|
||||
self.horizontalLayout_4.addWidget(self.pushButton_show_channel2)
|
||||
self.pushButton_show_channel3 = QtWidgets.QPushButton(parent=self.groupBox)
|
||||
self.pushButton_show_channel3.setObjectName("pushButton_show_channel3")
|
||||
self.horizontalLayout_4.addWidget(self.pushButton_show_channel3)
|
||||
self.verticalLayout_8.addWidget(self.groupBox)
|
||||
self.pushButton_do_image_manipulation = QtWidgets.QPushButton(
|
||||
parent=self.widget_image_information
|
||||
)
|
||||
self.pushButton_do_image_manipulation.setObjectName(
|
||||
"pushButton_do_image_manipulation"
|
||||
)
|
||||
self.verticalLayout_8.addWidget(self.pushButton_do_image_manipulation)
|
||||
spacerItem = QtWidgets.QSpacerItem(
|
||||
20,
|
||||
40,
|
||||
QtWidgets.QSizePolicy.Policy.Minimum,
|
||||
QtWidgets.QSizePolicy.Policy.Expanding,
|
||||
)
|
||||
self.verticalLayout_8.addItem(spacerItem)
|
||||
self.tabWidget_analysis.addTab(self.widget_image_information, "")
|
||||
self.widget_color_analysis = QtWidgets.QWidget()
|
||||
sizePolicy = QtWidgets.QSizePolicy(
|
||||
QtWidgets.QSizePolicy.Policy.Fixed, QtWidgets.QSizePolicy.Policy.Fixed
|
||||
)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
sizePolicy.setHeightForWidth(
|
||||
self.widget_color_analysis.sizePolicy().hasHeightForWidth()
|
||||
)
|
||||
self.widget_color_analysis.setSizePolicy(sizePolicy)
|
||||
self.widget_color_analysis.setObjectName("widget_color_analysis")
|
||||
self.verticalLayout_5 = QtWidgets.QVBoxLayout(self.widget_color_analysis)
|
||||
self.verticalLayout_5.setObjectName("verticalLayout_5")
|
||||
self.verticalLayout_color_analysis = QtWidgets.QVBoxLayout()
|
||||
self.verticalLayout_color_analysis.setObjectName(
|
||||
"verticalLayout_color_analysis"
|
||||
)
|
||||
self.label_color_analysis = QtWidgets.QLabel(parent=self.widget_color_analysis)
|
||||
self.label_color_analysis.setMaximumSize(QtCore.QSize(16777215, 20))
|
||||
self.label_color_analysis.setScaledContents(False)
|
||||
self.label_color_analysis.setAlignment(
|
||||
QtCore.Qt.AlignmentFlag.AlignLeading
|
||||
| QtCore.Qt.AlignmentFlag.AlignLeft
|
||||
| QtCore.Qt.AlignmentFlag.AlignTop
|
||||
)
|
||||
self.label_color_analysis.setObjectName("label_color_analysis")
|
||||
self.verticalLayout_color_analysis.addWidget(self.label_color_analysis)
|
||||
self.horizontalSlider_color_clusters = QtWidgets.QSlider(
|
||||
parent=self.widget_color_analysis
|
||||
)
|
||||
sizePolicy = QtWidgets.QSizePolicy(
|
||||
QtWidgets.QSizePolicy.Policy.Maximum, QtWidgets.QSizePolicy.Policy.Fixed
|
||||
)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
sizePolicy.setHeightForWidth(
|
||||
self.horizontalSlider_color_clusters.sizePolicy().hasHeightForWidth()
|
||||
)
|
||||
self.horizontalSlider_color_clusters.setSizePolicy(sizePolicy)
|
||||
self.horizontalSlider_color_clusters.setMinimumSize(QtCore.QSize(370, 0))
|
||||
self.horizontalSlider_color_clusters.setSizeIncrement(QtCore.QSize(380, 0))
|
||||
self.horizontalSlider_color_clusters.setMinimum(1)
|
||||
self.horizontalSlider_color_clusters.setMaximum(10)
|
||||
self.horizontalSlider_color_clusters.setSliderPosition(3)
|
||||
self.horizontalSlider_color_clusters.setOrientation(
|
||||
QtCore.Qt.Orientation.Horizontal
|
||||
)
|
||||
self.horizontalSlider_color_clusters.setTickPosition(
|
||||
QtWidgets.QSlider.TickPosition.TicksBelow
|
||||
)
|
||||
self.horizontalSlider_color_clusters.setTickInterval(1)
|
||||
self.horizontalSlider_color_clusters.setObjectName(
|
||||
"horizontalSlider_color_clusters"
|
||||
)
|
||||
self.verticalLayout_color_analysis.addWidget(
|
||||
self.horizontalSlider_color_clusters
|
||||
)
|
||||
self.line_2 = QtWidgets.QFrame(parent=self.widget_color_analysis)
|
||||
sizePolicy = QtWidgets.QSizePolicy(
|
||||
QtWidgets.QSizePolicy.Policy.Maximum, QtWidgets.QSizePolicy.Policy.Fixed
|
||||
)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
sizePolicy.setHeightForWidth(self.line_2.sizePolicy().hasHeightForWidth())
|
||||
self.line_2.setSizePolicy(sizePolicy)
|
||||
self.line_2.setMinimumSize(QtCore.QSize(370, 0))
|
||||
self.line_2.setSizeIncrement(QtCore.QSize(370, 0))
|
||||
self.line_2.setFrameShape(QtWidgets.QFrame.Shape.HLine)
|
||||
self.line_2.setFrameShadow(QtWidgets.QFrame.Shadow.Sunken)
|
||||
self.line_2.setObjectName("line_2")
|
||||
self.verticalLayout_color_analysis.addWidget(self.line_2)
|
||||
self.label_image_color_analysis_output = QtWidgets.QLabel(
|
||||
parent=self.widget_color_analysis
|
||||
)
|
||||
sizePolicy = QtWidgets.QSizePolicy(
|
||||
QtWidgets.QSizePolicy.Policy.Maximum, QtWidgets.QSizePolicy.Policy.Preferred
|
||||
)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
sizePolicy.setHeightForWidth(
|
||||
self.label_image_color_analysis_output.sizePolicy().hasHeightForWidth()
|
||||
)
|
||||
self.label_image_color_analysis_output.setSizePolicy(sizePolicy)
|
||||
self.label_image_color_analysis_output.setMinimumSize(QtCore.QSize(370, 0))
|
||||
self.label_image_color_analysis_output.setAlignment(
|
||||
QtCore.Qt.AlignmentFlag.AlignCenter
|
||||
)
|
||||
self.label_image_color_analysis_output.setObjectName(
|
||||
"label_image_color_analysis_output"
|
||||
)
|
||||
self.verticalLayout_color_analysis.addWidget(
|
||||
self.label_image_color_analysis_output
|
||||
)
|
||||
self.verticalLayout_5.addLayout(self.verticalLayout_color_analysis)
|
||||
self.tabWidget_analysis.addTab(self.widget_color_analysis, "")
|
||||
self.verticalLayout_7.addWidget(self.tabWidget_analysis)
|
||||
self.tabWidget_controller.addTab(self.tab_image_analysis, "")
|
||||
self.tab_geometric_adjustments = QtWidgets.QWidget()
|
||||
self.tab_geometric_adjustments.setObjectName("tab_geometric_adjustments")
|
||||
self.gridLayout_2 = QtWidgets.QGridLayout(self.tab_geometric_adjustments)
|
||||
self.gridLayout_2.setObjectName("gridLayout_2")
|
||||
self.lineEdit_image_width = QtWidgets.QLineEdit(
|
||||
parent=self.tab_geometric_adjustments
|
||||
)
|
||||
sizePolicy = QtWidgets.QSizePolicy(
|
||||
QtWidgets.QSizePolicy.Policy.Fixed, QtWidgets.QSizePolicy.Policy.Fixed
|
||||
)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
sizePolicy.setHeightForWidth(
|
||||
self.lineEdit_image_width.sizePolicy().hasHeightForWidth()
|
||||
)
|
||||
self.lineEdit_image_width.setSizePolicy(sizePolicy)
|
||||
self.lineEdit_image_width.setObjectName("lineEdit_image_width")
|
||||
self.gridLayout_2.addWidget(self.lineEdit_image_width, 1, 1, 1, 1)
|
||||
self.pushButton_adjust_image_size = QtWidgets.QPushButton(
|
||||
parent=self.tab_geometric_adjustments
|
||||
)
|
||||
self.pushButton_adjust_image_size.setObjectName("pushButton_adjust_image_size")
|
||||
self.gridLayout_2.addWidget(self.pushButton_adjust_image_size, 4, 0, 1, 2)
|
||||
self.checkBox_fix_image_size = QtWidgets.QCheckBox(
|
||||
parent=self.tab_geometric_adjustments
|
||||
)
|
||||
self.checkBox_fix_image_size.setChecked(True)
|
||||
self.checkBox_fix_image_size.setObjectName("checkBox_fix_image_size")
|
||||
self.gridLayout_2.addWidget(self.checkBox_fix_image_size, 2, 1, 1, 1)
|
||||
self.label_3 = QtWidgets.QLabel(parent=self.tab_geometric_adjustments)
|
||||
self.label_3.setObjectName("label_3")
|
||||
self.gridLayout_2.addWidget(self.label_3, 1, 0, 1, 1)
|
||||
self.lineEdit_image_height = QtWidgets.QLineEdit(
|
||||
parent=self.tab_geometric_adjustments
|
||||
)
|
||||
sizePolicy = QtWidgets.QSizePolicy(
|
||||
QtWidgets.QSizePolicy.Policy.Fixed, QtWidgets.QSizePolicy.Policy.Fixed
|
||||
)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
sizePolicy.setHeightForWidth(
|
||||
self.lineEdit_image_height.sizePolicy().hasHeightForWidth()
|
||||
)
|
||||
self.lineEdit_image_height.setSizePolicy(sizePolicy)
|
||||
self.lineEdit_image_height.setObjectName("lineEdit_image_height")
|
||||
self.gridLayout_2.addWidget(self.lineEdit_image_height, 0, 1, 1, 1)
|
||||
self.label_2 = QtWidgets.QLabel(parent=self.tab_geometric_adjustments)
|
||||
self.label_2.setObjectName("label_2")
|
||||
self.gridLayout_2.addWidget(self.label_2, 0, 0, 1, 1)
|
||||
spacerItem1 = QtWidgets.QSpacerItem(
|
||||
20,
|
||||
40,
|
||||
QtWidgets.QSizePolicy.Policy.Minimum,
|
||||
QtWidgets.QSizePolicy.Policy.Expanding,
|
||||
)
|
||||
self.gridLayout_2.addItem(spacerItem1, 5, 1, 1, 1)
|
||||
self.tabWidget_controller.addTab(self.tab_geometric_adjustments, "")
|
||||
self.tab_histogram_manip = QtWidgets.QWidget()
|
||||
self.tab_histogram_manip.setObjectName("tab_histogram_manip")
|
||||
self.verticalLayout_9 = QtWidgets.QVBoxLayout(self.tab_histogram_manip)
|
||||
self.verticalLayout_9.setObjectName("verticalLayout_9")
|
||||
self.pushButton_hist_stretch = QtWidgets.QPushButton(
|
||||
parent=self.tab_histogram_manip
|
||||
)
|
||||
self.pushButton_hist_stretch.setObjectName("pushButton_hist_stretch")
|
||||
self.verticalLayout_9.addWidget(self.pushButton_hist_stretch)
|
||||
self.pushButton_hist_equalization = QtWidgets.QPushButton(
|
||||
parent=self.tab_histogram_manip
|
||||
)
|
||||
self.pushButton_hist_equalization.setObjectName("pushButton_hist_equalization")
|
||||
self.verticalLayout_9.addWidget(self.pushButton_hist_equalization)
|
||||
self.line_3 = QtWidgets.QFrame(parent=self.tab_histogram_manip)
|
||||
self.line_3.setFrameShape(QtWidgets.QFrame.Shape.HLine)
|
||||
self.line_3.setFrameShadow(QtWidgets.QFrame.Shadow.Sunken)
|
||||
self.line_3.setObjectName("line_3")
|
||||
self.verticalLayout_9.addWidget(self.line_3)
|
||||
self.pushButton_hist_log = QtWidgets.QPushButton(
|
||||
parent=self.tab_histogram_manip
|
||||
)
|
||||
self.pushButton_hist_log.setObjectName("pushButton_hist_log")
|
||||
self.verticalLayout_9.addWidget(self.pushButton_hist_log)
|
||||
self.pushButton_hist_exp = QtWidgets.QPushButton(
|
||||
parent=self.tab_histogram_manip
|
||||
)
|
||||
self.pushButton_hist_exp.setObjectName("pushButton_hist_exp")
|
||||
self.verticalLayout_9.addWidget(self.pushButton_hist_exp)
|
||||
self.pushButton_hist_inv = QtWidgets.QPushButton(
|
||||
parent=self.tab_histogram_manip
|
||||
)
|
||||
self.pushButton_hist_inv.setObjectName("pushButton_hist_inv")
|
||||
self.verticalLayout_9.addWidget(self.pushButton_hist_inv)
|
||||
self.groupBox_6 = QtWidgets.QGroupBox(parent=self.tab_histogram_manip)
|
||||
self.groupBox_6.setObjectName("groupBox_6")
|
||||
self.verticalLayout = QtWidgets.QVBoxLayout(self.groupBox_6)
|
||||
self.verticalLayout.setContentsMargins(-1, 0, -1, 0)
|
||||
self.verticalLayout.setObjectName("verticalLayout")
|
||||
self.horizontalSlider_hist_threshold = QtWidgets.QSlider(parent=self.groupBox_6)
|
||||
self.horizontalSlider_hist_threshold.setMaximum(255)
|
||||
self.horizontalSlider_hist_threshold.setProperty("value", 128)
|
||||
self.horizontalSlider_hist_threshold.setOrientation(
|
||||
QtCore.Qt.Orientation.Horizontal
|
||||
)
|
||||
self.horizontalSlider_hist_threshold.setTickPosition(
|
||||
QtWidgets.QSlider.TickPosition.TicksBelow
|
||||
)
|
||||
self.horizontalSlider_hist_threshold.setTickInterval(0)
|
||||
self.horizontalSlider_hist_threshold.setObjectName(
|
||||
"horizontalSlider_hist_threshold"
|
||||
)
|
||||
self.verticalLayout.addWidget(self.horizontalSlider_hist_threshold)
|
||||
self.verticalLayout_9.addWidget(self.groupBox_6)
|
||||
self.pushButton_hist_fill = QtWidgets.QPushButton(
|
||||
parent=self.tab_histogram_manip
|
||||
)
|
||||
self.pushButton_hist_fill.setObjectName("pushButton_hist_fill")
|
||||
self.verticalLayout_9.addWidget(self.pushButton_hist_fill)
|
||||
spacerItem2 = QtWidgets.QSpacerItem(
|
||||
20,
|
||||
40,
|
||||
QtWidgets.QSizePolicy.Policy.Minimum,
|
||||
QtWidgets.QSizePolicy.Policy.Expanding,
|
||||
)
|
||||
self.verticalLayout_9.addItem(spacerItem2)
|
||||
self.tabWidget_controller.addTab(self.tab_histogram_manip, "")
|
||||
self.tab_filter = QtWidgets.QWidget()
|
||||
self.tab_filter.setObjectName("tab_filter")
|
||||
self.verticalLayout_6 = QtWidgets.QVBoxLayout(self.tab_filter)
|
||||
self.verticalLayout_6.setObjectName("verticalLayout_6")
|
||||
self.groupBox_3 = QtWidgets.QGroupBox(parent=self.tab_filter)
|
||||
sizePolicy = QtWidgets.QSizePolicy(
|
||||
QtWidgets.QSizePolicy.Policy.Minimum, QtWidgets.QSizePolicy.Policy.Minimum
|
||||
)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
sizePolicy.setHeightForWidth(self.groupBox_3.sizePolicy().hasHeightForWidth())
|
||||
self.groupBox_3.setSizePolicy(sizePolicy)
|
||||
self.groupBox_3.setObjectName("groupBox_3")
|
||||
self.verticalLayout_11 = QtWidgets.QVBoxLayout(self.groupBox_3)
|
||||
self.verticalLayout_11.setObjectName("verticalLayout_11")
|
||||
self.widget_2 = QtWidgets.QWidget(parent=self.groupBox_3)
|
||||
self.widget_2.setObjectName("widget_2")
|
||||
self.horizontalLayout_7 = QtWidgets.QHBoxLayout(self.widget_2)
|
||||
self.horizontalLayout_7.setContentsMargins(-1, 0, -1, 0)
|
||||
self.horizontalLayout_7.setObjectName("horizontalLayout_7")
|
||||
self.label_8 = QtWidgets.QLabel(parent=self.widget_2)
|
||||
self.label_8.setObjectName("label_8")
|
||||
self.horizontalLayout_7.addWidget(self.label_8)
|
||||
self.spinBox_filter_avg_size = QtWidgets.QSpinBox(parent=self.widget_2)
|
||||
self.spinBox_filter_avg_size.setReadOnly(False)
|
||||
self.spinBox_filter_avg_size.setButtonSymbols(
|
||||
QtWidgets.QAbstractSpinBox.ButtonSymbols.UpDownArrows
|
||||
)
|
||||
self.spinBox_filter_avg_size.setAccelerated(False)
|
||||
self.spinBox_filter_avg_size.setCorrectionMode(
|
||||
QtWidgets.QAbstractSpinBox.CorrectionMode.CorrectToNearestValue
|
||||
)
|
||||
self.spinBox_filter_avg_size.setKeyboardTracking(False)
|
||||
self.spinBox_filter_avg_size.setProperty("showGroupSeparator", False)
|
||||
self.spinBox_filter_avg_size.setMinimum(3)
|
||||
self.spinBox_filter_avg_size.setSingleStep(2)
|
||||
self.spinBox_filter_avg_size.setObjectName("spinBox_filter_avg_size")
|
||||
self.horizontalLayout_7.addWidget(self.spinBox_filter_avg_size)
|
||||
self.verticalLayout_11.addWidget(self.widget_2)
|
||||
self.widget_3 = QtWidgets.QWidget(parent=self.groupBox_3)
|
||||
self.widget_3.setObjectName("widget_3")
|
||||
self.horizontalLayout_6 = QtWidgets.QHBoxLayout(self.widget_3)
|
||||
self.horizontalLayout_6.setContentsMargins(-1, 0, -1, 0)
|
||||
self.horizontalLayout_6.setObjectName("horizontalLayout_6")
|
||||
self.pushButton_filter_movAvg = QtWidgets.QPushButton(parent=self.widget_3)
|
||||
self.pushButton_filter_movAvg.setObjectName("pushButton_filter_movAvg")
|
||||
self.horizontalLayout_6.addWidget(self.pushButton_filter_movAvg)
|
||||
self.pushButton_filter_gauss = QtWidgets.QPushButton(parent=self.widget_3)
|
||||
sizePolicy = QtWidgets.QSizePolicy(
|
||||
QtWidgets.QSizePolicy.Policy.Minimum, QtWidgets.QSizePolicy.Policy.Fixed
|
||||
)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
sizePolicy.setHeightForWidth(
|
||||
self.pushButton_filter_gauss.sizePolicy().hasHeightForWidth()
|
||||
)
|
||||
self.pushButton_filter_gauss.setSizePolicy(sizePolicy)
|
||||
self.pushButton_filter_gauss.setObjectName("pushButton_filter_gauss")
|
||||
self.horizontalLayout_6.addWidget(self.pushButton_filter_gauss)
|
||||
self.pushButton_filter_median = QtWidgets.QPushButton(parent=self.widget_3)
|
||||
self.pushButton_filter_median.setObjectName("pushButton_filter_median")
|
||||
self.horizontalLayout_6.addWidget(self.pushButton_filter_median)
|
||||
self.verticalLayout_11.addWidget(self.widget_3)
|
||||
self.verticalLayout_6.addWidget(self.groupBox_3)
|
||||
self.groupBox_4 = QtWidgets.QGroupBox(parent=self.tab_filter)
|
||||
sizePolicy = QtWidgets.QSizePolicy(
|
||||
QtWidgets.QSizePolicy.Policy.Minimum, QtWidgets.QSizePolicy.Policy.Preferred
|
||||
)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
sizePolicy.setHeightForWidth(self.groupBox_4.sizePolicy().hasHeightForWidth())
|
||||
self.groupBox_4.setSizePolicy(sizePolicy)
|
||||
self.groupBox_4.setObjectName("groupBox_4")
|
||||
self.horizontalLayout_3 = QtWidgets.QHBoxLayout(self.groupBox_4)
|
||||
self.horizontalLayout_3.setContentsMargins(-1, 0, -1, 0)
|
||||
self.horizontalLayout_3.setObjectName("horizontalLayout_3")
|
||||
self.pushButton_filter_sobelX = QtWidgets.QPushButton(parent=self.groupBox_4)
|
||||
self.pushButton_filter_sobelX.setObjectName("pushButton_filter_sobelX")
|
||||
self.horizontalLayout_3.addWidget(self.pushButton_filter_sobelX)
|
||||
self.pushButton_filter_sobelY = QtWidgets.QPushButton(parent=self.groupBox_4)
|
||||
self.pushButton_filter_sobelY.setObjectName("pushButton_filter_sobelY")
|
||||
self.horizontalLayout_3.addWidget(self.pushButton_filter_sobelY)
|
||||
self.verticalLayout_6.addWidget(self.groupBox_4)
|
||||
self.line_4 = QtWidgets.QFrame(parent=self.tab_filter)
|
||||
self.line_4.setFrameShape(QtWidgets.QFrame.Shape.HLine)
|
||||
self.line_4.setFrameShadow(QtWidgets.QFrame.Shadow.Sunken)
|
||||
self.line_4.setObjectName("line_4")
|
||||
self.verticalLayout_6.addWidget(self.line_4)
|
||||
self.groupBox_5 = QtWidgets.QGroupBox(parent=self.tab_filter)
|
||||
self.groupBox_5.setObjectName("groupBox_5")
|
||||
self.verticalLayout_10 = QtWidgets.QVBoxLayout(self.groupBox_5)
|
||||
self.verticalLayout_10.setContentsMargins(-1, 0, -1, 0)
|
||||
self.verticalLayout_10.setObjectName("verticalLayout_10")
|
||||
self.pushButton_filter_movAvg_conv = QtWidgets.QPushButton(
|
||||
parent=self.groupBox_5
|
||||
)
|
||||
self.pushButton_filter_movAvg_conv.setObjectName(
|
||||
"pushButton_filter_movAvg_conv"
|
||||
)
|
||||
self.verticalLayout_10.addWidget(self.pushButton_filter_movAvg_conv)
|
||||
self.pushButton_filter_movAvg_sep = QtWidgets.QPushButton(
|
||||
parent=self.groupBox_5
|
||||
)
|
||||
self.pushButton_filter_movAvg_sep.setObjectName("pushButton_filter_movAvg_sep")
|
||||
self.verticalLayout_10.addWidget(self.pushButton_filter_movAvg_sep)
|
||||
self.pushButton_filter_movAvg_int = QtWidgets.QPushButton(
|
||||
parent=self.groupBox_5
|
||||
)
|
||||
self.pushButton_filter_movAvg_int.setObjectName("pushButton_filter_movAvg_int")
|
||||
self.verticalLayout_10.addWidget(self.pushButton_filter_movAvg_int)
|
||||
self.line_5 = QtWidgets.QFrame(parent=self.groupBox_5)
|
||||
self.line_5.setFrameShape(QtWidgets.QFrame.Shape.HLine)
|
||||
self.line_5.setFrameShadow(QtWidgets.QFrame.Shadow.Sunken)
|
||||
self.line_5.setObjectName("line_5")
|
||||
self.verticalLayout_10.addWidget(self.line_5)
|
||||
self.pushButton_filter_evaluation = QtWidgets.QPushButton(
|
||||
parent=self.groupBox_5
|
||||
)
|
||||
self.pushButton_filter_evaluation.setObjectName("pushButton_filter_evaluation")
|
||||
self.verticalLayout_10.addWidget(self.pushButton_filter_evaluation)
|
||||
self.verticalLayout_6.addWidget(self.groupBox_5)
|
||||
spacerItem3 = QtWidgets.QSpacerItem(
|
||||
20,
|
||||
40,
|
||||
QtWidgets.QSizePolicy.Policy.Minimum,
|
||||
QtWidgets.QSizePolicy.Policy.Expanding,
|
||||
)
|
||||
self.verticalLayout_6.addItem(spacerItem3)
|
||||
self.tabWidget_controller.addTab(self.tab_filter, "")
|
||||
self.tab_AI = QtWidgets.QWidget()
|
||||
self.tab_AI.setObjectName("tab_AI")
|
||||
self.formLayout_3 = QtWidgets.QFormLayout(self.tab_AI)
|
||||
self.formLayout_3.setObjectName("formLayout_3")
|
||||
self.pushButton_AWS_Labeling = QtWidgets.QPushButton(parent=self.tab_AI)
|
||||
self.pushButton_AWS_Labeling.setObjectName("pushButton_AWS_Labeling")
|
||||
self.formLayout_3.setWidget(
|
||||
0, QtWidgets.QFormLayout.ItemRole.LabelRole, self.pushButton_AWS_Labeling
|
||||
)
|
||||
self.tabWidget_controller.addTab(self.tab_AI, "")
|
||||
self.layout_right.addWidget(self.tabWidget_controller)
|
||||
self.horizontalLayout.addLayout(self.layout_right)
|
||||
self.horizontalLayout_5.addLayout(self.horizontalLayout)
|
||||
MainWindow.setCentralWidget(self.centralwidget)
|
||||
self.menubar = QtWidgets.QMenuBar(parent=MainWindow)
|
||||
self.menubar.setGeometry(QtCore.QRect(0, 0, 1259, 37))
|
||||
self.menubar.setObjectName("menubar")
|
||||
self.menuMen = QtWidgets.QMenu(parent=self.menubar)
|
||||
self.menuMen.setObjectName("menuMen")
|
||||
MainWindow.setMenuBar(self.menubar)
|
||||
self.statusbar = QtWidgets.QStatusBar(parent=MainWindow)
|
||||
self.statusbar.setEnabled(True)
|
||||
self.statusbar.setObjectName("statusbar")
|
||||
MainWindow.setStatusBar(self.statusbar)
|
||||
self.actionBild_laden = QtGui.QAction(parent=MainWindow)
|
||||
self.actionBild_laden.setObjectName("actionBild_laden")
|
||||
self.actionBild_speichern = QtGui.QAction(parent=MainWindow)
|
||||
self.actionBild_speichern.setObjectName("actionBild_speichern")
|
||||
self.action_save_histogram = QtGui.QAction(parent=MainWindow)
|
||||
self.action_save_histogram.setObjectName("action_save_histogram")
|
||||
self.menuMen.addAction(self.actionBild_laden)
|
||||
self.menuMen.addAction(self.actionBild_speichern)
|
||||
self.menuMen.addAction(self.action_save_histogram)
|
||||
self.menubar.addAction(self.menuMen.menuAction())
|
||||
|
||||
self.retranslateUi(MainWindow)
|
||||
self.tab_widget_image.setCurrentIndex(0)
|
||||
self.tabWidget_controller.setCurrentIndex(0)
|
||||
self.tabWidget_analysis.setCurrentIndex(0)
|
||||
QtCore.QMetaObject.connectSlotsByName(MainWindow)
|
||||
|
||||
def retranslateUi(self, MainWindow):
|
||||
_translate = QtCore.QCoreApplication.translate
|
||||
MainWindow.setWindowTitle(_translate("MainWindow", "Image Playground"))
|
||||
self.label_output_image.setText(_translate("MainWindow", "Ausgabe"))
|
||||
self.pushButton_reset_output_image.setText(
|
||||
_translate("MainWindow", "Ausgabebild zurücksetzen")
|
||||
)
|
||||
self.pushButton_overwrite_input_image.setText(
|
||||
_translate("MainWindow", "Eingabebild durch aktuelle Ausgabe ersetzen")
|
||||
)
|
||||
self.tab_widget_image.setTabText(
|
||||
self.tab_widget_image.indexOf(self.tab_output_image),
|
||||
_translate("MainWindow", "Ausgabe"),
|
||||
)
|
||||
self.label_input_image.setText(_translate("MainWindow", "Eingabe"))
|
||||
self.tab_widget_image.setTabText(
|
||||
self.tab_widget_image.indexOf(self.tab_input_image),
|
||||
_translate("MainWindow", "Eingabe"),
|
||||
)
|
||||
self.label.setText(_translate("MainWindow", "Histogramm"))
|
||||
self.label_height_text.setText(_translate("MainWindow", "Höhe:"))
|
||||
self.label_height_image.setText(_translate("MainWindow", "0"))
|
||||
self.label_width_text.setText(_translate("MainWindow", "Breite:"))
|
||||
self.label_width_image.setText(_translate("MainWindow", "0"))
|
||||
self.groupBox_2.setTitle(
|
||||
_translate("MainWindow", "Farbinformation zu einzelnen Pixeln")
|
||||
)
|
||||
self.label_4.setText(_translate("MainWindow", "2. Reihe, 1. Spalte:"))
|
||||
self.label_color_pixel1.setText(_translate("MainWindow", "[x,y,z]"))
|
||||
self.label_5.setText(_translate("MainWindow", "1. Reihe, 2. Spalte:"))
|
||||
self.label_color_pixel2.setText(_translate("MainWindow", "[x,y,z]"))
|
||||
self.groupBox.setTitle(_translate("MainWindow", "Farbkanäle anzeigen"))
|
||||
self.pushButton_show_channel1.setText(_translate("MainWindow", "Kanal 1"))
|
||||
self.pushButton_show_channel2.setText(_translate("MainWindow", "Kanal 2"))
|
||||
self.pushButton_show_channel3.setText(_translate("MainWindow", "Kanal 3"))
|
||||
self.pushButton_do_image_manipulation.setText(
|
||||
_translate("MainWindow", "Meine erste Bildmanipulation anwenden")
|
||||
)
|
||||
self.tabWidget_analysis.setTabText(
|
||||
self.tabWidget_analysis.indexOf(self.widget_image_information),
|
||||
_translate("MainWindow", "Bildinformation"),
|
||||
)
|
||||
self.label_color_analysis.setText(_translate("MainWindow", "Anzahl Cluster: "))
|
||||
self.label_image_color_analysis_output.setText(
|
||||
_translate("MainWindow", "Output")
|
||||
)
|
||||
self.tabWidget_analysis.setTabText(
|
||||
self.tabWidget_analysis.indexOf(self.widget_color_analysis),
|
||||
_translate("MainWindow", "Farbanalyse"),
|
||||
)
|
||||
self.tabWidget_controller.setTabText(
|
||||
self.tabWidget_controller.indexOf(self.tab_image_analysis),
|
||||
_translate("MainWindow", "Bildanalyse"),
|
||||
)
|
||||
self.lineEdit_image_width.setPlaceholderText(_translate("MainWindow", "100"))
|
||||
self.pushButton_adjust_image_size.setText(
|
||||
_translate("MainWindow", "Größe anpassen")
|
||||
)
|
||||
self.checkBox_fix_image_size.setText(
|
||||
_translate("MainWindow", "Seitenverhältnis fixieren")
|
||||
)
|
||||
self.label_3.setText(_translate("MainWindow", "Neue Breite"))
|
||||
self.lineEdit_image_height.setPlaceholderText(_translate("MainWindow", "100"))
|
||||
self.label_2.setText(_translate("MainWindow", "Neue Höhe"))
|
||||
self.tabWidget_controller.setTabText(
|
||||
self.tabWidget_controller.indexOf(self.tab_geometric_adjustments),
|
||||
_translate("MainWindow", "Größe"),
|
||||
)
|
||||
self.pushButton_hist_stretch.setText(
|
||||
_translate("MainWindow", "Histogram Stretch")
|
||||
)
|
||||
self.pushButton_hist_equalization.setText(
|
||||
_translate("MainWindow", "Histogram Equalization")
|
||||
)
|
||||
self.pushButton_hist_log.setText(_translate("MainWindow", "Logarithmus"))
|
||||
self.pushButton_hist_exp.setText(
|
||||
_translate("MainWindow", "Exponentialfunktion")
|
||||
)
|
||||
self.pushButton_hist_inv.setText(
|
||||
_translate("MainWindow", "Histogramm invertieren")
|
||||
)
|
||||
self.groupBox_6.setTitle(_translate("MainWindow", "Threshold"))
|
||||
self.pushButton_hist_fill.setText(
|
||||
_translate("MainWindow", "Histogrammlücken füllen")
|
||||
)
|
||||
self.tabWidget_controller.setTabText(
|
||||
self.tabWidget_controller.indexOf(self.tab_histogram_manip),
|
||||
_translate("MainWindow", "Histogramm Mapping"),
|
||||
)
|
||||
self.groupBox_3.setTitle(_translate("MainWindow", "Weichzeichnungsfilter"))
|
||||
self.label_8.setText(_translate("MainWindow", "Filtergröße:"))
|
||||
self.pushButton_filter_movAvg.setText(
|
||||
_translate("MainWindow", "Moving Average")
|
||||
)
|
||||
self.pushButton_filter_gauss.setText(_translate("MainWindow", "Gauß-Filter"))
|
||||
self.pushButton_filter_median.setText(_translate("MainWindow", "Median-Filter"))
|
||||
self.groupBox_4.setTitle(_translate("MainWindow", "Kantenerkennung"))
|
||||
self.pushButton_filter_sobelX.setText(_translate("MainWindow", "Sobel X"))
|
||||
self.pushButton_filter_sobelY.setText(_translate("MainWindow", "Sobel Y"))
|
||||
self.groupBox_5.setTitle(
|
||||
_translate("MainWindow", "Moving Average - Auswertung")
|
||||
)
|
||||
self.pushButton_filter_movAvg_conv.setText(_translate("MainWindow", "Faltung"))
|
||||
self.pushButton_filter_movAvg_sep.setText(
|
||||
_translate("MainWindow", "Separierbarer Filter")
|
||||
)
|
||||
self.pushButton_filter_movAvg_int.setText(
|
||||
_translate("MainWindow", "Integralbild")
|
||||
)
|
||||
self.pushButton_filter_evaluation.setText(
|
||||
_translate("MainWindow", "Auswertung durchführen")
|
||||
)
|
||||
self.tabWidget_controller.setTabText(
|
||||
self.tabWidget_controller.indexOf(self.tab_filter),
|
||||
_translate("MainWindow", "Filter"),
|
||||
)
|
||||
self.pushButton_AWS_Labeling.setText(
|
||||
_translate("MainWindow", "AWS Rekognition Labeling")
|
||||
)
|
||||
self.tabWidget_controller.setTabText(
|
||||
self.tabWidget_controller.indexOf(self.tab_AI),
|
||||
_translate("MainWindow", "Recognition"),
|
||||
)
|
||||
self.menuMen.setTitle(_translate("MainWindow", "Menü"))
|
||||
self.actionBild_laden.setText(_translate("MainWindow", "Bild laden"))
|
||||
self.actionBild_speichern.setText(_translate("MainWindow", "Bild speichern"))
|
||||
self.action_save_histogram.setText(
|
||||
_translate("MainWindow", "Histogramm speichern")
|
||||
)
|
||||
|
||||
|
||||
from MplWidget import MplWidget
|
|
@ -0,0 +1,954 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>MainWindow</class>
|
||||
<widget class="QMainWindow" name="MainWindow">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>1259</width>
|
||||
<height>858</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Image Playground</string>
|
||||
</property>
|
||||
<widget class="QWidget" name="centralwidget">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Maximum" vsizetype="Maximum">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_5">
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<property name="spacing">
|
||||
<number>7</number>
|
||||
</property>
|
||||
<property name="sizeConstraint">
|
||||
<enum>QLayout::SetDefaultConstraint</enum>
|
||||
</property>
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="layout_left">
|
||||
<item>
|
||||
<widget class="QTabWidget" name="tab_widget_image">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>500</width>
|
||||
<height>500</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="autoFillBackground">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="currentIndex">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<widget class="QWidget" name="tab_output_image">
|
||||
<property name="autoFillBackground">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<attribute name="title">
|
||||
<string>Ausgabe</string>
|
||||
</attribute>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_3">
|
||||
<item>
|
||||
<widget class="QLabel" name="label_output_image">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="MinimumExpanding" vsizetype="MinimumExpanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::Box</enum>
|
||||
</property>
|
||||
<property name="frameShadow">
|
||||
<enum>QFrame::Plain</enum>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Ausgabe</string>
|
||||
</property>
|
||||
<property name="scaledContents">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="pushButton_reset_output_image">
|
||||
<property name="text">
|
||||
<string>Ausgabebild zurücksetzen</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="pushButton_overwrite_input_image">
|
||||
<property name="text">
|
||||
<string>Eingabebild durch aktuelle Ausgabe ersetzen</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="tab_input_image">
|
||||
<attribute name="title">
|
||||
<string>Eingabe</string>
|
||||
</attribute>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_4">
|
||||
<item>
|
||||
<widget class="QLabel" name="label_input_image">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="MinimumExpanding" vsizetype="MinimumExpanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="autoFillBackground">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::Box</enum>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Eingabe</string>
|
||||
</property>
|
||||
<property name="scaledContents">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="Line" name="line">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item alignment="Qt::AlignBottom">
|
||||
<widget class="QTextBrowser" name="text_output">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>150</height>
|
||||
</size>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="Line" name="vertical_line">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="layout_right">
|
||||
<item>
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>Histogramm</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="MplWidget" name="widget_histogram" native="true">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>400</width>
|
||||
<height>250</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="autoFillBackground">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="Line" name="horizontal_line">
|
||||
<property name="contextMenuPolicy">
|
||||
<enum>Qt::PreventContextMenu</enum>
|
||||
</property>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QTabWidget" name="tabWidget_controller">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Maximum" vsizetype="Expanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>400</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="currentIndex">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<widget class="QWidget" name="tab_image_analysis">
|
||||
<attribute name="title">
|
||||
<string>Bildanalyse</string>
|
||||
</attribute>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_7">
|
||||
<item>
|
||||
<widget class="QTabWidget" name="tabWidget_analysis">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Maximum" vsizetype="MinimumExpanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>380</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="currentIndex">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<widget class="QWidget" name="widget_image_information">
|
||||
<attribute name="title">
|
||||
<string>Bildinformation</string>
|
||||
</attribute>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_8">
|
||||
<item>
|
||||
<widget class="QWidget" name="widget" native="true">
|
||||
<layout class="QFormLayout" name="formLayout">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_height_text">
|
||||
<property name="text">
|
||||
<string>Höhe:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QLabel" name="label_height_image">
|
||||
<property name="text">
|
||||
<string>0</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_width_text">
|
||||
<property name="text">
|
||||
<string>Breite:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QLabel" name="label_width_image">
|
||||
<property name="text">
|
||||
<string>0</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox_2">
|
||||
<property name="title">
|
||||
<string>Farbinformation zu einzelnen Pixeln</string>
|
||||
</property>
|
||||
<layout class="QFormLayout" name="formLayout_4">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_4">
|
||||
<property name="text">
|
||||
<string>2. Reihe, 1. Spalte:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QLabel" name="label_color_pixel1">
|
||||
<property name="text">
|
||||
<string>[x,y,z]</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_5">
|
||||
<property name="text">
|
||||
<string>1. Reihe, 2. Spalte:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QLabel" name="label_color_pixel2">
|
||||
<property name="text">
|
||||
<string>[x,y,z]</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox">
|
||||
<property name="title">
|
||||
<string>Farbkanäle anzeigen</string>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_4">
|
||||
<item>
|
||||
<widget class="QPushButton" name="pushButton_show_channel1">
|
||||
<property name="text">
|
||||
<string>Kanal 1</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="pushButton_show_channel2">
|
||||
<property name="text">
|
||||
<string>Kanal 2</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="pushButton_show_channel3">
|
||||
<property name="text">
|
||||
<string>Kanal 3</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="pushButton_do_image_manipulation">
|
||||
<property name="text">
|
||||
<string>Meine erste Bildmanipulation anwenden</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer_3">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="widget_color_analysis">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<attribute name="title">
|
||||
<string>Farbanalyse</string>
|
||||
</attribute>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_5">
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_color_analysis">
|
||||
<item>
|
||||
<widget class="QLabel" name="label_color_analysis">
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>16777215</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Anzahl Cluster: </string>
|
||||
</property>
|
||||
<property name="scaledContents">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QSlider" name="horizontalSlider_color_clusters">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>370</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="sizeIncrement">
|
||||
<size>
|
||||
<width>380</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>10</number>
|
||||
</property>
|
||||
<property name="sliderPosition">
|
||||
<number>3</number>
|
||||
</property>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="tickPosition">
|
||||
<enum>QSlider::TicksBelow</enum>
|
||||
</property>
|
||||
<property name="tickInterval">
|
||||
<number>1</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="Line" name="line_2">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>370</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="sizeIncrement">
|
||||
<size>
|
||||
<width>370</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_image_color_analysis_output">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Maximum" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>370</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Output</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="tab_geometric_adjustments">
|
||||
<attribute name="title">
|
||||
<string>Größe</string>
|
||||
</attribute>
|
||||
<layout class="QGridLayout" name="gridLayout_2">
|
||||
<item row="1" column="1">
|
||||
<widget class="QLineEdit" name="lineEdit_image_width">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="placeholderText">
|
||||
<string>100</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0" colspan="2">
|
||||
<widget class="QPushButton" name="pushButton_adjust_image_size">
|
||||
<property name="text">
|
||||
<string>Größe anpassen</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QCheckBox" name="checkBox_fix_image_size">
|
||||
<property name="text">
|
||||
<string>Seitenverhältnis fixieren</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_3">
|
||||
<property name="text">
|
||||
<string>Neue Breite</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QLineEdit" name="lineEdit_image_height">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="placeholderText">
|
||||
<string>100</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="text">
|
||||
<string>Neue Höhe</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="1">
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="tab_histogram_manip">
|
||||
<attribute name="title">
|
||||
<string>Histogramm Mapping</string>
|
||||
</attribute>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_9">
|
||||
<item>
|
||||
<widget class="QPushButton" name="pushButton_hist_stretch">
|
||||
<property name="text">
|
||||
<string>Histogram Stretch</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="pushButton_hist_equalization">
|
||||
<property name="text">
|
||||
<string>Histogram Equalization</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="Line" name="line_3">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="pushButton_hist_log">
|
||||
<property name="text">
|
||||
<string>Logarithmus</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="pushButton_hist_exp">
|
||||
<property name="text">
|
||||
<string>Exponentialfunktion</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="pushButton_hist_inv">
|
||||
<property name="text">
|
||||
<string>Histogramm invertieren</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox_6">
|
||||
<property name="title">
|
||||
<string>Threshold</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QSlider" name="horizontalSlider_hist_threshold">
|
||||
<property name="maximum">
|
||||
<number>255</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>128</number>
|
||||
</property>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="tickPosition">
|
||||
<enum>QSlider::TicksBelow</enum>
|
||||
</property>
|
||||
<property name="tickInterval">
|
||||
<number>0</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="pushButton_hist_fill">
|
||||
<property name="text">
|
||||
<string>Histogrammlücken füllen</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer_4">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="tab_filter">
|
||||
<attribute name="title">
|
||||
<string>Filter</string>
|
||||
</attribute>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_6">
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox_3">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="Minimum">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="title">
|
||||
<string>Weichzeichnungsfilter</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_11">
|
||||
<item>
|
||||
<widget class="QWidget" name="widget_2" native="true">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_7">
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_8">
|
||||
<property name="text">
|
||||
<string>Filtergröße:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QSpinBox" name="spinBox_filter_avg_size">
|
||||
<property name="readOnly">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="buttonSymbols">
|
||||
<enum>QAbstractSpinBox::UpDownArrows</enum>
|
||||
</property>
|
||||
<property name="accelerated">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="correctionMode">
|
||||
<enum>QAbstractSpinBox::CorrectToNearestValue</enum>
|
||||
</property>
|
||||
<property name="keyboardTracking">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="showGroupSeparator" stdset="0">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<number>3</number>
|
||||
</property>
|
||||
<property name="singleStep">
|
||||
<number>2</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QWidget" name="widget_3" native="true">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_6">
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QPushButton" name="pushButton_filter_movAvg">
|
||||
<property name="text">
|
||||
<string>Moving Average</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="pushButton_filter_gauss">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Gauß-Filter</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="pushButton_filter_median">
|
||||
<property name="text">
|
||||
<string>Median-Filter</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox_4">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="title">
|
||||
<string>Kantenerkennung</string>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_3">
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QPushButton" name="pushButton_filter_sobelX">
|
||||
<property name="text">
|
||||
<string>Sobel X</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="pushButton_filter_sobelY">
|
||||
<property name="text">
|
||||
<string>Sobel Y</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="Line" name="line_4">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox_5">
|
||||
<property name="title">
|
||||
<string>Moving Average - Auswertung</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_10">
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QPushButton" name="pushButton_filter_movAvg_conv">
|
||||
<property name="text">
|
||||
<string>Faltung</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="pushButton_filter_movAvg_sep">
|
||||
<property name="text">
|
||||
<string>Separierbarer Filter</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="pushButton_filter_movAvg_int">
|
||||
<property name="text">
|
||||
<string>Integralbild</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="Line" name="line_5">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="pushButton_filter_evaluation">
|
||||
<property name="text">
|
||||
<string>Auswertung durchführen</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="tab_AI">
|
||||
<attribute name="title">
|
||||
<string>Recognition</string>
|
||||
</attribute>
|
||||
<layout class="QFormLayout" name="formLayout_3">
|
||||
<item row="0" column="0">
|
||||
<widget class="QPushButton" name="pushButton_AWS_Labeling">
|
||||
<property name="text">
|
||||
<string>AWS Rekognition Labeling</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QMenuBar" name="menubar">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>1259</width>
|
||||
<height>37</height>
|
||||
</rect>
|
||||
</property>
|
||||
<widget class="QMenu" name="menuMen">
|
||||
<property name="title">
|
||||
<string>Menü</string>
|
||||
</property>
|
||||
<addaction name="actionBild_laden"/>
|
||||
<addaction name="actionBild_speichern"/>
|
||||
<addaction name="action_save_histogram"/>
|
||||
</widget>
|
||||
<addaction name="menuMen"/>
|
||||
</widget>
|
||||
<widget class="QStatusBar" name="statusbar">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
<action name="actionBild_laden">
|
||||
<property name="text">
|
||||
<string>Bild laden</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionBild_speichern">
|
||||
<property name="text">
|
||||
<string>Bild speichern</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="action_save_histogram">
|
||||
<property name="text">
|
||||
<string>Histogramm speichern</string>
|
||||
</property>
|
||||
</action>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>MplWidget</class>
|
||||
<extends>QWidget</extends>
|
||||
<header>MplWidget</header>
|
||||
<container>1</container>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
|
@ -0,0 +1,81 @@
|
|||
import cv2
|
||||
from matplotlib import pyplot as plt
|
||||
|
||||
|
||||
def showHistogram(img):
|
||||
color = ("b", "g", "r")
|
||||
if len(img.shape) == 2:
|
||||
color = "b"
|
||||
|
||||
for i, col in enumerate(color):
|
||||
histr = cv2.calcHist([img], [i], None, [256], [0, 256])
|
||||
plt.plot(histr, color=col)
|
||||
plt.xlim([0, 256])
|
||||
plt.show()
|
||||
|
||||
|
||||
def calculate_histogram(img):
|
||||
color = ("b", "g", "r")
|
||||
histogram = [0, 0, 0]
|
||||
if len(img.shape) == 2:
|
||||
color = "b"
|
||||
histogram = [0]
|
||||
|
||||
for i, col in enumerate(color):
|
||||
histogram[i] = cv2.calcHist([img], [i], None, [256], [0, 256])
|
||||
|
||||
return histogram
|
||||
|
||||
|
||||
def plotHistogramVector(histogram):
|
||||
plt.plot(histogram, color="b")
|
||||
plt.xlim([0, len(histogram)])
|
||||
plt.show()
|
||||
|
||||
|
||||
def resize_image(img, height):
|
||||
aspect_ratio = img.shape[0] / img.shape[1]
|
||||
dim = (height, int(height * aspect_ratio))
|
||||
return cv2.resize(img, dim, interpolation=cv2.INTER_NEAREST)
|
||||
|
||||
|
||||
def resize_image(img, width, height, interpolation=cv2.INTER_NEAREST):
|
||||
dim = (width, height)
|
||||
return cv2.resize(img, dim, interpolation)
|
||||
|
||||
|
||||
def grabWebcam():
|
||||
cap = cv2.VideoCapture(0)
|
||||
while True:
|
||||
ret, im = cap.read()
|
||||
cv2.imshow("video test", im)
|
||||
key = cv2.waitKey(10)
|
||||
if key == 27:
|
||||
break
|
||||
# if key == ord(' '):
|
||||
# cv2.imwrite('vid_result.jpg',im)
|
||||
|
||||
|
||||
def ensure_one_channel_grayscale_image(img):
|
||||
if len(img.shape) == 2:
|
||||
# Das Bild ist bereits in Graustufen
|
||||
return img
|
||||
elif len(img.shape) == 3 and img.shape[2] == 3:
|
||||
# Das Bild ist farbig (3 Kanäle: BGR oder RGB)
|
||||
return cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
|
||||
else:
|
||||
raise ValueError("Ungültiges Bildformat.")
|
||||
|
||||
|
||||
def ensure_three_channel_grayscale_image(gray_scale_img):
|
||||
if len(gray_scale_img.shape) == 2:
|
||||
img = cv2.cvtColor(gray_scale_img, cv2.COLOR_GRAY2BGR)
|
||||
# Das Bild ist bereits in Graustufen
|
||||
return img
|
||||
elif len(gray_scale_img.shape) == 3 and gray_scale_img.shape[2] == 3:
|
||||
# Das Bild ist farbig (3 Kanäle: BGR oder RGB)
|
||||
img = cv2.cvtColor(gray_scale_img, cv2.COLOR_BGR2GRAY)
|
||||
img = cv2.cvtColor(img, cv2.COLOR_GRAY2BGR)
|
||||
return cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
|
||||
else:
|
||||
raise ValueError("Ungültiges Bildformat.")
|
|
@ -0,0 +1,21 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
import sys
|
||||
from models import ImageModel
|
||||
from views import MainView
|
||||
from controllers import MainController
|
||||
from PyQt6.QtWidgets import QApplication
|
||||
|
||||
|
||||
class App(QApplication):
|
||||
def __init__(self, sys_argv):
|
||||
super(App, self).__init__(sys_argv)
|
||||
self.model = ImageModel()
|
||||
self.main_controller = MainController(self.model)
|
||||
self.main_view = MainView(self.model, self.main_controller)
|
||||
self.main_view.show()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
app = App(sys.argv)
|
||||
sys.exit(app.exec())
|
|
@ -0,0 +1,148 @@
|
|||
import logging
|
||||
from loggers import LogEmitter
|
||||
|
||||
import cv2
|
||||
import numpy as np
|
||||
import Utilities
|
||||
import ColorAnalysis as CA
|
||||
import HistogramManipulation as HM
|
||||
import AWSRekognition as AI
|
||||
import ImageInformation as II
|
||||
import ImageFiltering as IF
|
||||
|
||||
|
||||
class MainController:
|
||||
def __init__(self, model):
|
||||
super().__init__()
|
||||
self._model = model
|
||||
|
||||
self.logger = logging.getLogger()
|
||||
self.log_handler = LogEmitter()
|
||||
self.logger.addHandler(self.log_handler)
|
||||
|
||||
# Set the log level to INFO
|
||||
self.logger.setLevel(logging.INFO)
|
||||
|
||||
def test_function(self):
|
||||
print("Test function")
|
||||
pass
|
||||
|
||||
def loadImage(self, str):
|
||||
img = cv2.imread(str, 1)
|
||||
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
|
||||
self._model.input_image = img
|
||||
self.logger.info("Image loaded: " + str)
|
||||
|
||||
def saveImage(self, str):
|
||||
img = cv2.cvtColor(self._model.image, cv2.COLOR_RGB2BGR)
|
||||
cv2.imwrite(str, img)
|
||||
self.logger.info("Image written to: " + str)
|
||||
|
||||
#
|
||||
def changeImage(self):
|
||||
image = np.zeros((256, 256, 3), np.uint8)
|
||||
image[0 : 256 // 2, :] = (255, 0, 0)
|
||||
image[256 // 2 : 256, :] = (0, 0, 255)
|
||||
Utilities.resize_image(image, 100)
|
||||
self._model.input_image = image
|
||||
|
||||
def set_image_as_input_image(self):
|
||||
self._model.input_image = self._model.image.copy()
|
||||
|
||||
def reset_output_image(self):
|
||||
self._model.image = self._model.input_image
|
||||
|
||||
def resize_image(self, new_width, new_height):
|
||||
self._model.image = Utilities.resize_image(
|
||||
self._model.input_image, new_width, new_height
|
||||
)
|
||||
|
||||
def analyseColors(self, ncluster):
|
||||
color_analyzer = CA.ColorAnalysis(self._model.image, ncluster)
|
||||
return color_analyzer.dominantColors()
|
||||
|
||||
def create_visual_output(self, colors, width, height_max):
|
||||
return CA.create_visual_output(colors, width, height_max)
|
||||
|
||||
def calculate_histogram(self, img):
|
||||
return Utilities.calculate_histogram(img)
|
||||
|
||||
def label_image(self):
|
||||
ai = AI.AWSRekognition()
|
||||
self._model.image = ai.label_image(self._model.input_image)
|
||||
self.logger.critical("Labeling successfull")
|
||||
|
||||
#####################################
|
||||
# Übung 1
|
||||
#####################################
|
||||
|
||||
def get_image_information(self):
|
||||
return II.imageSize(self._model.image)
|
||||
|
||||
def get_pixel_information(self):
|
||||
return II.getPixelColor(self._model.image)
|
||||
|
||||
def show_channel(self, channel):
|
||||
self._model.image = II.returnChannel(self._model.input_image, channel)
|
||||
|
||||
def do_first_image_manipulation(self):
|
||||
self._model.image = II.myFirstImageManipulation(self._model.image)
|
||||
|
||||
#####################################
|
||||
# Übung 2
|
||||
#####################################
|
||||
|
||||
def stretch_image(self):
|
||||
self._model.image = HM.stretchHistogram(self._model.input_image)
|
||||
|
||||
def equalize_image(self):
|
||||
self._model.image = HM.equalizeHistogram(self._model.input_image)
|
||||
|
||||
def apply_log(self):
|
||||
self._model.image = HM.apply_log(self._model.input_image)
|
||||
|
||||
def apply_exp(self):
|
||||
self._model.image = HM.apply_exp(self._model.input_image)
|
||||
|
||||
def apply_inv(self):
|
||||
self._model.image = HM.apply_inverse(self._model.input_image)
|
||||
|
||||
def apply_threshold(self, threshold):
|
||||
self._model.image = HM.apply_threshold(self._model.input_image, threshold)
|
||||
|
||||
#####################################
|
||||
# Übung 3
|
||||
#####################################
|
||||
|
||||
def apply_gaussian_filter(self, kernel_size):
|
||||
kernel = IF.createGaussianKernel(kernel_size)
|
||||
img = IF.applyKernelInSpatialDomain(self._model.input_image, kernel)
|
||||
self._model.image = Utilities.ensure_three_channel_grayscale_image(img)
|
||||
|
||||
def apply_moving_avg_filter(self, kernel_size):
|
||||
kernel = IF.createMovingAverageKernel(kernel_size)
|
||||
img = IF.applyKernelInSpatialDomain(self._model.input_image, kernel)
|
||||
self._model.image = Utilities.ensure_three_channel_grayscale_image(img)
|
||||
|
||||
def apply_moving_avg_filter_integral(self, kernel_size):
|
||||
img = IF.applyMovingAverageFilterWithIntegralImage(
|
||||
self._model.input_image, kernel_size
|
||||
)
|
||||
self._model.image = Utilities.ensure_three_channel_grayscale_image(img)
|
||||
|
||||
def apply_median_filter(self, kernel_size):
|
||||
img = IF.applyMedianFilter(self._model.input_image, kernel_size)
|
||||
self._model.image = Utilities.ensure_three_channel_grayscale_image(img)
|
||||
|
||||
def apply_filter_sobelX(self):
|
||||
kernel = IF.createSobelXKernel()
|
||||
img = IF.applyKernelInSpatialDomain(self._model.input_image, kernel)
|
||||
self._model.image = Utilities.ensure_three_channel_grayscale_image(img)
|
||||
|
||||
def apply_filter_sobelY(self):
|
||||
kernel = IF.createSobelYKernel()
|
||||
img = IF.applyKernelInSpatialDomain(self._model.input_image, kernel)
|
||||
self._model.image = Utilities.ensure_three_channel_grayscale_image(img)
|
||||
|
||||
def run_runtime_evaluation(self):
|
||||
IF.run_runtime_evaluation(self._model.input_image)
|
|
@ -0,0 +1,42 @@
|
|||
import logging
|
||||
from PyQt6.QtCore import pyqtSignal, QObject
|
||||
import html
|
||||
|
||||
|
||||
class LogEmitter(QObject, logging.Handler):
|
||||
"""A custom logging handler that emits a signal with the log message."""
|
||||
|
||||
messageEmitted = pyqtSignal(str)
|
||||
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
|
||||
# Define color codes
|
||||
self.color_codes = {
|
||||
logging.DEBUG: "gray",
|
||||
logging.INFO: "black",
|
||||
logging.WARNING: "orange",
|
||||
logging.ERROR: "red",
|
||||
logging.CRITICAL: "darkred",
|
||||
}
|
||||
|
||||
self.level_names = {
|
||||
logging.DEBUG: "DEBUG",
|
||||
logging.INFO: "INFO",
|
||||
logging.WARNING: "WARNING",
|
||||
logging.ERROR: "ERROR",
|
||||
logging.CRITICAL: "CRITICAL",
|
||||
}
|
||||
|
||||
def emit(self, record):
|
||||
msg = self.format(record)
|
||||
|
||||
# Get color code and level name based on log level
|
||||
level_color = self.color_codes.get(record.levelno, "black")
|
||||
level_name = self.level_names.get(record.levelno, "UNKNOWN")
|
||||
|
||||
# Create HTML string with color code and level name
|
||||
html_msg = f'<span style="color: {level_color}">{level_name}: {html.escape(msg)}</span>'
|
||||
|
||||
# Emit signal with HTML message
|
||||
self.messageEmitted.emit(html_msg)
|
|
@ -0,0 +1,61 @@
|
|||
import numpy as np
|
||||
import Utilities
|
||||
import cv2
|
||||
|
||||
from PyQt6.QtCore import QObject, pyqtSignal
|
||||
|
||||
|
||||
class ImageModel(QObject):
|
||||
image_changed = pyqtSignal(np.ndarray)
|
||||
input_image_changed = pyqtSignal(np.ndarray)
|
||||
|
||||
_image = None # output image
|
||||
_input_image = None # input image (backup)
|
||||
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self.initialize()
|
||||
|
||||
@property
|
||||
def image(self):
|
||||
return self._image
|
||||
|
||||
@property
|
||||
def input_image(self):
|
||||
return self._input_image
|
||||
|
||||
@image.setter
|
||||
def image(self, img):
|
||||
self._image = img.copy()
|
||||
print("M: image changed!")
|
||||
# update in model is reflected in view by sending a signal to view
|
||||
self.image_changed.emit(img)
|
||||
|
||||
@input_image.setter
|
||||
def input_image(self, img):
|
||||
self._input_image = img.copy()
|
||||
self.image = img
|
||||
self.input_image_changed.emit(img)
|
||||
|
||||
def initialize(self):
|
||||
image = np.zeros((256, 256, 3), np.uint8)
|
||||
image[:, 0 : 256 // 2] = (255, 0, 0)
|
||||
image[:, 256 // 2 : 256] = (0, 0, 255)
|
||||
self.input_image = image
|
||||
|
||||
class ColorAnalysis:
|
||||
|
||||
_clusters = None
|
||||
_image = None
|
||||
_colors = None
|
||||
_labels = None
|
||||
|
||||
def __init__(self, img, clusters=3):
|
||||
self.CLUSTERS = clusters
|
||||
self.IMAGE = Utilities.resize_image(img, 100)
|
||||
cv2.imshow("Input", self.IMAGE)
|
||||
|
||||
def load_rgb_image(self, path):
|
||||
image = cv2.imread(path, 1)
|
||||
# image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
|
||||
self.image = image
|
|
@ -0,0 +1,383 @@
|
|||
from PyQt6 import QtGui
|
||||
from PyQt6.QtCore import Qt, QRegularExpression
|
||||
from PyQt6.QtWidgets import QMainWindow
|
||||
from PyQt6.QtGui import QPixmap, QRegularExpressionValidator
|
||||
|
||||
|
||||
from PyQt6.QtCore import pyqtSlot
|
||||
|
||||
from PyQt6.QtWidgets import QFileDialog
|
||||
|
||||
|
||||
from Playground_UI import Ui_MainWindow
|
||||
|
||||
|
||||
class MainView(QMainWindow):
|
||||
def __init__(self, model, main_controller):
|
||||
super().__init__()
|
||||
self._model = model
|
||||
self._main_controller = main_controller
|
||||
self._ui = Ui_MainWindow()
|
||||
self._ui.setupUi(self)
|
||||
self.update_image()
|
||||
self.update_input_image()
|
||||
|
||||
self._ui.widget_histogram.controller = self._main_controller
|
||||
|
||||
####################
|
||||
# Input validators
|
||||
####################
|
||||
# Create a regular expression that matches integer values between 1 and infinity
|
||||
regex = QRegularExpression("[1-9][0-9]*")
|
||||
# Create a validator based on the regular expression
|
||||
validator = QRegularExpressionValidator(regex)
|
||||
# Set the validator for the line edit widget
|
||||
self._ui.lineEdit_image_height.setValidator(validator)
|
||||
self._ui.lineEdit_image_width.setValidator(validator)
|
||||
|
||||
####################################################################
|
||||
# connect widgets to controllers
|
||||
####################################################################
|
||||
# open file buttons
|
||||
# self._ui.pushButton.clicked.connect(self._main_controller.test_function)
|
||||
self._ui.actionBild_laden.triggered.connect(self.on_open_image_from_filesystem)
|
||||
self._ui.actionBild_speichern.triggered.connect(
|
||||
self.on_save_image_to_filesystem
|
||||
)
|
||||
self._ui.action_save_histogram.triggered.connect(
|
||||
self.on_save_histogram_to_filesystem
|
||||
)
|
||||
self._ui.horizontalSlider_color_clusters.sliderReleased.connect(
|
||||
self.on_color_cluster_slider_changed
|
||||
)
|
||||
self._ui.pushButton_hist_stretch.clicked.connect(
|
||||
self.on_hist_stretch_button_clicked
|
||||
)
|
||||
self._ui.pushButton_hist_equalization.clicked.connect(
|
||||
self.on_hist_equal_button_clicked
|
||||
)
|
||||
self._ui.pushButton_AWS_Labeling.clicked.connect(
|
||||
self.on_AWS_Rekognition_button_clicked
|
||||
)
|
||||
self._ui.pushButton_adjust_image_size.clicked.connect(
|
||||
self.on_resize_button_clicked
|
||||
)
|
||||
|
||||
self._ui.pushButton_reset_output_image.clicked.connect(
|
||||
self.on_reset_output_image_button_clicked
|
||||
)
|
||||
self._ui.pushButton_overwrite_input_image.clicked.connect(
|
||||
self.on_overwrite_input_image_button_clicked
|
||||
)
|
||||
self._ui.lineEdit_image_height.editingFinished.connect(
|
||||
self.on_new_image_height_requested
|
||||
)
|
||||
self._ui.lineEdit_image_width.editingFinished.connect(
|
||||
self.on_new_image_width_requested
|
||||
)
|
||||
|
||||
#########
|
||||
# Buttons für Übung
|
||||
#########
|
||||
self._ui.pushButton_show_channel1.clicked.connect(
|
||||
self.on_channel_1_button_clicked
|
||||
)
|
||||
self._ui.pushButton_show_channel2.clicked.connect(
|
||||
self.on_channel_2_button_clicked
|
||||
)
|
||||
self._ui.pushButton_show_channel3.clicked.connect(
|
||||
self.on_channel_3_button_clicked
|
||||
)
|
||||
self._ui.pushButton_do_image_manipulation.clicked.connect(
|
||||
self.on_do_first_image_manipulation_button_clicked
|
||||
)
|
||||
|
||||
self._ui.pushButton_hist_log.clicked.connect(
|
||||
self.on_apply_log_on_hist_button_clicked
|
||||
)
|
||||
self._ui.pushButton_hist_exp.clicked.connect(
|
||||
self.on_apply_exp_on_hist_button_clicked
|
||||
)
|
||||
self._ui.pushButton_hist_inv.clicked.connect(
|
||||
self.on_apply_inverse_on_hist_button_clicked
|
||||
)
|
||||
self._ui.horizontalSlider_hist_threshold.sliderReleased.connect(
|
||||
self.on_apply_threshold_on_hist_button_clicked
|
||||
)
|
||||
|
||||
self._ui.pushButton_filter_sobelX.clicked.connect(
|
||||
self.on_filter_sobelX_button_clicked
|
||||
)
|
||||
self._ui.pushButton_filter_sobelY.clicked.connect(
|
||||
self.on_filter_sobelY_button_clicked
|
||||
)
|
||||
self._ui.pushButton_filter_gauss.clicked.connect(
|
||||
self.on_filter_gauss_button_clicked
|
||||
)
|
||||
self._ui.pushButton_filter_movAvg.clicked.connect(
|
||||
self.on_filter_moving_avg_button_clicked
|
||||
)
|
||||
self._ui.pushButton_filter_movAvg_int.clicked.connect(
|
||||
self.on_filter_moving_avg_integral_button_clicked
|
||||
)
|
||||
self._ui.pushButton_filter_median.clicked.connect(
|
||||
self.on_filter_median_button_clicked
|
||||
)
|
||||
self._ui.pushButton_filter_evaluation.clicked.connect(
|
||||
self.on_runtime_evaluation_button_clicked
|
||||
)
|
||||
|
||||
####################################################################
|
||||
# listen for model event signals
|
||||
####################################################################
|
||||
# file name is updated
|
||||
self._model.image_changed.connect(self.on_image_changed)
|
||||
self._model.input_image_changed.connect(self.on_input_image_changed)
|
||||
|
||||
###################
|
||||
# Connect Logging
|
||||
###################
|
||||
|
||||
self._main_controller.log_handler.messageEmitted.connect(self.add_log_message)
|
||||
|
||||
def show(self):
|
||||
super().show()
|
||||
self.on_input_image_changed()
|
||||
|
||||
@pyqtSlot(str)
|
||||
def add_log_message(self, msg):
|
||||
"""Add a log message to the QTextBrowser widget."""
|
||||
self._ui.text_output.append(msg)
|
||||
|
||||
def resizeEvent(self, a0):
|
||||
self.on_input_image_changed()
|
||||
QMainWindow.resizeEvent(self, a0)
|
||||
|
||||
def on_open_image_from_filesystem(self):
|
||||
fname = QFileDialog.getOpenFileName(
|
||||
self, "Open file", "../", "Image Files (*.png *.jpg *.bmp)"
|
||||
)
|
||||
self._main_controller.loadImage(fname[0])
|
||||
print(fname[0])
|
||||
|
||||
def on_save_image_to_filesystem(self):
|
||||
fname, _ = QFileDialog.getSaveFileName(
|
||||
self, "Save file", "../", "Image Files (*.png *.jpg *.bmp)"
|
||||
)
|
||||
if fname:
|
||||
self._main_controller.saveImage(fname)
|
||||
|
||||
def on_save_histogram_to_filesystem(self):
|
||||
fname, _ = QFileDialog.getSaveFileName(
|
||||
self, "Save file", "../", "Image Files (*.png *.jpg *.bmp)"
|
||||
)
|
||||
if fname:
|
||||
self._ui.widget_histogram.save_histogram(fname)
|
||||
|
||||
def on_image_changed(self):
|
||||
self.update_image()
|
||||
self.update_histogram()
|
||||
self.update_image_information()
|
||||
|
||||
def on_input_image_changed(self):
|
||||
self.update_input_image()
|
||||
self.on_image_changed()
|
||||
|
||||
def on_image_mouse_pressed(self):
|
||||
self._main_controller.logger.logger.critical("Mouse pressed")
|
||||
|
||||
def on_overwrite_input_image_button_clicked(self):
|
||||
self._main_controller.set_image_as_input_image()
|
||||
|
||||
def on_reset_output_image_button_clicked(self):
|
||||
self._main_controller.reset_output_image()
|
||||
|
||||
def on_new_image_height_requested(self):
|
||||
if self._ui.checkBox_fix_image_size.isChecked():
|
||||
image_size = self._main_controller.get_image_information()
|
||||
aspect_ratio = image_size[0] / image_size[1]
|
||||
# dim = (height, int(height * aspect_ratio))
|
||||
self._ui.lineEdit_image_width.setText(
|
||||
str(int(int(self._ui.lineEdit_image_height.text()) / aspect_ratio))
|
||||
)
|
||||
pass
|
||||
|
||||
def on_new_image_width_requested(self):
|
||||
if self._ui.checkBox_fix_image_size.isChecked():
|
||||
image_size = self._main_controller.get_image_information()
|
||||
aspect_ratio = image_size[0] / image_size[1]
|
||||
# dim = (height, int(height * aspect_ratio))
|
||||
self._ui.lineEdit_image_height.setText(
|
||||
str(int(int(self._ui.lineEdit_image_width.text()) * aspect_ratio))
|
||||
)
|
||||
pass
|
||||
|
||||
def on_color_cluster_slider_changed(self):
|
||||
dominant_colors = self._main_controller.analyseColors(
|
||||
self._ui.horizontalSlider_color_clusters.sliderPosition()
|
||||
)
|
||||
self.update_color_cluster_output(dominant_colors)
|
||||
print(self._ui.horizontalSlider_color_clusters.sliderPosition())
|
||||
|
||||
def on_hist_stretch_button_clicked(self):
|
||||
self._main_controller.stretch_image()
|
||||
self.on_image_changed()
|
||||
|
||||
def on_hist_equal_button_clicked(self):
|
||||
self._main_controller.equalize_image()
|
||||
self.on_image_changed()
|
||||
|
||||
def on_AWS_Rekognition_button_clicked(self):
|
||||
self._main_controller.label_image()
|
||||
|
||||
def update_color_cluster_output(self, dominant_colors):
|
||||
size = self._ui.label_image_color_analysis_output.size()
|
||||
visual_output = self._main_controller.create_visual_output(
|
||||
dominant_colors, size.width(), size.height()
|
||||
)
|
||||
qt_img = convert_cv_qt(visual_output, size.width(), size.height())
|
||||
self._ui.label_image_color_analysis_output.setPixmap(qt_img)
|
||||
|
||||
def on_resize_button_clicked(self):
|
||||
self._main_controller.resize_image(
|
||||
int(self._ui.lineEdit_image_width.text()),
|
||||
int(self._ui.lineEdit_image_height.text()),
|
||||
)
|
||||
# self.on_image_changed()
|
||||
|
||||
def update_image(self):
|
||||
frame = self._model.image
|
||||
size = self._ui.label_output_image.size()
|
||||
# qt_img = convert_cv_qt(frame, size.width(), size.height())
|
||||
qt_img = convert_cv2scaledqt(frame, size.width(), size.height())
|
||||
# self._ui.label_output_image.loadImage(qt_img)
|
||||
self._ui.label_output_image.setPixmap(qt_img)
|
||||
|
||||
def update_input_image(self):
|
||||
frame = self._model.input_image
|
||||
size = self._ui.label_output_image.size()
|
||||
qt_img = convert_cv2scaledqt(frame, size.width(), size.height())
|
||||
# qt_img = convert_cv_qt(frame, size.width(), size.height())
|
||||
self._ui.label_input_image.setPixmap(qt_img)
|
||||
|
||||
def update_histogram(self):
|
||||
self._ui.widget_histogram.drawHistogram(self._model.image)
|
||||
|
||||
def update_image_information(self):
|
||||
image_size = self._main_controller.get_image_information()
|
||||
self._ui.label_height_image.setText(str(image_size[0]))
|
||||
self._ui.label_width_image.setText(str(image_size[1]))
|
||||
|
||||
self._ui.lineEdit_image_height.setText(str(image_size[0]))
|
||||
self._ui.lineEdit_image_width.setText(str(image_size[1]))
|
||||
|
||||
pixel_colors = self._main_controller.get_pixel_information()
|
||||
self._ui.label_color_pixel1.setText(str(pixel_colors[0]))
|
||||
self._ui.label_color_pixel2.setText(str(pixel_colors[1]))
|
||||
|
||||
#####################
|
||||
# Übung 1
|
||||
#####################
|
||||
|
||||
def on_channel_1_button_clicked(self):
|
||||
self._main_controller.show_channel(0)
|
||||
self.on_image_changed()
|
||||
|
||||
def on_channel_2_button_clicked(self):
|
||||
self._main_controller.show_channel(1)
|
||||
self.on_image_changed()
|
||||
|
||||
def on_channel_3_button_clicked(self):
|
||||
self._main_controller.show_channel(2)
|
||||
self.on_image_changed()
|
||||
|
||||
def on_do_first_image_manipulation_button_clicked(self):
|
||||
self._main_controller.do_first_image_manipulation()
|
||||
self.on_image_changed()
|
||||
|
||||
#####################
|
||||
# Übung 2
|
||||
#####################
|
||||
|
||||
def on_apply_log_on_hist_button_clicked(self):
|
||||
self._main_controller.apply_log()
|
||||
self.on_image_changed()
|
||||
|
||||
def on_apply_exp_on_hist_button_clicked(self):
|
||||
self._main_controller.apply_exp()
|
||||
self.on_image_changed()
|
||||
|
||||
def on_apply_inverse_on_hist_button_clicked(self):
|
||||
self._main_controller.apply_inv()
|
||||
self.on_image_changed()
|
||||
|
||||
def on_apply_threshold_on_hist_button_clicked(self):
|
||||
self._main_controller.apply_threshold(
|
||||
self._ui.horizontalSlider_hist_threshold.sliderPosition()
|
||||
)
|
||||
self.on_image_changed()
|
||||
|
||||
#####################
|
||||
# Übung 3
|
||||
#####################
|
||||
|
||||
def on_filter_sobelX_button_clicked(self):
|
||||
self._main_controller.apply_filter_sobelX()
|
||||
self.on_image_changed()
|
||||
|
||||
def on_filter_sobelY_button_clicked(self):
|
||||
self._main_controller.apply_filter_sobelY()
|
||||
self.on_image_changed()
|
||||
|
||||
def on_filter_gauss_button_clicked(self):
|
||||
self._main_controller.apply_gaussian_filter(
|
||||
self._ui.spinBox_filter_avg_size.value()
|
||||
)
|
||||
self.on_image_changed()
|
||||
|
||||
def on_filter_moving_avg_button_clicked(self):
|
||||
self._main_controller.apply_moving_avg_filter(
|
||||
self._ui.spinBox_filter_avg_size.value()
|
||||
)
|
||||
self.on_image_changed()
|
||||
|
||||
def on_filter_moving_avg_integral_button_clicked(self):
|
||||
self._main_controller.apply_moving_avg_filter_integral(
|
||||
self._ui.spinBox_filter_avg_size.value()
|
||||
)
|
||||
self.on_image_changed()
|
||||
|
||||
def on_filter_median_button_clicked(self):
|
||||
self._main_controller.apply_median_filter(
|
||||
self._ui.spinBox_filter_avg_size.value()
|
||||
)
|
||||
self.on_image_changed()
|
||||
|
||||
def on_runtime_evaluation_button_clicked(self):
|
||||
self._main_controller.run_runtime_evaluation()
|
||||
|
||||
|
||||
def convert_cv_qt(cv_img, display_width, display_height):
|
||||
"""Convert from an opencv image to QPixmap"""
|
||||
h, w, ch = cv_img.shape
|
||||
bytes_per_line = ch * w
|
||||
convert_to_Qt_format = QtGui.QImage(
|
||||
cv_img.data, w, h, bytes_per_line, QtGui.QImage.Format.Format_RGB888
|
||||
)
|
||||
convert_to_Qt_format.scaled(
|
||||
display_width, display_height, Qt.AspectRatioMode.KeepAspectRatio
|
||||
)
|
||||
return QPixmap.fromImage(convert_to_Qt_format)
|
||||
|
||||
|
||||
def convert_cv2scaledqt(cv_img, display_width, display_height):
|
||||
"""Convert from an opencv image to QPixmap"""
|
||||
h, w, ch = cv_img.shape
|
||||
bytes_per_line = ch * w
|
||||
convert_to_Qt_format = QtGui.QImage(
|
||||
cv_img.data, w, h, bytes_per_line, QtGui.QImage.Format.Format_RGB888
|
||||
)
|
||||
p = convert_to_Qt_format.scaled(
|
||||
display_width, display_height, Qt.AspectRatioMode.KeepAspectRatio
|
||||
)
|
||||
return QPixmap.fromImage(p)
|
Loading…
Reference in New Issue