diff --git a/ROI_face.py b/ROI_face.py index 01cdb8b..b598164 100644 --- a/ROI_face.py +++ b/ROI_face.py @@ -21,13 +21,13 @@ def roi(frame): color = (255, 255, 255) # Color in BGR format (white) # thickness = 2 mask = np.zeros((height, width), dtype=np.uint8) - cv2.ellipse(mask, center_ellipse, axes, angle, 0, 360, 255, -1) # 255 for a white oval + cv2.ellipse(mask, center_ellipse, axes, angle, 0, 360, 0, -1) # 255 for a white oval # Apply the inverted mask to the face result = cv2.bitwise_and(frame, frame, mask=mask) - #black_mask = (result[:, :, 0] == 0) & (result[:, :, 1] == 0) & (result[:, :, 2] == 0) + black_mask = (result[:, :, 3] == 0)# & (result[:, :, 1] == 0) & (result[:, :, 2] == 0) #print(result[c_x2, c_y2,1]) # Replace black pixels with white pixels - #result[black_mask] = [result[10, 10, 0], result[10, 10, 1], result[10, 10, 2]] + result[black_mask] = [result[0, 0, 0], result[0, 0, 1], result[0, 0, 2]] - return result + return frame diff --git a/coordinates_change.py b/coordinates_change.py new file mode 100644 index 0000000..24ea5f4 --- /dev/null +++ b/coordinates_change.py @@ -0,0 +1,67 @@ +import numpy as np + +def coord(contours, x_offset, y_offset, x_scale, y_scale): + new_contours = [] + for i in range(len(contours)): + for j in range(len(contours[i])): + x = contours[i][j][0][0]*x_scale + x_offset + y = contours[i][j][0][1]*y_scale + y_offset + new_contours.append([x, y]) + return new_contours + +def scale_calculator(contours, size): + x_max = contours[0][0][0][0] + x_min = contours[0][0][0][0] + y_max = contours[0][0][0][1] + y_min = contours[0][0][0][1] + + for i in range(len(contours)): + for j in range(len(contours[i])): + x = contours[i][j][0][0] + y = contours[i][j][0][1] + if x_min > x: + x_min = x + if x > x_max: + x_max = x + if y_min > y: + y_min = y + if y > y_max: + y_max = y + # print([[x_min, x_max], [y_min, y_max]]) #display max and min in x and y + + x_scale = 1.0 + y_scale = 1.0 + if size[0] != 0: + x_scale = size[0]/(x_max - x_min) + if size[1] != 0: + y_scale = size[1]/(y_max - y_min) + if size[0] == 0: + x_scale = y_scale + if size[1] == 0: + y_scale = x_scale + + x_min = x_min*x_scale + y_min = y_min*y_scale + + return [x_min, y_min, x_scale, y_scale] + + +def get_size(coords): + x_max = coords[0][0] + x_min = coords[0][0] + y_max = coords[0][1] + y_min = coords[0][1] + + for i in range(len(coords)): + x = coords[i][0] + y = coords[i][1] + if x_min > x: + x_min = x + if x > x_max: + x_max = x + if y_min > y: + y_min = y + if y > y_max: + y_max = y + + return [[x_min, x_max], [y_min, y_max]] #display max and min in x and y \ No newline at end of file diff --git a/get_head.py b/get_head.py index 1ad0ab8..af869ea 100644 --- a/get_head.py +++ b/get_head.py @@ -1,37 +1,39 @@ import cv2 import time -cap = cv2.VideoCapture(0) - def get_image(): - # Set the window name + cap = cv2.VideoCapture(0) + window_name = 'Camera Capture' + countdown_duration = 60 - # Get the default frames per second (fps) of the camera - fps = int(cap.get(cv2.CAP_PROP_FPS)) + # Check if the camera is opened successfully + if not cap.isOpened(): + print("Error: Could not open the camera.") + return None - # Set the countdown duration in seconds - countdown_duration = 10 - # Start the countdown for countdown in range(countdown_duration, 10, -1): ret, frame = cap.read() - # Display the camera feed - cv2.imshow(window_name, frame) - # Display the countdown on the image + # Check if the frame is read successfully + if not ret: + print("Error: Could not read frame.") + return None + font = cv2.FONT_HERSHEY_SIMPLEX cv2.putText(frame, str(countdown)[0], (10, 30), font, 1, (0, 255, 0), 2, cv2.LINE_AA) cv2.imshow(window_name, frame) + cv2.waitKey(100) - # Wait for 1 second and check for key press - if cv2.waitKey(100) & 0xFF == 27: # 27 is the ASCII code for the 'ESC' key - break + output_path = 'image.png' + cv2.imwrite(output_path, frame) - # Take a picture at the end of the countdown - ret, frame = cap.read() - #cv2.imwrite("image.png", frame) - - # Release the camera and close the OpenCV window + # Release the camera capture object cap.release() - cv2 - return frame + + # Destroy all OpenCV windows + cv2.destroyAllWindows() + + print(f"Image saved successfully at '{output_path}'.") + return output_path + diff --git a/goutput.png b/goutput.png new file mode 100644 index 0000000..39d2680 Binary files /dev/null and b/goutput.png differ diff --git a/image.png b/image.png index 0ca0111..995b713 100644 Binary files a/image.png and b/image.png differ diff --git a/main.py b/main.py index 42190c8..b1675ba 100644 --- a/main.py +++ b/main.py @@ -1,17 +1,42 @@ import cv2 + import show_img_conditions -import ROI_face +import remove_bg import get_head +import coordinates_change +import numpy as np #show_img_conditions.show() -gray = get_head.get_image() -cv2.imshow('Grey Image', gray) -face = ROI_face.roi(gray) -cv2.imshow('Face', face) -edges = cv2.Canny(face, 10, 100) -cv2.imshow('Image avec Contours de Visage', edges) +image_path = get_head.get_image() +image = cv2.imread(image_path) +#cv2.imshow('Image', image) + +image_path = 'image.png' + +background_path = remove_bg.rmbg(image_path) +background = cv2.imread(background_path) +#cv2.imshow('Image without background', background) + +gray_image = cv2.cvtColor(background, cv2.COLOR_BGR2GRAY) +edges = cv2.Canny(gray_image, 20, 80) +cv2.imshow("contours", edges) cv2.waitKey(0) -cv2.destroyAllWindows() +contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) +x_offset = 0 # offset in the x_axis +y_offset = 0 # offset in the y_axis +new_size = [150, 0] # new size of the picture in mm, write 0 if you want to be proportional + +[x_min, y_min, x_scale, y_scale] = coordinates_change.scale_calculator(contours, new_size) + +x_offset = x_offset - x_min +y_offset = y_offset - y_min + +new_coords = coordinates_change.coord(contours, x_offset, y_offset, x_scale, y_scale) + +size = coordinates_change.get_size(new_coords) +print("x offset : ", int(x_offset+x_min), "mm") +print("y offset : ", int(y_offset+y_min), "mm") +print("size : ", int(size[0][1] - size[0][0]), "x", int(size[1][1] - size[1][0]), "mm") diff --git a/output.png b/output.png new file mode 100644 index 0000000..5a0c5fe Binary files /dev/null and b/output.png differ diff --git a/remove_bg.py b/remove_bg.py new file mode 100644 index 0000000..5ae4316 --- /dev/null +++ b/remove_bg.py @@ -0,0 +1,11 @@ +from rembg import remove +from PIL import Image + +output_path = 'output.png' + +def rmbg(input_path): + input = Image.open(input_path) + output = remove(input) + output.save(output_path) + return output_path + diff --git a/test2.py b/test2.py index 41330b2..6f7e7a2 100644 --- a/test2.py +++ b/test2.py @@ -1,35 +1,35 @@ import cv2 -import numpy as np -# Load an image -image = cv2.imread('image.jpg') +# Open a connection to the webcam (default camera index is 0) +cap = cv2.VideoCapture(0) -# Convert the image to grayscale -gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) +# Check if the camera is opened successfully +if not cap.isOpened(): + print("Error: Could not open the camera.") + exit() -# Apply thresholding to create a binary image -_, thresh = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY) +# Create a window to display the webcam feed +window_name = 'Webcam Feed' +cv2.namedWindow(window_name, cv2.WINDOW_NORMAL) -# Find contours in the binary image -contours, _ = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) +while True: + # Read a frame from the webcam + ret, frame = cap.read() -# Choose the contour you want to remove (in this example, the first contour is removed) -contour_to_remove = contours[0] + # Check if the frame is read successfully + if not ret: + print("Error: Could not read frame.") + break -# Create a mask with the same shape as the image -mask = np.zeros_like(image) + # Display the frame in the window + cv2.imshow(window_name, frame) -# Fill the contour with a background color (white in this case) -cv2.fillPoly(mask, [contour_to_remove], (255, 255, 255)) + # Break the loop if 'q' key is pressed + if cv2.waitKey(1) & 0xFF == ord('q'): + break -# Invert the mask to keep the rest of the image -mask_inv = cv2.bitwise_not(mask) +# Release the camera capture object +cap.release() -# Bitwise AND the original image with the inverted mask -result = cv2.bitwise_and(image, mask_inv) - -# Display the original and processed images -cv2.imshow('Original Image', image) -cv2.imshow('Result', result) -cv2.waitKey(0) +# Destroy the OpenCV window cv2.destroyAllWindows()