-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
ff42089
commit 4797273
Showing
10 changed files
with
431 additions
and
307 deletions.
There are no files selected for viewing
Binary file renamed
BIN
+36 MB
dist/pyAutoRef-2.1.0-py3-none-any.whl → dist/pyAutoRef-2.2.1-py3-none-any.whl
Binary file not shown.
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,6 @@ | ||
[metadata] | ||
name = pyAutoRef | ||
version = 2.1.0 | ||
version = 2.2.1 | ||
author = Mohammed R. S. Sunoqrot | ||
author_email = [email protected] | ||
description = Python pakage to perfom AutoRef (prostate T2w MRI dual reference tissue [fat and muscle] normalization). | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,32 +1,48 @@ | ||
import numpy as np | ||
import SimpleITK as sitk | ||
|
||
|
||
def normalize_image(processed_images_intensities, corrected_image, fat_reference_value=121, muscle_reference_value=40, | ||
fat_intensity_percentile=95, muscle_intensity_percentile=5): | ||
""" | ||
Normalize the corrected 3D image using linear scaling based on the 90th percentile for fat and | ||
the 10th percentile for muscle. | ||
Normalize the corrected 3D image using linear scaling based on the specified percentiles for fat and muscle intensities. | ||
This function performs normalization of the 3D image by calculating the intensity values for fat and muscle | ||
based on specified percentiles and then scaling the corrected image accordingly. | ||
Parameters: | ||
processed_images_intensities (numpy.ndarray): An array contains all the intensites | ||
under the post-processed area under bounding box for all images each class separtly. | ||
corrected_image (SimpleITK.Image): The 3D image after correction and post-processing. | ||
fat_reference_value (float, optional): The reference value for fat after normalization. | ||
Default is 121. | ||
muscle_reference_value (float, optional): The reference value for muscle after normalization. | ||
Default is 40. | ||
fat_intensity_percentile (int, optional): The percentile for fat intensity to represent detected fat. Default is 95. | ||
muscle_intensity_percentile (int, optional): The percentile for muscle intensity to represent detected muscle. Default is 5. | ||
processed_images_intensities (dict): A dictionary containing arrays of intensities extracted from post-processed areas. | ||
Keys are class names ('fat', 'muscle') and values are arrays of intensities. | ||
corrected_image (SimpleITK.Image): The 3D image that has been corrected and post-processed. | ||
fat_reference_value (float, optional): The target reference value for fat after normalization. Default is 121. | ||
muscle_reference_value (float, optional): The target reference value for muscle after normalization. Default is 40. | ||
fat_intensity_percentile (int, optional): The percentile value to determine fat intensity. Default is 95. | ||
muscle_intensity_percentile (int, optional): The percentile value to determine muscle intensity. Default is 5. | ||
Returns: | ||
normalized_image (SimpleITK.Image): The normalized 3D image. | ||
SimpleITK.Image: The normalized 3D image. | ||
""" | ||
# Calculate the 95th/defined percentile for fat and the 5th/defined percentile for muscle | ||
fat_intensity = np.percentile(processed_images_intensities['fat'], fat_intensity_percentile) | ||
muscle_intensity = np.percentile(processed_images_intensities['muscle'], muscle_intensity_percentile) | ||
# Extract the intensity values for fat and muscle | ||
fat_intensities = processed_images_intensities.get('fat', np.array([])) | ||
muscle_intensities = processed_images_intensities.get( | ||
'muscle', np.array([])) | ||
|
||
# Calculate intensity percentiles | ||
fat_intensity = np.percentile( | ||
fat_intensities, fat_intensity_percentile) if fat_intensities.size > 0 else 1 | ||
muscle_intensity = np.percentile( | ||
muscle_intensities, muscle_intensity_percentile) if muscle_intensities.size > 0 else 0 | ||
|
||
# Convert SimpleITK image to NumPy array for processing | ||
corrected_image_np = sitk.GetArrayFromImage(corrected_image) | ||
|
||
# Apply linear normalization | ||
normalized_image_np = ((corrected_image_np - muscle_intensity) / (fat_intensity - muscle_intensity) | ||
) * (fat_reference_value - muscle_reference_value) + muscle_reference_value | ||
|
||
# Linearly scale the corrected image to the fat and muscle reference values | ||
normalized_image = ((corrected_image - muscle_intensity) / (fat_intensity - muscle_intensity) | ||
) * (fat_reference_value - muscle_reference_value) + muscle_reference_value | ||
# Convert the NumPy array back to SimpleITK image | ||
normalized_image = sitk.GetImageFromArray(normalized_image_np) | ||
normalized_image.CopyInformation(corrected_image) | ||
|
||
# Return the normalized image | ||
return normalized_image |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,61 +1,86 @@ | ||
import os | ||
|
||
import logging | ||
from pyAutoRef.utils import detect_objects_on_image | ||
|
||
# Set up logging | ||
logging.basicConfig(level=logging.INFO, | ||
format='%(asctime)s - %(levelname)s - %(message)s') | ||
|
||
|
||
def object_detection(input_folder, model_path, yolo_classes=["fat", "muscle"], slice_percent=[0.15, 0.85]): | ||
def object_detection(input_folder, model_path, yolo_classes=None, slice_percent=None): | ||
""" | ||
Perform prediction on multiple images in an input folder and select the top 3 images | ||
with the highest prediction score for each class. | ||
Perform object detection on multiple images in an input folder and select the top 3 images | ||
with the highest prediction scores for each class. | ||
Parameters: | ||
input_folder (str): The path to the folder containing the input images. | ||
model_path (str): The path to the YOLO v8 ONNX model file. | ||
yolo_classes (list): The classes of the trained model. Default is ["fat", "muscle"]. | ||
slice_percent (list): The percentage range of slices to be detected. Default is [0.15, 0.85]. Remove the first 15% and the last 15% of slices. | ||
yolo_classes (list, optional): The classes of the trained model. Default is ["fat", "muscle"]. | ||
slice_percent (list, optional): The percentage range of slices to be detected. Default is [0.15, 0.85]. | ||
Removes the first 15% and the last 15% of slices. | ||
Returns: | ||
top_predictions (dict): A dictionary containing the top 3 predictions for each class. | ||
The keys are class names, and the values are lists of dictionaries. | ||
Each dictionary contains the 'slice' name (without the ".jpg"), | ||
the bounding box coordinates, and the probability score. | ||
""" | ||
if yolo_classes is None: | ||
yolo_classes = ["fat", "muscle"] | ||
if slice_percent is None: | ||
slice_percent = [0.15, 0.85] | ||
|
||
# Initialize a dictionary to store the top 3 predictions for each class. | ||
top_predictions = {class_name: [] for class_name in yolo_classes} | ||
|
||
# Get a list of image filenames in the input folder. | ||
image_filenames = [filename for filename in os.listdir( | ||
input_folder) if filename.endswith(".jpg")] | ||
try: | ||
image_filenames = [filename for filename in os.listdir( | ||
input_folder) if filename.endswith(".jpg")] | ||
except FileNotFoundError as e: | ||
logging.error(f"Input folder not found: {e}") | ||
raise | ||
|
||
# Sort the image filenames (assuming filenames are in the format '00.jpg', '01.jpg', etc.) | ||
# Sort the image filenames | ||
image_filenames.sort() | ||
|
||
# Calculate the number of images | ||
num_images = len(image_filenames) | ||
|
||
# Calculate the middle part range | ||
if num_images == 0: | ||
logging.warning("No images found in the input folder.") | ||
return top_predictions | ||
|
||
# Calculate the range of slices to process | ||
start_index = int(num_images * slice_percent[0]) | ||
end_index = int(num_images * slice_percent[1]) | ||
|
||
# Loop through the images in the input folder and perform object detection on them. | ||
# Perform object detection on the selected range of images | ||
for filename in image_filenames[start_index:end_index]: | ||
image_path = os.path.join(input_folder, filename) | ||
result = detect_objects_on_image(image_path, model_path) | ||
try: | ||
result = detect_objects_on_image(image_path, model_path) | ||
except Exception as e: | ||
logging.error(f"Error detecting objects in {filename}: {e}") | ||
continue | ||
|
||
# For each detected object, store the information in the top_predictions dictionary. | ||
# Store the prediction results | ||
for prediction in result: | ||
class_name = prediction[4] | ||
top_predictions[class_name].append({ | ||
'slice': os.path.splitext(filename)[0], | ||
'bbox': prediction[:4], | ||
'probability': prediction[5] | ||
}) | ||
if class_name in top_predictions: | ||
top_predictions[class_name].append({ | ||
'slice': os.path.splitext(filename)[0], | ||
'bbox': prediction[:4], | ||
'probability': prediction[5] | ||
}) | ||
|
||
# Sort the predictions by probability score in descending order for each class. | ||
# Sort and select top 3 predictions for each class | ||
for class_name in yolo_classes: | ||
top_predictions[class_name].sort( | ||
key=lambda x: x['probability'], reverse=True) | ||
top_predictions[class_name] = top_predictions[class_name][:3] | ||
logging.info( | ||
f"Top predictions for class {class_name}: {top_predictions[class_name]}") | ||
|
||
# Return the final dictionary containing the top 3 predictions for each class. | ||
return top_predictions |
Oops, something went wrong.