]> OzVa Git service - rust_fft/commitdiff
Fully built the LUT system
authorMax Value <greenwoodw50@gmail.com>
Tue, 7 Oct 2025 17:22:48 +0000 (18:22 +0100)
committerMax Value <greenwoodw50@gmail.com>
Tue, 7 Oct 2025 17:22:48 +0000 (18:22 +0100)
implemented into the main program via correct.rs but not yet tested

.gitignore
Cargo.lock
Cargo.toml
src/correct.rs [new file with mode: 0644]
src/cube/camera.py [new file with mode: 0644]
src/cube/cube.py [changed mode: 0644->0755]
src/cube/frame.py [new file with mode: 0644]
src/cube/graph.py [new file with mode: 0755]
src/cube/main.py [new file with mode: 0755]
src/cube/test.py [new file with mode: 0755]
src/main.rs

index 96804589f64a93b4d781badac893005c79caf765..370aa2a0a7f20049f49f19268a306c3279fca4b5 100644 (file)
@@ -1,2 +1,5 @@
-/target
+target/
 camera.a
+cube.npy
+__pycache__/
+cargo.lock
index de3f3402ad4a6cd31a5ffcf9da7371683adfb09e..b7efc4ea6e3581e3d5829f432398dfc76a1c329f 100644 (file)
@@ -1,6 +1,6 @@
 # This file is automatically @generated by Cargo.
 # It is not intended for manual editing.
-version = 3
+version = 4
 
 [[package]]
 name = "ab_glyph"
@@ -147,7 +147,7 @@ checksum = "0ae92a5119aa49cdbcf6b9f893fe4e1d98b04ccbf82ee0584ad948a44a734dea"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.77",
+ "syn 2.0.87",
 ]
 
 [[package]]
@@ -230,7 +230,7 @@ dependencies = [
  "regex",
  "rustc-hash",
  "shlex",
- "syn 2.0.77",
+ "syn 2.0.87",
 ]
 
 [[package]]
@@ -278,6 +278,15 @@ version = "0.1.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "0d8c1fef690941d3e7788d328517591fecc684c084084702d6ff1641e993699a"
 
+[[package]]
+name = "block-buffer"
+version = "0.10.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71"
+dependencies = [
+ "generic-array",
+]
+
 [[package]]
 name = "block-sys"
 version = "0.1.0-beta.1"
@@ -343,7 +352,7 @@ dependencies = [
  "log",
  "nix 0.25.1",
  "slotmap",
- "thiserror",
+ "thiserror 1.0.63",
  "vec_map",
 ]
 
@@ -521,6 +530,15 @@ dependencies = [
  "windows 0.54.0",
 ]
 
+[[package]]
+name = "cpufeatures"
+version = "0.2.17"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280"
+dependencies = [
+ "libc",
+]
+
 [[package]]
 name = "crc32fast"
 version = "1.4.2"
@@ -561,6 +579,16 @@ version = "0.2.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7"
 
+[[package]]
+name = "crypto-common"
+version = "0.1.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3"
+dependencies = [
+ "generic-array",
+ "typenum",
+]
+
 [[package]]
 name = "d3d12"
 version = "0.7.0"
@@ -578,6 +606,16 @@ version = "0.11.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "0c87e182de0887fd5361989c677c4e8f5000cd9491d6d563161a8f3a5519fc7f"
 
+[[package]]
+name = "digest"
+version = "0.10.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292"
+dependencies = [
+ "block-buffer",
+ "crypto-common",
+]
+
 [[package]]
 name = "dispatch"
 version = "0.2.0"
@@ -678,7 +716,7 @@ checksum = "1a5c6c585bc94aaf2c7b51dd4c2ba22680844aba4c687be581871a6f518c5742"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.77",
+ "syn 2.0.87",
 ]
 
 [[package]]
@@ -770,6 +808,16 @@ dependencies = [
  "slab",
 ]
 
+[[package]]
+name = "generic-array"
+version = "0.14.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a"
+dependencies = [
+ "typenum",
+ "version_check",
+]
+
 [[package]]
 name = "getrandom"
 version = "0.2.15"
@@ -778,7 +826,19 @@ checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7"
 dependencies = [
  "cfg-if",
  "libc",
- "wasi",
+ "wasi 0.11.0+wasi-snapshot-preview1",
+]
+
+[[package]]
+name = "getrandom"
+version = "0.3.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "26145e563e54f2cadc477553f1ec5ee650b00862f0a58bcd12cbdc5f0ea2d2f4"
+dependencies = [
+ "cfg-if",
+ "libc",
+ "r-efi",
+ "wasi 0.14.7+wasi-0.2.4",
 ]
 
 [[package]]
