From 8e79d0fd8f38a78d37dc7512f0157249bbac3f0e Mon Sep 17 00:00:00 2001 From: Alexandros Sigaras Date: Mon, 21 Sep 2020 12:06:56 -0400 Subject: [PATCH 01/14] Added convert_dicom.py --- src/ai_biopsy_src/convert_dicom.py | 34 ++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 src/ai_biopsy_src/convert_dicom.py diff --git a/src/ai_biopsy_src/convert_dicom.py b/src/ai_biopsy_src/convert_dicom.py new file mode 100644 index 0000000..2a5090a --- /dev/null +++ b/src/ai_biopsy_src/convert_dicom.py @@ -0,0 +1,34 @@ +#convert all .dcm images to .png with exception of those images with "ValueError: The length of the pixel data" error + +import numpy as np +import png, os, pydicom + +source_folder = './source' +output_folder = './output' + +def dicom2png(source_folder, output_folder): + list_of_files = os.listdir(source_folder) + for file in list_of_files: + try: + ds = pydicom.dcmread(os.path.join(source_folder,file)) + shape = ds.pixel_array.shape + + # Convert to float to avoid overflow or underflow losses. + image_2d = ds.pixel_array.astype(float) + + # Rescaling grey scale between 0-255 + image_2d_scaled = (np.maximum(image_2d,0) / image_2d.max()) * 255.0 + + # Convert to uint + image_2d_scaled = np.uint8(image_2d_scaled) + + # Write the PNG file + with open(os.path.join(output_folder,file)+ '.png' , 'wb') as png_file: + w = png.Writer(shape[1], shape[0], greyscale=True) + w.write(png_file, image_2d_scaled) + except: + print('Could not convert: ', file) + + +dicom2png(source_folder, output_folder) +print ('done') \ No newline at end of file From 16e7d46a77159d16e88d484d0a92fd067426b4fe Mon Sep 17 00:00:00 2001 From: Alexandros Sigaras Date: Mon, 21 Sep 2020 13:01:36 -0400 Subject: [PATCH 02/14] updated .dockerignore file --- .dockerignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.dockerignore b/.dockerignore index 54caf01..49fd3c8 100644 --- a/.dockerignore +++ b/.dockerignore @@ -1,4 +1,5 @@ README.md data +env .git \ No newline at end of file From a5cd3fbf2842d2af87b08b2556562c14756e201b Mon Sep 17 00:00:00 2001 From: Alexandros Sigaras Date: Mon, 21 Sep 2020 14:53:14 -0400 Subject: [PATCH 03/14] Updated Dockerfile and requirements --- Dockerfile | 8 +++----- requirements.txt | 12 +++++++----- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/Dockerfile b/Dockerfile index 5f3fe0a..f1c5cc5 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,18 +1,16 @@ -FROM python:3.6.8-stretch +FROM python:3.7.9-buster #===============================# # Docker Image Configuration # #===============================# LABEL vendor='Englander Institute for Precision Medicine' \ description='AI Biopsy' \ - maintainer='als2076@med.cornell.edu' \ - base_image='python' \ - base_image_version='3.6.8-stretch' \ - base_image_SHA256='sha256:ab2670ec57d486f73e49e7352de6a80b6767e3c996c1c0d0c158f17ae6f2d113' + maintainer='als2076@med.cornell.edu' ENV APP_NAME='ai_biopsy' \ TZ='US/Eastern' \ AI_BIOPSY_SRC_DIR='/ai_biopsy/src/ai_biopsy_src' \ PREDICT_DIR='/ai_biopsy/src/ai_biopsy_src/slim' + ENV RESULT_DIR=${AI_BIOPSY}/result \ PROCESS_DIR=${AI_BIOPSY}/process \ PYTHONPATH=${PYTHONPATH}:${AI_BIOPSY}:${PREDICT_DIR} diff --git a/requirements.txt b/requirements.txt index 33c0c82..7f1e835 100644 --- a/requirements.txt +++ b/requirements.txt @@ -14,11 +14,11 @@ h5py==2.9.0 idna==2.7 itsdangerous==1.1.0 Jinja2==2.10 -Keras-Applications==1.0.6 +Keras-Applications==1.0.8 Keras-Preprocessing==1.0.5 Markdown==3.0.1 MarkupSafe==1.1.0 -numpy==1.15.2 +numpy==1.16.0 protobuf==3.6.1 pyasn1==0.4.4 pyasn1-modules==0.2.2 @@ -27,11 +27,13 @@ requests==2.20.0 rsa==4.0 selenium==3.14.1 six==1.12.0 -tensorboard==1.12.2 -tensorflow==1.12.0 +tensorboard==1.15.0 +tensorflow==1.15.0 termcolor==1.1.0 urllib3==1.24 virtualenv==16.2.0 Werkzeug==0.14.1 opencv-python==4.0.0.21 -matplotlib==3.0.3 \ No newline at end of file +matplotlib==3.0.3 +pydicom==1.0.2 +pypng==0.0.18 \ No newline at end of file From 88fb18442265fd64502e33be65bcaaf9b7a50a0e Mon Sep 17 00:00:00 2001 From: Alexandros Sigaras Date: Mon, 21 Sep 2020 15:17:48 -0400 Subject: [PATCH 04/14] version bump to 1.1.0 --- src/api/version.py | 2 +- src/static/index.html | 2 +- src/static/login.html | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/api/version.py b/src/api/version.py index 7cb55d7..de5f76c 100644 --- a/src/api/version.py +++ b/src/api/version.py @@ -1,4 +1,4 @@ -version = '1.0.0' +version = '1.1.0' def api_version(): return version \ No newline at end of file diff --git a/src/static/index.html b/src/static/index.html index 6920eb8..eba24bd 100644 --- a/src/static/index.html +++ b/src/static/index.html @@ -54,7 +54,7 @@
Copyright © 2019 Englander Institute for Precision Medicine
-
AI Biopsy Version 1.0.0
+
AI Biopsy Version 1.1.0
diff --git a/src/static/login.html b/src/static/login.html index 1eee034..8095d80 100644 --- a/src/static/login.html +++ b/src/static/login.html @@ -32,7 +32,7 @@
Copyright © 2019 Englander Institute for Precision Medicine
-
AI Biopsy Version 1.0.0
+
AI Biopsy Version 1.1.0
From 89d51d42a6526d941e81ab06a1982c421c200c81 Mon Sep 17 00:00:00 2001 From: Alexandros Sigaras Date: Mon, 21 Sep 2020 15:20:15 -0400 Subject: [PATCH 05/14] updated requirements addressing dependabot alerts --- requirements.txt | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/requirements.txt b/requirements.txt index 7f1e835..ca6ddca 100644 --- a/requirements.txt +++ b/requirements.txt @@ -13,7 +13,7 @@ grpcio==1.15.0 h5py==2.9.0 idna==2.7 itsdangerous==1.1.0 -Jinja2==2.10 +Jinja2==2.11.2 Keras-Applications==1.0.8 Keras-Preprocessing==1.0.5 Markdown==3.0.1 @@ -23,16 +23,16 @@ protobuf==3.6.1 pyasn1==0.4.4 pyasn1-modules==0.2.2 pytz==2018.5 -requests==2.20.0 +requests==2.24.0 rsa==4.0 selenium==3.14.1 six==1.12.0 tensorboard==1.15.0 -tensorflow==1.15.0 +tensorflow==1.15.3 termcolor==1.1.0 -urllib3==1.24 +urllib3==1.25.10 virtualenv==16.2.0 -Werkzeug==0.14.1 +Werkzeug==1.0.1 opencv-python==4.0.0.21 matplotlib==3.0.3 pydicom==1.0.2 From cc7f15e26fdf283f49101a401107bafbe53f6156 Mon Sep 17 00:00:00 2001 From: Alexandros Sigaras Date: Mon, 21 Sep 2020 16:35:31 -0400 Subject: [PATCH 06/14] Accept .dcm files and convert to .png --- src/ai_biopsy_src/slim/predict.py | 2 +- src/api/app.py | 31 ++++++++++++++++++++++++++----- src/static/assets/ai_biopsy.js | 4 ++-- src/static/index.html | 2 +- 4 files changed, 30 insertions(+), 9 deletions(-) diff --git a/src/ai_biopsy_src/slim/predict.py b/src/ai_biopsy_src/slim/predict.py index d399db2..e89e33b 100644 --- a/src/ai_biopsy_src/slim/predict.py +++ b/src/ai_biopsy_src/slim/predict.py @@ -14,7 +14,7 @@ session = tf.Session() def get_test_images(mypath): - return [mypath + '/' + f for f in listdir(mypath) if isfile(join(mypath, f)) and f.find('.jpg') != -1] + return [mypath + '/' + f for f in listdir(mypath) if isfile(join(mypath, f)) and f.find('.png') != -1] def transform_img_fn(path_list): out = [] diff --git a/src/api/app.py b/src/api/app.py index 67ed4c1..2e70af6 100644 --- a/src/api/app.py +++ b/src/api/app.py @@ -9,6 +9,8 @@ import glob import ntpath import datetime +import numpy as np +import png, pydicom from ast import literal_eval # Relative Imports @@ -20,7 +22,7 @@ STATIC_DIR = '/ai_biopsy/src' RESULT_DIR = '/ai_biopsy/src/ai_biopsy_src/result/' -ALLOWED_EXTENSIONS = set(['jpg', 'png', 'tif', 'tiff']) +ALLOWED_EXTENSIONS = set(['jpg', 'png', 'tif', 'tiff', 'dcm']) static_file_dir = os.path.join(STATIC_DIR, 'static') @@ -103,10 +105,29 @@ def upload_image(): # 3. Normalize images to jpeg format for image in glob.glob(os.path.join(request_dir, '*.*')): - img = cv2.imread(image) - os.remove(image) - filename = '%s.jpg' % os.path.splitext(image)[0] - cv2.imwrite(os.path.join(request_dir, filename), img) + filename = os.path.splitext(image)[0] + if os.path.splitext(image)[1] == '.dcm': + ds = pydicom.dcmread(image) + shape = ds.pixel_array.shape + + # Convert to float to avoid overflow or underflow losses. + image_2d = ds.pixel_array.astype(float) + + # Rescaling grey scale between 0-255 + image_2d_scaled = (np.maximum(image_2d,0) / image_2d.max()) * 255.0 + + # Convert to uint + image_2d_scaled = np.uint8(image_2d_scaled) + + # Write the PNG file + with open(os.path.join(request_dir, filename) + '.png' , 'wb') as png_file: + w = png.Writer(shape[1], shape[0], greyscale=True) + w.write(png_file, image_2d_scaled) + else: + img = cv2.imread(image) + os.remove(image) + filename = '%s.png' % filename + cv2.imwrite(os.path.join(request_dir, filename), img) # 4. Specify Output log output_filename = 'output_' + request_id + '.txt' diff --git a/src/static/assets/ai_biopsy.js b/src/static/assets/ai_biopsy.js index b4f7bb5..3ab53f3 100644 --- a/src/static/assets/ai_biopsy.js +++ b/src/static/assets/ai_biopsy.js @@ -68,8 +68,8 @@ function average(array) { } function isAnImage(file) { - if (file && file.type) { - return file.type.startsWith('image/jpeg') || file.type.startsWith('image/png') || file.type.startsWith('image/tiff'); + if (file && (file.type || file.name)) { + return file.type.startsWith('image/jpeg') || file.type.startsWith('image/png') || file.type.startsWith('image/tiff') || file.name.endsWith('.dcm'); } return false; diff --git a/src/static/index.html b/src/static/index.html index eba24bd..575fc54 100644 --- a/src/static/index.html +++ b/src/static/index.html @@ -27,7 +27,7 @@ - + From 0de4654aa3122c24da7920f9d095ad4e4607b072 Mon Sep 17 00:00:00 2001 From: Alexandros Sigaras Date: Mon, 21 Sep 2020 16:40:32 -0400 Subject: [PATCH 07/14] Updated copyright year to get always current year --- src/static/assets/ai_biopsy.js | 2 ++ src/static/index.html | 2 +- src/static/login.html | 2 +- 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/static/assets/ai_biopsy.js b/src/static/assets/ai_biopsy.js index 3ab53f3..6b4ef4d 100644 --- a/src/static/assets/ai_biopsy.js +++ b/src/static/assets/ai_biopsy.js @@ -6,6 +6,8 @@ const baseApiUrl = 'api' let token = getCookie('ai-biopsy-auth'); checkTokenAndRedirectIfEmpty(); +document.getElementById('year').innerHTML = new Date().getFullYear(); + setInterval(function(){ checkTokenAndRedirectIfEmpty(); }, 5000); diff --git a/src/static/index.html b/src/static/index.html index 575fc54..08248d1 100644 --- a/src/static/index.html +++ b/src/static/index.html @@ -53,7 +53,7 @@
-
Copyright © 2019 Englander Institute for Precision Medicine
+
Copyright © Englander Institute for Precision Medicine
AI Biopsy Version 1.1.0
diff --git a/src/static/login.html b/src/static/login.html index 8095d80..e8e68ce 100644 --- a/src/static/login.html +++ b/src/static/login.html @@ -31,7 +31,7 @@
-
Copyright © 2019 Englander Institute for Precision Medicine
+
Copyright © Englander Institute for Precision Medicine
AI Biopsy Version 1.1.0
From b47018819daf5bfe296bb6f129e02958a8f982d4 Mon Sep 17 00:00:00 2001 From: Alexandros Sigaras Date: Mon, 21 Sep 2020 17:20:24 -0400 Subject: [PATCH 08/14] updated js and html --- README.md | 8 +++----- src/static/assets/ai_biopsy.js | 23 ++++++++++++++++++++--- src/static/index.html | 1 + 3 files changed, 24 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 28b00f9..70ab3f9 100644 --- a/README.md +++ b/README.md @@ -1,12 +1,10 @@ -# AI Biopsy +![AI Biopsy Logo](docs/images/logo.png) -Needs to be updated +# AI Biopsy -[![Python 3.6](https://img.shields.io/badge/python-3.6-blue.svg)](https://www.python.org/downloads/release/python-360/) +[![Python 3.7.9](https://img.shields.io/badge/python-3.7.9-blue.svg)](https://www.python.org/downloads/release/python-379/) [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) -![AI Biopsy Logo](docs/images/logo.png) - ## AI Biopsy Requirements - Docker. Get it from [here](https://www.docker.com/). diff --git a/src/static/assets/ai_biopsy.js b/src/static/assets/ai_biopsy.js index 6b4ef4d..5977b26 100644 --- a/src/static/assets/ai_biopsy.js +++ b/src/static/assets/ai_biopsy.js @@ -211,9 +211,7 @@ function createImagesUIFromFiles(files, imagesPlaceholder) { imagePlaceholder.id = `image-card-${file.name}`; imagePlaceholder.innerHTML = `
-
- ${file.name} -
+
${file.name}
@@ -229,6 +227,25 @@ function createImagesUIFromFiles(files, imagesPlaceholder) {
`; imagesPlaceholder.appendChild(imagePlaceholder); + const cardImage = imagePlaceholder.getElementsByClassName('card-image')[0]; + + if (file.name.endsWith('.dcm')) { + cornerstone.enable(cardImage); + cornerstone.loadImage(file.name).then(function(image) { + cornerstone.displayImage(cardImage, image); + }); + + // const imageId = 'example://1'; + // const element = document.getElementById('dicomImage'); + // cornerstone.enable(element); + // cornerstone.loadImage(imageId).then(function(image) { + // cornerstone.displayImage(element, image); + // }); + + + } else { + cardImage.innerHTML = `${file.name}`; + } const image = imagePlaceholder.getElementsByTagName('img')[0]; const reader = new FileReader(); diff --git a/src/static/index.html b/src/static/index.html index 08248d1..72b3aab 100644 --- a/src/static/index.html +++ b/src/static/index.html @@ -6,6 +6,7 @@ +