Using AI to democratize access to diagnostic healthcare for all, version 1.0
First of all, Thank you so much for your amazing project.
You are awesome!
You are entitled to contribute and get free code updates to this product + exceptional support from the author directly.
This documentation is to help you regarding each step of setting up and running it locally. Please go through the documentation carefully to understand how to setup properly. Python knowledge is required to setup and contribute to this project. You may learn basics here, here and here.
You will need the following softwares to get started.
Be careful while installing dependencies. If not installed properly, the code may break completely. We would recommend setting up a virtual environment.
No support is provided for older libraries not included in the dependencies.
NeuralSight is an Intelligent tool that offers a great opportunity to enhance and augment radiology services thereby relieving the bottleneck in medical imaging diagnosis. NeuralSight provides a high-level web-interface equipped with advanced annotation tools and project management features. NeuralSight was designed from the ground up to enhance the radiology workflow and reduce backlogs in the workflow.
NeuralSightâ„¢ provides automated interpretation of radiology exams like CXRs, CTs and MRI scans to identify pathologies and diseases such as Pneumothorax, Cardiomegaly, Benign breast Tumour, Malignant breast Cancer, Atelectasis, Infiltration, Emphysema, Mass/Nodule, Pleural Thickening, Effusion, Consolidation, Tuberculosis, Pneumonia, Prostate and Lung cancer.
To provide a thorough and actionable innovation artificial intelligence solutions that will help the healthcare sector achieve its objectives. reduces workload and thereby eases such costs and provides a friendly pricing model to patients. Offering affordable health care services will ensure that everyone, even those in marginalised communities, are able to receive healthcare services. AI to solve the overwhelming UN Strategic Development Goal 3 Good Health and Wellbeing has the potential to ensure that Africa improves its healthcare system.
NEURALSIGHT system is a combination of YOLOv5 trained model and a set of endpoints that allows users to detect 14 Chest X-ray pathologies. The model is trained using a VinBig dataset of X-ray images and annotations of the 14 pathologies of interest. The model is able to predict bounding boxes and class probabilities for each object (pathology) in an image. The endpoints allow users to perform tasks such as logging in and uploading images for prediction, as well as viewing and downloading the prediction results and reports. The model is already trained hence the users only require to upload their XRAY images and be able to get response as the prediction and reports. The model has been evaluated on a test dataset and has shown to have good performance in terms of metrics such as average precision and mean average precision. The model is deployed using FastAPI, which is a lightweight web framework for building web applications and APIs, and is easily integrated with other technologies.
For this dataset, the main aim was to come up with an object classifying system for common thoracic lung diseases and localizing critical findings. This is an object detection and classification problem. The images are in png file with difference dimensions i.e 1024, 216 and 512. In this project, Images that were used were the one with 512 dimensions.
The dataset comprises 67914 annotated and those not annotated images where there was only 4394 unique patients images that were annotated for posterior-anterior (PA) Xrays scans in PNG format. All images were labeled by a panel of experienced radiologists for the presence of 14 critical radiographic findings as listed below:
0 - Aortic enlargement
1 - Atelectasis
2 - Calcification
3 - Cardiomegaly
4 - Consolidation
5 - ILD
6 - Infiltration
7 - Lung Opacity
8 - Nodule/Mass
9 - Other lesion
10 - Pleural effusion
11 - Pleural thickening
12 - Pneumothorax
13 - Pulmonary fibrosis
The "No finding" observation (14) was intended to capture the absence of all
findings above but in this case it was ignored.
The Model (YOLOv5) requires specific data preprocessing steps in order to work
effectively. In this case, we were to process our information to meets this standard.
The following is a detailed workflow documentation of the data preprocessing steps
that were taken in this particular case:
The main difference between GroupKFold and other cross-validation techniques like
train_test_split is that it helped takes into account pathologies or labels for each
class in the sample split equally. i.e, Since some pathologies had more class Distribution
than others, It helped us ensure that the samples from one class label of pathology
do not end up in the same group and are equally Distributed in both groups. For this
project, since the data is split into 5 folds, 1/5 (or 20%) of the data will be used
as the test set, while 4/5 (or 80%) will be used as the training set.
To structure the images and labels for YOLOv5 training, We created the following 4 directories where the training and validation information was to reside.
1. `/WORKING_DIR/PROJECT_DIR/labels/train` - This directory will store the labels (annotations) for the training images.
2. `/WORKING_DIR/PROJECT_DIR/labels/val` - This directory will store the labels (annotations) for the validation images.
3. `/WORKING_DIR/PROJECT_DIR/images/train` - This directory will store the training images.
4. `/WORKING_DIR/PROJECT_DIR/images/val` - This directory will store the validation images.
Once the directories were created, We then moved or copy the images and their corresponding labels to the appropriate directories. The labels for each image should have the same file name as the image, and should be placed in the appropriate label directory
(either `/WORKING_DIR/PROJECT_DIR/labels/train` or
`/WORKING_DIR/PROJECT_DIR/labels/val`).
The labels were also in their own format. Each image had a single text file as labels. The format of labels for YOLOv5 model used was a plain text file with the same name as the corresponding image file, and with a `.txt` extension. The file should contain one line for each object in the image, with the following format:
Get started by setting up your environment.
Or try our demo with neurallabs.africa.
Please read more about NeuralSight here. NeuralSight Github Repository.
Python version 3.5 or above:
Clone the repository to your local machine.
git clone https://github.com/NeuralSight/NeuralSight_AI.git
You can type this command into Command Prompt, Powershell, Terminal, or any other integrated terminal of your code editor.
Clone the repository to your local machine.
git clone https://github.com/NeuralSight/NeuralSight_AI.git
You can type this command into Command Prompt, Powershell, Terminal, or any other integrated terminal of your code editor.
cd NeuralSight_AI
The cd command changes the directory you're working with. In order to work with your
newly created Docusaurus site, you'll need to navigate the terminal there.
Install all the dependencies using the requirements.txt file.
pip install -r requirements.txt
The command installs all necessary dependencies you need to run NeuralSight.
Add Medical files to the workspace for preprocessing:
python preprocess.py
Create a file at NeuralSight_AI/training/process.py:
#import some modules
from tqdm.notebook import tqdm
from glob import glob
import shutil, os
import cv2
import pandas as pd
import numpy as np
from cleaning import create_data
import warnings
warnings.filterwarnings("ignore");
import dotenv
dotenv.load_dotenv()
DATA_DIR = os.getenv("DATA_DIRECTORY")
TRAIN_DIR = os.getenv("TRAIN_DIR")
WANDB_API_KEY = os.getenv("WANDB_API_KEY")
#check if the file exists
if not os.path.isfile(f'{DATA_DIR}/train.csv'):
print(f"No SUch Directory in the path Passed : PATH SEND :: {DATA_DIR}/train.csv")
print("Exiting....")
exit(0)
# read the data
df = pd.read_csv(f'{DATA_DIR}/train.csv')
df1 = df[["image_id","x_min","y_min","x_max","y_max","class_id", "height", "width", "class_name"]].dropna()
df1['path'] = df1['image_id'].apply(lambda x: f"{DATA_DIR}/train/{x}.png")
# get class id
class_dict = {v:k for k,v in dict(df1[['class_name', "class_id"]].values).items()}
# save df1 in order to use it for plotting
df1.to_csv("train_clean.csv", index=False)
check_df = create_data(df1)
# class names available
classes = list(check_df['class_name'].unique())
# Yolo normaly requires bbox to be normalized between 0 and 1.
# Since we have have height and width for a particular image, we gonna just divide bbox against either widht or height.
# We then extract the widht and height of the bbox from the above calibrations
df = check_df.copy()
df['x_min'] = df.apply(lambda x: (x.x_min)/x.width, axis =1)
df['y_min'] = df.apply(lambda x: (x.y_min)/x.height, axis =1)
df['x_max'] = df.apply(lambda x: (x.x_max)/x.width, axis =1)
df['y_max'] = df.apply(lambda x: (x.y_max)/x.height, axis =1)
df['x_mid'] = df.apply(lambda x: (x.x_max+x.x_min)/2, axis =1)
df['y_mid'] = df.apply(lambda x: (x.y_max+x.y_min)/2, axis =1)
df['w'] = df.apply(lambda x: (x.x_max-x.x_min), axis =1)
df['h'] = df.apply(lambda x: (x.y_max-x.y_min), axis =1)
df['area'] = df['w']*df['h']
selected_classes = (df['class_name'].value_counts(normalize=True).T[df['class_name'].value_counts(normalize=True).T >0.0001])
SELECTED_CLASS_NAMES = list(selected_classes.index)
# Get a dataframe with selected classes
selected_df = df[df['class_name'].isin(SELECTED_CLASS_NAMES)]
# only which have below 40 bbox instances
img_ids = list((df['image_id'].value_counts(normalize=False).T[df['image_id'].value_counts(normalize=False).T <=40]).index)
# pd.DataFrame(base_details)
TRAIN =[]
# for img_id in selected_df['image_id'].unique():
for img_id in selected_df[selected_df['image_id'].isin(img_ids)]['image_id'].unique():
curr_df = selected_df[selected_df['image_id'] ==img_id].reset_index(drop=True)
base_details = dict(curr_df.loc[0][['image_id',"path",'width', 'height']])
information =[]
for indx in range(curr_df.shape[0]):
other_details = dict(curr_df.loc[indx][['class_name', "x_min", "y_min","x_max","y_max", "x_mid", "y_mid", "w", "h", "area" ]])
information.append(other_details)
TRAIN.append([base_details['image_id'],base_details['path'] ,base_details['width'],base_details['height'],information])
final_data = pd.DataFrame(TRAIN, columns =['image_id',"path", "width", "height", "information"])
from pprint import pprint
print(final_data.head())
# save this data for feature usage.
final_data.to_csv("processed.csv", index=False)
Add Medical files to the workspace for preprocessing:
python preprocess.py
Create a file at NeuralSight_AI/training/process.py:
from tqdm.notebook import tqdm
from glob import glob
import shutil, os
import cv2
import pandas as pd
import numpy as np
from cleaning import create_data
import warnings
warnings.filterwarnings("ignore");
import dotenv
dotenv.load_dotenv()
DATA_DIR = os.getenv("DATA_DIRECTORY")
TRAIN_DIR = os.getenv("TRAIN_DIR")
WANDB_API_KEY = os.getenv("WANDB_API_KEY")
#check if the file exists
if not os.path.isfile(f'{DATA_DIR}/train.csv'):
print(f"No SUch Directory in the path Passed : PATH SEND :: {DATA_DIR}/train.csv")
print("Exiting....")
exit(0)
# read the data
df = pd.read_csv(f'{DATA_DIR}/train.csv')
df1 = df[["image_id","x_min","y_min","x_max","y_max","class_id", "height", "width", "class_name"]].dropna()
df1['path'] = df1['image_id'].apply(lambda x: f"{DATA_DIR}/train/{x}.png")
# get class id
class_dict = {v:k for k,v in dict(df1[['class_name', "class_id"]].values).items()}
# save df1 in order to use it for plotting
df1.to_csv("train_clean.csv", index=False)
check_df = create_data(df1)
# class names available
classes = list(check_df['class_name'].unique())
# Yolo normaly requires bbox to be normalized between 0 and 1.
# Since we have have height and width for a particular image, we gonna just divide bbox against either widht or height.
# We then extract the widht and height of the bbox from the above calibrations
df = check_df.copy()
df['x_min'] = df.apply(lambda x: (x.x_min)/x.width, axis =1)
df['y_min'] = df.apply(lambda x: (x.y_min)/x.height, axis =1)
df['x_max'] = df.apply(lambda x: (x.x_max)/x.width, axis =1)
df['y_max'] = df.apply(lambda x: (x.y_max)/x.height, axis =1)
df['x_mid'] = df.apply(lambda x: (x.x_max+x.x_min)/2, axis =1)
df['y_mid'] = df.apply(lambda x: (x.y_max+x.y_min)/2, axis =1)
df['w'] = df.apply(lambda x: (x.x_max-x.x_min), axis =1)
df['h'] = df.apply(lambda x: (x.y_max-x.y_min), axis =1)
df['area'] = df['w']*df['h']
selected_classes = (df['class_name'].value_counts(normalize=True).T[df['class_name'].value_counts(normalize=True).T >0.0001])
SELECTED_CLASS_NAMES = list(selected_classes.index)
# Get a dataframe with selected classes
selected_df = df[df['class_name'].isin(SELECTED_CLASS_NAMES)]
# only which have below 40 bbox instances
img_ids = list((df['image_id'].value_counts(normalize=False).T[df['image_id'].value_counts(normalize=False).T <=40]).index)
# pd.DataFrame(base_details)
TRAIN =[]
# for img_id in selected_df['image_id'].unique():
for img_id in selected_df[selected_df['image_id'].isin(img_ids)]['image_id'].unique():
curr_df = selected_df[selected_df['image_id'] ==img_id].reset_index(drop=True)
base_details = dict(curr_df.loc[0][['image_id',"path",'width', 'height']])
information =[]
for indx in range(curr_df.shape[0]):
other_details = dict(curr_df.loc[indx][['class_name', "x_min", "y_min","x_max","y_max", "x_mid", "y_mid", "w", "h", "area" ]])
information.append(other_details)
TRAIN.append([base_details['image_id'],base_details['path'] ,base_details['width'],base_details['height'],information])
final_data = pd.DataFrame(TRAIN, columns =['image_id',"path", "width", "height", "information"])
from pprint import pprint
print(final_data.head())
# save this data for feature usage.
final_data.to_csv("processed.csv", index=False)
To structure the images and labels for YOLOv5 training, We created the following 4 directories where the training and validation information was to reside.
1. `/WORKING_DIR/PROJECT_DIR/labels/train` - This directory will store the labels (annotations) for the training images.
2. `/WORKING_DIR/PROJECT_DIR/labels/val` - This directory will store the labels (annotations) for the validation images.
3. `/WORKING_DIR/PROJECT_DIR/images/train` - This directory will store the training images.
4. `/WORKING_DIR/PROJECT_DIR/images/val` - This directory will store the validation images.
Once the directories were created, We then moved or copy the images and their corresponding labels to the appropriate directories. The labels for each image should have the same file name as the image, and should be placed in the appropriate labels directory (either `/WORKING_DIR/PROJECT_DIR/labels/train` or `/WORKING_DIR/PROJECT_DIR/labels/val`). The labels were also in their own format. Each image had a single text file as labels. The format of labels for YOLOv5 model used was a plain text file with the same name as the corresponding image file, and with a `.txt` extension. The file should contain one line for each object in the image, with the following format:
````
class_id x_center y_center width height
````
where:
````
12 0.5 0.5 0.2 0.2
3 0.7 0.7 0.1 0.1
````
This means that there is one Pneumothorax object with class label 12, center coordinates
(0.5,0.5), width and height as 0.2 and one Cardiomegaly object with class label 3, center
coordinates (0.7,0.7), width and height as 0.1
A YAML file was created which contained all information about the training and validation dataset. The file had the following information.
````yaml
names:
- Cardiomegaly
- Pleural effusion
- Pleural thickening
- Aortic enlargement
- Pulmonary fibrosis
- ILD
- Nodule/Mass
- Other lesion
- Lung Opacity
- Infiltration
- Consolidation
- Calcification
- Atelectasis
- Pneumothorax
nc: 14
train: /kaggle/working/train.txt
val: /kaggle/working/val.txt
````
where:
Project support will be updated in due course. Please be patient.
Please visit our profile page or ask question info@neurallabs.africa
Support for the project includes:You can find the version history (changelog.txt) file on yourthemename-full.zip folder or you can check changelog on theme sale page.
Once again, thank you so much for purchasing this theme. As I said at the beginning, I'd be glad to help you if you have any questions relating to this theme. No guarantees, but I'll do my best to assist. If you have a more general question relating to the themes on ThemeForest, you might consider visiting the forums and asking your question in the "Item Discussion" section.
-----------------------------------------------------------------------------------------
Version 1.0 - Dec 7th, 2023
-----------------------------------------------------------------------------------------
- Updated version as a result of clinical trials.
-----------------------------------------------------------------------------------------
Version 0.1 - May 7th, 2022
-----------------------------------------------------------------------------------------
Pilot project version.
Code released under the GPL 3.0 License License.
For more information about copyright and license check Open Source License.