Final commit
|
After Width: | Height: | Size: 84 KiB |
|
After Width: | Height: | Size: 30 KiB |
|
After Width: | Height: | Size: 271 KiB |
|
After Width: | Height: | Size: 362 KiB |
|
After Width: | Height: | Size: 189 KiB |
|
After Width: | Height: | Size: 3.5 KiB |
BIN
assets/sins.jpg
|
Before Width: | Height: | Size: 100 KiB |
|
|
@ -0,0 +1,266 @@
|
|||
import cv2
|
||||
import tkinter as tk
|
||||
import mediapipe as mp
|
||||
import numpy as np
|
||||
import os
|
||||
import math
|
||||
from rembg import remove
|
||||
from PIL import Image
|
||||
|
||||
import dobot
|
||||
import vector_draw
|
||||
|
||||
# Load images with transparency
|
||||
mario_hat_image_path = "Filters/MArio.png"
|
||||
sunglasses_image_path = "Filters/glasses.png"
|
||||
moustache_image_path = "Filters/MoustacheMario.png"
|
||||
|
||||
# Load images
|
||||
mario_hat = cv2.imread(mario_hat_image_path, cv2.IMREAD_UNCHANGED)
|
||||
sunglasses = cv2.imread(sunglasses_image_path, cv2.IMREAD_UNCHANGED)
|
||||
moustache = cv2.imread(moustache_image_path, cv2.IMREAD_UNCHANGED)
|
||||
|
||||
# Check if images were loaded correctly
|
||||
if mario_hat is None:
|
||||
print("Error: Mario hat image not found.")
|
||||
exit()
|
||||
if sunglasses is None:
|
||||
print("Error: Sunglasses image not found.")
|
||||
exit()
|
||||
if moustache is None:
|
||||
print("Error: Moustache image not found.")
|
||||
exit()
|
||||
|
||||
# Initialize MediaPipe FaceMesh
|
||||
mp_face_mesh = mp.solutions.face_mesh
|
||||
face_mesh = mp_face_mesh.FaceMesh(min_detection_confidence=0.5, min_tracking_confidence=0.5)
|
||||
|
||||
# Variables for toggling filters
|
||||
mario_hat_active = False
|
||||
sunglasses_active = False
|
||||
moustache_active = False
|
||||
show_angles = False
|
||||
|
||||
# Open webcam for capturing live feed
|
||||
cap = cv2.VideoCapture(0)
|
||||
if not cap.isOpened():
|
||||
print("Error: The webcam cannot be opened")
|
||||
exit()
|
||||
|
||||
# Variable to hold the contour frame
|
||||
contour_frame = None
|
||||
resized_edges = None
|
||||
|
||||
def calculate_angles(landmarks):
|
||||
left_eye = np.array(landmarks[33])
|
||||
right_eye = np.array(landmarks[263])
|
||||
nose_tip = np.array(landmarks[1])
|
||||
chin = np.array(landmarks[152])
|
||||
yaw = math.degrees(math.atan2(right_eye[1] - left_eye[1], right_eye[0] - left_eye[0]))
|
||||
pitch = math.degrees(math.atan2(chin[1] - nose_tip[1], chin[0] - nose_tip[0]))
|
||||
return yaw, pitch
|
||||
|
||||
def apply_mario_hat(frame, landmarks):
|
||||
global mario_hat
|
||||
if mario_hat_active and mario_hat is not None:
|
||||
forehead = landmarks[10]
|
||||
chin = landmarks[152]
|
||||
left_side = landmarks[234]
|
||||
right_side = landmarks[454]
|
||||
face_width = int(np.linalg.norm(np.array(left_side) - np.array(right_side)))
|
||||
hat_width = int(face_width * 4.0)
|
||||
hat_height = int(hat_width * mario_hat.shape[0] / mario_hat.shape[1])
|
||||
mario_hat_resized = cv2.resize(mario_hat, (hat_width, hat_height))
|
||||
x = int(forehead[0] - hat_width / 2)
|
||||
y = int(forehead[1] - hat_height * 0.7)
|
||||
alpha_channel = mario_hat_resized[:, :, 3] / 255.0
|
||||
hat_rgb = mario_hat_resized[:, :, :3]
|
||||
for i in range(hat_height):
|
||||
for j in range(hat_width):
|
||||
if 0 <= y + i < frame.shape[0] and 0 <= x + j < frame.shape[1]:
|
||||
alpha = alpha_channel[i, j]
|
||||
if alpha > 0:
|
||||
for c in range(3):
|
||||
frame[y + i, x + j, c] = (1 - alpha) * frame[y + i, x + j, c] + alpha * hat_rgb[i, j, c]
|
||||
return frame
|
||||
|
||||
def apply_sunglasses(frame, landmarks):
|
||||
global sunglasses
|
||||
if sunglasses_active and sunglasses is not None:
|
||||
left_eye = landmarks[33]
|
||||
right_eye = landmarks[263]
|
||||
eye_dist = np.linalg.norm(np.array(left_eye) - np.array(right_eye))
|
||||
scaling_factor = 1.75
|
||||
sunglasses_width = int(eye_dist * scaling_factor)
|
||||
sunglasses_height = int(sunglasses_width * sunglasses.shape[0] / sunglasses.shape[1])
|
||||
sunglasses_resized = cv2.resize(sunglasses, (sunglasses_width, sunglasses_height))
|
||||
center_x = int((left_eye[0] + right_eye[0]) / 2)
|
||||
center_y = int((left_eye[1] + right_eye[1]) / 2)
|
||||
x = int(center_x - sunglasses_resized.shape[1] / 2)
|
||||
y = int(center_y - sunglasses_resized.shape[0] / 2)
|
||||
alpha_channel = sunglasses_resized[:, :, 3] / 255.0
|
||||
sunglasses_rgb = sunglasses_resized[:, :, :3]
|
||||
for i in range(sunglasses_resized.shape[0]):
|
||||
for j in range(sunglasses_resized.shape[1]):
|
||||
if alpha_channel[i, j] > 0:
|
||||
for c in range(3):
|
||||
frame[y + i, x + j, c] = (1 - alpha_channel[i, j]) * frame[y + i, x + j, c] + alpha_channel[i, j] * sunglasses_rgb[i, j, c]
|
||||
return frame
|
||||
|
||||
def apply_moustache(frame, landmarks):
|
||||
global moustache
|
||||
if moustache_active and moustache is not None:
|
||||
nose_base = landmarks[1]
|
||||
mouth_left = landmarks[61]
|
||||
mouth_right = landmarks[291]
|
||||
mouth_width = int(np.linalg.norm(np.array(mouth_left) - np.array(mouth_right)))
|
||||
moustache_width = int(mouth_width * 1.5)
|
||||
moustache_height = int(moustache_width * moustache.shape[0] / moustache.shape[1])
|
||||
moustache_resized = cv2.resize(moustache, (moustache_width, moustache_height))
|
||||
x = int(nose_base[0] - moustache_width / 2)
|
||||
y = int(nose_base[1])
|
||||
alpha_channel = moustache_resized[:, :, 3] / 255.0
|
||||
moustache_rgb = moustache_resized[:, :, :3]
|
||||
for i in range(moustache_height):
|
||||
for j in range(moustache_width):
|
||||
if 0 <= y + i < frame.shape[0] and 0 <= x + j < frame.shape[1]:
|
||||
alpha = alpha_channel[i, j]
|
||||
if alpha > 0:
|
||||
for c in range(3):
|
||||
frame[y + i, x + j, c] = (1 - alpha) * frame[y + i, x + j, c] + alpha * moustache_rgb[i, j, c]
|
||||
return frame
|
||||
|
||||
def update_frame():
|
||||
global mario_hat_active, sunglasses_active, show_angles, contour_frame, moustache_active
|
||||
ret, frame = cap.read()
|
||||
if ret:
|
||||
rgb_frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
|
||||
results = face_mesh.process(rgb_frame)
|
||||
if results.multi_face_landmarks:
|
||||
for face_landmarks in results.multi_face_landmarks:
|
||||
landmarks = [(lm.x * frame.shape[1], lm.y * frame.shape[0]) for lm in face_landmarks.landmark]
|
||||
yaw, pitch = calculate_angles(landmarks)
|
||||
if mario_hat_active:
|
||||
frame = apply_mario_hat(frame, landmarks)
|
||||
if sunglasses_active:
|
||||
frame = apply_sunglasses(frame, landmarks)
|
||||
if moustache_active:
|
||||
frame = apply_moustache(frame, landmarks)
|
||||
if show_angles:
|
||||
cv2.putText(frame, f"Yaw: {yaw:.2f}", (10, 30), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 255, 0), 2)
|
||||
cv2.putText(frame, f"Pitch: {pitch:.2f}", (10, 70), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 255, 0), 2)
|
||||
cv2.imshow("Webcam Feed", frame)
|
||||
contour_frame = frame
|
||||
root.after(100, update_frame)
|
||||
|
||||
def toggle_mario_hat():
|
||||
global mario_hat_active
|
||||
mario_hat_active = not mario_hat_active
|
||||
status = "activated" if mario_hat_active else "deactivated"
|
||||
print(f"Mario hat filter {status}")
|
||||
|
||||
def toggle_sunglasses():
|
||||
global sunglasses_active
|
||||
sunglasses_active = not sunglasses_active
|
||||
status = "activated" if sunglasses_active else "deactivated"
|
||||
print(f"Sunglasses filter {status}")
|
||||
|
||||
def toggle_moustache():
|
||||
global moustache_active
|
||||
moustache_active = not moustache_active
|
||||
status = "activated" if moustache_active else "deactivated"
|
||||
print(f"Moustache filter {status}")
|
||||
|
||||
def toggle_angles():
|
||||
global show_angles
|
||||
show_angles = not show_angles
|
||||
status = "shown" if show_angles else "hidden"
|
||||
print(f"Angles display {status}")
|
||||
|
||||
def show_contour_frame():
|
||||
if contour_frame is not None:
|
||||
# Display the result
|
||||
cv2.imshow('Edges', resized_edges)
|
||||
|
||||
|
||||
def save_image():
|
||||
global contour_frame, resized_edges
|
||||
if contour_frame is not None:
|
||||
save_path = "Tmp/captured_face.png"
|
||||
cv2.imwrite(save_path, contour_frame)
|
||||
print(f"Image saved to {save_path}")
|
||||
|
||||
# Store path of the image in the variable input_path
|
||||
input_path = 'Tmp/captured_face.png'
|
||||
|
||||
# Store path of the output image in the variable output_path
|
||||
output_path = 'Tmp/captured_face_nobg.png'
|
||||
|
||||
# Processing the image
|
||||
input = Image.open(input_path)
|
||||
|
||||
# Removing the background from the given Image
|
||||
output = remove(input)
|
||||
|
||||
#Saving the image in the given path
|
||||
output.save(output_path)
|
||||
image = cv2.imread(output_path, cv2.IMREAD_GRAYSCALE)
|
||||
mask = (image > 1) & (image < 254)
|
||||
blurred_image = cv2.GaussianBlur(image, (9, 9), 0)
|
||||
median_val = np.median(blurred_image[mask])
|
||||
lower_threshold = int(max(0, 0.5 * median_val))
|
||||
upper_threshold = int(min(255, 1.2 * median_val))
|
||||
print(f"Automatic lower threshold: {lower_threshold}")
|
||||
print(f"Automatic upper threshold: {upper_threshold}")
|
||||
|
||||
# Apply Canny edge detection using the calculated thresholds
|
||||
edges = cv2.Canny(blurred_image, lower_threshold, upper_threshold)
|
||||
|
||||
# Resize the output image to a smaller size (e.g., 50% of the original size)
|
||||
output_height, output_width = edges.shape[:2]
|
||||
resized_edges = cv2.resize(edges, (output_width // 2, output_height // 2), interpolation=cv2.INTER_AREA)
|
||||
|
||||
# Save the resized result to a file
|
||||
cv2.imwrite('Tmp/final_output_image.png', resized_edges)
|
||||
|
||||
def start_dobot():
|
||||
vector_draw.vector_draw()
|
||||
|
||||
# Tkinter GUI setup
|
||||
root = tk.Tk()
|
||||
root.title("Control Tab")
|
||||
root.geometry("300x370")
|
||||
root.configure(bg="#004346")
|
||||
|
||||
# Buttons on the control window with updated font and colors
|
||||
mario_hat_button = tk.Button(root, text="Add Mario Hat", font=("Arial", 12, "bold"), command=toggle_mario_hat, bg="#4C8577", fg="white", padx=10, pady=5, height=1, width=20)
|
||||
mario_hat_button.pack(pady=10)
|
||||
|
||||
sunglasses_button = tk.Button(root, text="Add Glasses", font=("Arial", 12, "bold"), command=toggle_sunglasses, bg="#4C8577", fg="white", padx=10, pady=5, height=1, width=20)
|
||||
sunglasses_button.pack(pady=10)
|
||||
|
||||
moustache_button = tk.Button(root, text="Add Mario Moustache", font=("Arial", 12, "bold"), command=toggle_moustache, bg="#4C8577", fg="white", padx=10, pady=5,height=1, width=20)
|
||||
moustache_button.pack(pady=10)
|
||||
|
||||
save_image_button = tk.Button(root, text="Save/Retake Image", font=("Arial", 12, "bold"), command=save_image, bg="#49A078", fg="white", padx=10, pady=5,height=1, width=20)
|
||||
save_image_button.pack(pady=10)
|
||||
|
||||
contour_frame_button = tk.Button(root, text="Show Contour Image", font=("Arial", 12, "bold"), command=show_contour_frame, bg="#216869", fg="white", padx=10, pady=5,height=1, width=20)
|
||||
contour_frame_button.pack(pady=10)
|
||||
|
||||
contour_frame_button = tk.Button(root, text="Start Dobot Drawing", font=("Arial", 12, "bold"), command=start_dobot, bg="#49A078", fg="white", padx=10, pady=5,height=1, width=20)
|
||||
contour_frame_button.pack(pady=10)
|
||||
|
||||
# Graceful exit
|
||||
def on_closing():
|
||||
cap.release()
|
||||
cv2.destroyAllWindows()
|
||||
root.destroy()
|
||||
|
||||
root.protocol("WM_DELETE_WINDOW", on_closing)
|
||||
|
||||
show_contour_frame()
|
||||
|
||||
# Start Tkinter event loop and OpenCV frame updates
|
||||
update_frame()
|
||||
root.mainloop()
|
||||
|
|
@ -1,50 +0,0 @@
|
|||
import matplotlib.pyplot as plt
|
||||
import sys
|
||||
#sys.path.insert(0, './dobot/librairies')
|
||||
import dobot
|
||||
import time
|
||||
|
||||
dobot.setQueuedCmdClear()
|
||||
dobot.setQueuedCmdStartExec()
|
||||
|
||||
def moyenneMobile(list, length):
|
||||
mm = []
|
||||
for i in range(0, len(list) - length, 1):
|
||||
sum = 0
|
||||
for k in range(0, length, 1):
|
||||
sum += list[i+k]
|
||||
|
||||
mm.append(sum / length)
|
||||
return(mm)
|
||||
|
||||
y = []
|
||||
z = []
|
||||
|
||||
dobot.setPTPJumpParams(60,130,1)
|
||||
dobot.setPTPCmd(0, 259.6, 111, 9.8, 0, 1)
|
||||
dobot.setPTPCmd(0, 206, -130, 52.8, 0, 1)
|
||||
|
||||
print(dobot.getPTPJumpParams())
|
||||
|
||||
|
||||
delay = 0.02
|
||||
|
||||
for i in range(0, 300):
|
||||
valeurs = dobot.getPose()
|
||||
y.append(-valeurs[1])
|
||||
z.append(valeurs[2])
|
||||
|
||||
time.sleep(delay)
|
||||
|
||||
|
||||
# On trace le graphique
|
||||
|
||||
plt.xlabel("y")
|
||||
plt.ylabel("z")
|
||||
plt.plot(y, z, 'r')
|
||||
plt.axis([-130, 150, 0, 150])
|
||||
|
||||
plt.show()
|
||||
|
||||
|
||||
|
||||
|
|
@ -1,69 +0,0 @@
|
|||
import matplotlib.pyplot as plt
|
||||
import dobot
|
||||
import time
|
||||
import cv2 as cv
|
||||
|
||||
# Drawing parameters
|
||||
DRAW_MODE = 1
|
||||
DRAW_SPEED = 1 # Drawing speed for
|
||||
DRAW_DEPTH = -67.8 # Initial height (null)
|
||||
DRAW_RES = 1 # Space between pixels
|
||||
THRESHOLD = 70 # Min. intensityfrom which a pixel must be drawn
|
||||
|
||||
INIT_POSITION = [210, -60]
|
||||
|
||||
dobot.setQueuedCmdClear()
|
||||
dobot.setQueuedCmdStartExec()
|
||||
|
||||
def pixel_draw(imagepath):
|
||||
|
||||
# Load Image
|
||||
im = cv.imread(imagepath)
|
||||
if im is None:
|
||||
print("Error: Image not found at", imagepath)
|
||||
exit()
|
||||
|
||||
# Resize Image
|
||||
im = cv.resize(im, (0, 0), fx = 0.05, fy = 0.05, interpolation=cv.INTER_LINEAR)
|
||||
|
||||
# Convert to Grayscale
|
||||
im = cv.cvtColor(im, cv.COLOR_BGR2GRAY)
|
||||
|
||||
# Window name in which image is displayed
|
||||
window_name = 'Display'
|
||||
|
||||
# Using cv2.imshow() method
|
||||
# Displaying the image
|
||||
im_display = cv.resize(im, (0, 0), fx = 10, fy = 10, interpolation=cv.INTER_LINEAR)
|
||||
print(im)
|
||||
print(im.shape[0], im.shape[1])
|
||||
cv.imshow(window_name, im_display)
|
||||
# waits for user to press any key
|
||||
# (this is necessary to avoid Python kernel form crashing)
|
||||
cv.waitKey(0)
|
||||
|
||||
for x in range(0, im.shape[0]-1):
|
||||
for y in range(0, im.shape[1]-1):
|
||||
value = im[x][y]
|
||||
print(value)
|
||||
|
||||
if value >= THRESHOLD:
|
||||
dobot.setPTPCmd(1, INIT_POSITION[0]+x*DRAW_RES, INIT_POSITION[1]+y*DRAW_RES, DRAW_DEPTH+2.5, 0, 1)
|
||||
dobot.setPTPCmd(1, INIT_POSITION[0]+x*DRAW_RES, INIT_POSITION[1]+y*DRAW_RES, DRAW_DEPTH-(value/255), 0, 1)
|
||||
dobot.setPTPCmd(1, INIT_POSITION[0]+x*DRAW_RES, INIT_POSITION[1]+y*DRAW_RES, DRAW_DEPTH+2.5, 0, 1)
|
||||
|
||||
#dobot.setWaitCmd(5)
|
||||
time.sleep(0.8)
|
||||
|
||||
def vector_draw(array):
|
||||
for vector in array:
|
||||
dobot.setCPCmd(DRAW_MODE, array.x, array.y, array.z, DRAW_SPEED, 1)
|
||||
|
||||
pixel_draw("C:/Users/alexl/Documents/Cours/S7/IT and Robotics/GrpC_Identikit/assets/sins.jpg")
|
||||
|
||||
# Stop the current execution
|
||||
"""if input("Appuyez sur Entrer pour arrêter.") == "":
|
||||
dobot.setQueuedCmdForceStopExec()
|
||||
dobot.setQueuedCmdClear()
|
||||
"""
|
||||
# Define current workspace
|
||||
|
|
@ -1,46 +0,0 @@
|
|||
import matplotlib.pyplot as plt
|
||||
import sys
|
||||
#sys.path.insert(0, './dobot/librairies')
|
||||
import dobot
|
||||
import time
|
||||
import math
|
||||
|
||||
dobot.setQueuedCmdClear()
|
||||
dobot.setQueuedCmdStartExec()
|
||||
|
||||
dobot.setPTPjointParams(200,200,200,200,200,200,200,200,1)
|
||||
|
||||
dobot.setPTPCmd(1, 250, 0, 150, 0, 1)
|
||||
|
||||
dobot.setPTPjointParams(200,1400,1400,200,200,1400,1400,200,1)
|
||||
|
||||
dobot.setPTPCmd(1, 250, 0, -90, 0, 1)
|
||||
|
||||
dobot.setPTPjointParams(200,200,200,200,200,200,200,200,1)
|
||||
|
||||
dobot.setPTPCmd(1, 250, 0, 150, 0, 1)
|
||||
|
||||
"""
|
||||
dobot.setPTPCmd(1, -181, -272, 12, 0, 1)
|
||||
|
||||
dobot.setEndEffectorSuctionCup(1,1)
|
||||
|
||||
dobot.setWaitCmd(3000,1)
|
||||
|
||||
dobot.setPTPjointParams(2000,200,200,200,1100,200,200,200,1)
|
||||
print(dobot.getPTPjointParams())
|
||||
|
||||
dobot.setPTPCmd(6, 245, 0, 0, 0, 1)
|
||||
|
||||
dobot.setPTPjointParams(400,200,200,200,400,200,200,200,1)
|
||||
|
||||
dobot.setPTPCmd(1, -181, -272, 12, 0, 1)
|
||||
|
||||
time.sleep(3.7)
|
||||
|
||||
dobot.setEndEffectorSuctionCup(0,0)
|
||||
"""
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,90 @@
|
|||
import matplotlib.pyplot as plt
|
||||
import dobot
|
||||
import time
|
||||
import cv2
|
||||
import numpy as np
|
||||
import os
|
||||
|
||||
def vector_draw():
|
||||
dobot.setQueuedCmdClear()
|
||||
dobot.setQueuedCmdStartExec()
|
||||
|
||||
# Drawing parameters
|
||||
DRAW_SPEED = 1 # Drawing speed for
|
||||
DRAW_DEPTH = -38 # Initial height (null)
|
||||
INIT_POSITION = [-100, 150]
|
||||
|
||||
# --------------------------------------------------------------------------
|
||||
# IMAGE TREATMENT
|
||||
# --------------------------------------------------------------------------
|
||||
# Load the image in grayscale
|
||||
output_path = os.getcwd() + "\Tmp\captured_face_nobg.png"
|
||||
image = cv2.imread(output_path, cv2.IMREAD_GRAYSCALE)
|
||||
|
||||
# Create a mask to exclude background pixels (assuming background is near white or black)
|
||||
# For example, exclude pixels that are close to white (255) and black (0)
|
||||
mask = (image > 1) & (image < 254) # Keep only pixels that are not close to white or black
|
||||
|
||||
# Apply Gaussian Blur to reduce noise
|
||||
blurred_image = cv2.GaussianBlur(image, (11, 11), 0)
|
||||
|
||||
# Calculate the median of only the foreground pixels
|
||||
median_val = np.median(blurred_image[mask])
|
||||
|
||||
# Automatically calculate thresholds based on the median pixel intensity
|
||||
lower_threshold = int(max(0, 0.5 * median_val))
|
||||
upper_threshold = int(min(255, 1.2 * median_val))
|
||||
print(f"Automatic lower threshold: {lower_threshold}")
|
||||
print(f"Automatic upper threshold: {upper_threshold}")
|
||||
|
||||
# Apply Canny edge detection using the calculated thresholds
|
||||
edges = cv2.Canny(blurred_image, lower_threshold, upper_threshold)
|
||||
|
||||
# Find Contours
|
||||
contours, _ = cv2.findContours(edges, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
|
||||
print(contours)
|
||||
|
||||
# Initialize an array to store all points
|
||||
all_points = []
|
||||
|
||||
# Define Dobot workspace dimensions (e.g., in mm)
|
||||
robot_workspace = (200, 200*2/3) # Replace with your Dobot's range in mm
|
||||
|
||||
# Scale function to map image coordinates to Dobot's workspace
|
||||
def scale_coordinates(point, img_dim, robot_dim):
|
||||
img_x, img_y = point
|
||||
img_width, img_height = img_dim
|
||||
robot_x_range, robot_y_range = robot_dim
|
||||
# Map x and y with scaling
|
||||
robot_x = (img_x / img_width) * robot_x_range
|
||||
robot_y = (img_y / img_height) * robot_y_range
|
||||
return robot_x, robot_y
|
||||
|
||||
# Collect points for Dobot
|
||||
for cnt in contours:
|
||||
# Scale and store points
|
||||
for point in cnt:
|
||||
x, y = point[0]
|
||||
x, y = scale_coordinates((x, y), (image.shape[1], image.shape[0]), robot_workspace)
|
||||
all_points.append((x, y))
|
||||
all_points.append((-1,-1))
|
||||
|
||||
# Delete all duplicate points
|
||||
#all_points = list(dict.fromkeys(all_points))
|
||||
|
||||
robot_x_old = 0
|
||||
robot_y_old = 0
|
||||
|
||||
for i, (robot_x, robot_y) in enumerate(all_points):
|
||||
|
||||
if robot_x == -1 or robot_y == -1:
|
||||
# Lift the pen at the end of each contour
|
||||
dobot.setCPCmd(1, robot_x_old + INIT_POSITION[0], robot_y_old + INIT_POSITION[1], DRAW_DEPTH+15, DRAW_SPEED, 1)
|
||||
else:
|
||||
if robot_x_old == -1 or robot_y_old == -1:
|
||||
dobot.setCPCmd(1, robot_x + INIT_POSITION[0], robot_y + INIT_POSITION[1], DRAW_DEPTH+15, DRAW_SPEED, 1)
|
||||
dobot.setCPCmd(1, robot_x + INIT_POSITION[0], robot_y + INIT_POSITION[1], DRAW_DEPTH, DRAW_SPEED, 1)
|
||||
time.sleep(0.15)
|
||||
|
||||
robot_x_old = robot_x
|
||||
robot_y_old = robot_y
|
||||