add excercise 1 source files

This commit is contained in:
Sven Vogel 2025-01-27 19:57:20 +01:00
parent fde88ed0d9
commit 32290bc8a6
20 changed files with 3885 additions and 0 deletions

1
.gitignore vendored Normal file
View File

@ -0,0 +1 @@
__pycache__

18
Pipfile Normal file
View File

@ -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"

716
Pipfile.lock generated Normal file
View File

@ -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": {}
}

BIN
digitaldog.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 244 KiB

6
requirements.txt Normal file
View File

@ -0,0 +1,6 @@
PyQt6
numpy
matplotlib
scikit-learn
boto3
opencv-python

36
src/AWSRekognition.py Executable file
View File

@ -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

80
src/ColorAnalysis.py Executable file
View File

@ -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

60
src/HistogramManipulation.py Executable file
View File

@ -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

67
src/ImageFiltering.py Normal file
View File

@ -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

110
src/ImageInformation.py Normal file
View File

@ -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

262
src/ImagePlotter.py Executable file
View File

@ -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

60
src/MplWidget.py Executable file
View File

@ -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)

779
src/Playground_UI.py Executable file
View File

@ -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

954
src/Playground_UI.ui Executable file
View File

@ -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>

81
src/Utilities.py Executable file
View File

@ -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.")

21
src/app.py Executable file
View File

@ -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())

148
src/controllers.py Executable file
View File

@ -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)

42
src/loggers.py Executable file
View File

@ -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)

61
src/models.py Executable file
View File

@ -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

383
src/views.py Executable file
View File

@ -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)