Skip to content

Commit

Permalink
feat : convert img, labels -> nii.gz #24
Browse files Browse the repository at this point in the history
  • Loading branch information
Batwan01 committed Nov 18, 2024
1 parent e41b81d commit 88a109d
Showing 1 changed file with 200 additions and 0 deletions.
200 changes: 200 additions & 0 deletions hand_bone/visualize.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,206 @@
" # Visualize slices from the saved NIfTI file\n",
" visualize_nifti_slices(output_nifti_path)\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# Define input and output paths\n",
"input_folder_path = '/data/ephemeral/home/dataset_nnunet/test'\n",
"output_nifti_path = '/data/ephemeral/home/dataset_nnunet/train/test_images_combined.nii.gz'\n",
"\n",
"# Step 1: Load and sort images\n",
"def load_and_sort_images(input_folder):\n",
" \"\"\"\n",
" Load PNG images from a folder and sort them naturally.\n",
" \"\"\"\n",
" png_files = sorted(\n",
" [f for f in os.listdir(input_folder) if f.lower().endswith(\".png\")],\n",
" key=lambda x: int(''.join(filter(str.isdigit, x))) # Sort by numeric part of filenames\n",
" )\n",
" if not png_files:\n",
" raise ValueError(f\"No PNG files found in the folder: {input_folder}\")\n",
" \n",
" print(f\"Total images found: {len(png_files)}\")\n",
" return png_files\n",
"\n",
"# Step 2: Stack images into a 3D volume\n",
"def stack_images_to_volume(input_folder, png_files):\n",
" \"\"\"\n",
" Stack sorted PNG images into a 3D NumPy array.\n",
" \"\"\"\n",
" image_slices = []\n",
" for filename in png_files:\n",
" img_path = os.path.join(input_folder, filename)\n",
" img = Image.open(img_path).convert('L') # Convert to grayscale\n",
" img_np = np.array(img, dtype=np.uint8) # Ensure consistent data type\n",
" image_slices.append(img_np)\n",
"\n",
" # Stack slices along the depth axis\n",
" volume_np = np.stack(image_slices, axis=0) # Depth-first stacking\n",
" print(f\"Volume shape: {volume_np.shape}\")\n",
" return volume_np\n",
"\n",
"# Step 3: Save as NIfTI file\n",
"def save_volume_as_nifti(volume_np, output_path):\n",
" \"\"\"\n",
" Save a 3D NumPy array as a NIfTI (.nii.gz) file.\n",
" \"\"\"\n",
" sitk_image = sitk.GetImageFromArray(volume_np) # Convert NumPy array to SimpleITK image\n",
" sitk_image.SetSpacing((1.0, 1.0, 1.0)) # Set spacing (adjust if necessary)\n",
" sitk.WriteImage(sitk_image, output_path)\n",
" print(f\"NIfTI file saved at: {output_path}\")\n",
"\n",
"# Step 4: Visualize original images\n",
"def visualize_original_images(input_folder, png_files):\n",
" \"\"\"\n",
" Visualize the first few original PNG images.\n",
" \"\"\"\n",
" print(\"Visualizing original PNG images...\")\n",
" for i, filename in enumerate(png_files[:2]): # Show first 5 images\n",
" img_path = os.path.join(input_folder, filename)\n",
" img = Image.open(img_path)\n",
" plt.imshow(img, cmap='gray')\n",
" plt.title(f\"Original PNG: {filename}\")\n",
" plt.axis(\"off\")\n",
" plt.show()\n",
"\n",
"# Step 5: Visualize slices from NIfTI file\n",
"def visualize_nifti_slices(nifti_path):\n",
" \"\"\"\n",
" Visualize slices from a NIfTI file to verify integrity.\n",
" \"\"\"\n",
" sitk_image = sitk.ReadImage(nifti_path)\n",
" volume_np = sitk.GetArrayFromImage(sitk_image) # Get 3D volume as NumPy array\n",
" print(f\"NIfTI volume shape: {volume_np.shape}\")\n",
" \n",
" print(\"Visualizing NIfTI slices...\")\n",
" for i in range(1, volume_np.shape[0], 10): # Show every 10th slice\n",
" plt.imshow(volume_np[i, :, :], cmap=\"gray\")\n",
" plt.title(f\"NIfTI Slice {i}\")\n",
" plt.axis(\"off\")\n",
" plt.show()\n",
"\n",
"# Main script\n",
"if __name__ == \"__main__\":\n",
" # Load and sort PNG images\n",
" png_files = load_and_sort_images(input_folder_path)\n",
"\n",
" # Visualize original images\n",
" visualize_original_images(input_folder_path, png_files)\n",
"\n",
" # Stack images into a 3D volume\n",
" volume_np = stack_images_to_volume(input_folder_path, png_files)\n",
"\n",
" # Save the 3D volume as a NIfTI file\n",
" save_volume_as_nifti(volume_np, output_nifti_path)\n",
"\n",
" # Visualize slices from the saved NIfTI file\n",
" visualize_nifti_slices(output_nifti_path)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"import os\n",
"import json\n",
"import numpy as np\n",
"import SimpleITK as sitk\n",
"from skimage.draw import polygon\n",
"import matplotlib.pyplot as plt\n",
"\n",
"# Paths\n",
"input_folder_path = '/data/ephemeral/home/dataset_nnunet/train/labels' # JSON 파일이 있는 폴더\n",
"output_nifti_path = '/data/ephemeral/home/dataset_nnunet/train/train_labels_combined.nii.gz' # 저장될 하나의 NIfTI 파일 경로\n",
"image_dimensions = (2048, 2048) # 이미지 크기 (height, width)\n",
"\n",
"# Step 1: Parse JSON and Extract Annotations\n",
"def parse_json(json_path):\n",
" with open(json_path, 'r') as f:\n",
" data = json.load(f)\n",
" annotations = data.get(\"annotations\", [])\n",
" return annotations\n",
"\n",
"# Step 2: Generate Labeled Mask from Annotations\n",
"def generate_mask_from_annotations(annotations, dimensions):\n",
" \"\"\"\n",
" Create a labeled mask from polygon annotations.\n",
" Each unique annotation gets a unique integer label.\n",
" \"\"\"\n",
" mask = np.zeros(dimensions, dtype=np.uint16) # uint16으로 더 많은 레이블 ID 허용\n",
" for i, annotation in enumerate(annotations):\n",
" points = np.array(annotation[\"points\"], dtype=np.int32) # 좌표를 NumPy 배열로 변환\n",
" label = i + 1 # 고유 레이블 지정 (1부터 시작)\n",
" rr, cc = polygon(points[:, 1], points[:, 0], dimensions) # Row, column 좌표 생성\n",
" mask[rr, cc] = label # 마스크에 레이블 할당\n",
" return mask\n",
"\n",
"# Step 3: Save Mask as NIfTI File\n",
"def save_mask_as_nifti(volume, output_path):\n",
" \"\"\"\n",
" Save a 3D volume as a NIfTI (.nii.gz) file.\n",
" \"\"\"\n",
" sitk_image = sitk.GetImageFromArray(volume) # NumPy 배열을 SimpleITK 이미지로 변환\n",
" sitk_image.SetSpacing((1.0, 1.0, 1.0)) # 픽셀 간격 설정 (필요에 따라 조정)\n",
" sitk.WriteImage(sitk_image, output_path)\n",
" print(f\"NIfTI file saved at: {output_path}\")\n",
"\n",
"# Step 4: Visualize Slices from the Combined NIfTI\n",
"def visualize_slices(volume, num_slices=5):\n",
" \"\"\"\n",
" Visualize a few slices from the 3D volume.\n",
" \"\"\"\n",
" slice_indices = np.linspace(0, volume.shape[0] - 1, num_slices, dtype=int) # 균등한 간격으로 슬라이스 선택\n",
" for idx in slice_indices:\n",
" plt.imshow(volume[idx, :, :], cmap='nipy_spectral') # 다양한 레이블 표시를 위한 컬러맵 사용\n",
" plt.title(f\"Slice {idx}\")\n",
" plt.axis(\"off\")\n",
" plt.show()\n",
"\n",
"# Main Process\n",
"if __name__ == \"__main__\":\n",
" # Get all JSON files in the folder\n",
" json_files = sorted([f for f in os.listdir(input_folder_path) if f.endswith('.json')])\n",
"\n",
" if not json_files:\n",
" raise FileNotFoundError(f\"No JSON files found in folder: {input_folder_path}\")\n",
"\n",
" print(f\"Found {len(json_files)} JSON files.\")\n",
"\n",
" # Initialize a list to store 2D masks\n",
" volume_slices = []\n",
"\n",
" # Process each JSON file\n",
" for idx, json_file in enumerate(json_files):\n",
" json_path = os.path.join(input_folder_path, json_file)\n",
"\n",
" # Parse the JSON file\n",
" annotations = parse_json(json_path)\n",
"\n",
" # Generate a 2D labeled mask\n",
" mask = generate_mask_from_annotations(annotations, image_dimensions)\n",
" volume_slices.append(mask)\n",
"\n",
" print(f\"Processed {json_file} into a 2D mask.\")\n",
"\n",
" # Stack 2D masks into a 3D volume\n",
" volume = np.stack(volume_slices, axis=0) # (Depth, Height, Width)\n",
" print(f\"Combined volume shape: {volume.shape}\")\n",
"\n",
" # Save the 3D volume as a single NIfTI file\n",
" save_mask_as_nifti(volume, output_nifti_path)\n",
"\n",
" # Visualize a few slices from the combined volume\n",
" visualize_slices(volume, num_slices=5)\n",
"\n",
" print(\"Conversion to single NIfTI file completed successfully!\")\n"
]
}
],
"metadata": {
Expand Down

0 comments on commit 88a109d

Please sign in to comment.