]> OzVa Git service - rust_fft/commitdiff
Added comments to python
authorMax Value <greenwoodw50@gmail.com>
Sat, 25 Oct 2025 01:19:03 +0000 (02:19 +0100)
committerMax Value <greenwoodw50@gmail.com>
Sat, 25 Oct 2025 01:19:03 +0000 (02:19 +0100)
cube/camera.py
cube/config.py
cube/cube.py
cube/frame.py
cube/graph.py
cube/test.py
make.py

index f46caff0fb325adb56f4ca14c25dfe03b32354e6..1c26b4b9eed497e219683bd28d2037544182e044 100644 (file)
@@ -1,9 +1,8 @@
-from .config import IMAGE_WIDTH, IMAGE_HEIGHT
+from .config import IMAGE_WIDTH, IMAGE_HEIGHT, CAP_WAIT
 
 import numpy as np
 import cv2 as cv
 
-CAP_WAIT = 1
 
 class Camera():
        def __init__(self, device):
@@ -14,16 +13,24 @@ class Camera():
 
                #self.calibrate()
 
+       # get image from camera and fix perspective
        def get(self, image):
                cv.imshow("LUT Calibration", image)
                cv.waitKey(CAP_WAIT)
 
-               #_, capture = self.camera.read()
-               #capture = cv.warpPerspective(capture, self.homography, (IMAGE_WIDTH, IMAGE_HEIGHT))
+               """
+               _, capture = self.camera.read()
+               capture = cv.warpPerspective(
+                       capture,
+                       self.homography,
+                       (IMAGE_WIDTH, IMAGE_HEIGHT)
+                       )
+               """
 
                return image
                return capture
 
+       # standard calibration function
        def calibrate(self):
                calibration_image = cv.imread("../calibration.jpg")
 
index a66128ea842a4b7880b82aeab805f7c65a79a2ee..e992e6ae27f262d5bdd8ecf348cc330fb50c1a19 100644 (file)
@@ -1,7 +1,22 @@
+"""
+edge length of LUT
+
+very light testing in python outside of the real world has shown 12 to be
+optimal, conventially 33 is used. This will need to be tested with a camera.
+"""
 LUT_SIZE = 12
 
-IMAGE_WIDTH = 640#1920
-IMAGE_HEIGHT = 360#1080
+IMAGE_WIDTH = 640 #1920
+IMAGE_HEIGHT = 360 #1080
 
+# size of the qr codes and the space around them (px)
 QR_SIZE = 100
 QR_PADDING = 10
+
+# the wait time between each camera check after we stop generating
+WAIT_TIME = 0.1 #s
+# number of times to wait
+WAIT_TICKS = 100 #s
+
+# how long to wait before capturing image (1 minimum)
+CAP_WAIT = 1
index b89256aa806592869faa2570642748b6613613f5..48dad07750b81c67f826322bcfc7af1b765eab1c 100755 (executable)
@@ -1,7 +1,5 @@
-#!.venv/bin/python
-
 from .frame import blank, generate, result
-from .config import LUT_SIZE
+from .config import LUT_SIZE, WAIT_TIME, WAIT_TICKS
 
 from scipy.interpolate import make_interp_spline
 from tqdm import tqdm
@@ -9,14 +7,13 @@ import numpy as np
 import cv2 as cv
 import time
 
-WAIT_TIME = 0.1
-WAIT_TICKS = 100
-
 class Cube():
        def __init__(self, camera):
                self.camera = camera
                self.size = LUT_SIZE
                self.lut = np.zeros((LUT_SIZE, LUT_SIZE, LUT_SIZE, 3), dtype=np.uint8)
+
+               # the scaling factor of each color to turn it into a index
                self.s = 255 / (self.size-1)
 
                print(f"""
@@ -27,6 +24,7 @@ scaler:\t{self.s}
 colors:\t{self.size**3}
                """)
 
+       # go through each color and put pass it through the screen/camera
        def process(self):
                seq = [i * self.s for i in range(0,self.size)]
                for r in tqdm(seq):
@@ -40,10 +38,22 @@ colors:\t{self.size**3}
 
                self.invert()
 
+       """
+               the rust program needs to be able to index easy into the LUT, this means
+               getting the color you have, scaling it, and using it as the index. at
+               the moment we have a cube that was indexed by its inputs not by its
+               outputs. this is easy if you have a cube of 255 width but we dont.
+
+               the solution to this is to take each contour of each channel, and
+               interpolate it at the regular inteval of the size of the LUT. this means
+               that the quality of the interpolation algorithim is the quality of the
+               LUT. see below.
+       """
        def invert(self):
 
                print("inverting LUT...")
 
+               # helper function to rotate and resample each channel
                def iter_channels(a):
                        r = self.lut[:,:,:,0]
                        g = self.lut[:,:,:,1]
@@ -59,6 +69,7 @@ colors:\t{self.size**3}
 
                        return np.stack((r, g, b), axis=-1)
 
