import cv2 as cv
import numpy as np
import queue
+import time
import threading
import random
+import matplotlib.pyplot as plt
class VideoCapture:
def __init__(self, device_id, backend):
self.camera = cv.VideoCapture(device_id, backend)
+ self.camera.set(cv.CAP_PROP_BUFFERSIZE, 1)
self.camera.set(cv.CAP_PROP_FRAME_WIDTH, 1920.0)
self.camera.set(cv.CAP_PROP_FRAME_HEIGHT, 1080.0)
device_id: int = 0,
debug: bool = True,
dummy: bool = False,
+ use_lookup: bool = False,
use_files: bool = False
):
self.match_histograms = False
self.show_debug = debug
self.dummy = dummy
+ self.use_lookup = use_lookup
+ self.use_files = use_files
- self.camera = VideoCapture(device_id, cv.CAP_V4L)
+ self.camera = cv.VideoCapture(device_id, cv.CAP_V4L)
- self.camera.set(cv.CAP_PROP_BUFFERSIZE, 38)
+ self.camera.set(cv.CAP_PROP_FPS, 30)
+ self.camera.set(cv.CAP_PROP_BUFFERSIZE, 1)
self.camera.set(cv.CAP_PROP_FRAME_WIDTH, 1920.0)
self.camera.set(cv.CAP_PROP_FRAME_HEIGHT, 1080.0)
self.homography = None
- self.lookup_color = None
- self.lookup_vingette = None
- self.lookup_compression = None
+ self.lookup = None
+ self.lookup_compression = 100
self.last_display = None
self.last_capture = None
self.last_recovered = None
else:
print("calibration failed")
+ quit()
+
+ if self.use_file == True:
+ self.get_lookup()
def get_lookup(
self
) -> None:
- if self.dummy == True:
- pass #return
-
- vingette_compression = 50
-
- self.lookup_vingette = np.zeros((
- 255 // vingette_compression + 1,
- self.display_size[0] // vingette_compression + 1,
- self.display_size[1] // vingette_compression + 1
- ), dtype=np.uint8)
-
- for v in range(0, 255, vingette_compression):
- pixel = np.array([[[0, 0, v]]], dtype=np.uint8)
- pixel = cv.cvtColor(pixel, cv.COLOR_HSV2BGR)
-
- self.display(pixel)
- #capture = self.capture()
- #capture = cv.cvtColor(capture, cv.COLOR_BGR2HSV)
-
- # apply vingette overlay
- capture = cv.resize(pixel, self.display_size, interpolation=cv.INTER_NEAREST_EXACT)
-
- rows = len(capture)
- columns = len(capture[0])
- for y, row in enumerate(capture):
- for x, pixel in enumerate(row):
- y -= rows // 2
- x -= columns // 2
- math_pixel = pixel.astype(np.int16)
- if x > y:
- math_pixel += round(y * 0.0043)
- else:
- math_pixel += round(x * 0.0043)
-
- pixel = np.clip(math_pixel, 0, 255).astype(np.uint8)
-
-
- for y in range(0, self.display_size[0], vingette_compression):
- for x in range(0, self.display_size[1], vingette_compression):
- self.lookup_vingette[v // vingette_compression, y // vingette_compression, x // vingette_compression] = capture[y, x, 2] - v
-
- color_compression = 90
+ if self.use_lookup == True:
+ return
- self.lookup_color = np.zeros((
- 180 // color_compression + 1,
- 255 // color_compression + 1,
- 255 // color_compression + 1,
- 3
- ), dtype=np.uint8)
+ if self.use_files == True:
+ self.lookup = np.load("lookup.npy")
+ return
- for h in range(0, 180, color_compression):
- for s in range(0, 255, color_compression):
- for v in range(0, 255, color_compression):
- pixel = np.array([[[h, s, v]]], dtype=np.uint8)
- pixel = cv.cvtColor(pixel, cv.COLOR_HSV2BGR)
+ lookup = None
+ for r in range(0, 255, self.lookup_compression):
+ for g in range(0, 255, self.lookup_compression):
+ for b in range(0, 255, self.lookup_compression):
+ pixel = np.array([[[b, g, r]]], dtype=np.int8)
+ pixel = cv.resize(pixel, self.display_size, interpolation=cv.INTER_NEAREST_EXACT)
self.display(pixel)
- #capture = self.capture()
- #capture = cv.cvtColor(capture, cv.COLOR_BGR2HSV)
-
- # apply the color ovelay
- pixel = np.sin(pixel / (127.5 / np.pi)) * 2
- pixel = np.clip(pixel, 0, 255)
- capture = cv.resize(pixel, self.display_size, interpolation=cv.INTER_NEAREST_EXACT)
-
- cx = self.display_size[1] // 2
- cy = self.display_size[0] // 2
- sample_diameter = 5
- color = np.average(capture[cy - sample_diameter:cy + sample_diameter, cx - sample_diameter:cx + sample_diameter], axis=(0,1))
-
- self.lookup_color[h // color_compression, s // color_compression, v // color_compression, 0:2] = color - [h, s, v]
-
- np.save("lookup_vingette", self.lookup_vingette)
- np.save("lookup_color", self.lookup_color)
- def apply_lookup(
- self,
- image: np.ndarray
- ) -> np.ndarray:
- # must be given an array in the HSV color space
+ for i in range(10): # silly hack
+ time.sleep(0.2)
+ recovered = self.capture()
- # apply the vingentte and color lookup table
- for y, row in enumerate(image):
- for x, pixel in enumerate(row):
- pixel[2] += self.lookup_vingette[pixel[2] // self.lookup_compression][y // self.lookup_compression][x // self.lookup_compression]
- pixel = self.lookup_color[pixel[0] // self.lookup_compression][pixel[1] // self.lookup_compression][pixel[2] // self.lookup_compression]
+ error = np.copy(recovered.astype(np.int16))
+ error[..., 0] -= b
+ error[..., 1] -= g
+ error[..., 2] -= r
- return image
-
- def lookup_debug(
- self,
- tests: int
- ) -> np.ndarray:
+ error = np.clip(error, -50, 255)
- error_array = None
-
- # begin loop over the desired sample size
- for i in range(tests):
- pixel = [[[random.randint(0,255), random.randint(0,255), random.randint(0,255)]]]
-
- # apply the color ovelay
- pixel = np.sin(pixel / (127.5 / np.pi)) * 2
- pixel = np.clip(pixel, 0, 255)
-
- capture = cv.resize(pixel, self.display_size, interpolation=cv.INTER_NEAREST_EXACT)
- rows = len(capture)
- columns = len(capture[0])
- for y, row in enumerate(capture):
- for x, pixel in enumerate(y):
- y -= rows
- x -= columns
- distance = np.sqrt((x ^ 2) + (y ^ 2)) * 0.02
- pixel += distance
- capture = np.clip(capture, 0, 255)
-
- returned = self.apply_lookup(capture)
- self.display(returned)
-
- if error_array is None:
- error_array = error
- error_array = (error_array + error) / 2
+ if lookup is None:
+ lookup = error
+ else:
+ lookup += error
+ lookup = lookup // 2
- error_array = cv.cvtColor(error_array, cv.COLOR_BGR2HSV)
- cv.imwrite("error_array.png", error_array)
+ self.lookup = lookup
+ np.save("lookup.npy", lookup)
def display(
self,
image = cv.warpPerspective(image, self.homography, self.display_size)
image = cv.resize(image, (self.window_size, self.window_height))
- if self.lookup_vingette is not None and self.lookup_color is not None:
- pass
+ if type(self.lookup) == np.ndarray and self.use_lookup == True:
+ image = np.clip(image + self.lookup, 0, 255).astype(np.uint8)
self.last_recovered = image