This is the code where I perform thresholding on an image to detect the piece and I would like to be able to smooth the edge even more. I've never worked with Python, but I'd be interested in doing this project to find a solution to a puzzle. Therefore, I need the edges of the piece to be as smooth as possible. from PIL import Image, ExifTags, ImageFilter EXPECTED_PHOTO_ORIENTATION = 1 # Horizontal (normal) def get_photo_orientation(img): exif = img._getexif() if exif: for tag, value in exif.items(): if tag in ExifTags.TAGS: if ExifTags.TAGS[tag] == 'Orientation': return value return None def binary_pixel_data_for_photo(path, threshold, max_width=None, crop=None): """ Given a bitmap image path, returns a 2D array of 1s and 0s crop is either None or (top, right, bottom, left) in pixels """ with Image.open(path) as img: if (orientation := get_photo_orientation(img)) is not None and orientation != EXPECTED_PHOTO_ORIENTATION: raise Exception(f"Image {path} is not oriented correctly: {orientation}") w, h = img.size if max_width is not None and img.size[0] > max_width: scale_factor = max_width / img.size[0] try: img = img.resize((max_width, int(img.size[1] * scale_factor)), resample=Image.NEAREST) except Exception as e: print(f"Error resizing {path}") raise e else: scale_factor = 1.0 if crop: w, h = img.size img = img.crop((crop[3], crop[0], w - crop[1], h - crop[2])) data, out_w, out_h = threshold_pixels(img, threshold) return data, out_w, out_h, scale_factor def threshold_pixels(img, threshold): # Convert image to grayscale numpy array grayscale = img.convert('L') data = np.array(grayscale) # Aplicar convolución filtered = cv2.GaussianBlur(data, (9, 9), sigmaX=0) # Apply threshold to get binary representation binary_data = np.where(filtered <= threshold, 0, 1).astype(np.int8) return binary_data, binary_data.shape[1], binary_data.shape[0] binary_data, out_w, out_h, scale_factor = binary_pixel_data_for_photo("ejemplo.jpeg", 100) binary_uint8 = binary_data.astype(np.uint8) * 255 contours, _ = cv2.findContours(binary_uint8, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) if contours: largest = max(contours, key=cv2.contourArea) contour_img = np.zeros_like(binary_uint8) cv2.drawContours(contour_img, [largest], 0, 255, -1) # Mostrar resultado plt.imshow(cv2.imread("ejemplo.jpeg")) plt.title("Imagen original") plt.axis("off") plt.show() plt.figure(figsize=(6, 8)) plt.imshow(contour_img) plt.title("Contorno de la pieza") plt.axis("off") plt.show() Continue reading...