-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathgenerate_DDSMpatches.py
123 lines (94 loc) · 4.74 KB
/
generate_DDSMpatches.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
# -*- coding: utf-8 -*-
"""
python3
@author: jcx9dy
"""
import sys
import os
import numpy as np
#import matplotlib.pyplot as plt
#import cv2
from PIL import Image
from scipy.ndimage import binary_erosion, imread
#from scipy.misc import imsave
#from skimage import io, img_as_bool
#from skimage.transform import resize
#import glob
def genPatches(png, mask, patchsize=101, erosion_d=0, numpatches=10):
erosion_d = int(np.round(0.4*patchsize))
patchlist = []
#erode by x pixels maybe 100?
#http://www.scipy-lectures.org/advanced/image_processing/
#http://scikit-image.org/docs/dev/auto_examples/applications/plot_morphology.html
#http://stackoverflow.com/questions/14385921/scipy-binary-closing-edge-pixels-lose-value
eroded = binary_erosion(mask, iterations=erosion_d, border_value=0)
if np.sum(eroded) == 0:
print('WARNING: nothing left after erosion!')
return(patchlist) #empty list
#use eroded as sampling set to get center of candidate patchmask
rows, cols = np.nonzero(eroded)
indices = np.arange(len(rows))
#estimate number of unique patches in mask
n = int( np.floor( np.sum(mask)/patchsize**2) )
if n < 2:
print('WARNING: mask_area less than 2*patch_area!')
return(patchlist) #empty list
for i in range(numpatches):
succeeded = False
while not succeeded:
index = np.random.choice(indices)
row = rows[index]
col = cols[index]
x1 = row - int(np.floor(patchsize*0.5))
x2 = x1 + patchsize
y1 = col - int(np.floor(patchsize*0.5))
y2 = y1 + patchsize
patchmask = mask[x1:x2, y1:y2]
if (np.sum(patchmask) > 0.8*patchsize**2):
succeeded = True
patch = png[x1:x2, y1:y2]
patchlist.append({'row': row, 'col': col, 'patch': patch})
return patchlist
############################################################
########## MAIN
#Given a .npy file path (these were generated by generate_DDSMmasks.py)
# assumes this format: '.../cancer_01/case3013/masks/B_3013_1.RIGHT_CC.groundtruth.npy'
# assumes mammogram in: '.../cancer_01/case3013/PNGFiles/B_3013_1.RIGHT_CC.png'
# assumes mask in: '.../cancer_01/case3013/masks/B_3013_1.RIGHT_CC_\{BENIGN,MALIGNANT\}\{0-9\}.mask.png'
#RUN AS FOLLOWS: python3 generate_DDSMpatches.py ./cancer_01/case3013/masks/B_3013_1.RIGHT_CC.groundtruth.npy
# or parallelize: parallel --eta -a npyfiles.txt python3 generate_DDSMpatches.py {}
# ~ for just patches on 8-core
npypath = sys.argv[1] #'./cancer_01/case3013/masks/B_3013_1.RIGHT_CC.groundtruth.npy'
#print('Processing: ' + npypath)
basepath, npyfile = os.path.split(npypath)
imagename = os.path.splitext(os.path.splitext(npyfile)[0])[0]
casename = npypath.split('/')[-3]
volumename = npypath.split('/')[-4]
view = imagename.split('.')[1]
patchdir_benign = os.path.split(basepath)[0] + '/patch/benign'
patchdir_malign = os.path.split(basepath)[0] + '/patch/malignant'
os.makedirs(patchdir_benign, exist_ok=True)
os.makedirs(patchdir_malign, exist_ok=True)
#load data
groundtruth = np.load(npypath).item()
mamm = imread(os.path.split(basepath)[0] + '/PNGFiles/' + imagename + '.png')
### generate patches
for i, e in enumerate(groundtruth['BENIGN']):
prefix = '-'.join([volumename, imagename, 'B'+str(e['ASSESSMENT']), 'D'+str(e['DENSITY']), 'A'+str(e['PATIENT_AGE']), 'S'+str(e['SUBTLETY'])])
mask = imread(basepath + '/' + imagename + '_BENIGN' + str(i) + '.mask.png').astype('bool')
patchlist = genPatches(mamm, mask, patchsize=101)
for p in patchlist:
Image.fromarray(p['patch']).save(patchdir_benign + '/' + prefix + '-m' + str(i) + '-r'+str(p['row']) + '-c'+str(p['col']) + '.png')
for i, e in enumerate(groundtruth['MALIGNANT']):
prefix = '-'.join([volumename, imagename, 'B'+str(e['ASSESSMENT']), 'D'+str(e['DENSITY']), 'A'+str(e['PATIENT_AGE']), 'S'+str(e['SUBTLETY'])])
mask = imread(basepath + '/' + imagename + '_MALIGNANT' + str(i) + '.mask.png').astype('bool')
patchlist = genPatches(mamm, mask, patchsize=101)
for p in patchlist:
Image.fromarray(p['patch']).save(patchdir_malign + '/' + prefix + '-m' + str(i) + '-r'+str(p['row']) + '-c'+str(p['col']) + '.png')
#Can later load patches as follows:
#np.array(PIL.Image.open('patch.png'))
#scipy.ndimage.imread('patch.png')
#these are 16bit uint values stored in int32 array
#if converting to float, should maybe divide by 2**16
#os.chdir(outdir+'/input')
#np.save(filename, myimg.reshape((newpixdim*newpixdim)).astype('float32'))