@@ -848,7 +908,7 @@ checksum = "ce95f9e2e11c2c6fadfce42b5af60005db06576f231f5c92550fdded43c423e8"
 dependencies = [
  "backtrace",
  "log",
- "thiserror",
+ "thiserror 1.0.63",
  "winapi",
  "windows 0.44.0",
 ]
@@ -909,7 +969,7 @@ dependencies = [
  "com-rs",
  "libc",
  "libloading 0.7.4",
- "thiserror",
+ "thiserror 1.0.63",
  "widestring",
  "winapi",
 ]
@@ -1011,7 +1071,7 @@ checksum = "c34819042dc3d3971c46c2190835914dfbe0c3c13f61449b2997f4e9722dfa60"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.77",
+ "syn 2.0.87",
 ]
 
 [[package]]
@@ -1043,7 +1103,7 @@ dependencies = [
  "combine",
  "jni-sys",
  "log",
- "thiserror",
+ "thiserror 1.0.63",
  "walkdir",
  "windows-sys 0.45.0",
 ]
@@ -1273,7 +1333,7 @@ checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c"
 dependencies = [
  "libc",
  "log",
- "wasi",
+ "wasi 0.11.0+wasi-snapshot-preview1",
  "windows-sys 0.48.0",
 ]
 
@@ -1294,7 +1354,7 @@ dependencies = [
  "rustc-hash",
  "spirv",
  "termcolor",
- "thiserror",
+ "thiserror 1.0.63",
  "unicode-xid",
 ]
 
@@ -1309,7 +1369,7 @@ dependencies = [
  "ndk-sys 0.4.1+23.1.7779620",
  "num_enum 0.5.11",
  "raw-window-handle",
- "thiserror",
+ "thiserror 1.0.63",
 ]
 
 [[package]]
@@ -1323,7 +1383,7 @@ dependencies = [
  "log",
  "ndk-sys 0.5.0+25.2.9519653",
  "num_enum 0.7.3",
- "thiserror",
+ "thiserror 1.0.63",
 ]
 
 [[package]]
@@ -1397,6 +1457,17 @@ version = "0.3.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "0676bb32a98c1a483ce53e500a81ad9c3d5b3f7c920c28c24e9cb0980d0b5bc8"
 
+[[package]]
+name = "npyz"
+version = "0.8.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9f0e759e014e630f90af745101b614f761306ddc541681e546649068e25ec1b9"
+dependencies = [
+ "byteorder",
+ "num-bigint",
+ "py_literal",
+]
+
 [[package]]
 name = "num-bigint"
 version = "0.4.6"
@@ -1424,7 +1495,7 @@ checksum = "ed3955f1a9c7c0c15e092f9c887db08b1fc683305fdf6eb6684f22555355e202"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.77",
+ "syn 2.0.87",
 ]
 
 [[package]]
@@ -1504,7 +1575,7 @@ dependencies = [
  "proc-macro-crate",
  "proc-macro2",
  "quote",
- "syn 2.0.77",
+ "syn 2.0.87",
 ]
 
 [[package]]
@@ -1516,7 +1587,7 @@ dependencies = [
  "proc-macro-crate",
  "proc-macro2",
  "quote",
- "syn 2.0.77",
+ "syn 2.0.87",
 ]
 
 [[package]]
@@ -1655,6 +1726,50 @@ version = "2.3.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e"
 
+[[package]]
+name = "pest"
+version = "2.8.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "21e0a3a33733faeaf8651dfee72dd0f388f0c8e5ad496a3478fa5a922f49cfa8"
+dependencies = [
+ "memchr",
+ "thiserror 2.0.16",
+ "ucd-trie",
+]
+
+[[package]]
+name = "pest_derive"
+version = "2.8.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bc58706f770acb1dbd0973e6530a3cff4746fb721207feb3a8a6064cd0b6c663"
+dependencies = [
+ "pest",
+ "pest_generator",
+]
+
+[[package]]
+name = "pest_generator"
+version = "2.8.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6d4f36811dfe07f7b8573462465d5cb8965fffc2e71ae377a33aecf14c2c9a2f"
+dependencies = [
+ "pest",
+ "pest_meta",
+ "proc-macro2",
+ "quote",
+ "syn 2.0.87",
+]
+
+[[package]]
+name = "pest_meta"
+version = "2.8.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "42919b05089acbd0a5dcd5405fb304d17d1053847b81163d09c4ad18ce8e8420"
+dependencies = [
+ "pest",
+ "sha2",
+]
+
 [[package]]
 name = "petgraph"
 version = "0.6.5"
