diff --git a/PyNutil/coordinate_extraction.py b/PyNutil/coordinate_extraction.py index 989ea9b22beb6f46af078ff84c5c3086bc6c0676..2243a276a48cc9574ccfdecbafe633a3109ee7d7 100644 --- a/PyNutil/coordinate_extraction.py +++ b/PyNutil/coordinate_extraction.py @@ -10,6 +10,8 @@ import cv2 from skimage import measure import threading import re +from .reconstruct_dzi import reconstruct_dzi + def number_sections(filenames, legacy=False): """ @@ -208,7 +210,10 @@ def segmentation_to_atlas_space( ): """Combines many functions to convert a segmentation to atlas space. It takes care of deformations.""" - segmentation = cv2.imread(segmentation_path) + if segmentation_path.endswith(".dzip"): + segmentation = reconstruct_dzi(segmentation_path) + else: + segmentation = cv2.imread(segmentation_path) if pixel_id == "auto": # Remove the background from the segmentation segmentation_no_background = segmentation[~np.all(segmentation == 255, axis=2)] diff --git a/PyNutil/main.py b/PyNutil/main.py index 2e34d566876bf67f47ce211f33a14a013400b6e4..df9d5f838801d76d6b03269cae238c2dc5341273 100644 --- a/PyNutil/main.py +++ b/PyNutil/main.py @@ -8,6 +8,7 @@ from datetime import datetime import os + class PyNutil: """A utility class for working with brain atlases and segmentation data. diff --git a/PyNutil/reconstruct_dzi.py b/PyNutil/reconstruct_dzi.py new file mode 100644 index 0000000000000000000000000000000000000000..8a436977865d971d56de674316b89a0b3492bb36 --- /dev/null +++ b/PyNutil/reconstruct_dzi.py @@ -0,0 +1,51 @@ +import cv2 +import numpy as np +import os +import zipfile +import xmltodict + +def reconstruct_dzi(zip_file_path): + """ + Reconstructs a Deep Zoom Image (DZI) from a zip file containing the tiles. + :param zip_file_path: Path to the zip file containing the tiles. + :return: The reconstructed DZI. + """ + with zipfile.ZipFile(zip_file_path, "r") as zip_file: + # Get the highest level of the pyramid + highest_level = str( + np.max( + [ + int(os.path.split(os.path.split(i)[0])[1]) + for i in zip_file.namelist() + if i.endswith(".png") + ] + ) + ) + + # Get the filenames of the highest level tiles + highest_level_files = [ + i for i in zip_file.namelist() if i.endswith(".png") and i.split("/")[-2] == highest_level + ] + + # Read the DZI file + dzi_file = zip_file.open([i for i in zip_file.namelist() if i.endswith(".dzi")][0]) + xml = dzi_file.read() + json_data = xmltodict.parse(xml) + tileSize = json_data["Image"]["@TileSize"] + width, height = int(json_data["Image"]["Size"]["@Width"]), int(json_data["Image"]["Size"]["@Height"]) + + # Create an empty image + image = np.zeros((height, width, 3), dtype=np.uint8) + + # Fill in the image with the highest level tiles + for file in highest_level_files: + with zip_file.open(file) as f: + contents = f.read() + # Decode the binary PNG data + image_ = cv2.imdecode(np.frombuffer(contents, np.uint8), cv2.IMREAD_COLOR) + x, y = map(int, os.path.splitext(os.path.split(file)[1])[0].split("_")) + x, y = x * int(tileSize), y * int(tileSize) + image[y : y + image_.shape[0], x : x + image_.shape[1], :] = image_ + + # Save the image + return image \ No newline at end of file