diff --git a/host/config.json b/host/config.json index 565ee1f03e1a11cdf61c302b6a680c80234b165c..bd635ae82d2dcc8038f99edf5778855305314cda 100644 --- a/host/config.json +++ b/host/config.json @@ -6,7 +6,9 @@ "yes_no": "img/yes_no.png", "3": "img/3.png", "2": "img/2.png", - "1": "img/1.png" + "1": "img/1.png", + "processing": "img/processing.png", + "plotting": "img/plotting.png" }, "ports": { "solenoid": "4150325537323119", diff --git a/host/filtering.py b/host/filtering.py index 5c7ce0bdf151370b205a92e625082285e7a778ea..ae58e3b5e82c239b109b4d4078f1176db8d82341 100644 --- a/host/filtering.py +++ b/host/filtering.py @@ -26,8 +26,7 @@ def bf(img): return edges -def stroke(img): - img_copy = np.ones_like(img)*255 +def get_polylines(img, min_length=5.0, n_max=200): img2 = bf(img) img_float = img2.astype(np.float32) / 255.0 img_binary = img_float > 0.5 @@ -40,13 +39,49 @@ def stroke(img): rects = [] polys = trace_skeleton_old.traceSkeleton(im, 0, 0, im.shape[1], im.shape[0], 10, 999, rects) + polys = [np.array(x, dtype=np.float32) for x in polys] + + polys_length_keep = [] + for line in polys: + deltas = line[1:] - line[:-1] + length = np.sum(np.linalg.norm(deltas, axis=1)) + if length >= min_length: + polys_length_keep.append([line, length]) + + polys_length_keep = sorted(polys_length_keep, key=lambda x: x[1])[::-1] + polys_length_keep = polys_length_keep[:n_max] + + polys_keep = [x[0] for x in polys_length_keep] + return polys_keep + + +def draw_polylines(img, polys): for l in polys: - # c = (200 * random.random(), 200 * random.random(), 200 * random.random()) for i in range(0, len(l) - 1): - # cv2.line(img_copy, (l[i][0], l[i][1]), (l[i + 1][0], l[i + 1][1]), c) - cv2.line(img_copy, (l[i][0], l[i][1]), (l[i + 1][0], l[i + 1][1]), (0, 0, 0)) + cv2.line(img, (int(l[i][0]), int(l[i][1])), (int(l[i + 1][0]), int(l[i + 1][1])), (0, 0, 0), 2) + + +def scale_offset_polylines(polys, img_w, img_h, mm_w, offset): + scale = mm_w / img_w + + polys_new = [np.copy(x) for x in polys] - return img_copy, polys + polys_new = sorted(polys_new, key=lambda x: -x[0, 1]) + + for i in range(len(polys)): + # flip + polys_new[i][:, 1] = img_h - polys_new[i][:, 1] + # zero center + polys_new[i][:, 0] -= img_w/2 + polys_new[i][:, 1] -= img_h/2 + # scale to mm + polys_new[i][:, :] *= scale + + # offset + polys_new[i][:, 0] += offset[0] + polys_new[i][:, 1] += offset[1] + + return polys_new if __name__ == "__main__": @@ -59,10 +94,30 @@ if __name__ == "__main__": # plt.plot(cnt[:, 0], cnt[:, 1]) # plt.show() # # print(contours[0]) - img = cv2.imread("test.png", cv2.IMREAD_UNCHANGED) + img = cv2.imread("test/test.png", cv2.IMREAD_UNCHANGED) img = img[:, :, :3] + h, w, _ = img.shape # img_copy = np.copy(cv2.cvtColor(img, cv2.COLOR_BGR2GRAY))*0 - img_stroke, polys = stroke(img) + polys = get_polylines(img) + img_draw = 255*np.ones((h, w, 3), dtype=np.uint8) + draw_polylines(img_draw, polys) + + lines = scale_offset_polylines(polys, w, h, 100, (130, 118)) + + import matplotlib.pyplot as plt + + plt.figure() + plt.imshow(img_draw) + + plt.figure() + for xy in lines: + plt.plot(xy[:, 0], xy[:, 1]) + plt.axis("equal") + plt.show() + + # import pickle + # with open("test/polys.obj", "wb") as f: + # pickle.dump(polys, f) - cv2.imshow("test", img_stroke) - cv2.waitKey(0) + # cv2.imshow("test", img_stroke) + # cv2.waitKey(0) diff --git a/host/img/plotting.png b/host/img/plotting.png new file mode 100644 index 0000000000000000000000000000000000000000..5583954622eb3ca7568c7dd379a9add5f29aea5a Binary files /dev/null and b/host/img/plotting.png differ diff --git a/host/img/processing.png b/host/img/processing.png new file mode 100644 index 0000000000000000000000000000000000000000..cc633c34cfda44a3f52f8e322be2c96e1d8d944f Binary files /dev/null and b/host/img/processing.png differ diff --git a/host/machine.py b/host/machine.py index b39c3d0e0922c6ad59d1c60dd2aa7b654c79c49f..63ca139444ddab7ffddc95967cbcc51c62b096a1 100644 --- a/host/machine.py +++ b/host/machine.py @@ -9,7 +9,7 @@ home_rate = 60 home_accel = 2000 home_backoff_time = 0.2 -go_rate = 150 +go_rate = 180 go_accel = 2000 use_current = 0.4 @@ -35,25 +35,6 @@ class Machine: self.x_top_motor.set_current(use_current) def home(self): - # home Y .... - # if we're on the switch, backoff: - if self.y_motor.get_states()['limit'] > 0: - self.y_motor.set_target_velocity(home_rate, home_accel) - time.sleep(home_backoff_time) - self.y_motor.set_target_velocity(0, home_accel) - time.sleep(home_backoff_time) - - # let's home it, - self.y_motor.set_target_velocity(-home_rate, home_accel) - - # then check-wait on states, - while True: - states = self.y_motor.get_states() - if states['limit'] > 0: - break - - self.y_motor.set_target_velocity(0, home_accel) - # home X ... if self.x_bottom_motor.get_states()['limit'] > 0: self.x_bottom_motor.set_target_velocity(home_rate, home_accel) @@ -75,6 +56,25 @@ class Machine: self.x_top_motor.set_target_velocity(0, home_accel) time.sleep(home_backoff_time) + # home Y .... + # if we're on the switch, backoff: + if self.y_motor.get_states()['limit'] > 0: + self.y_motor.set_target_velocity(home_rate, home_accel) + time.sleep(home_backoff_time) + self.y_motor.set_target_velocity(0, home_accel) + time.sleep(home_backoff_time) + + # let's home it, + self.y_motor.set_target_velocity(-home_rate, home_accel) + + # then check-wait on states, + while True: + states = self.y_motor.get_states() + if states['limit'] > 0: + break + + self.y_motor.set_target_velocity(0, home_accel) + # set zeroes, self.x_bottom_motor.set_position(0) self.x_top_motor.set_position(0) @@ -128,15 +128,34 @@ if __name__ == "__main__": m.goto(0, origin[1]) m.goto(origin[0], origin[1]) - w = 25 - h = 25 + # w = 35 + # h = 35 + # + # m.goto(origin[0]+w, origin[1]+h) + # m.pen_action(2, True) + # m.goto(origin[0]-w, origin[1]+h) + # m.goto(origin[0]-w, origin[1]-h) + # m.goto(origin[0]+w, origin[1]-h) + # m.goto(origin[0]+w, origin[1]+h) + # m.pen_action(2, False) + # m.goto(0, origin[1]) + # m.goto(0, 0) + + import pickle + + with open("test/polys_np_keep.obj", "rb") as f: + data = pickle.load(f) + + for line, _ in data: + m.goto(line[0, 0], line[0, 1]) + m.pen_action(2, True) + m.goto_list(line[:, 0], line[:, 1]) + m.pen_action(2, False) + # for x, y in line: + # print(x, y) - m.goto(origin[0]+w, origin[1]+h) - m.pen_action(2, True) - m.goto(origin[0]-w, origin[1]+h) - m.goto(origin[0]-w, origin[1]-h) - m.goto(origin[0]+w, origin[1]-h) - m.goto(origin[0]+w, origin[1]+h) - m.pen_action(2, False) + m.goto(origin[0], origin[1]) m.goto(0, origin[1]) m.goto(0, 0) + + # print(data) diff --git a/host/main.py b/host/main.py index 757d68719395764120855f7a8f809d7b78a459ff..f408f2a1df9fbd93111deea19735fc48dd3f81b1 100644 --- a/host/main.py +++ b/host/main.py @@ -5,6 +5,7 @@ import json import time import datetime import filtering +import machine STATE_INIT = 0 STATE_STREAM = 1 @@ -30,6 +31,8 @@ class MainApplication: self.rotate = rotate self.t_state = 0 self.dt_state = 0 + self.strokes = None + self.machine = None cv2.imshow("main", self.img) cv2.setMouseCallback("main", self.on_click) @@ -97,11 +100,46 @@ class MainApplication: else: self.state = STATE_STREAM elif self.state == STATE_VECTORIZED: - img_strokes, strokes = filtering.stroke(self.img_captured) - - self.img = img_strokes - self.state = STATE_DRAWING - # self.running = False + if self.dt_state < 0.5: + self.img = np.zeros((self.height, self.width, 3), dtype=np.uint8) + overlay = "processing" + else: + if self.strokes is None: + polys = filtering.get_polylines(self.img_captured) + img_draw = 255 * np.ones((self.height, self.width, 3), dtype=np.uint8) + filtering.draw_polylines(img_draw, polys) + self.strokes = filtering.scale_offset_polylines(polys, + self.width, + self.height, + 100, + machine.origin) + self.img = np.copy(img_draw) + overlay = "yes_no" + if self.click is not None: + x, y = self.click + self.click = None + if x < self.width // 2: + self.state = STATE_DRAWING + else: + self.state = STATE_STREAM + elif self.state == STATE_DRAWING: + if self.dt_state < 0.5: + self.img = np.zeros((self.height, self.width, 3), np.uint8) + overlay = "plotting" + else: + if self.strokes is not None and self.machine is not None: + self.machine.goto(0, machine.origin[1]) + self.machine.goto(machine.origin[0], machine.origin[1]) + for line in self.strokes: + self.machine.goto(line[0, 0], line[0, 1]) + self.machine.pen_action(2, True) + self.machine.goto_list(line[:, 0], line[:, 1]) + self.machine.pen_action(2, False) + self.machine.goto(machine.origin[0], machine.origin[1]) + self.machine.goto(0, machine.origin[1]) + self.machine.goto(0, 0) + self.strokes = None + self.state = STATE_STREAM self.show(overlay=overlay) if self.state != previous_state: @@ -131,7 +169,12 @@ class MainApplication: def main(): with open("config.json", "r") as f: config = json.load(f) + + m = machine.Machine(config["ports"]) + m.pen_action(2, False) + m.home() app = MainApplication(fullscreen=config["fullscreen"], rotate=config["rotate"]) + app.machine = m app.load_overlays(config["overlays"]) app.run() app.video.release() @@ -140,3 +183,4 @@ def main(): if __name__ == "__main__": main() ++ \ No newline at end of file diff --git a/host/test/polys.obj b/host/test/polys.obj new file mode 100644 index 0000000000000000000000000000000000000000..6071ce638da07f83ad167efc0b4be66b6b8ddbcc Binary files /dev/null and b/host/test/polys.obj differ diff --git a/host/test/polys_np_keep.obj b/host/test/polys_np_keep.obj new file mode 100644 index 0000000000000000000000000000000000000000..5b96882813f09081c65cfe2ec4e9b5378595c84f Binary files /dev/null and b/host/test/polys_np_keep.obj differ diff --git a/host/test.png b/host/test/test.png similarity index 100% rename from host/test.png rename to host/test/test.png diff --git a/host/test/test_prune.py b/host/test/test_prune.py new file mode 100644 index 0000000000000000000000000000000000000000..2be1e607b1a3c01c99c2d72ef5a71ae30a9fb68d --- /dev/null +++ b/host/test/test_prune.py @@ -0,0 +1,104 @@ +import pickle +import cv2 +import numpy as np +import matplotlib.pyplot as plt + + +def process_polylines(polylines, img_w, img_h, mm_w, offset): + polys_np_keep = [] + for line in polylines: + deltas = line[1:] - line[:-1] + length = np.sum(np.linalg.norm(deltas, axis=1)) + if length > 5.0: + polys_np_keep.append([line, length]) + + polys_np_keep = sorted(polys_np_keep, key=lambda x : x[1])[::-1] + + n_max = 200 + + scale = mm_w / img_w + + polys_np_keep = polys_np_keep[:n_max] + + for i in range(len(polys_np_keep)): + # flip + polys_np_keep[i][0][:, 1] = img_h - polys_np_keep[i][0][:, 1] + # zero center + polys_np_keep[i][0][:, 0] -= img_w/2 + polys_np_keep[i][0][:, 1] -= img_h/2 + # scale to mm + polys_np_keep[i][0][:, :] *= scale + polys_np_keep[i][1] *= scale + + # offset + polys_np_keep[i][0][:, 0] += offset[0] + polys_np_keep[i][0][:, 1] += offset[1] + + return polys_np_keep + +""" +def main(): + with open("polys.obj", "rb") as f: + polys = pickle.load(f) + + img = cv2.imread("test.png", cv2.IMREAD_UNCHANGED) + polys_np = [np.array(x, dtype=np.float32) for x in polys] + print(polys_np[0].shape) + polys_np_keep = [] + # lengths = [] + for line in polys_np: + deltas = line[1:] - line[:-1] + length = np.sum(np.linalg.norm(deltas, axis=1)) + if length > 5.0: + polys_np_keep.append([line, length]) + + polys_np_keep = sorted(polys_np_keep, key=lambda x : x[1])[::-1] + + n_max = 200 + + polys_np_keep = polys_np_keep[:n_max] + + h, w, _ = img.shape + # for line in + + print(w, h) + + # mm per px + scale = 100 / w + offset = (130, 118) + # offset = (0, 0) + + for i in range(len(polys_np_keep)): + # flip + polys_np_keep[i][0][:, 1] = h - polys_np_keep[i][0][:, 1] + # zero center + polys_np_keep[i][0][:, 0] -= w/2 + polys_np_keep[i][0][:, 1] -= h/2 + # scale to mm + polys_np_keep[i][0][:, :] *= scale + polys_np_keep[i][1] *= scale + + # offset + polys_np_keep[i][0][:, 0] += offset[0] + polys_np_keep[i][0][:, 1] += offset[1] + + # for line, length in polys_np_keep: + # plt.plot(line[:, 0], -line[:, 1]) + # + # # print(polys_np_keep[:50]) + plt.figure() + for line, _ in polys_np_keep: + plt.plot(line[:, 0], line[:, 1]) + # plt.hist(lengths, bins=np.linspace(0, 160, 64)) + plt.axis("equal") + plt.show() + + polys_np_keep = sorted(polys_np_keep, key=lambda x: x[0][0, 1]) + + with open("polys_np_keep.obj", "wb") as f: + pickle.dump(polys_np_keep, f) +""" + + +# if __name__ == "__main__": +# main()