@@ -1749,7 +1864,20 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "a65f2e60fbf1063868558d69c6beacf412dc755f9fc020f514b7955fc914fe30"
 dependencies = [
  "quote",
- "syn 2.0.77",
+ "syn 2.0.87",
+]
+
+[[package]]
+name = "py_literal"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "102df7a3d46db9d3891f178dcc826dc270a6746277a9ae6436f8d29fd490a8e1"
+dependencies = [
+ "num-bigint",
+ "num-complex",
+ "num-traits",
+ "pest",
+ "pest_derive",
 ]
 
 [[package]]
@@ -1776,6 +1904,12 @@ dependencies = [
  "proc-macro2",
 ]
 
+[[package]]
+name = "r-efi"
+version = "5.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f"
+
 [[package]]
 name = "rand"
 version = "0.8.5"
@@ -1783,8 +1917,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
 dependencies = [
  "libc",
- "rand_chacha",
- "rand_core",
+ "rand_chacha 0.3.1",
+ "rand_core 0.6.4",
+]
+
+[[package]]
+name = "rand"
+version = "0.9.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6db2770f06117d490610c7488547d543617b21bfa07796d7a12f6f1bd53850d1"
+dependencies = [
+ "rand_chacha 0.9.0",
+ "rand_core 0.9.3",
 ]
 
 [[package]]
@@ -1794,7 +1938,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88"
 dependencies = [
  "ppv-lite86",
- "rand_core",
+ "rand_core 0.6.4",
+]
+
+[[package]]
+name = "rand_chacha"
+version = "0.9.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb"
+dependencies = [
+ "ppv-lite86",
+ "rand_core 0.9.3",
 ]
 
 [[package]]
@@ -1803,7 +1957,16 @@ version = "0.6.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
 dependencies = [
- "getrandom",
+ "getrandom 0.2.15",
+]
+
+[[package]]
+name = "rand_core"
+version = "0.9.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "99d9a13982dcf210057a8a78572b2217b667c3beacbf3a0d8b454f6f82837d38"
+dependencies = [
+ "getrandom 0.3.3",
 ]
 
 [[package]]
@@ -1838,11 +2001,11 @@ dependencies = [
  "once_cell",
  "paste",
  "profiling",
- "rand",
- "rand_chacha",
+ "rand 0.8.5",
+ "rand_chacha 0.3.1",
  "simd_helpers",
  "system-deps",
- "thiserror",
+ "thiserror 1.0.63",
  "v_frame",
  "wasm-bindgen",
 ]
@@ -1973,6 +2136,8 @@ dependencies = [
  "hound",
  "image",
  "libc",
+ "npyz",
+ "rand 0.9.2",
  "rscam",
  "rustfft",
  "show-image",
@@ -2071,7 +2236,7 @@ checksum = "243902eda00fad750862fc144cea25caca5e20d615af0a81bee94ca738f1df1f"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.77",
+ "syn 2.0.87",
 ]
 
 [[package]]
@@ -2083,6 +2248,17 @@ dependencies = [
  "serde",
 ]
 
+[[package]]
+name = "sha2"
+version = "0.10.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283"
+dependencies = [
+ "cfg-if",
+ "cpufeatures",
+ "digest",
+]
+
 [[package]]
 name = "shlex"
 version = "1.3.0"
@@ -2215,9 +2391,9 @@ dependencies = [
 
 [[package]]
 name = "syn"
-version = "2.0.77"
+version = "2.0.87"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9f35bcdf61fd8e7be6caf75f429fdca8beb3ed76584befb503b1569faee373ed"
+checksum = "25aa4ce346d03a6dcd68dd8b4010bcb74e54e62c90c573f394c46eae99aba32d"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -2258,7 +2434,16 @@ version = "1.0.63"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "c0342370b38b6a11b6cc11d6a805569958d54cfa061a29969c3b5ce2ea405724"
 dependencies = [
- "thiserror-impl",
+ "thiserror-impl 1.0.63",
+]
+
+[[package]]
+name = "thiserror"
+version = "2.0.16"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3467d614147380f2e4e374161426ff399c91084acd2363eaf549172b3d5e60c0"
+dependencies = [
+ "thiserror-impl 2.0.16",
 ]
 
 [[package]]
@@ -2269,7 +2454,18 @@ checksum = "a4558b58466b9ad7ca0f102865eccc95938dca1a74a856f2b57b6629050da261"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.77",
+ "syn 2.0.87",
+]
+
+[[package]]
+name = "thiserror-impl"
+version = "2.0.16"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6c5e1be1c48b9172ee610da68fd9cd2770e7a4056cb3fc98710ee6906f0c7960"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.87",
 ]
 
 [[package]]
