]> AND Private Git Repository - myo-class.git/blob - topng.py
Logo AND Algorithmique Numérique Distribuée

Private GIT Repository
trim image, remove bad black border
[myo-class.git] / topng.py
1 import cv2
2 import os
3 from os.path import isdir, join
4 from os import mkdir
5 import pydicom
6 from pprint import pprint
7 import numpy as np
8 import pathlib
9
10 from decimal import Decimal as d, ROUND_HALF_UP as rhu
11
12 PNG16_MAX = pow(2, 16) - 1 # here if thinks the heaviest weight bit is for transparency or something not in use with dicom imgs
13 PNG8_MAX = pow(2, 8+1) - 1 # heaviest weight bit is 8 => 2**8, but dont forget the others: the reason of +1
14
15 INPUT_DIR = '../../Data/Images_anonymous/Case_0350/'
16 OUT_DIR = './generated/'
17 #os.mkdir(outdir)
18
19 def ftrim(Mat):
20         # private func to trim the Matrix, but in one direction, vertically | horizontally
21         # return the slice, don't affect the Matrix
22         # y | : for column, x -> : for rows
23         #   v
24         # not my fault, numpy architecture
25         y1 = y2 = i = 0
26         while i < len(Mat):# search by top
27                 if max(Mat[i]) > 0:
28                         y1 = i
29                         break
30                 i += 1
31         i = len(Mat) - 1
32         while i >= 0:# search by bottom
33                 if max(Mat[i]) > 0:
34                         y2 = i
35                         break
36                 i -= 1
37         # print('y1, y2', y1, y2)
38         return slice(y1, y2+1)# +1 to stop at y2
39
40 def trim(Mat):
41         # most use who make implicit call of ftrim twice
42         horizontal = ftrim(Mat)
43         vertical = ftrim(Mat.T)
44         # print('horizontal:vertical', horizontal, vertical)
45         return Mat[horizontal, vertical]
46
47 def map16(array):# can be useful in future
48         return array * 16
49
50 # def dround(n):
51 #       return d(str(n)).quantize(d('1'), rounding=rhu)# safe round without
52
53 def affine(Mat, ab, cd):
54         """
55                 Affine transformation
56                 ab: the 'from' interval (2, 384) or {begin:2, end:384} begin is 0, and end is 1
57                 cd: the 'to' interval (0, 1024) {begin:0, end:1024}
58         """
59         a, b = ab[0], ab[1]
60         c, d = cd[0], cd[1]
61         
62         with np.nditer(Mat, op_flags=['readwrite']) as M:
63                 for x in M:
64                         x[...] = max( 0, round( (x-a) * (d-c) / (b-a) + c ) ) # could not be negative
65
66
67 def getdir(filepath):
68         return '/'.join(filepath.split('/')[:-1]) + '/'
69
70 def topng(inputfile, outfile=None, overwrite=True):
71         """
72                 return (64, 64) : the width and height
73         """
74         try:
75                 dicimg = pydicom.read_file(inputfile) # read dicom image
76         except pydicom.errors.InvalidDicomError as e:
77                 # @TODO: log, i can't read this file
78                 return
79         img = trim(dicimg.pixel_array)# get image array (12bits)
80
81         # test <<
82         # return img.shape # $$ COMMENT OR REMOVE THIS LINE 
83         # print('img', img)
84         # print('img', type(img))
85         # print('min', img.min(), 'max', img.max())
86         # dicimg.convert_pixel_data() # same as using dicimg.pixel_array
87         # pixa = dicimg._pixel_array
88         # print('dicimg._pixel_array', pixa)
89         # print('dicimg.pixel_array==pixa', dicimg.pixel_array==pixa)
90         # test >>
91
92         # affine transfo to png 16 bits, func affects img variable
93         maxdepth = pow(2, dicimg.BitsStored) - 1
94         print('dicimg.BitsStored, PNG8_MAX', dicimg.BitsStored, PNG8_MAX) # testing..
95         affine(img, 
96                 (0, maxdepth), # img.min() replace 0 may be, but not sure it would be good choice
97                 (0, PNG16_MAX if maxdepth > PNG8_MAX else PNG8_MAX)
98         )
99         
100         savepath = (outfile or inputfile) + '.png'
101         savedir = getdir(savepath)
102         if overwrite and not isdir( savedir ):
103                 pathlib.Path(savedir).mkdir(parents=True, exist_ok=True)
104
105
106         # test <<
107         # tmp = np.array(img) # to get eye on the numpy format of img
108         # tmp = np.array(img) # to get eye on the numpy format of img
109         # print("img[0,0]", img[0,0])
110         # img[0,0] = 0
111         # tmp.dtype = 'uint32'
112         # np.savetxt(savepath + '.npy', img)
113         # test >>
114
115         cv2.imwrite(savepath, img, [cv2.IMWRITE_PNG_COMPRESSION, 0]) # write png image
116
117         # test
118         return img.shape
119
120 def topngs(inputdir, outdir):
121         """
122                 inputdir : directory which contains directly dicom files
123         """
124         files = [f for f in os.listdir(inputdir)]
125
126         for f in files:
127                 topng( inputdir + f, join(outdir, f) )
128
129 if __name__ == '__main__':
130         topngs( INPUT_DIR, join(OUT_DIR, INPUT_DIR.split('/')[-2]) )
131         # topng(INPUT_DIR+'Image00001', OUT_DIR + INPUT_DIR.split('/')[-2] +'-Image00001')