Le but de ce programme est de transformer un fichier PNG ou JPG en STL (3D). L'image doit être en fond transparent ou en fond noir, voir gris clair avec l'objet en Blanc ou noir (exemple ci-dessous).
Image
# Programme : Eric LEFEBURE : 2025
      import cv2
      import os
      import numpy as np
      # Nom de l'image à traiter
      image_name = "image_objet.png"
      # Charger l'image PNG avec alpha (si elle existe déjà)
      image = cv2.imread(image_name, cv2.IMREAD_UNCHANGED)
      if image is None:
          print("Erreur de chargement de l'image.")
          exit()
      # Si l'image n'a pas de canal alpha, ajouter un canal alpha
      if image.shape[2] == 3:
          image = cv2.cvtColor(image, cv2.COLOR_BGR2BGRA)
      # Créer une copie de l'image
      new_image = image.copy()
      # Conversion de l'image en niveaux de gris
      gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
      # Seuillage pour obtenir une image binaire (noir et blanc)
      ret, binary = cv2.threshold(gray, 100, 255, cv2.THRESH_OTSU)
      # Inversion de l'image binaire (fond noir, objet blanc)
      inverted_binary = ~binary
      # Détection des contours
      contours, hierarchy = cv2.findContours(inverted_binary, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
      # Créer un masque vide pour l'objet
      mask = np.zeros_like(gray)
      # Dessiner les contours sur le masque (les deux contours internes et externes)
      cv2.drawContours(mask, contours, -1, (255), thickness=cv2.FILLED)
      # Créer une image avec fond transparent
      transparent_background = np.zeros_like(image)
      # Placer l'objet détecté sur le fond transparent
      transparent_background[:, :, :3] = cv2.bitwise_and(image[:, :, :3], image[:, :, :3], mask=mask)
      # Ajouter un canal alpha (transparence) avec 255 pour l'objet et 0 pour le fond
      transparent_background[:, :, 3] = mask
      # Enregistrer l'image avec fond transparent
      output_image_name = os.path.splitext(image_name)[0] + '-transparent.png'
      cv2.imwrite(output_image_name, transparent_background)
      print(f"Image enregistrée sous : {output_image_name}")
      # Afficher l'image pour vérification
      from stl import mesh
      # Définir le nom de l'image PNG avec fond transparent
      image_path = output_image_name
      # Charger l'image (en supposant que l'image a déjà été traitée pour avoir une transparence)
      # Charger l'image en niveau de gris, on suppose que l'image binaire existe
      image = cv2.imread(image_path, cv2.IMREAD_UNCHANGED)
      # Vérifier si l'image est bien chargée
      if image is None:
          print(f"Erreur : Impossible de charger l'image depuis {image_path}.")
          exit()
      # Extraire le canal alpha de l'image pour créer le masque
      alpha_channel = image[:, :, 3]  # Canal alpha (transparence)
      # Appliquer un seuil pour obtenir un masque binaire
      _, threshold = cv2.threshold(alpha_channel, 1, 255, cv2.THRESH_BINARY)
      # Paramètres d'épaisseur
      thickness = 15  # Épaisseur de l'objet (distance entre les deux faces)
      # Créer une grille de points 3D basée sur la carte de profondeur
      height, width = threshold.shape
      vertices = []
      faces = []
      # Créer la topologie de la forme 3D en fonction du masque
      for y in range(height - 1):
          for x in range(width - 1):
              if threshold[y, x] > 0 and threshold[y + 1, x] > 0 and threshold[y, x + 1] > 0 and threshold[y + 1, x + 1] > 0:
                  # Calculer la hauteur (z) en fonction de la valeur du pixel
                  z_top = threshold[y, x] / 255.0 * 10  # Face supérieure
                  z_bottom = z_top - thickness  # Face inférieure (épaisseur ajoutée)
                  # Définir les quatre coins du carré pour la face supérieure
                  v1_top = (x, y, z_top)
                  v2_top = (x + 1, y, z_top)
                  v3_top = (x, y + 1, z_top)
                  v4_top = (x + 1, y + 1, z_top)
                  # Définir les quatre coins du carré pour la face inférieure
                  v1_bottom = (x, y, z_bottom)
                  v2_bottom = (x + 1, y, z_bottom)
                  v3_bottom = (x, y + 1, z_bottom)
                  v4_bottom = (x + 1, y + 1, z_bottom)
                  # Ajouter les sommets
                  vertex_index = len(vertices)
                  vertices.extend([v1_top, v2_top, v3_top, v4_top, v1_bottom, v2_bottom, v3_bottom, v4_bottom])
                  # Ajouter les faces pour la face supérieure
                  faces.append([vertex_index, vertex_index + 1, vertex_index + 2])  # Triangle 1
                  faces.append([vertex_index + 1, vertex_index + 3, vertex_index + 2])  # Triangle 2
                  # Ajouter les faces pour la face inférieure (inversées pour respecter l'orientation)
                  faces.append([vertex_index + 4, vertex_index + 6, vertex_index + 5])  # Triangle 1
                  faces.append([vertex_index + 6, vertex_index + 7, vertex_index + 5])  # Triangle 2
                  # Ajouter les faces latérales pour connecter les deux faces
                  faces.append([vertex_index, vertex_index + 4, vertex_index + 5])  # Côté 1
                  faces.append([vertex_index, vertex_index + 5, vertex_index + 1])
                  faces.append([vertex_index + 1, vertex_index + 5, vertex_index + 6])  # Côté 2
                  faces.append([vertex_index + 1, vertex_index + 6, vertex_index + 3])
                  faces.append([vertex_index + 3, vertex_index + 7, vertex_index + 6])  # Côté 3
                  faces.append([vertex_index + 3, vertex_index + 2, vertex_index + 7])
                  faces.append([vertex_index + 2, vertex_index + 4, vertex_index + 7])  # Côté 4
                  faces.append([vertex_index + 2, vertex_index + 6, vertex_index + 7])
      # Convertir les points et les faces en tableaux NumPy
      vertices = np.array(vertices, dtype=np.float32)
      faces = np.array(faces, dtype=np.uint32)
      # Créer le maillage STL
      stl_mesh = mesh.Mesh(np.zeros(faces.shape[0], dtype=mesh.Mesh.dtype))
      for i, f in enumerate(faces):
          for j in range(3):
              stl_mesh.vectors[i][j] = vertices[f[j], :]
      # Enregistrer le fichier STL
      output_path =  os.path.splitext(image_name)[0] +  "-Traitement.stl"
      stl_mesh.save(output_path)
      print(f"Le modèle 3D avec épaisseur a été enregistré dans {output_path}.")