|
a |
|
b/Segmentation_PDF_Generation.py |
|
|
1 |
# %% importing packages |
|
|
2 |
|
|
|
3 |
import numpy as np |
|
|
4 |
from skimage import measure |
|
|
5 |
from skimage import morphology |
|
|
6 |
from skimage import segmentation |
|
|
7 |
from scipy import ndimage |
|
|
8 |
import cv2 as cv |
|
|
9 |
import os |
|
|
10 |
import matplotlib.pyplot as plt |
|
|
11 |
import tqdm |
|
|
12 |
import random |
|
|
13 |
from glob import glob |
|
|
14 |
from natsort import natsorted |
|
|
15 |
from fpdf import FPDF |
|
|
16 |
plt.rcParams['figure.figsize'] = [50, 150] |
|
|
17 |
|
|
|
18 |
|
|
|
19 |
# %% Sources |
|
|
20 |
############################################################# |
|
|
21 |
############################################################# |
|
|
22 |
|
|
|
23 |
# https://pypi.org/project/img2pdf/ |
|
|
24 |
# https://stackoverflow.com/questions/57576686/how-to-overlay-segmented-image-on-top-of-main-image-in-python |
|
|
25 |
# https://stackoverflow.com/questions/27327513/create-pdf-from-a-list-of-images |
|
|
26 |
# https://docs.opencv.org/3.4/d4/d73/tutorial_py_contours_begin.html |
|
|
27 |
|
|
|
28 |
# Defining Functions |
|
|
29 |
############################################################# |
|
|
30 |
############################################################# |
|
|
31 |
|
|
|
32 |
def filter_fun_vasculature(file_name:str): |
|
|
33 |
'''I realize this isn't very functional programming, but this function |
|
|
34 |
is paired with the "filter_fun_nerves" function for filtering file names |
|
|
35 |
according to the class for which the tile was selected using the |
|
|
36 |
DatasetCreation.py file''' |
|
|
37 |
class_id = 'vasc_seg' |
|
|
38 |
|
|
|
39 |
if class_id in file_name: |
|
|
40 |
return(True) |
|
|
41 |
else: |
|
|
42 |
return(False) |
|
|
43 |
|
|
|
44 |
############################################################# |
|
|
45 |
|
|
|
46 |
def filter_fun_nerves(file_name:str): |
|
|
47 |
'''Performs filtering of file names according to the class for which the |
|
|
48 |
tile was selected when using the DatasetCreation.py file''' |
|
|
49 |
class_id = 'neural_seg' |
|
|
50 |
|
|
|
51 |
if class_id in file_name: |
|
|
52 |
return(True) |
|
|
53 |
else: |
|
|
54 |
return(False) |
|
|
55 |
|
|
|
56 |
|
|
|
57 |
############################################################# |
|
|
58 |
|
|
|
59 |
|
|
|
60 |
def sample_image_names_from_directory(directory,number_of_samples): |
|
|
61 |
'''Randomly selects number_of_samples file names of each of the two |
|
|
62 |
different classes (vasculature and neural) from the sub_sampled |
|
|
63 |
dataset created by the DatasetCreation.py script. Returns those file |
|
|
64 |
names.''' |
|
|
65 |
|
|
|
66 |
os.chdir(directory) |
|
|
67 |
file_names = glob('./*.png') |
|
|
68 |
|
|
|
69 |
vasc_filt = filter(filter_fun_vasculature,file_names) |
|
|
70 |
nerve_filt = filter(filter_fun_nerves,file_names) |
|
|
71 |
|
|
|
72 |
vasc_image_names = list(vasc_filt) |
|
|
73 |
nerve_image_names = list(nerve_filt) |
|
|
74 |
|
|
|
75 |
rand_vasc_images = random.choices(vasc_image_names,k=number_of_samples) |
|
|
76 |
rand_nerve_images = random.choices(nerve_image_names,k=number_of_samples) |
|
|
77 |
|
|
|
78 |
random_image_names = rand_vasc_images + rand_nerve_images |
|
|
79 |
|
|
|
80 |
random.shuffle(random_image_names) |
|
|
81 |
|
|
|
82 |
return(random_image_names) |
|
|
83 |
|
|
|
84 |
############################################################# |
|
|
85 |
|
|
|
86 |
def create_segment_outline_image(image_name): |
|
|
87 |
'''Uses openCV to create an border for the segmentations of interest in the |
|
|
88 |
image whose file name is provided as an argument. Returns an image with the |
|
|
89 |
vasculature highlighted in red, and the neural tissue highlighted in |
|
|
90 |
green.''' |
|
|
91 |
|
|
|
92 |
current_image = cv.imread(image_name,cv.IMREAD_UNCHANGED) |
|
|
93 |
color = current_image[:,:,0:3] |
|
|
94 |
# color = cv.cvtColor(color,cv.COLOR_BGR2RGB) |
|
|
95 |
seg = current_image[:,:,3] |
|
|
96 |
dilation_amount = 50 |
|
|
97 |
vasculature = seg==5 |
|
|
98 |
neural = seg==6 |
|
|
99 |
|
|
|
100 |
vasculature = morphology.binary_dilation( |
|
|
101 |
vasculature, |
|
|
102 |
np.ones((dilation_amount,dilation_amount)) |
|
|
103 |
) |
|
|
104 |
|
|
|
105 |
neural = morphology.binary_dilation( |
|
|
106 |
neural, |
|
|
107 |
np.ones((dilation_amount,dilation_amount)) |
|
|
108 |
) |
|
|
109 |
|
|
|
110 |
vasc_contours,_heirarchy = cv.findContours(vasculature.astype(np.uint8), |
|
|
111 |
cv.RETR_EXTERNAL, |
|
|
112 |
cv.CHAIN_APPROX_NONE) |
|
|
113 |
|
|
|
114 |
neural_contours,_heirarchy = cv.findContours(neural.astype(np.uint8), |
|
|
115 |
cv.RETR_EXTERNAL, |
|
|
116 |
cv.CHAIN_APPROX_NONE) |
|
|
117 |
|
|
|
118 |
contoured_image = cv.drawContours( |
|
|
119 |
np.ascontiguousarray(color,np.uint8), vasc_contours, -1, (0,0,255), 10 |
|
|
120 |
) |
|
|
121 |
contoured_image = cv.drawContours( |
|
|
122 |
contoured_image, neural_contours, -1, (0,255,0), 10 |
|
|
123 |
) |
|
|
124 |
|
|
|
125 |
|
|
|
126 |
return(contoured_image) |
|
|
127 |
|
|
|
128 |
############################################################# |
|
|
129 |
|
|
|
130 |
def save_images_to_PDF(image_name_list,file_name,create_contour = True): |
|
|
131 |
'''Uses the above functions to save images sequentially to a PDF for use |
|
|
132 |
in validating the segmentations performed. The PDF has space at the bottom |
|
|
133 |
for adding check boxes in a separate program such as Adobe Acrobat.''' |
|
|
134 |
|
|
|
135 |
pdf = FPDF() |
|
|
136 |
pdf.set_auto_page_break(False) |
|
|
137 |
pdf.set_left_margin(margin=5) |
|
|
138 |
|
|
|
139 |
save_directory = dataset_directory + '/../PDF_images/' |
|
|
140 |
|
|
|
141 |
current_directory = os.getcwd() |
|
|
142 |
|
|
|
143 |
if not os.path.isdir(save_directory): |
|
|
144 |
os.mkdir(save_directory) |
|
|
145 |
|
|
|
146 |
|
|
|
147 |
for idx in tqdm.tqdm(range(len(image_name_list))): |
|
|
148 |
if create_contour: |
|
|
149 |
image_name = image_name_list[idx] |
|
|
150 |
|
|
|
151 |
contoured_image = create_segment_outline_image(image_name) |
|
|
152 |
|
|
|
153 |
image_name_split = image_name.split('/')[1].split('.')[0] |
|
|
154 |
new_image_name = image_name_split+'_outlined.png' |
|
|
155 |
|
|
|
156 |
os.chdir(save_directory) |
|
|
157 |
cv.imwrite(new_image_name,contoured_image) |
|
|
158 |
|
|
|
159 |
pdf.add_page(format=(610,350)) |
|
|
160 |
pdf.image(new_image_name,h=300) |
|
|
161 |
os.chdir(current_directory) |
|
|
162 |
else: |
|
|
163 |
image_name = image_name_list[idx] |
|
|
164 |
pdf.add_page(format=(610,350)) |
|
|
165 |
pdf.image(image_name,h=300) |
|
|
166 |
|
|
|
167 |
os.chdir(save_directory) |
|
|
168 |
|
|
|
169 |
pdf.output(file_name,'F') |
|
|
170 |
|
|
|
171 |
return(True) |
|
|
172 |
|
|
|
173 |
############################################################# |
|
|
174 |
############################################################# |
|
|
175 |
# %% |
|
|
176 |
|
|
|
177 |
dataset_directory = '/var/confocaldata/HumanNodal/HeartData/08/01/PDFImages' |
|
|
178 |
|
|
|
179 |
filtered_names = sample_image_names_from_directory(dataset_directory,20) |
|
|
180 |
|
|
|
181 |
save_images_to_PDF(filtered_names,'test_file.pdf',create_contour=False) |
|
|
182 |
|
|
|
183 |
# %% |