-/target
+target/
camera.a
+cube.npy
+__pycache__/
+cargo.lock
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
-version = 3
+version = 4
[[package]]
name = "ab_glyph"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.77",
+ "syn 2.0.87",
]
[[package]]
"regex",
"rustc-hash",
"shlex",
- "syn 2.0.77",
+ "syn 2.0.87",
]
[[package]]
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"
"log",
"nix 0.25.1",
"slotmap",
- "thiserror",
+ "thiserror 1.0.63",
"vec_map",
]
"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"
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"
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"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.77",
+ "syn 2.0.87",
]
[[package]]
"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"
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]]
dependencies = [
"backtrace",
"log",
- "thiserror",
+ "thiserror 1.0.63",
"winapi",
"windows 0.44.0",
]
"com-rs",
"libc",
"libloading 0.7.4",
- "thiserror",
+ "thiserror 1.0.63",
"widestring",
"winapi",
]
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.77",
+ "syn 2.0.87",
]
[[package]]
"combine",
"jni-sys",
"log",
- "thiserror",
+ "thiserror 1.0.63",
"walkdir",
"windows-sys 0.45.0",
]
dependencies = [
"libc",
"log",
- "wasi",
+ "wasi 0.11.0+wasi-snapshot-preview1",
"windows-sys 0.48.0",
]
"rustc-hash",
"spirv",
"termcolor",
- "thiserror",
+ "thiserror 1.0.63",
"unicode-xid",
]
"ndk-sys 0.4.1+23.1.7779620",
"num_enum 0.5.11",
"raw-window-handle",
- "thiserror",
+ "thiserror 1.0.63",
]
[[package]]
"log",
"ndk-sys 0.5.0+25.2.9519653",
"num_enum 0.7.3",
- "thiserror",
+ "thiserror 1.0.63",
]
[[package]]
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"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.77",
+ "syn 2.0.87",
]
[[package]]
"proc-macro-crate",
"proc-macro2",
"quote",
- "syn 2.0.77",
+ "syn 2.0.87",
]
[[package]]
"proc-macro-crate",
"proc-macro2",
"quote",
- "syn 2.0.77",
+ "syn 2.0.87",
]
[[package]]
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"
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]]
"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"
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]]
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]]
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]]
"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",
]
"hound",
"image",
"libc",
+ "npyz",
+ "rand 0.9.2",
"rscam",
"rustfft",
"show-image",
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.77",
+ "syn 2.0.87",
]
[[package]]
"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"
[[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",
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]]
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]]
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"
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"
"once_cell",
"proc-macro2",
"quote",
- "syn 2.0.77",
+ "syn 2.0.87",
"wasm-bindgen-shared",
]
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.77",
+ "syn 2.0.87",
"wasm-bindgen-backend",
"wasm-bindgen-shared",
]
"raw-window-handle",
"rustc-hash",
"smallvec",
- "thiserror",
+ "thiserror 1.0.63",
"web-sys",
"wgpu-hal",
"wgpu-types",
"renderdoc-sys",
"rustc-hash",
"smallvec",
- "thiserror",
+ "thiserror 1.0.63",
"wasm-bindgen",
"web-sys",
"wgpu-types",
"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"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.77",
+ "syn 2.0.87",
]
[[package]]
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"
--- /dev/null
+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
+ ]
+ }
+}
--- /dev/null
+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")
#!.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
+
+
--- /dev/null
+#!.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]
--- /dev/null
+#!.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)
--- /dev/null
+#!.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)
+
+
--- /dev/null
+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)
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;
struct ImageArray {
data: Vec<u8>,
homography: [f64; 9],
+ corrector: Correcter,
camera_buffer: Vec<u8>,
camera: Camera,
chunks: usize
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
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) {
#[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);