Kalbe-x-Bangkit
commited on
Commit
•
8b1ee3f
1
Parent(s):
37ab671
Update app.py
Browse filesadd images to gcs
app.py
CHANGED
@@ -97,8 +97,15 @@ def load_gradcam_model():
|
|
97 |
|
98 |
# Utility Functions
|
99 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
100 |
def upload_to_gcs(image_data: io.BytesIO, filename: str, content_type='application/dicom'):
|
101 |
-
|
102 |
try:
|
103 |
blob = bucket_result.blob(filename)
|
104 |
blob.upload_from_file(image_data, content_type=content_type)
|
@@ -106,9 +113,9 @@ def upload_to_gcs(image_data: io.BytesIO, filename: str, content_type='applicati
|
|
106 |
except Exception as e:
|
107 |
st.error(f"An unexpected error occurred: {e}")
|
108 |
|
109 |
-
def load_dicom_from_gcs(
|
110 |
# Get the blob object
|
111 |
-
blob = bucket_load.blob(
|
112 |
|
113 |
# Download the file as a bytes object
|
114 |
dicom_bytes = blob.download_as_bytes()
|
@@ -116,75 +123,95 @@ def load_dicom_from_gcs(file_name: str = "dicom_00000001_000.dcm"):
|
|
116 |
# Wrap bytes object into BytesIO (file-like object)
|
117 |
dicom_stream = io.BytesIO(dicom_bytes)
|
118 |
|
119 |
-
# Load the DICOM file
|
120 |
ds = pydicom.dcmread(dicom_stream)
|
121 |
|
122 |
return ds
|
123 |
|
124 |
-
def png_to_dicom(image_path: str, image_name: str, dicom: str = None):
|
125 |
-
|
126 |
-
|
127 |
-
else
|
128 |
-
ds = load_dicom_from_gcs(dicom)
|
129 |
|
130 |
-
|
|
|
131 |
print("Image Mode:", jpg_image.mode)
|
132 |
-
if jpg_image.mode == 'L':
|
133 |
-
np_image = np.array(jpg_image.getdata(), dtype=np.uint8)
|
134 |
-
ds.Rows = jpg_image.height
|
135 |
-
ds.Columns = jpg_image.width
|
136 |
-
ds.PhotometricInterpretation = "MONOCHROME1"
|
137 |
-
ds.SamplesPerPixel = 1
|
138 |
-
ds.BitsStored = 8
|
139 |
-
ds.BitsAllocated = 8
|
140 |
-
ds.HighBit = 7
|
141 |
-
ds.PixelRepresentation = 0
|
142 |
-
ds.PixelData = np_image.tobytes()
|
143 |
-
ds.save_as(image_name)
|
144 |
|
145 |
-
|
146 |
-
|
147 |
-
|
148 |
-
|
149 |
-
|
150 |
-
|
151 |
-
ds.BitsStored = 8
|
152 |
-
ds.BitsAllocated = 8
|
153 |
-
ds.HighBit = 7
|
154 |
-
ds.PixelRepresentation = 0
|
155 |
-
ds.PixelData = np_image.tobytes()
|
156 |
-
ds.save_as(image_name)
|
157 |
-
elif jpg_image.mode == 'RGB':
|
158 |
-
np_image = np.array(jpg_image.getdata(), dtype=np.uint8)[:, :3] # Remove alpha if present
|
159 |
ds.Rows = jpg_image.height
|
160 |
ds.Columns = jpg_image.width
|
161 |
-
ds.PhotometricInterpretation = "RGB"
|
162 |
-
ds.SamplesPerPixel = 3
|
163 |
ds.BitsStored = 8
|
164 |
ds.BitsAllocated = 8
|
165 |
ds.HighBit = 7
|
166 |
ds.PixelRepresentation = 0
|
167 |
ds.PixelData = np_image.tobytes()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
168 |
ds.save_as(image_name)
|
169 |
else:
|
170 |
-
raise ValueError("Unsupported image mode:
|
|
|
171 |
return ds
|
172 |
|
173 |
-
def
|
174 |
-
|
175 |
-
|
176 |
-
|
177 |
-
|
|
|
|
|
|
|
|
|
|
|
178 |
|
179 |
-
def upload_folder_images(original_image_path, enhanced_image_path):
|
180 |
-
# Extract the base name of the uploaded image without the extension
|
181 |
-
folder_name = os.path.splitext(uploaded_file.name)[0]
|
182 |
# Create the folder in Cloud Storage
|
183 |
bucket_result.blob(folder_name + '/').upload_from_string('', content_type='application/x-www-form-urlencoded')
|
|
|
184 |
enhancement_name = enhancement_type.split('_')[-1]
|
185 |
-
|
186 |
-
|
187 |
-
enhanced_dicom = png_to_dicom(enhanced_image_path, enhancement_name + ".dcm")
|
188 |
|
189 |
# Convert DICOM to byte stream for uploading
|
190 |
original_dicom_bytes = io.BytesIO()
|
@@ -199,6 +226,7 @@ def upload_folder_images(original_image_path, enhanced_image_path):
|
|
199 |
upload_to_gcs(enhanced_dicom_bytes, folder_name + '/' + enhancement_name + '.dcm', content_type='application/dicom')
|
200 |
|
201 |
|
|
|
202 |
def get_mean_std_per_batch(image_path, H=320, W=320):
|
203 |
sample_data = []
|
204 |
for idx, img in enumerate(df.sample(100)["Image Index"].values):
|
@@ -391,6 +419,7 @@ def redirect_button(url):
|
|
391 |
# File uploader for DICOM files
|
392 |
if uploaded_file is not None:
|
393 |
if hasattr(uploaded_file, 'name'):
|
|
|
394 |
file_extension = uploaded_file.name.split(".")[-1] # Get the file extension
|
395 |
if file_extension.lower() == "dcm":
|
396 |
# Process DICOM file
|
@@ -475,7 +504,8 @@ if uploaded_file is not None:
|
|
475 |
# Save original image to a file
|
476 |
original_image_path = "original_image.png"
|
477 |
cv2.imwrite(original_image_path, original_image)
|
478 |
-
|
|
|
479 |
# Add the redirect button
|
480 |
col1, col2, col3 = st.columns(3)
|
481 |
with col1:
|
|
|
97 |
|
98 |
# Utility Functions
|
99 |
|
100 |
+
# Dictionaries to track InstanceNumbers and StudyInstanceUIDs per filename
|
101 |
+
# Initialize session state for instance numbers and study UIDs
|
102 |
+
if 'instance_numbers' not in st.session_state:
|
103 |
+
st.session_state.instance_numbers = {}
|
104 |
+
if 'study_uids' not in st.session_state:
|
105 |
+
st.session_state.study_uids = {}
|
106 |
+
|
107 |
def upload_to_gcs(image_data: io.BytesIO, filename: str, content_type='application/dicom'):
|
108 |
+
#Uploads an image to Google Cloud Storage.
|
109 |
try:
|
110 |
blob = bucket_result.blob(filename)
|
111 |
blob.upload_from_file(image_data, content_type=content_type)
|
|
|
113 |
except Exception as e:
|
114 |
st.error(f"An unexpected error occurred: {e}")
|
115 |
|
116 |
+
def load_dicom_from_gcs(dicom_name: str = "dicom_00000001_000.dcm"):
|
117 |
# Get the blob object
|
118 |
+
blob = bucket_load.blob(dicom_name)
|
119 |
|
120 |
# Download the file as a bytes object
|
121 |
dicom_bytes = blob.download_as_bytes()
|
|
|
123 |
# Wrap bytes object into BytesIO (file-like object)
|
124 |
dicom_stream = io.BytesIO(dicom_bytes)
|
125 |
|
126 |
+
# Load the DICOM file
|
127 |
ds = pydicom.dcmread(dicom_stream)
|
128 |
|
129 |
return ds
|
130 |
|
131 |
+
def png_to_dicom(image_path: str, image_name: str, file_name: str, instance_number: int = 1, dicom: str = None, study_instance_uid: str = None, ):
|
132 |
+
|
133 |
+
# Load the template DICOM file
|
134 |
+
ds = load_dicom_from_gcs() if dicom is None else load_dicom_from_gcs(dicom)
|
|
|
135 |
|
136 |
+
# Process the image
|
137 |
+
jpg_image = Image.open(image_path) # the PNG or JPG file to be replaced
|
138 |
print("Image Mode:", jpg_image.mode)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
139 |
|
140 |
+
if jpg_image.mode in ('L', 'RGBA', 'RGB'):
|
141 |
+
if jpg_image.mode == 'RGBA':
|
142 |
+
np_image = np.array(jpg_image.getdata(), dtype=np.uint8)[:,:3]
|
143 |
+
else:
|
144 |
+
np_image = np.array(jpg_image.getdata(),dtype=np.uint8)
|
145 |
+
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
146 |
ds.Rows = jpg_image.height
|
147 |
ds.Columns = jpg_image.width
|
148 |
+
ds.PhotometricInterpretation = "MONOCHROME1" if jpg_image.mode == 'L' else "RGB"
|
149 |
+
ds.SamplesPerPixel = 1 if jpg_image.mode == 'L' else 3
|
150 |
ds.BitsStored = 8
|
151 |
ds.BitsAllocated = 8
|
152 |
ds.HighBit = 7
|
153 |
ds.PixelRepresentation = 0
|
154 |
ds.PixelData = np_image.tobytes()
|
155 |
+
|
156 |
+
if not hasattr(ds, 'PatientName') or ds.PatientName == '':
|
157 |
+
ds.PatientName = os.path.splitext(file_name)[0] # Remove extension
|
158 |
+
|
159 |
+
ds.SeriesDescription = 'original image' if image_name == 'original_image.dcm' else enhancement_type
|
160 |
+
|
161 |
+
if hasattr(ds, 'StudyDescription'):
|
162 |
+
del ds.StudyDescription
|
163 |
+
|
164 |
+
if study_instance_uid:
|
165 |
+
ds.StudyInstanceUID = study_instance_uid
|
166 |
+
else:
|
167 |
+
# Check if a StudyInstanceUID exists for the file name
|
168 |
+
if file_name in st.session_state.study_uids:
|
169 |
+
ds.StudyInstanceUID = st.session_state.study_uids[file_name]
|
170 |
+
print(f"Reusing StudyInstanceUID for '{file_name}'")
|
171 |
+
else:
|
172 |
+
# Generate a new StudyInstanceUID and store it
|
173 |
+
new_study_uid = generate_uid()
|
174 |
+
st.session_state.study_uids[file_name] = new_study_uid
|
175 |
+
ds.StudyInstanceUID = new_study_uid
|
176 |
+
print(f"New StudyInstanceUID generated for '{file_name}'")
|
177 |
+
|
178 |
+
# Generate a new SeriesInstanceUID and SOPInstanceUID for the added image
|
179 |
+
ds.SeriesInstanceUID = generate_uid()
|
180 |
+
ds.SOPInstanceUID = generate_uid()
|
181 |
+
|
182 |
+
if hasattr(ds, 'InstanceNumber'):
|
183 |
+
st.session_state.instance_numbers[file_name] = int(ds.InstanceNumber) + 1
|
184 |
+
else:
|
185 |
+
# Manage InstanceNumber based on filename
|
186 |
+
if file_name in st.session_state.instance_numbers:
|
187 |
+
st.session_state.instance_numbers[file_name] += 1
|
188 |
+
else:
|
189 |
+
st.session_state.instance_numbers[file_name] = 1
|
190 |
+
ds.InstanceNumber = int(st.session_state.instance_numbers[file_name])
|
191 |
+
|
192 |
ds.save_as(image_name)
|
193 |
else:
|
194 |
+
raise ValueError(f"Unsupported image mode: {jpg_image.mode}")
|
195 |
+
|
196 |
return ds
|
197 |
|
198 |
+
def upload_folder_images(original_image_path, enhanced_image_path, file_name):
|
199 |
+
# Convert images to DICOM if result is png
|
200 |
+
if not original_image_path.lower().endswith('.dcm'):
|
201 |
+
original_dicom = png_to_dicom(original_image_path, "original_image.dcm", file_name=file_name)
|
202 |
+
else:
|
203 |
+
original_dicom = pydicom.dcmread(original_image_path)
|
204 |
+
study_instance_uid = original_dicom.StudyInstanceUID
|
205 |
+
|
206 |
+
# Use StudyInstanceUID as folder name
|
207 |
+
folder_name = study_instance_uid
|
208 |
|
|
|
|
|
|
|
209 |
# Create the folder in Cloud Storage
|
210 |
bucket_result.blob(folder_name + '/').upload_from_string('', content_type='application/x-www-form-urlencoded')
|
211 |
+
|
212 |
enhancement_name = enhancement_type.split('_')[-1]
|
213 |
+
|
214 |
+
enhanced_dicom = png_to_dicom(enhanced_image_path, enhancement_name + ".dcm", study_instance_uid=study_instance_uid, file_name=file_name)
|
|
|
215 |
|
216 |
# Convert DICOM to byte stream for uploading
|
217 |
original_dicom_bytes = io.BytesIO()
|
|
|
226 |
upload_to_gcs(enhanced_dicom_bytes, folder_name + '/' + enhancement_name + '.dcm', content_type='application/dicom')
|
227 |
|
228 |
|
229 |
+
|
230 |
def get_mean_std_per_batch(image_path, H=320, W=320):
|
231 |
sample_data = []
|
232 |
for idx, img in enumerate(df.sample(100)["Image Index"].values):
|
|
|
419 |
# File uploader for DICOM files
|
420 |
if uploaded_file is not None:
|
421 |
if hasattr(uploaded_file, 'name'):
|
422 |
+
file_name = uploaded_file.name
|
423 |
file_extension = uploaded_file.name.split(".")[-1] # Get the file extension
|
424 |
if file_extension.lower() == "dcm":
|
425 |
# Process DICOM file
|
|
|
504 |
# Save original image to a file
|
505 |
original_image_path = "original_image.png"
|
506 |
cv2.imwrite(original_image_path, original_image)
|
507 |
+
upload_folder_images(original_image_path, enhanced_image_path, file_name)
|
508 |
+
|
509 |
# Add the redirect button
|
510 |
col1, col2, col3 = st.columns(3)
|
511 |
with col1:
|