@@ -2369,6 +2565,18 @@ version = "0.24.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "5be21190ff5d38e8b4a2d3b6a3ae57f612cc39c96e83cedeaf7abc338a8bac4a"
 
+[[package]]
+name = "typenum"
+version = "1.18.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1dccffe3ce07af9386bfd29e80c0ab1a8205a2fc34e4bcd40364df902cfa8f3f"
+
+[[package]]
+name = "ucd-trie"
+version = "0.1.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2896d95c02a80c6d6a5d6e953d479f5ddf2dfdb6a244441010e373ac0fb88971"
+
 [[package]]
 name = "unicode-ident"
 version = "1.0.13"
@@ -2432,6 +2640,24 @@ version = "0.11.0+wasi-snapshot-preview1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
 
+[[package]]
+name = "wasi"
+version = "0.14.7+wasi-0.2.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "883478de20367e224c0090af9cf5f9fa85bed63a95c1abf3afc5c083ebc06e8c"
+dependencies = [
+ "wasip2",
+]
+
+[[package]]
+name = "wasip2"
+version = "1.0.1+wasi-0.2.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0562428422c63773dad2c345a1882263bbf4d65cf3f42e90921f787ef5ad58e7"
+dependencies = [
+ "wit-bindgen",
+]
+
 [[package]]
 name = "wasm-bindgen"
 version = "0.2.93"
@@ -2454,7 +2680,7 @@ dependencies = [
  "once_cell",
  "proc-macro2",
  "quote",
- "syn 2.0.77",
+ "syn 2.0.87",
  "wasm-bindgen-shared",
 ]
 
@@ -2488,7 +2714,7 @@ checksum = "afc340c74d9005395cf9dd098506f7f44e38f2b4a21c6aaacf9a105ea5e1e836"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.77",
+ "syn 2.0.87",
  "wasm-bindgen-backend",
  "wasm-bindgen-shared",
 ]
