{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### MAIN NOTEBOOK DE ARMADO DE DATASET PARA SEGMENTACIÓN ÍNTEGRA -> CÁLCULO DE VOLUMEN (después de probar todo lo posible)"
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [],
"source": [
"import os\n",
"import nibabel as nib\n",
"import numpy as np\n",
"import cv2\n",
"import torchio as tio\n",
"import matplotlib.pyplot as plt\n",
"import SimpleITK as sitk\n",
"from PIL import Image\n",
"import elasticdeform\n",
"from sklearn.model_selection import train_test_split\n",
"import shutil\n",
"from nyul import nyul_train_standard_scale\n",
"from nyul import nyul_apply_standard_scale"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"### INFO GENERAL DEL DATASET\n",
"\n",
"Hay 6 datasets rejuntados -> total de 116 pacientes -> todas secuencias T2 con sus máscaras anexas en formato .nii
\n",
"Todo los dataset tienen secuencias mixtas en tamaño de pixel y cantidad de slices.
\n",
"Además, algunas tienen endorectal coil.
\n",
"Aclaración: no se realizó ningun registro (centrado en base a imágen madre) ya que el dataset ya viene preprocesado en ese sentido.
\n",
"\n",
"#### PREPROCESADO\n",
"\n",
"A priori, se renombraron todos las secuencias y sus máscaras en un formato conveniente.
\n",
"\n",
"1. Se realizó un flip de 90° ya que las imágenes viniero rotadas. Además se binarizaron las máscaras ya que algunos datasets tenian multiclase.
\n",
"\n",
"2. Se aplicó Bias Correction (N4ITK) a todas las secuencias (incluidas las de TEST ya que se supone parte del preprocesado).
\n",
"\n",
"3. Se separaron los 116 pacientes en 10% test (12), del 90% restante (104), 75% train (77), 25% validation (27).
\n",
">* Se separó a nivel paciente siguiendo los criterios del \"Checklist for Artificial Intelligence in Medical Imaging\" (CLAIM).
\n",
"\n",
"4. Se normalizaron las secuencias utilizando el algoritmo de Nyul.
\n",
">* Del entrenamiento de Nyul (con img de train) surgen los landmarks para el preprocesado de futuras secuencias.
\n",
"\n",
"5. Se separaron los slices de todas las secuencias en archivos formato .npy.
\n",
">* Se recortó el centro de las imágenes llevandolas de 384x384 a 256x256.
\n",
">* Se estandarizaron las imágenes con z-score normalization utilizando la media y desviación estándar las imágenes recortadas.
\n",
">* media = 3.4506247419236113, var = 42.43344987315689
\n",
"\n",
"6. Se realizó Data Augmentation del set de training y validation.
\n",
">* Se aplicó Elastic Deformation 2D aleatoriamente al casi 50% (randint) de slices.
\n",
">* Se hizo 2D por que 3D generaba artefactos. Además se realizo a la imágen completa, para recortar los defectos de borde.
\n",
">* Se utilizó la librería elasticdeformation con sigma=5 y points=10
\n",
"\n",
"Al final del split la cantidad de imágenes por set quedó: train: 2665, validation: 826, test: 396
\n",
"Total = 3887
\n",
"Con augmentation quedó: train: 4003, validation: 1228, test: 396
\n",
"Total = 5627
"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"---\n",
"RENAME"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"fp = r\"C:\\Users\\Pier\\Desktop\\PFI_main\\ds_mezcla_segmentacion integra\\nuevas\"\n",
"fp2 = r\"C:\\Users\\Pier\\Desktop\\PFI_main\\ds_mezcla_segmentacion integra\\nuevas2\"\n",
"allfiles = os.listdir(fp)\n",
"allfilesfinales = os.listdir(fp2)\n",
"cont = int(len(allfilesfinales)/2)\n",
"cont2 = int(len(allfilesfinales)/2)\n",
"for file in sorted(allfiles):\n",
" print(file)\n",
" if (\"segmentation\" in file ) or (\"Segmentation\" in file): \n",
" cont+=1\n",
" os.rename(os.path.join(fp,file),os.path.join(fp2,\"segmentacion_\"+str(cont).zfill(3)+\".nii\"))\n",
" else:\n",
" cont2+=1\n",
" os.rename(os.path.join(fp,file),os.path.join(fp2,\"sujeto_\"+str(cont2).zfill(3)+\".nii\"))\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"---\n",
"FLIP Y BINARIZADO "
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"fp = r\"C:\\Users\\Pier\\Desktop\\PFI_main\\ds_mezcla_segmentacion integra\\nuevas2\"\n",
"fp2 = r\"C:\\Users\\Pier\\Desktop\\PFI_main\\ds_mezcla_segmentacion integra\\nuevas\"\n",
"allfiles = os.listdir(fp)\n",
"for file in sorted(allfiles):\n",
" print(file)\n",
" x = nib.load(os.path.join(fp,file))\n",
" img = x.get_fdata()\n",
" img = np.rot90(img,3)\n",
" if \"segmentacion\" in file: img = np.any(img)\n",
" nifti = nib.Nifti1Image(img, header = x.header, affine= x.affine)\n",
" nib.save(nifti, os.path.join(fp2, file)) "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"---\n",
"BIAS CORRECTION"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"fp = r\"C:\\Users\\Pier\\Desktop\\PFI_main\\ds_mezcla_segmentacion integra\\aa\"\n",
"fp2 = r\"C:\\Users\\Pier\\Desktop\\PFI_main\\ds_mezcla_segmentacion integra\\flipped\"\n",
"allfiles = os.listdir(fp)\n",
"for file in sorted(allfiles):\n",
" if \"sujeto\" in file:\n",
" x = nib.load(os.path.join(fp,file))\n",
" img = x.get_fdata()\n",
" inputImage = sitk.ReadImage(os.path.join(fp,file))\n",
" maskImage = sitk.OtsuThreshold(inputImage,0,1,200)\n",
" inputImage = sitk.Cast(inputImage,sitk.sitkFloat32)\n",
" corrector = sitk.N4BiasFieldCorrectionImageFilter()\n",
" output = corrector.Execute(inputImage,maskImage)\n",
" newimg = np.transpose(sitk.GetArrayViewFromImage(output))\n",
" nifti = nib.Nifti1Image(newimg, header = x.header, affine= x.affine)\n",
" nib.save(nifti, os.path.join(fp2, file)) \n",
" else:\n",
" shutil.copy2(os.path.join(fp,file), os.path.join(fp2,file))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"---\n",
"SPLIT TRAIN-VALIDATION-TEST"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {},
"outputs": [],
"source": [
"fp1 = r\"C:\\Users\\Pier\\Desktop\\PFI_main\\ds_mezcla_segmentacion integra\\bias_corrected_sec\\sujetos\"\n",
"fp2 = r\"C:\\Users\\Pier\\Desktop\\PFI_main\\ds_mezcla_segmentacion integra\\bias_corrected_sec\\mascaras\"\n",
"sujetos = os.listdir(fp1)\n",
"segmentaciones = os.listdir(fp2)\n",
"suj_train,suj_test,seg_train,seg_test = train_test_split(sujetos,segmentaciones,train_size=0.9,random_state=23) #random_state = 23"
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {},
"outputs": [],
"source": [
"\n",
"fp1 = r\"C:\\Users\\Pier\\Desktop\\PFI_main\\ds_mezcla_segmentacion integra\\bias_corrected_sec\\sujetos\"\n",
"fp0 = r\"C:\\Users\\Pier\\Desktop\\PFI_main\\ds_mezcla_segmentacion integra\\bias_corrected_sec\\mascaras\"\n",
"fp2 = r\"C:\\Users\\Pier\\Desktop\\PFI_main\\DS_VOLUMEN\\main\\train_data\\sujetos\"\n",
"fp3 = r\"C:\\Users\\Pier\\Desktop\\PFI_main\\DS_VOLUMEN\\main\\test_data\\sujetos\"\n",
"fp4 = r\"C:\\Users\\Pier\\Desktop\\PFI_main\\DS_VOLUMEN\\main\\train_data\\mascaras\"\n",
"fp5 = r\"C:\\Users\\Pier\\Desktop\\PFI_main\\DS_VOLUMEN\\main\\test_data\\mascaras\"\n",
"\n",
"for file in suj_train:\n",
" shutil.copy2(os.path.join(fp1,file), os.path.join(fp2,file))\n",
"for file in suj_test:\n",
" shutil.copy2(os.path.join(fp1,file), os.path.join(fp3,file))\n",
"for file in seg_train:\n",
" shutil.copy2(os.path.join(fp0,file), os.path.join(fp4,file))\n",
"for file in seg_test:\n",
" shutil.copy2(os.path.join(fp0,file), os.path.join(fp5,file))"
]
},
{
"cell_type": "code",
"execution_count": 9,
"metadata": {},
"outputs": [],
"source": [
"fp1 = r\"C:\\Users\\Pier\\Desktop\\PFI_main\\DS_VOLUMEN\\main\\train_data\\sujetos\"\n",
"fp2 = r\"C:\\Users\\Pier\\Desktop\\PFI_main\\DS_VOLUMEN\\main\\train_data\\mascaras\"\n",
"sujetos = os.listdir(fp1)\n",
"segmentaciones = os.listdir(fp2)\n",
"suj_train,suj_val,seg_train,seg_val = train_test_split(sujetos,segmentaciones,train_size=0.75,random_state=23) #random_state = 23"
]
},
{
"cell_type": "code",
"execution_count": 10,
"metadata": {},
"outputs": [],
"source": [
"fp1 = r\"C:\\Users\\Pier\\Desktop\\PFI_main\\DS_VOLUMEN\\main\\train_data\\sujetos\"\n",
"fp0 = r\"C:\\Users\\Pier\\Desktop\\PFI_main\\DS_VOLUMEN\\main\\train_data\\mascaras\"\n",
"fp3 = r\"C:\\Users\\Pier\\Desktop\\PFI_main\\DS_VOLUMEN\\main\\validation_data\\sujetos\"\n",
"fp5 = r\"C:\\Users\\Pier\\Desktop\\PFI_main\\DS_VOLUMEN\\main\\validation_data\\mascaras\"\n",
"\n",
"for file in suj_val:\n",
" shutil.move(os.path.join(fp1,file), os.path.join(fp3,file))\n",
"for file in seg_val:\n",
" shutil.move(os.path.join(fp0,file), os.path.join(fp5,file))"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"fp = r\"C:\\Users\\Pier\\Desktop\\PFI_main\\ds_mezcla_segmentacion integra\\bias_corrected_sec\\mascaras\"\n",
"allfiles = os.listdir(fp)\n",
"allz = 0\n",
"allnz = 0\n",
"\n",
"for file in allfiles:\n",
" if \"segmentacion\" in file:\n",
" x = nib.load(os.path.join(fp,file))\n",
" x = x.get_fdata()\n",
" for slice in range(np.size(x,2)):\n",
" if not np.any(x[:,:,slice]): allz+=1\n",
" else: allnz+=1\n",
"\n",
"print(allz,allnz) #2020 1867 -> 48% de máscaras tienen próstata"
]
},
{
"cell_type": "code",
"execution_count": 13,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"1416 1249 53.13320825515947\n",
"416 410 50.363196125908\n",
"188 208 47.474747474747474\n"
]
}
],
"source": [
"fp0 = [r\"C:\\Users\\Pier\\Desktop\\PFI_main\\DS_VOLUMEN\\main\\train_data\\mascaras\",\n",
" r\"C:\\Users\\Pier\\Desktop\\PFI_main\\DS_VOLUMEN\\main\\validation_data\\mascaras\",\n",
" r\"C:\\Users\\Pier\\Desktop\\PFI_main\\DS_VOLUMEN\\main\\test_data\\mascaras\"]\n",
"for fp in fp0:\n",
" allfiles = os.listdir(fp)\n",
" allz = 0\n",
" allnz = 0\n",
" for file in allfiles:\n",
" if \"segmentacion\" in file:\n",
" x = nib.load(os.path.join(fp,file))\n",
" x = x.get_fdata()\n",
" for slice in range(np.size(x,2)):\n",
" if not np.any(x[:,:,slice]): allz+=1\n",
" else: allnz+=1\n",
" print(allz,allnz,allz/(allz+allnz)*100) #cantidad de mascaras SIN prostata / CON prostata / SIN en % -> aprox 50+/-3% (dataset balanceado)"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"---\n",
"SEPARACION DE SLICES (formato .npy)"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"Se normalizó y estandarizó el dataset (training).\n",
"\n",
"Primero, se calcularon los landmarks de la normalización de histogramas Nyul para MRI.
\n",
"El objetivo de Nyul es eliminar las discrepancias en brillo para los mismos tejidos en distintas secuencias debidas a la diferencia de resonadores.
\n",
"De alguna forma simula una escala similar a la que se encuentra en CT.
"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {},
"outputs": [],
"source": [
"standard_path = 'nyul_landmarks.npy'"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"processing scan C:\\Users\\Pier\\Desktop\\PFI_main\\DS_VOLUMEN\\main\\train_data\\sujeto_001.nii\n",
"processing scan C:\\Users\\Pier\\Desktop\\PFI_main\\DS_VOLUMEN\\main\\train_data\\sujeto_002.nii\n",
"processing scan C:\\Users\\Pier\\Desktop\\PFI_main\\DS_VOLUMEN\\main\\train_data\\sujeto_004.nii\n",
"processing scan C:\\Users\\Pier\\Desktop\\PFI_main\\DS_VOLUMEN\\main\\train_data\\sujeto_007.nii\n",
"processing scan C:\\Users\\Pier\\Desktop\\PFI_main\\DS_VOLUMEN\\main\\train_data\\sujeto_008.nii\n",
"processing scan C:\\Users\\Pier\\Desktop\\PFI_main\\DS_VOLUMEN\\main\\train_data\\sujeto_009.nii\n",
"processing scan C:\\Users\\Pier\\Desktop\\PFI_main\\DS_VOLUMEN\\main\\train_data\\sujeto_012.nii\n",
"processing scan C:\\Users\\Pier\\Desktop\\PFI_main\\DS_VOLUMEN\\main\\train_data\\sujeto_013.nii\n",
"processing scan C:\\Users\\Pier\\Desktop\\PFI_main\\DS_VOLUMEN\\main\\train_data\\sujeto_014.nii\n",
"processing scan C:\\Users\\Pier\\Desktop\\PFI_main\\DS_VOLUMEN\\main\\train_data\\sujeto_015.nii\n",
"processing scan C:\\Users\\Pier\\Desktop\\PFI_main\\DS_VOLUMEN\\main\\train_data\\sujeto_016.nii\n",
"processing scan C:\\Users\\Pier\\Desktop\\PFI_main\\DS_VOLUMEN\\main\\train_data\\sujeto_017.nii\n",
"processing scan C:\\Users\\Pier\\Desktop\\PFI_main\\DS_VOLUMEN\\main\\train_data\\sujeto_018.nii\n",
"processing scan C:\\Users\\Pier\\Desktop\\PFI_main\\DS_VOLUMEN\\main\\train_data\\sujeto_020.nii\n",
"processing scan C:\\Users\\Pier\\Desktop\\PFI_main\\DS_VOLUMEN\\main\\train_data\\sujeto_022.nii\n",
"processing scan C:\\Users\\Pier\\Desktop\\PFI_main\\DS_VOLUMEN\\main\\train_data\\sujeto_024.nii\n",
"processing scan C:\\Users\\Pier\\Desktop\\PFI_main\\DS_VOLUMEN\\main\\train_data\\sujeto_026.nii\n",
"processing scan C:\\Users\\Pier\\Desktop\\PFI_main\\DS_VOLUMEN\\main\\train_data\\sujeto_029.nii\n",
"processing scan C:\\Users\\Pier\\Desktop\\PFI_main\\DS_VOLUMEN\\main\\train_data\\sujeto_032.nii\n",
"processing scan C:\\Users\\Pier\\Desktop\\PFI_main\\DS_VOLUMEN\\main\\train_data\\sujeto_035.nii\n",
"processing scan C:\\Users\\Pier\\Desktop\\PFI_main\\DS_VOLUMEN\\main\\train_data\\sujeto_036.nii\n",
"processing scan C:\\Users\\Pier\\Desktop\\PFI_main\\DS_VOLUMEN\\main\\train_data\\sujeto_037.nii\n",
"processing scan C:\\Users\\Pier\\Desktop\\PFI_main\\DS_VOLUMEN\\main\\train_data\\sujeto_038.nii\n",
"processing scan C:\\Users\\Pier\\Desktop\\PFI_main\\DS_VOLUMEN\\main\\train_data\\sujeto_039.nii\n",
"processing scan C:\\Users\\Pier\\Desktop\\PFI_main\\DS_VOLUMEN\\main\\train_data\\sujeto_040.nii\n",
"processing scan C:\\Users\\Pier\\Desktop\\PFI_main\\DS_VOLUMEN\\main\\train_data\\sujeto_041.nii\n",
"processing scan C:\\Users\\Pier\\Desktop\\PFI_main\\DS_VOLUMEN\\main\\train_data\\sujeto_043.nii\n",
"processing scan C:\\Users\\Pier\\Desktop\\PFI_main\\DS_VOLUMEN\\main\\train_data\\sujeto_044.nii\n",
"processing scan C:\\Users\\Pier\\Desktop\\PFI_main\\DS_VOLUMEN\\main\\train_data\\sujeto_045.nii\n",
"processing scan C:\\Users\\Pier\\Desktop\\PFI_main\\DS_VOLUMEN\\main\\train_data\\sujeto_046.nii\n",
"processing scan C:\\Users\\Pier\\Desktop\\PFI_main\\DS_VOLUMEN\\main\\train_data\\sujeto_049.nii\n",
"processing scan C:\\Users\\Pier\\Desktop\\PFI_main\\DS_VOLUMEN\\main\\train_data\\sujeto_051.nii\n",
"processing scan C:\\Users\\Pier\\Desktop\\PFI_main\\DS_VOLUMEN\\main\\train_data\\sujeto_054.nii\n",
"processing scan C:\\Users\\Pier\\Desktop\\PFI_main\\DS_VOLUMEN\\main\\train_data\\sujeto_055.nii\n",
"processing scan C:\\Users\\Pier\\Desktop\\PFI_main\\DS_VOLUMEN\\main\\train_data\\sujeto_058.nii\n",
"processing scan C:\\Users\\Pier\\Desktop\\PFI_main\\DS_VOLUMEN\\main\\train_data\\sujeto_059.nii\n",
"processing scan C:\\Users\\Pier\\Desktop\\PFI_main\\DS_VOLUMEN\\main\\train_data\\sujeto_060.nii\n",
"processing scan C:\\Users\\Pier\\Desktop\\PFI_main\\DS_VOLUMEN\\main\\train_data\\sujeto_061.nii\n",
"processing scan C:\\Users\\Pier\\Desktop\\PFI_main\\DS_VOLUMEN\\main\\train_data\\sujeto_062.nii\n",
"processing scan C:\\Users\\Pier\\Desktop\\PFI_main\\DS_VOLUMEN\\main\\train_data\\sujeto_063.nii\n",
"processing scan C:\\Users\\Pier\\Desktop\\PFI_main\\DS_VOLUMEN\\main\\train_data\\sujeto_064.nii\n",
"processing scan C:\\Users\\Pier\\Desktop\\PFI_main\\DS_VOLUMEN\\main\\train_data\\sujeto_065.nii\n",
"processing scan C:\\Users\\Pier\\Desktop\\PFI_main\\DS_VOLUMEN\\main\\train_data\\sujeto_066.nii\n",
"processing scan C:\\Users\\Pier\\Desktop\\PFI_main\\DS_VOLUMEN\\main\\train_data\\sujeto_067.nii\n",
"processing scan C:\\Users\\Pier\\Desktop\\PFI_main\\DS_VOLUMEN\\main\\train_data\\sujeto_069.nii\n",
"processing scan C:\\Users\\Pier\\Desktop\\PFI_main\\DS_VOLUMEN\\main\\train_data\\sujeto_070.nii\n",
"processing scan C:\\Users\\Pier\\Desktop\\PFI_main\\DS_VOLUMEN\\main\\train_data\\sujeto_071.nii\n",
"processing scan C:\\Users\\Pier\\Desktop\\PFI_main\\DS_VOLUMEN\\main\\train_data\\sujeto_073.nii\n",
"processing scan C:\\Users\\Pier\\Desktop\\PFI_main\\DS_VOLUMEN\\main\\train_data\\sujeto_074.nii\n",
"processing scan C:\\Users\\Pier\\Desktop\\PFI_main\\DS_VOLUMEN\\main\\train_data\\sujeto_076.nii\n",
"processing scan C:\\Users\\Pier\\Desktop\\PFI_main\\DS_VOLUMEN\\main\\train_data\\sujeto_077.nii\n",
"processing scan C:\\Users\\Pier\\Desktop\\PFI_main\\DS_VOLUMEN\\main\\train_data\\sujeto_080.nii\n",
"processing scan C:\\Users\\Pier\\Desktop\\PFI_main\\DS_VOLUMEN\\main\\train_data\\sujeto_081.nii\n",
"processing scan C:\\Users\\Pier\\Desktop\\PFI_main\\DS_VOLUMEN\\main\\train_data\\sujeto_082.nii\n",
"processing scan C:\\Users\\Pier\\Desktop\\PFI_main\\DS_VOLUMEN\\main\\train_data\\sujeto_083.nii\n",
"processing scan C:\\Users\\Pier\\Desktop\\PFI_main\\DS_VOLUMEN\\main\\train_data\\sujeto_084.nii\n",
"processing scan C:\\Users\\Pier\\Desktop\\PFI_main\\DS_VOLUMEN\\main\\train_data\\sujeto_085.nii\n",
"processing scan C:\\Users\\Pier\\Desktop\\PFI_main\\DS_VOLUMEN\\main\\train_data\\sujeto_087.nii\n",
"processing scan C:\\Users\\Pier\\Desktop\\PFI_main\\DS_VOLUMEN\\main\\train_data\\sujeto_090.nii\n",
"processing scan C:\\Users\\Pier\\Desktop\\PFI_main\\DS_VOLUMEN\\main\\train_data\\sujeto_091.nii\n",
"processing scan C:\\Users\\Pier\\Desktop\\PFI_main\\DS_VOLUMEN\\main\\train_data\\sujeto_092.nii\n",
"processing scan C:\\Users\\Pier\\Desktop\\PFI_main\\DS_VOLUMEN\\main\\train_data\\sujeto_093.nii\n",
"processing scan C:\\Users\\Pier\\Desktop\\PFI_main\\DS_VOLUMEN\\main\\train_data\\sujeto_095.nii\n",
"processing scan C:\\Users\\Pier\\Desktop\\PFI_main\\DS_VOLUMEN\\main\\train_data\\sujeto_097.nii\n",
"processing scan C:\\Users\\Pier\\Desktop\\PFI_main\\DS_VOLUMEN\\main\\train_data\\sujeto_101.nii\n",
"processing scan C:\\Users\\Pier\\Desktop\\PFI_main\\DS_VOLUMEN\\main\\train_data\\sujeto_103.nii\n",
"processing scan C:\\Users\\Pier\\Desktop\\PFI_main\\DS_VOLUMEN\\main\\train_data\\sujeto_104.nii\n",
"processing scan C:\\Users\\Pier\\Desktop\\PFI_main\\DS_VOLUMEN\\main\\train_data\\sujeto_105.nii\n",
"processing scan C:\\Users\\Pier\\Desktop\\PFI_main\\DS_VOLUMEN\\main\\train_data\\sujeto_106.nii\n",
"processing scan C:\\Users\\Pier\\Desktop\\PFI_main\\DS_VOLUMEN\\main\\train_data\\sujeto_107.nii\n",
"processing scan C:\\Users\\Pier\\Desktop\\PFI_main\\DS_VOLUMEN\\main\\train_data\\sujeto_108.nii\n",
"processing scan C:\\Users\\Pier\\Desktop\\PFI_main\\DS_VOLUMEN\\main\\train_data\\sujeto_109.nii\n",
"processing scan C:\\Users\\Pier\\Desktop\\PFI_main\\DS_VOLUMEN\\main\\train_data\\sujeto_110.nii\n",
"processing scan C:\\Users\\Pier\\Desktop\\PFI_main\\DS_VOLUMEN\\main\\train_data\\sujeto_111.nii\n",
"processing scan C:\\Users\\Pier\\Desktop\\PFI_main\\DS_VOLUMEN\\main\\train_data\\sujeto_112.nii\n",
"processing scan C:\\Users\\Pier\\Desktop\\PFI_main\\DS_VOLUMEN\\main\\train_data\\sujeto_114.nii\n",
"processing scan C:\\Users\\Pier\\Desktop\\PFI_main\\DS_VOLUMEN\\main\\train_data\\sujeto_115.nii\n"
]
}
],
"source": [
"DATA_DIR = r\"C:\\Users\\Pier\\Desktop\\PFI_main\\DS_VOLUMEN\\main\\train_data\"\n",
"\n",
"train_scans = []\n",
"for file in os.listdir(DATA_DIR):\n",
" path = os.path.join(DATA_DIR,file)\n",
" if not os.path.isdir(path):\n",
" if \"sujeto\" in file:\n",
" train_scans.append(path)\n",
"\n",
"standard_scale, perc = nyul_train_standard_scale(train_scans)\n",
"\n",
"np.save(standard_path, [standard_scale, perc])"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"El siguiente paso es la z-normalization de todo el dataset (training).
\n",
"Se obtienen la media y desviación estándar del conjunto y luego se aplica individualmente a cada imágen."
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {},
"outputs": [],
"source": [
"fp = r\"C:\\Users\\Pier\\Desktop\\PFI_main\\DS_VOLUMEN\\main\\train_data\"\n",
"todas = []\n",
"for file in os.listdir(fp):\n",
" path = os.path.join(fp,file)\n",
" if not os.path.isdir(path):\n",
" if \"sujeto\" in file:\n",
" x = nib.load(path)\n",
" x = x.get_fdata()\n",
" x = nyul_apply_standard_scale(x, standard_path)\n",
" for slice in range(np.size(x,2)):\n",
" todas.append(x[63:319,63:319,slice])#(256,256)\n",
"ds_hist = np.ravel(todas)"
]
},
{
"cell_type": "code",
"execution_count": 9,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"(174653440,) -105.35324697378185 1438.5698506254516 128.5606638621487\n",
"-105.35324697378185 127.20468995920034\n",
"3.469224631926393 42.501930251698305\n",
"5.8424965928392e-16 0.9999999999999982\n"
]
}
],
"source": [
"print(ds_hist.shape,np.min(ds_hist),np.max(ds_hist),3*np.std(ds_hist))\n",
"p1, p2 = np.percentile(ds_hist,0), np.percentile(ds_hist,99.8)\n",
"print(p1,p2) #-107.75208459640474 128.45794968358558\n",
"ds_hist_per = np.clip(ds_hist,p1,p2) #si menor a p1 -> p1, si mayor a p2 -> p2\n",
"media, var = np.mean(ds_hist_per), np.std(ds_hist_per) #3.4506247419236113 42.43344987315689\n",
"print(media,var)\n",
"ds_hist_norm= (ds_hist_per-media)/var\n",
"print(np.mean(ds_hist_norm),np.std(ds_hist_norm))"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"pruebas sin percentile y clipping"
]
},
{
"cell_type": "code",
"execution_count": 20,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"3.54715519304951 42.85355462071623\n",
"-1.9040429020822806e-16 1.000000000000004\n"
]
}
],
"source": [
"media, var = np.mean(ds_hist), np.std(ds_hist) #3.54715519304951 42.85355462071623\n",
"print(media,var)\n",
"ds_hist_norm= (ds_hist-media)/var\n",
"print(np.mean(ds_hist_norm),np.std(ds_hist_norm))"
]
},
{
"cell_type": "code",
"execution_count": 10,
"metadata": {},
"outputs": [
{
"data": {
"image/png": "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bN68OS644ILU+o6OjqitrY329vZ46qmn4p577only5fH/PnzM/GW6EPPPfdc3HXXXXHqqad2W66PFLY///nPcdZZZ8Vhhx0WDz/8cLz44ovx/e9/P4488shUm5tuuiluvfXWuPPOO+OZZ56JI444ImpqauLdd99NtbnkkkvihRdeiNWrV8fKlSvjySefjK985SuZeEuk2Xe/+9244447YunSpfH73/8+vvvd78ZNN90Ut912W6qNPlJYdu7cGZMmTYply5btc306+kNra2vMmDEjjj322GhqaorFixfHN7/5zfjhD3/Y5++PD+5AfeQvf/lLrF27Nr7xjW/E2rVr49/+7d9iw4YN8bd/+7fd2ukj+etg+5AuK1asiKeffjrGjBmz1zr9o48lQJIkSTJt2rSkrq4u9byjoyMZM2ZMsnDhwgxWRSZs3bo1iYhkzZo1SZIkyfbt25PDDjssefDBB1Ntfv/73ycRkTQ2NiZJkiS/+MUvkuLi4qS5uTnV5o477kjKysqStra2/n0D9JkdO3YkH/7wh5PVq1cn/+k//afk2muvTZJEHyFJ5syZk3z84x/f7/rOzs5k9OjRyeLFi1PLtm/fnpSWliY//elPkyRJkhdffDGJiOS5555LtXn44YeToqKi5PXXX++74ukXtbW1yeWXX95t2QUXXJBccsklSZLoI4UuIpIVK1aknqerP9x+++3JkUce2e17Zs6cOckJJ5zQx++IdNuzj+zLs88+m0RE8qc//SlJEn2kkOyvf/y///f/kmOOOSZZv359cuyxxyY333xzap3+0ffMcIOIaG9vj6amppg+fXpqWXFxcUyfPj0aGxszWBmZ0NLSEhERw4cPj4iIpqam2LVrV7f+ceKJJ8a4ceNS/aOxsTFOOeWUqKioSLWpqamJ1tbWeOGFF/qxevpSXV1d1NbWdusLEfoIEf/rf/2vmDJlSnzhC1+IUaNGxemnnx7/43/8j9T6V199NZqbm7v1kfLy8qiqqurWR4YNGxZTpkxJtZk+fXoUFxfHM888039vhj7xsY99LBoaGuIPf/hDRET89re/jV/96ldx7rnnRoQ+Qnfp6g+NjY3xyU9+MkpKSlJtampqYsOGDfHnP/+5n94N/aWlpSWKiopi2LBhEaGPFLrOzs649NJL4/rrr4+PfvSje63XP/qewA0i4s0334yOjo5uB8IR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Bx98MNasWRObN2+OCy64IIPVQv7YuXNnTJo0KZYtW7bP9TfddFPceuutceedd8YzzzwTRxxxRNTU1MS7776banPJJZfECy+8EKtXr46VK1fGk08+GV/5ylf66y1AeiXwAd19991JeXn5Xst/8YtfJMXFxUlzc3Nq2R133JGUlZUlbW1tSZIkyQ033JB89KMf7fZzF110UVJTU9OnNUO+O/bYY5Obb755v+tvv/325Mgjj0xti0mSJHPmzElOOOGEfqgOCsO0adOSurq61POOjo5kzJgxycKFCzNYFeS3BQsWJJMmTdrnuu3btyeHHXZY8uCDD6aW/f73v08iImlsbOynCqEwRESyYsWK1PPOzs5k9OjRyeLFi1PLtm/fnpSWliY//elPkyRJkhdffDGJiOS5555LtXn44YeToqKi5PXXX++32iFdzHCjzzQ2NsYpp5wSFRUVqWU1NTXR2toaL7zwQqrN9OnTu/1cTU1NNDY29mutkI8WLVoUI0aMiNNPPz0WL17c7XTuxsbG+OQnPxklJSWpZTU1NbFhw4b485//nIlyIa+0t7dHU1NTt++44uLimD59uu846GMvv/xyjBkzJo477ri45JJLYuPGjRER0dTUFLt27eq2XZ544okxbtw42yX0sVdffTWam5u7bX/l5eVRVVWV2v4aGxtj2LBhMWXKlFSb6dOnR3FxcTzzzDP9XjN8UAMzXQD5q7m5uVvYFhGp583NzQds09raGu+8804MHjy4f4qFPPPVr341zjjjjBg+fHg89dRTMW/evHjjjTfiBz/4QUS8v+1NmDCh28/svn0eeeSR/V4z5JM333wzOjo69vkd99JLL2WoKsh/VVVVsXz58jjhhBPijTfeiBtvvDE+8YlPxPr166O5uTlKSkr2uvZwRUVFamwK9I2ubWxf34u7HxuOGjWq2/qBAwfG8OHDbaPkJIEb3cydOze++93vHrDN73//+24XnwX6R2+2z/r6+tSyU089NUpKSuK//tf/GgsXLozS0tK+LhUAMuLcc89N/fvUU0+NqqqqOPbYY+OBBx7wh1wA+pXAjW6+9rWvxZe//OUDtjnuuON69FqjR4/e625sXXeBGj16dOq/e94ZasuWLVFWVmZQBHv4INtnVVVVvPfee/Haa6/FCSecsN9tL+Kv2ydw6EaOHBkDBgzY53ZmG4P+M2zYsPjI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",
"text/plain": [
"