diff --git a/aruco_tags.json b/aruco_tags.json new file mode 100644 index 0000000000000000000000000000000000000000..d83d93e96459e7286ab610a4c7b2607195fba63e --- /dev/null +++ b/aruco_tags.json @@ -0,0 +1 @@ +{"arucos": []} \ No newline at end of file diff --git a/demo.py b/demo.py index ff3e7cd96eb7ec47769091ab25295062fac0c1f7..0829b33e888570b123f05714cbb50fae7c47afc3 100644 --- a/demo.py +++ b/demo.py @@ -1,5 +1,5 @@ -# from ar_sandbox import Sandbox -# from ar_sandbox.wrapper import sandbox_wrapper as sw +import falcon +from ar_sandbox import Sandbox import sys import cv2 import numpy as np @@ -9,17 +9,15 @@ from PIL import Image import requests import time import math - +import json NORMALIZATION_BETWEEN = (0.8, 1.2) LO_NORM = NORMALIZATION_BETWEEN[0] HI_NORM = NORMALIZATION_BETWEEN[1] - SHOW_LINES = True USE_HARD_COLORS = False LINE_COLORS = [255, 255, 255] - COLORS_FULL_SPECTRUM_SOFT = [ (0.2, (0, 0, 255)), (.25, (0, 255, 255)), @@ -66,7 +64,6 @@ COLOR_B_HARD = [c[1][2] for c in COLORS_FULL_SPECTRUM_HARD] COLORMAP = None COLORMAP_HARD = None -DEFAULT_URL = "http://localhost:8000" def try_and_ignore(ignore=Exception, default_value=0.0): @@ -87,6 +84,9 @@ def try_and_ignore(ignore=Exception, default_value=0.0): parse_int = try_and_ignore(ValueError, 0)(int) parse_float = try_and_ignore(ValueError, 0.0)(float) +api_content_esri = "" +api_content_aruco = "" + class FakeSandbox: """Placeholder for testing purposes""" @@ -100,19 +100,16 @@ class FakeSandbox: def start(self, *args): cap = cv2.VideoCapture(0) while cap.isOpened(): - # im = Image.open("test_aru.png") ret, fr = cap.read() frame = cv2.resize(fr, (588, 432)) mat = np.loadtxt("depth") - # mat = cv2.cvtColor(fr, cv2.COLOR_BGR2GRAY) mat2 = frame if self.on_frame is not None: frame = self.on_frame(mat, mat2) cv2.imshow("frame", frame) - # time.sleep(self.refresh // 1000) k = cv2.waitKey(self.refresh) if k == 27: break @@ -131,16 +128,7 @@ def get_color(depth, hard_colors=False) -> np.ndarray: A 3 channel BGR matrix of the same size as depth_matrix. """ depth_matrix = depth.copy() - # if hard_colors: - # pts = POINTS_HARD - # r = COLOR_R_HARD - # g = COLOR_G_HARD - # b = COLOR_B_HARD - # else: - # pts = POINTS - # r = COLOR_R - # g = COLOR_G - # b = COLOR_B + if hard_colors: pts = COLORMAP_HARD[0] r = COLORMAP_HARD[1] @@ -153,11 +141,8 @@ def get_color(depth, hard_colors=False) -> np.ndarray: b = COLORMAP[3] r_val = np.interp(depth_matrix, pts, r) - # print(r_val) g_val = np.interp(depth_matrix, pts, g) - # print(g_val) b_val = np.interp(depth_matrix, pts, b) - # print(b_val) res = np.dstack((b_val, g_val, r_val)).astype(np.uint8) return res @@ -178,6 +163,7 @@ def send_request(body, url="http://localhost:8000/map"): print(e) +# This is the older method that was used to transmit arucos over the network def build_req_body(map, tag_list): arucos = [] for t in tag_list: @@ -201,6 +187,29 @@ def build_req_body(map, tag_list): return body +# This new method is basically a copy pasted version of the one above without the map +# Maybe both of them are not needed anymore +def build_arucos_json(tag_list): + arucos = [] + for t in tag_list: + print(t) + (x, y), id, r = t + (x, y) = (parse_int(x), parse_int(y)) + id = parse_int(id) + r = parse_float(r) + arucos.append({ + "tag_id": id, + "position": { + "x": x, + "y": y + }, + "rotation": r + }) + body = { + "arucos": arucos + } + return body + def normalize_array(array): return (array - array.min())/(array.max() - array.min()) @@ -216,6 +225,7 @@ def normalize_array_between(array, lower_bound, higher_bound): def make_esri_and_send(depth, color, *args): + global api_content_esri, api_content_aruco if COLORMAP is None or COLORMAP_HARD is None: gen_global_default_cmaps() # Normalization step @@ -241,16 +251,30 @@ def make_esri_and_send(depth, color, *args): # Aruco detection grayscale_frame = cv2.cvtColor(color, cv2.COLOR_BGR2GRAY) - _, (corn, ids, rej), centers, rots = detect_aruco(grayscale_frame) + + _, (corn, ids, rej), centers, rots = detect_aruco(grayscale_frame) #TODO # Create map and tag dictionary esri_map = EsriAscii.from_ndarray(depth) - detected = build_tag_list(ids, centers, rots) + detected = build_tag_list(ids, centers, rots) #TODO # Send it toward api - send_request(build_req_body(esri_map, detected), url=DEFAULT_URL) - # May locally save the esri_map - # esri_map.to_file("depth_map_v2.asc") + #send_request(build_req_body(esri_map, detected), url=DEFAULT_URL) + #TODO + #send_request(build_req_body(esri_map, detected), url=dest) + #send_request(build_req_body(esri_map, []), url=dest) + #send_request(build_req_body(esri_map, detected), url=DEFAULT_URL2) + + + # May locally save the esri_map & arucos + # esri_map.to_file("depth_map.asc") + api_content_esri = esri_map.to_ascii() + api_content_aruco = build_arucos_json(detected) + # tags = build_arucos_json(detected) + + # with open("aruco_tags.json", "w") as fp: + # json.dump(tags, fp) + # Return value will be displayed on the beamer return levels @@ -266,12 +290,17 @@ def get_center(corner): c0, _, c2, _ = corner[0] return int(c0[0] + (c2[0]-c0[0]) // 2), int(c0[1] + (c2[1]-c0[1]) // 2) +# TODO def detect_aruco(a, b=None, c=None): return def detect_aruco(frame, - aruco_dict=cv2.aruco.Dictionary_get(cv2.aruco.DICT_4X4_50), - aruco_params=cv2.aruco.DetectorParameters_create()): - output = frame.copy() - (corners, ids, rejected) = cv2.aruco.detectMarkers(frame, aruco_dict, parameters=aruco_params) + aruco_dict=cv2.aruco.getPredefinedDictionary(cv2.aruco.DICT_4X4_50), + aruco_params=cv2.aruco.DetectorParameters()): + # output = frame.copy() + + #(corners, ids, rejected) = cv2.aruco.detectMarkers(frame, aruco_dict, parameters=aruco_params) + detector = cv2.aruco.ArucoDetector(aruco_dict, aruco_params) + (corners, ids, rejected) = detector.detectMarkers(frame) + centers = [] rotations = [] for c in range(len(corners)): @@ -279,14 +308,13 @@ def detect_aruco(frame, ctr = get_center(corners[c]) top_left = corners[c][0][0] centers.append(get_center(corners[c])) - # print("Corner is", corners[c], "Center is", get_center(corners[c])) (w1, w2) = [-1, -1] (v1, v2) = top_left - ctr rotation_in_degree = math.degrees(math.atan2(w2 * v1 - w1 * v2, w1 * v1 + w2 * v2)) rotations.append(round(rotation_in_degree, 2)) except Exception as e: print(e) - return output, (corners, ids, rejected), centers, rotations + return None, (corners, ids, rejected), centers, rotations def save_matrices(depth, frame, *args): @@ -335,18 +363,18 @@ def rgb_to_hex(rgb): return '#%02x%02x%02x' % rgb -if __name__ == "__main__": - import argparse - parser = argparse.ArgumentParser() - parser.add_argument("-c", "--colors", default="") - parser.add_argument("-u", "--url", default=DEFAULT_URL) - parser.add_argument("-l", "--lines", action="store_true") - parser.add_argument("-H", "--hard", action="store_true") - arguments = parser.parse_args() +class ApiEsri: + def on_get(self, req, resp): + resp.media = api_content_esri + +class ApiAruco: + def on_get(self, req, resp): + # resp.media = json.dumps(api_content_aruco) + resp.media = api_content_aruco + - print(arguments) - DEFAULT_URL = arguments.url if arguments.url.startswith("http://") else "http://" + arguments.url - arg_colors = arguments.colors +def main(): + arg_colors = "" if arg_colors != "": colours = [] cols = arg_colors.split(",") @@ -361,22 +389,38 @@ if __name__ == "__main__": COLORMAP_HARD = create_colormap(create_hard_colors(cmap)) SHOW_LINES = False - if arguments.lines: - SHOW_LINES = True - USE_HARD_COLORS = False - if arguments.hard: - USE_HARD_COLORS = True # colours = [(.2, (0,0,128)), (.25, (68, 87, 227)), (.3, (236, 255, 89)),(.4, (67, 138, 65)),(.6, (128,128,128)), (.8, (255, 255, 255))] # colours = [(.2, (128,0,0)),(.3, (255,0,0)),(.4, (255,255,255)), (.5, (0,0,255)), (.6,(0, 0, 128))] # COLORMAP = create_colormap(color_array=colours) # COLORMAP_HARD = create_colormap(create_hard_colors(colours)) - # USE_HARD_COLORS=True - LINE_COLORS = [0,0,0] - box = FakeSandbox(refresh=1000) + box = Sandbox(refresh=1000) + box.verbosity = 5 box.init() box.on_frame = make_esri_and_send box.start(box) + +# ---- MAIN ---- + +from wsgiref.simple_server import make_server +from threading import Thread + +app = falcon.App() +app.add_route('/sandbox', ApiEsri()) +app.add_route('/aruco', ApiAruco()) + +class ApiThread(Thread): + def run(self): + print("run") + with make_server('', 8000, app) as httpd: + print('Serving on port 8000...') + + # Serve until process is killed + httpd.serve_forever() + + +ApiThread().start() +main() diff --git a/env.sh b/env.sh index c58ef142030d2ead41f1f46f3b9cda323b7fc5c9..5cef6089bc5515a761151f95691a7fb24c690ae0 100644 --- a/env.sh +++ b/env.sh @@ -1 +1,2 @@ -export LD_LIBRARY_PATH=/home/alexis/sandbox/sandbox_docker-builder/build/lib/ +#export LD_LIBRARY_PATH=/home/alexis/sandbox/sandbox_docker-builder/build/lib/ +export LD_LIBRARY_PATH=/home/sandbox/Documents/ar_sandbox_lib/build diff --git a/sandbox_conf.yaml b/sandbox_conf.yaml index 9fa6ebd2d61e28205719b28168e50d0078888247..a59661043208415b2ddfe2ac04d13cd7c0494fa2 100644 --- a/sandbox_conf.yaml +++ b/sandbox_conf.yaml @@ -1,27 +1,35 @@ AdjustingMatrix: - angle: 1.4119340386036046 + #angle: 0.5119340386036046 + angle: 0.5 width: 3 height: 2 - matrix: [0.999696374, 0.0246404037, 0, -0.0246404037, 0.999696374, 0] + matrix: [1.0, 0, 50, -0, 1, 70] + #matrix: [1.0, 0, 50, -0, 1, 50] + # [?, rotation, ?, ?, ?, ?] + #angle: 0 + #width: 3 + #height: 2 + #matrix: [1, 0, 0, -0, 1, 0] DistanceTopSandbox: - distance: 1 + distance: 1.11300004 CroppingMask: x: 52 y: 19 - width: 588 # 568 - height: 432 + width: 588 + height: 437 BeamerResolution: - width: 1400 - height: 1050 + width: 1280 + height: 1024 BeamerPosition: - x: 0.0536931753 - y: 0.260815978 - z: -0.325273067 + x: -0.0419691354 + #x: -0.0419691354 + y: 0.238534391 + z: -0.126809254 FrameProcessProfil: - contrast: 1.0900000000000001 - brightness: 14 - minDistance: 15 - cannyEdgeThreshold: 184 - houghAccThreshold: 35 - minRadius: 0 - maxRadius: 0 + contrast: 1.1200000000000001 + brightness: -148 + minDistance: 100 + cannyEdgeThreshold: 86 + houghAccThreshold: 44 + minRadius: 2 + maxRadius: 14 diff --git a/sandbox_conf_backup.yaml b/sandbox_conf_backup.yaml new file mode 100644 index 0000000000000000000000000000000000000000..4a32850888b9e5c1bd6451e6af0b746fc86de00d --- /dev/null +++ b/sandbox_conf_backup.yaml @@ -0,0 +1,27 @@ +AdjustingMatrix: + angle: 1.4119340386036046 + width: 3 + height: 2 + matrix: [0.999696374, 0.0246404037, 0, -0.0246404037, 0.999696374, 0] +DistanceTopSandbox: + distance: 1 +CroppingMask: + x: 52 + y: 19 + width: 588 # 568 + height: 432 +BeamerResolution: + width: 1280 + height: 1024 +BeamerPosition: + x: 0.0536931753 + y: 0.260815978 + z: -0.325273067 +FrameProcessProfil: + contrast: 1.0900000000000001 + brightness: 14 + minDistance: 15 + cannyEdgeThreshold: 184 + houghAccThreshold: 35 + minRadius: 0 + maxRadius: 0