Comment sauvegarder une image pour une publication
définir la zone d’interet sur qupath
Ouvrir Qupath et selectionnez votre zone d’interet
sauver le geojson
Sauver votre objet geojson dans le meme dossier que votre lame et avec le meme nom
lancer le script
import cv2
import openslide
import math
import json
import numpy as np
from shapely.geometry import Polygon
from PIL import Image
from skimage import transform,util
import os
def extract_and_plot_lowest_mag_roi_svs(fpath: str, rotation=False)
print(fpath)
"""
Extrait une région définie par un GeoJSON d'un fichier SVS au niveau de grandissement le plus faible,
l'exporte en OME-TIFF et affiche les étapes intermédiaires.
Args:
svs_path (str): Chemin du fichier SVS.
geojson_path (str): Chemin du fichier GeoJSON contenant la région à extraire.
output_path (str): Chemin de sortie pour l'image OME-TIFF.
"""
svs_path=fpath+".svs"
geojson_path=fpath+".geojson"
i=0
# Charger l'image SVS
slide = openslide.OpenSlide(svs_path)
# Charger le GeoJSON
with open(geojson_path, 'r') as f:
geojson_data = json.load(f)
# Extraire les coordonnées du polygone du GeoJSON
for feature in geojson_data["features"]:
i=i+1
output_path=fpath+"."+str(i)+".jpg"
polygon_coords = feature["geometry"]["coordinates"][0]
# mettre le polygone à l'echelle
polygon_coords= [(int(xi ), int(yi )) for xi, yi in polygon_coords]
# Convertir en tableau NumPy pour utiliser min et max
polygon_coords_np = np.array(polygon_coords)
min_x, min_y, max_x, max_y = map(int, Polygon(polygon_coords).bounds)
# Déterminer les min et max des coordonnées
Min_x, Min_y = polygon_coords_np.min(axis=0)
# Normalisation et mise à l’échelle
scaled_coords = [(int((x - Min_x)),int((y - Min_y)))for x, y in polygon_coords]
# Lire la région d'intérêt (ROI) depuis le niveau de faible grandissement
roi = slide.read_region((int(min_x), int(min_y)), 0, (max_x - min_x, max_y - min_y))
roi = roi.convert("RGB")
roi_np = np.array(roi)
# Créer un masque pour ne garder que la zone définie par le polygone
mask = np.zeros((roi_np.shape[0], roi_np.shape[1]), dtype=np.uint8)
cv2.fillPoly(mask, [np.array(scaled_coords, np.int32)], 255)
# Convertir en BGR pour OpenCV
#roi_np_bgr = cv2.cvtColor(roi_np, cv2.COLOR_RGB2BGR)
roi_np_bgr = roi_np
roi_np_masked = cv2.bitwise_and(roi_np_bgr, roi_np_bgr, mask=mask)
# Appliquer le masque sur l'image
if rotation:
X=int(np.min((np.where(roi_np_masked[0,:,0]>0))[0]))
Y=int(np.min((np.where(roi_np_masked[:,0,0]>0))[0]))
roi_np_masked = cv2.resize(roi_np_masked, (0, 0), fx=0.8, fy=0.8)
if X!=0:
roi_np_masked=transform.rotate(roi_np_masked, 180-math.atan(Y/X)*180/np.pi, resize=True)
x,y=np.where(roi_np_masked[:,:,0]>0)
roi_np_masked=roi_np_masked[min(x):max(x),min(y):max(y),:]
if roi_np_masked.shape[1]<roi_np_masked.shape[0]:
print("haut")
roi_np_masked=transform.rotate(roi_np_masked, 90, resize=True)
x,y=np.where(roi_np_masked[:,:,0]>0)
roi_np_masked=roi_np_masked[min(x):max(x),min(y):max(y),:]
Image.fromarray(util.img_as_ubyte(roi_np_masked)).save(output_path, quality=95)