@@ -2629,7 +2855,7 @@ dependencies = [
  "raw-window-handle",
  "rustc-hash",
  "smallvec",
- "thiserror",
+ "thiserror 1.0.63",
  "web-sys",
  "wgpu-hal",
  "wgpu-types",
@@ -2669,7 +2895,7 @@ dependencies = [
  "renderdoc-sys",
  "rustc-hash",
  "smallvec",
- "thiserror",
+ "thiserror 1.0.63",
  "wasm-bindgen",
  "web-sys",
  "wgpu-types",
@@ -3020,6 +3246,12 @@ dependencies = [
  "memchr",
 ]
 
+[[package]]
+name = "wit-bindgen"
+version = "0.46.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f17a85883d4e6d00e8a97c586de764dabcc06133f7f1d55dce5cdc070ad7fe59"
+
 [[package]]
 name = "x11-dl"
 version = "2.21.0"
@@ -3061,7 +3293,7 @@ checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.77",
+ "syn 2.0.87",
 ]
 
 [[package]]
index ecee24fef069d1e1f0eef5fd206f719843d8ab83..c7bbe3bfadde875ae6398e44e435dfa379fb41a5 100644 (file)
@@ -13,6 +13,8 @@ show-image = {version = "0.14.0", features = ["image"]}
 hound = "3.5.1"
 cpal = "0.15.3"
 rscam = "0.5.5"
+npyz = "0.8.4"
+rand = "0.9.2"
 
 [build-dependencies]
 cc = "1.0"
diff --git a/src/correct.rs b/src/correct.rs
new file mode 100644 (file)
index 0000000..2fc909b
--- /dev/null
@@ -0,0 +1,89 @@
+use npyz::NpyFile;
+use std::io::BufReader;
+use std::fs::File;
+
+pub struct Correcter {
+       lut: Vec<u8>,
+       strides: [u64;4],
+       scaler: f64
+}
+
+impl Correcter {
+       pub fn new(path: &str) -> Self {
+               let file = BufReader::new(File::open(path).unwrap());
+               let npy = NpyFile::new(file).unwrap();
+
+               let strides = npy.strides().try_into().expect("Wrong number of dimentions!");
+               let scaler = npy.shape()[0] as f64 / 255.;
+
+               let data: Vec<u8> = npy.into_vec().unwrap();
+
+               Self {
+                       lut: data,
+                       strides,
+                       scaler
+               }
+       }
+
+       pub fn correct(&self, r: u8, g:u8, b:u8) -> [u8; 3] {
+               let r_scale = r as f64 * self.scaler * self.strides[0] as f64;
+               let g_scale = g as f64 * self.scaler * self.strides[1] as f64;
+               let b_scale = b as f64 * self.scaler * self.strides[2] as f64;
+
+               println!("scaler {}", self.scaler);
+               println!("strides {:?}", self.strides);
+               println!("r scale {}", r_scale);
+               println!("g scale {}", g_scale);
+               println!("b scale {}", b_scale);
+
+               let r_upper = r_scale.ceil();
+               let g_upper = g_scale.ceil();
+               let b_upper = b_scale.ceil();
+               let r_lower = r_scale.floor();
+               let g_lower = g_scale.floor();
+               let b_lower = b_scale.floor();
+
+               println!("r upper {}", r_upper);
+               println!("g upper {}", g_upper);
+               println!("b upper {}", b_upper);
+
+               println!("r lower {}", r_lower);
+               println!("g lower {}", g_lower);
+               println!("b lower {}", b_lower);
+
+               let r_remainder = r_scale.fract();
+               let g_remainder = g_scale.fract();
+               let b_remainder = b_scale.fract();
+
+               println!("r remainder {}", r_remainder);
+               println!("g remainder {}", g_remainder);
+               println!("b remainder {}", b_remainder);
+
+               let i_upper = (r_upper + g_upper + b_upper) as usize;
+               let i_lower = (r_lower + g_lower + b_lower) as usize;
+
+               println!("i upper {}", i_upper);
+               println!("i lower {}", i_lower);
+
+               let r_upper = self.lut[i_upper] as f64;
+               let g_upper = self.lut[i_upper+1] as f64;
+               let b_upper = self.lut[i_upper+2] as f64;
+               let r_lower = self.lut[i_lower] as f64;
+               let g_lower = self.lut[i_lower+1] as f64;
+               let b_lower = self.lut[i_lower+2] as f64;
+
+               println!("r upper real {}", r_upper);
+               println!("g upper real {}", g_upper);
+               println!("b upper real {}", b_upper);
+
+               println!("r lower real {}", r_lower);
+               println!("g lower real {}", g_lower);
+               println!("b lower real {}", b_lower);
+
+               [
+                       (((r_upper - r_lower) * r_remainder) + r_lower) as u8,
+                       (((g_upper - g_lower) * g_remainder) + g_lower) as u8,
+                       (((b_upper - b_lower) * b_remainder) + b_lower) as u8
+               ]
+       }
+}
diff --git a/src/cube/camera.py b/src/cube/camera.py
new file mode 100644 (file)
index 0000000..bed2a29
--- /dev/null
@@ -0,0 +1,59 @@
+import numpy as np
+import cv2 as cv
+
+CAP_WAIT = 1
+
+class Camera():
+       def __init__(self, device):
+               cv.namedWindow("LUT Calibration", cv.WINDOW_GUI_NORMAL)
+
+               self.camera = cv.VideoCapture(device)
+               self.homography = None
+
+               #self.calibrate()
+
+       def get(self, image):
+               import main
+
+               cv.imshow("LUT Calibration", image)
+               cv.waitKey(CAP_WAIT)
+
+               #_, capture = self.camera.read()
+               #capture = cv.warpPerspective(capture, self.homography, (main.IMAGE_WIDTH, main.IMAGE_HEIGHT))
+
+               return image
+               return capture
+
+       def calibrate(self):
+               calibration_image = cv.imread("../calibration.jpg")
+
+               # remove toolbar from named calibration window
+               cv.imshow("LUT Calibration", calibration_image)
+               cv.waitKey(0)
+
+               _, capture = self.camera.read()
+
+               sift = cv.SIFT_create()
+               kp1, des1 = sift.detectAndCompute(calibration_image, None)
+               kp2, des2 = sift.detectAndCompute(capture, None)
+
+               # get good matches between calibration image and the captured image
+               flann = cv.FlannBasedMatcher(
+                               {"algorithm": 1, "trees": 5},
+                               {"checks": 50}
+               )
+               matches = flann.knnMatch(des1, des2, k=2)
+
+               #get good matches via ratio test
+               good = []
+               for m,n in matches:
+                               if m.distance < 0.7 * n.distance:
+                                               good.append(m)
+
+               if len(good) > 10:
+                               src_pts = np.float32([ kp1[m.queryIdx].pt for m in good ]).reshape(-1,1,2)
+                               dst_pts = np.float32([ kp2[m.trainIdx].pt for m in good ]).reshape(-1,1,2)
+                               self.homography, _ = cv.findHomography(dst_pts, src_pts, cv.RANSAC, 5.0)
+
+               else:
+                               raise Exception("Calibration failed")
old mode 100644 (file)
new mode 100755 (executable)
index ad3062c..ba6cf6f
@@ -1,4 +1,89 @@
 #!.venv/bin/python
 
+from tqdm import tqdm
+import numpy as np
 import cv2 as cv
+import time
+
+WAIT_TIME = 0.1
+WAIT_TICKS = 100
+
+class Cube():
+       def __init__(self, camera, size):
+               self.camera = camera
+               self.size = size
+               self.lut = np.zeros((size, size, size, 3), dtype=np.uint8)
+               self.s = 255 / (self.size-1)
+
+               print(f"""
+creating LUT...
+
+size:\t{self.size}
+scaler:\t{self.s}
+colors:\t{self.size**3}
+               """)
+
+       def process(self):
+               seq = [i * self.s for i in range(0,self.size)]
+               for r in tqdm(seq):
+                       for g in seq:
+                               for b in seq:
+                                       self.check(color=[r, g, b])
+
+               for _ in range(WAIT_TICKS):
+                       pass#self.check()
+                       #time.sleep(WAIT_TIME)
+
+               self.invert()
+
+       def invert(self):
+
+               print("inverting LUT...")
+
+               def iter_channels(a):
+                       r = self.lut[:,:,:,0]
+                       g = self.lut[:,:,:,1]
+                       b = self.lut[:,:,:,2]
+
+                       r = resample_channel(np.rot90(r, 1, (0,2)))
+                       g = resample_channel(np.rot90(g, 1, (1,2)))
+
+                       r = np.rot90(r, -1, (0,2))
+                       g = np.rot90(g, -1, (1,2))
+
+                       b = resample_channel(b)
+
+                       return np.stack((r, g, b), axis=-1)
+
+               def resample_channel(c):
+                       c = np.reshape(c, (self.size * self.size, self.size))
+
+                       for i in range(self.size * self.size):
+                               seq = np.linspace(0, 255, self.size)
+
+                               c[i] = np.interp(seq, c[i], seq)
+
+                       c = np.reshape(c, (self.size, self.size, self.size))
+                       return c
+
+               self.lut = iter_channels(self.lut)
+
+       def check(self, color=None):
+               from frame import blank, generate, result
+
+               if color is None:
+                       image = blank()
+               else:
+                       image = generate(color)
+
+               capture = self.camera.get(image)
+
+               data, new = result(capture)
+
+               if data is not None:
+                       data = np.divide(data, self.s).round().astype(np.uint8)
+
+                       self.lut[data[0], data[1], data[2]] = new
+
+
 
diff --git a/src/cube/frame.py b/src/cube/frame.py
new file mode 100644 (file)
index 0000000..d331c2e
--- /dev/null
@@ -0,0 +1,73 @@
+#!.venv/bin/python
+
+from pyzbar.pyzbar import decode
+import numpy as np
+import cv2 as cv
+import random
+import qrcode
+import os
+
+def cast(a):
+       a = np.array(a, dtype=np.float64)
+       a = ((a / 255.) ** 0.4) * 255.
+       a = np.clip(a.astype(np.uint8), 0, 255)
+
+       return a
+
+def generate(color):
+       import main
+
+       # make qr code
+       qr = qrcode.QRCode(
+               version=1,
+               error_correction=qrcode.constants.ERROR_CORRECT_L,
+               border=4,
+       )
+       qr.add_data(" ".join(["{:03d}".format(int(x)) for x in color]))
+       qr.make(fit=True)
+
+       # transform qr into array with correct shape
+       qr_image = np.array(qr.get_matrix())
+       qr_image = np.where(qr_image, 0, 255).astype(np.uint8)
+       qr_image = np.repeat(qr_image[:, :, np.newaxis], 3, axis=2)
+       qr_image = cv.resize(qr_image, (main.QR_SIZE,main.QR_SIZE), interpolation=cv.INTER_NEAREST)
+
+       color = cast(color)
+
+       # create color image of correct shape
+       c_image = np.array([[color[::-1]]], dtype=np.uint8)
+       c_image = cv.resize(c_image, (main.IMAGE_WIDTH, main.IMAGE_HEIGHT))
+
+       # put qr codes in the corners
+       tl = np.s_[:main.QR_SIZE,:main.QR_SIZE]
+       tr = np.s_[:main.QR_SIZE,-main.QR_SIZE:]
+       bl = np.s_[-main.QR_SIZE:,:main.QR_SIZE]
+       br = np.s_[-main.QR_SIZE:,-main.QR_SIZE:]
+
+       c_image[tl] = c_image[tr] = c_image[bl] = c_image[br] = qr_image
+
+       return c_image
+
+def blank():
+       import main
+
+       image = np.zeros((main.IMAGE_HEIGHT,main.IMAGE_WIDTH,3), dtype=np.uint8)
+       return image
+
+def result(capture):
+       import main
+
+       l = main.QR_SIZE + main.QR_PADDING
+
+       new = np.mean(capture[l:-l,l:-l], axis=(0,1)).astype(np.uint8)
+
+       codes = decode(capture)
+
+       if codes == []: return None, None
+
+       codes.sort(key=lambda x:x.quality)
+       data = codes[0].data
+       data = [int(x) for x in data.split()]
+       data = np.array(data)
+
+       return data, new[::-1]
diff --git a/src/cube/graph.py b/src/cube/graph.py
new file mode 100755 (executable)
index 0000000..79139f0
--- /dev/null
@@ -0,0 +1,49 @@
+#!.venv/bin/python
+
+import matplotlib.pyplot as plt
+import numpy as np
+
+def show(a):
+       size = a.shape[0]
+       fig = plt.figure(figsize=plt.figaspect(1.))
+
+       ax = fig.add_subplot(2, 1, 1)
+
+       b = a.astype(np.float64)
+
+       ax.plot(b[1,1,...,2]+50, c="blue")
+       ax.plot(b[1,...,1,1]+25, c="green")
+       ax.plot(b[...,1,1,0], c="red")
+
+       ax = fig.add_subplot(2, 1, 2, projection='3d')
+
+       xs = []
+       ys = []
+       zs = []
+       cs = []
+
+       # look im going to do this in a lazy way please forgive me
+       for x in range(size):
+               for y in range(size):
+                       for z in range(size):
+                               xs.append(x)
+                               ys.append(y)
+                               zs.append(z)
+
+                               r, g, b = a[x][y][z]
+                               cs.append("#{0:02x}{1:02x}{2:02x}".format(r, g, b))
+
+       ax.scatter(xs, ys, zs, c=cs)
+       ax.set_xlabel("r")
+       ax.set_ylabel("g")
+       ax.set_zlabel("b")
+       plt.show()
+
+def compare(a, b):
+       plt.hist(a.flat, bins=range(100), fc='k', ec='k', color="red")
+       plt.hist(b.flat, bins=range(100), fc='k', ec='k', color="blue")
+       plt.show()
+
+if __name__ == "__main__":
+       a = np.load("../../cube.npy")
+       show(a)
diff --git a/src/cube/main.py b/src/cube/main.py
new file mode 100755 (executable)
index 0000000..02dccbd
--- /dev/null
@@ -0,0 +1,32 @@
+#!.venv/bin/python
+
+import cube
+from camera import Camera
+from numpy import save
+from graph import show
+from test import validate
+
+import matplotlib.pyplot as plt
+
+LUT_SIZE = 12
+
+IMAGE_WIDTH = 640#1920
+IMAGE_HEIGHT = 360#1080
+
+QR_SIZE = 100
+QR_PADDING = 10
+
+if __name__ == "__main__":
+       eye = Camera(0)
+
+       times = []
+       means = []
+
+       lut = cube.Cube(eye, LUT_SIZE)
+       lut.process()
+       show(lut.lut)
+       validate(lut)
+
+       save("../../cube.npy", lut.lut)
+
+
diff --git a/src/cube/test.py b/src/cube/test.py
new file mode 100755 (executable)
index 0000000..f5d0834
--- /dev/null
@@ -0,0 +1,68 @@
+from frame import cast
+import cv2 as cv
+import numpy as np
+from graph import compare
+import time
+
+def validate(cube):
+       print("testing LUT...")
+
+       image = cv.imread("../calibration.jpg")
+       height, width, _ = image.shape
+       a = cast(np.flip(image, axis=-1)).astype(np.uint8)
+       casted = cast(np.flip(image, axis=-1)).astype(np.uint8)
+
+       start = time.time()
+
+       a = np.divide(a, cube.s)
+
+       c1 = np.floor(a).astype(np.uint8)
+       c2 = np.ceil(a).astype(np.uint8)
+       rem = np.remainder(a, 1)
+
+       def index_lut(a, i):
+               for ih in range(height):
+                       for iw in range(width):
+                               pos = i[ih,iw]
+                               pos = np.clip(pos, 0, a.shape[0])
+                               i[ih,iw] = a[pos[0], pos[1], pos[2]]
+
+               return i
+
+       c1 = index_lut(cube.lut, c1)
+       c2 = index_lut(cube.lut, c2)
+
+       a = c1 + np.array((c2 - c1) * rem, dtype=np.uint8)
+       a = np.flip(a, axis=-1)
+
+       dur = time.time() - start
+
+       casted = np.flip(casted, axis=-1)
+
+       # do the diff
+
+       diff = np.abs(image.sum(axis=-1, dtype=np.int16) - a.sum(axis=-1, dtype=np.int16))
+       diff = np.clip(diff, 0, 255).astype(np.uint8)
+       diff = np.stack((diff, diff, diff), axis=-1)
+
+       print(f"""
+cast mean:\t\t{np.mean(np.abs(casted - a))}
+
+max error:\t\t{diff.max()}
+mean error:\t\t{np.mean(diff)}
+standard deviation:\t{np.std(diff)}
+
+time taken:\t\t{dur}s
+          """)
+
+       # make the composite image
+
+       left = np.vstack((image, a), dtype=np.uint8)
+       right = np.vstack((casted, diff), dtype=np.uint8)
+
+       composite = np.hstack((left, right))
+
+       composite = cv.resize(composite, (640,360))
+       cv.imshow("LUT Calibration", composite)
+
+       cv.waitKey(0)
index 832355d4dd09319475faac4ca934b26b8daf4690..dc73dc2631b597811e19e261170aeb217f4905e6 100644 (file)
@@ -11,6 +11,12 @@ use std::sync::mpsc::Sender;
 use rscam::{Camera, Config};
 use image::ImageReader;
 
+use rand::Rng;
+
+mod correct;
+
+use crate::correct::Correcter;
+
 const WINDOW_SIZE: usize = 128;
 const CHUNK_SIZE: usize = 72;
 const SPECTOGRAM_AREA: usize = WINDOW_SIZE * CHUNK_SIZE;
@@ -48,6 +54,7 @@ extern "C" {
 struct ImageArray {
        data: Vec<u8>,
        homography: [f64; 9],
+       corrector: Correcter,
        camera_buffer: Vec<u8>,
        camera: Camera,
        chunks: usize
@@ -58,8 +65,9 @@ impl ImageArray {
                let mut array = Self {
                        data: vec![0u8; SPECTOGRAM_AREA * 3],
                        homography,
-                       camera_buffer: vec![0u8; IMAGE_AREA],
+                       corrector: Correcter::new("./cube.npy"),
 
+                       camera_buffer: vec![0u8; IMAGE_AREA],
                        camera: Camera::new("/dev/video2").unwrap(),
 
                        chunks: SPECTOGRAM_AREA
@@ -78,6 +86,18 @@ impl ImageArray {
                self.camera_buffer = self.camera.capture().unwrap()[..].try_into().expect("Image is wrong size");
 
                unsafe{ApplyHomography (self.camera_buffer.as_ptr() as usize, self.data.as_ptr() as usize, self.homography.as_ptr() as usize);}
+
+               for i in 0..self.camera_buffer.len()/3 {
+                       let mut r = self.camera_buffer[i*3];
+                       let mut g = self.camera_buffer[(i*3)+1];
+                       let mut b = self.camera_buffer[(i*3)+3];
+
+                       [r, g, b] = self.corrector.correct(r, g, b);
+
+                       self.camera_buffer[i*3] = r;
+                       self.camera_buffer[(i*3)+1] = g;
+                       self.camera_buffer[(i*3)+3] = b;
+               }
        }
 
        fn calibrate (&mut self) {
@@ -213,6 +233,28 @@ impl SampleBuffer {
 
 #[show_image::main]
 fn main () -> Result<(), Box<dyn std::error::Error>> {
+
+
+       let mut rng = rand::rng();
+
+       let cor = Correcter::new("./cube.npy");
+
+       let r = rng.gen_range(0..255) as u8;
+       let g = rng.gen_range(0..255) as u8;
+       let b = rng.gen_range(0..255) as u8;
+
+       println!("{}", r);
+       println!("{}", g);
+       println!("{}", b);
+
+       let c = cor.correct(r, g, b);
+
+       println!("{:?}", c);
+
+       std::process::exit(1);
+
+
+
        // pregenerate the fft transformers
        let forward_transform = Radix4::<f32>::new(WINDOW_SIZE, FftDirection::Forward);
        let inverse_transform = Radix4::<f32>::new(WINDOW_SIZE, FftDirection::Inverse);