+               # helper function to resample a channel
                def resample_channel(c):
                        c = np.reshape(c, (self.size * self.size, self.size))
 
@@ -83,8 +94,14 @@ colors:\t{self.size**3}
 
                self.lut = iter_channels(self.lut)
 
+       """
+               'check' what a color looks like through the camera.  color returned may
+               not be the transformed version of the color you put in due to the lag
+               between the display and the capture. waiting a long time, clearing the
+               cap etc.. all proved ineffective. therefore all images are tagged with a
+               qr code of their color.
+       """
        def check(self, color=None):
-
                if color is None:
                        image = blank()
                else:
index 110bd20575fa2de4239d56ee503565e596420e1f..83ab87f7616366af8d1fc08bbe281cc2e108fb84 100644 (file)
@@ -1,5 +1,3 @@
-#!.venv/bin/python
-
 from .config import QR_SIZE, QR_PADDING, IMAGE_WIDTH, IMAGE_HEIGHT
 
 from pyzbar.pyzbar import decode
@@ -9,6 +7,7 @@ import random
 import qrcode
 import os
 
+# helper function to apply non-linear error to each channel of image
 def cast(a):
        a = np.array(a, dtype=np.float64)
        a[...,0] = ((a[...,0] / 255.) ** 2) * 255.
@@ -18,6 +17,7 @@ def cast(a):
 
        return a
 
+# generate image display color tagged with qr code
 def generate(color):
        # make qr code
        qr = qrcode.QRCode(
@@ -50,19 +50,26 @@ def generate(color):
 
        return c_image
 
+# make blank image
 def blank():
        image = np.zeros((IMAGE_HEIGHT,IMAGE_WIDTH,3), dtype=np.uint8)
        return image
 
+# decode captured image to origional color and new color
 def result(capture):
        l = QR_SIZE + QR_PADDING
 
+       """
+               get the mean across a rectangular section of the image described by the
+               innermost corners of all the qr codes.
+       """
        new = np.mean(capture[l:-l,l:-l], axis=(0,1)).astype(np.uint8)
 
        codes = decode(capture)
 
        if codes == []: return None, None
 
+       # always use the code which has the best quality capture
        codes.sort(key=lambda x:x.quality)
        data = codes[0].data
        data = [int(x) for x in data.split()]
index 79139f08f96b499ac194ec9c363465b8583e5595..b505aa81a2b325e553af8221afb650cf7b84c4fc 100755 (executable)
@@ -3,6 +3,7 @@
 import matplotlib.pyplot as plt
 import numpy as np
 
+# make dual plot showing the curves and the 3d plot
 def show(a):
        size = a.shape[0]
        fig = plt.figure(figsize=plt.figaspect(1.))
@@ -11,6 +12,7 @@ def show(a):
 
        b = a.astype(np.float64)
 
+       # get slice of the LUT to graph as the curves
        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")
@@ -39,6 +41,7 @@ def show(a):
        ax.set_zlabel("b")
        plt.show()
 
+# unused
 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")
index f76e0e3d283d301061f050472c7620419b0cfec4..bd4a540f9d3b884c3594dc933fc096a824f67939 100755 (executable)
@@ -5,22 +5,28 @@ import cv2 as cv
 import numpy as np
 import time
 
+# monolithic validator
 def validate(cube):
        print("testing LUT...")
 
+       # get test image and apply cast to it
        image = cv.imread("src/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)
 
+       # track the application time
        start = time.time()
 
+       # scale cube
        a = np.divide(a, cube.s)
 
+       # calculate the two points enclosing the real point as well as the remainder
        c1 = np.floor(a).astype(np.uint8)
        c2 = np.ceil(a).astype(np.uint8)
        rem = np.remainder(a, 1)
 
+       # helper function to index at location
        def index_lut(a, i):
                for ih in range(height):
                        for iw in range(width):
@@ -30,18 +36,20 @@ def validate(cube):
 
                return i
 
+       # get the real values for each of the enclosing colors
        c1 = index_lut(cube.lut, c1)
        c2 = index_lut(cube.lut, c2)
 
+       # average between the two colors weighted with the remainder
        a = c1 + np.array((c2 - c1) * rem, dtype=np.uint8)
        a = np.flip(a, axis=-1)
 
        dur = time.time() - start
 
+       # flip to bgr for display
        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)
@@ -57,7 +65,6 @@ 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)
 
diff --git a/make.py b/make.py
index 0e65896774c4c1354fbd3c87559124e88c1f2de5..531a83548ba4d2f4ac436e66e792ac9b0d2c6376 100755 (executable)
--- a/make.py
+++ b/make.py
@@ -7,13 +7,17 @@ from numpy import save
 import matplotlib.pyplot as plt
 
 if __name__ == "__main__":
+       # make camera object
        eye = Camera(0)
 
+       # make the LUT and process through the camera
        lut = Cube(eye)
        lut.process()
 
+       # use graphing func to show the curves for debug
        show(lut.lut)
 
+       # validate error of LUT
        validate(lut)
 
        save("./cube.npy", lut.lut)