rsbox.ml

File: ml.py

Contains useful functions that I may import while programming machine learning projects.

  1"""
  2File: ml.py 
  3-------------- 
  4Contains useful functions that I may import while programming 
  5machine learning projects.  
  6""" 
  7
  8from matplotlib import pyplot as plt
  9from PIL import Image
 10import requests
 11import torch 
 12import numpy as np 
 13from glob import glob
 14from tqdm.auto import tqdm
 15import random
 16import torchvision.transforms as T
 17
 18
 19def plot_png(file_path, color):
 20	"""
 21	Plots a png file (or jpeg really) using matplotlib. Color is a bool value. 
 22	If true, image will be displayed in color. Else, it will be displayed in 
 23	greyscale.
 24	"""
 25	image = Image.open(file_path)
 26	if color == True:
 27		plt.imshow(image, interpolation='nearest')
 28		plt.show()
 29	else:
 30		plt.imshow(image, interpolation='nearest', cmap='Greys_r')
 31		plt.show()
 32
 33
 34def plot_np_img(image_array, color):
 35	"""
 36    (Here for longevity purposes... use plot instead)
 37	Plots a numpy array using matplotlib. Color is a bool value. If true, 
 38	image will be displayed in color. Else, it will be displayed in 
 39	greyscale.
 40
 41    input: image_array must be of shape (1, H, W) or (H, W) for greyscale
 42    and (3, H, W) for color. 
 43	"""
 44	if color == True:
 45		plt.imshow(image_array, interpolation='nearest')
 46		plt.show()
 47	else:
 48		plt.imshow(image_array, interpolation='nearest', cmap='Greys_r')
 49		plt.show()
 50
 51
 52def plot(image_array, color=True):
 53    """
 54    Plots a numpy array using matplotlib. Color is a bool value which
 55    is true by default. If passed in as False, image will be displayed in 
 56    greyscale. 
 57
 58    input: image_array must be of shape (1, H, W) or (H, W, 1) or (H, W) for greyscale
 59    and (3, H, W) or (H, W, 3) for color. 
 60    """
 61
 62    # move to numpy is not already in numpy array format 
 63    image_array = np.array(image_array)
 64    image_array = np.squeeze(image_array)
 65
 66    if color == True:
 67        if image_array.shape[0] == 3:
 68            image_array = np.moveaxis(image_array, 0, -1)
 69        plt.imshow(image_array, interpolation='nearest')
 70        plt.show()
 71    else:
 72        plt.imshow(image_array, interpolation='nearest', cmap='Greys_r')
 73        plt.show()
 74
 75
 76def image_dir_to_data(dirpath, extension):
 77    """
 78    Takes in a directory containing images
 79    and returns a list of numpy arrays representing
 80    those images. 
 81    Args:
 82        - dirpath: path to directory 
 83        - extension: image extension type (e.g. png) (string)
 84    """
 85    data_subset = []
 86    sub_set = glob(dirpath + '/*.' + extension)
 87    for elem in sub_set:
 88        image = Image.open(elem)
 89        image_array = np.array(image)
 90        data_subset.append(image_array)
 91    return data_subset  
 92
 93
 94def image_dir_to_data_norm(dirpath, extension):
 95    """
 96    (Same as image_dir_to_data but with max value 
 97    (255) normalization). 
 98    Takes in a directory containing images
 99    and returns a list of numpy arrays representing
100    those images. 
101    Args:
102        - dirpath: path to directory 
103        - extension: image extension type (e.g. png) (string)
104    """
105    data_subset = []
106    sub_set = glob(dirpath + '/*.' + extension)
107    for elem in sub_set:
108        image = Image.open(elem)
109        image_array = np.array(image)
110        image_array = image_array.astype(float)
111        image_array = image_array/255.0
112        data_subset.append(image_array)
113    return data_subset    
114
115
116def gen_label_pair(data_samples, label):
117	"""
118	Takes in a list of data samples (i.e. images, x)
119	and a corresponding label and returns a list of tuples
120	where each tuple is an (x, y) pair. 
121	"""
122	d_set = []
123	for elem in data_samples:
124	    sample_pair = (elem, label)
125	    d_set.append(sample_pair)
126	return d_set 
127
128
129def gen_distro(master_list):
130    """
131    Takes in a list of lists who each contain
132    (x, y) tuple samples for that class and returns 
133    a randomly concatenated version. 
134    """
135    generated_distro = []
136    for class_list in master_list:
137        generated_distro = generated_distro + class_list
138    random.shuffle(generated_distro)
139    return generated_distro
140
141
142def get_img(url='https://stanford.edu/~rsikand/assets/images/seal.png', resize=True, size=(128, 128)):
143    """
144    Returns a sample numpy image to play with. 
145    Arguments:
146    -----------
147    - url: Can pass in custom url if you want a different image. 
148    Defaults to a baby seal!  
149    - resize: by default, all images are resized to 128x128. If you'd
150    like to keep the default size, specify False. 
151    - size: size to resize to. Default is 128x128. 
152    """
153
154    image = np.array(Image.open(requests.get(url, stream=True).raw))
155
156
157    if resize:
158        if len(image.shape) == 3:
159            image = np.array(T.Resize(size=size)(torch.movedim(torch.tensor(image), -1, 0)))
160        else:
161            image = np.array(T.Resize(size=size)(torch.tensor(image)))
162    else:
163        if len(image.shape) == 3:
164            if image.shape[0] != 3 and image.shape[2] == 3:
165                image = np.moveaxis(image, -1, 0)
166            elif image.shape[0] != 1 and image.shape[2] == 1:
167                image = np.moveaxis(image, -1, 0)
168            else:
169                image = image
170        else:
171            image = image
172
173    return image
174
175
176def img_dataset_from_dir(dir_path):
177    """
178    Given a directory containing folders
179    representing classes of images, this
180    functions builds a valid numpy
181    dataset distribution. 
182    Input (dir_path) structure: 
183    dir_path/class_1, class_n/1.png 
184    Note: 'dir_path' must be the raw
185    dir name (no trailing dash) 
186    Output: [(x,y), ..., (x,y)]
187    """
188
189    dir_path = dir_path + "/*/"
190    class_list = glob(dir_path, recursive = True)
191    
192    master_list = []
193    idx = 0
194    for class_ in class_list:
195        curr_class = image_dir_to_data_norm(class_, "png")
196        new_arrays = []
197        for elem in curr_class:
198            if len(elem.shape) == 2:
199                elem = np.expand_dims(elem, axis=0)
200            assert len(elem.shape) == 3
201            if elem.shape[0] != 3 and elem.shape[2] == 3:
202                elem = np.moveaxis(elem, -1, 0)
203            elif elem.shape[0] != 1 and elem.shape[2] == 1:
204                elem = np.moveaxis(elem, -1, 0)
205            new_arrays.append(elem)
206
207        labeled_list = gen_label_pair(new_arrays, idx)
208        master_list.append(labeled_list)
209        idx += 1
210
211    return gen_distro(master_list)
212
213
214def print_model_size(net):
215    """
216    Function that calculates PyTorch model size
217    and prints it out in mb, bytes, and num params.  
218    """
219    # taken from 
220    # https://stackoverflow.com/questions/49201236/check-the-total-number-of-parameters-in-a-pytorch-model
221    total_params = sum(p.numel() for p in net.parameters())
222    
223    # taken from 
224    # https://discuss.pytorch.org/t/finding-model-size/130275/2 
225    param_size = 0
226    for param in net.parameters():
227        param_size += param.nelement() * param.element_size()
228    buffer_size = 0
229    for buffer in net.buffers():
230        buffer_size += buffer.nelement() * buffer.element_size()
231
232    size_all_mb = (param_size + buffer_size) / 1024**2
233    
234    print("Total number of parameters: ", total_params)
235    print("model size (bytes): ", (param_size + buffer_size))
236    print('model size (mb): {:.3f}MB'.format(size_all_mb))
237
238
239class MeanMetric:
240  """
241  Scalar metric designed to use on a per-epoch basis 
242  and updated on per-batch basis. For getting average across
243  the epoch. 
244  """
245
246  def __init__(self):
247    self.vals = []
248
249  def update(self, new_val):
250    self.vals.append(new_val)
251
252  def reset(self):
253    self.vals = []
254
255  def get(self):
256    mean_value = sum(self.vals)/len(self.vals)
257    return mean_value
258    
259
260
261def numpy_collate(batch):
262    """batch collate function but keep as numpy array instead 
263    of converting to torch tensor like pytorch default does. inputs
264    must be np.arrays 
265    https://github.com/pytorch/pytorch/blob/35c8f93fd238d42aaea8fd6e730c3da9e18257cc/torch/utils/data/dataloader.py#L218
266    """
267
268    r_tuple = []
269
270    for i in range(len(batch[0])):
271        arrays_to_stack = []
272        for j in range(len(batch)):
273            arrays_to_stack.append(batch[j][i])
274        stacked = np.stack(arrays_to_stack, axis=0)
275        r_tuple.append(stacked)
276    
277    return tuple(r_tuple)
278
279
280def load_image(img_path, resize=None, normalize=True):
281    """
282    Loads an image file into a numpy array in (C, H, W) form. 
283    Arguments:
284    -----------
285    - img_path (str): image filename (relative) 
286    - resize (tuple): (x, y) size to resize to. If None, won't resize. Default = None. 
287    - normalize: if True, divide by 255. 
288    Returns:
289    -----------
290    - image_array: loaded numpy array of the image file     
291    """
292    
293    x = Image.open(img_path)
294    image_array = np.array(x)
295
296    # remove transparency dimension if it exists 
297    if image_array.shape[-1] == 4 and len(image_array.shape) == 3:
298        image_array = image_array[:, :, :3]
299    elif image_array.shape[0] == 4 and len(image_array.shape) == 3:
300        image_array = image_array[:3, :, :]
301    
302    # if image has only 2 channels, add a third channel
303    if len(image_array.shape) == 3 and image_array.shape[-1] == 2:
304        image_array = np.concatenate([np.expand_dims(image_array[:, :, -1], axis=-1), image_array], axis=-1)
305    elif len(image_array.shape) == 3 and image_array.shape[0] == 2:
306        image_array = np.concatenate([np.expand_dims(image_array[-1, :, :], axis=0), image_array], axis=0)
307
308    if normalize:
309        image_array = image_array / 255.0
310
311    # if image is grayscale, add a channel dimension
312    if len(image_array.shape) == 2:
313        image_array = np.expand_dims(image_array, axis=0)
314    
315    assert len(image_array.shape) == 3
316
317    # switch dim 
318    if (image_array.shape[0] != 3 and image_array.shape[2] == 3) or (image_array.shape[0] != 1 and image_array.shape[2] == 1):
319        image_array = np.moveaxis(image_array, -1, 0)
320
321    assert image_array.shape[0] == 3 or image_array.shape[0] == 1
322
323    # resize 
324    if resize is not None:
325        image_array = np.array(T.Resize(size=resize)(torch.tensor(image_array)))
326
327    return image_array
328
329
330
331# v2 functions 
332
333def img_dir_to_data(dirpath, resize=None, normalize=True, extension=None):
334    """
335    (New version of image_dir_to_data). 
336    Takes in a directory containing images
337    and returns a list of numpy arrays representing
338    those images. 
339    Args:
340        - dirpath: path to directory 
341        - extension: include only files with this extension. Default = None. 
342        - resize: tuple of (h, w) for what to resize the images to. If None, won't resize. Default = None. 
343        - normalize: if True, divide by 255. 
344    """
345    data_subset = []
346    if extension is not None:
347        dirpath = dirpath + "/*." + extension
348    else:
349        dirpath = dirpath + "/*"
350    sub_set = glob(dirpath)
351
352    for elem in sub_set:
353        image = load_image(elem, resize=resize, normalize=normalize)
354        data_subset.append(image)
355
356    return data_subset  
357
358
359
360def classification_dataset(dir_path, resize=None, normalize=True, extension=None):
361    """
362    (New version of img_dataset_from_dir).  
363    Given a directory containing folders
364    representing classes of images, this
365    functions builds a valid numpy
366    dataset distribution. 
367    Input (dir_path) structure: 
368    dir_path/class_1, class_n/1.png 
369    Note: 'dir_path' must be the raw
370    dir name (no trailing dash) 
371    Output: [(x,y), ..., (x,y)]
372    Arguments:
373    - dir_path (str): path to the directory containing the class folders. 
374    - resize: tuple of (h, w) for what to resize the images to. If None, won't resize. Default = None. 
375    - normalize: if True, divide by 255. Default = True. 
376    - extension: include only files with this extension. Default = None. 
377    """
378
379    dir_path = dir_path + "/*/"
380    class_list = glob(dir_path, recursive = True)
381    
382    master_list = []
383    idx = 0
384    tqdm_class_idx = 1
385    tqdm_class_list = tqdm(class_list)
386    for class_ in tqdm_class_list:
387        tqdm_class_list.set_description(f"Loading class {tqdm_class_idx}")
388        tqdm_class_idx += 1
389        curr_class = img_dir_to_data(class_, resize, normalize, extension)
390        new_arrays = []
391        for elem in curr_class:
392            if len(elem.shape) == 2:
393                elem = np.expand_dims(elem, axis=0)
394            assert len(elem.shape) == 3
395            if elem.shape[0] != 3 and elem.shape[2] == 3:
396                elem = np.moveaxis(elem, -1, 0)
397            elif elem.shape[0] != 1 and elem.shape[2] == 1:
398                elem = np.moveaxis(elem, -1, 0)
399            new_arrays.append(elem)
400
401        labeled_list = gen_label_pair(new_arrays, idx)
402        master_list.append(labeled_list)
403        idx += 1
404
405    return gen_distro(master_list)
def plot_png(file_path, color):
20def plot_png(file_path, color):
21	"""
22	Plots a png file (or jpeg really) using matplotlib. Color is a bool value. 
23	If true, image will be displayed in color. Else, it will be displayed in 
24	greyscale.
25	"""
26	image = Image.open(file_path)
27	if color == True:
28		plt.imshow(image, interpolation='nearest')
29		plt.show()
30	else:
31		plt.imshow(image, interpolation='nearest', cmap='Greys_r')
32		plt.show()

Plots a png file (or jpeg really) using matplotlib. Color is a bool value. If true, image will be displayed in color. Else, it will be displayed in greyscale.

def plot_np_img(image_array, color):
35def plot_np_img(image_array, color):
36	"""
37    (Here for longevity purposes... use plot instead)
38	Plots a numpy array using matplotlib. Color is a bool value. If true, 
39	image will be displayed in color. Else, it will be displayed in 
40	greyscale.
41
42    input: image_array must be of shape (1, H, W) or (H, W) for greyscale
43    and (3, H, W) for color. 
44	"""
45	if color == True:
46		plt.imshow(image_array, interpolation='nearest')
47		plt.show()
48	else:
49		plt.imshow(image_array, interpolation='nearest', cmap='Greys_r')
50		plt.show()

(Here for longevity purposes... use plot instead) Plots a numpy array using matplotlib. Color is a bool value. If true, image will be displayed in color. Else, it will be displayed in greyscale.

input: image_array must be of shape (1, H, W) or (H, W) for greyscale and (3, H, W) for color.

def plot(image_array, color=True):
53def plot(image_array, color=True):
54    """
55    Plots a numpy array using matplotlib. Color is a bool value which
56    is true by default. If passed in as False, image will be displayed in 
57    greyscale. 
58
59    input: image_array must be of shape (1, H, W) or (H, W, 1) or (H, W) for greyscale
60    and (3, H, W) or (H, W, 3) for color. 
61    """
62
63    # move to numpy is not already in numpy array format 
64    image_array = np.array(image_array)
65    image_array = np.squeeze(image_array)
66
67    if color == True:
68        if image_array.shape[0] == 3:
69            image_array = np.moveaxis(image_array, 0, -1)
70        plt.imshow(image_array, interpolation='nearest')
71        plt.show()
72    else:
73        plt.imshow(image_array, interpolation='nearest', cmap='Greys_r')
74        plt.show()

Plots a numpy array using matplotlib. Color is a bool value which is true by default. If passed in as False, image will be displayed in greyscale.

input: image_array must be of shape (1, H, W) or (H, W, 1) or (H, W) for greyscale and (3, H, W) or (H, W, 3) for color.

def image_dir_to_data(dirpath, extension):
77def image_dir_to_data(dirpath, extension):
78    """
79    Takes in a directory containing images
80    and returns a list of numpy arrays representing
81    those images. 
82    Args:
83        - dirpath: path to directory 
84        - extension: image extension type (e.g. png) (string)
85    """
86    data_subset = []
87    sub_set = glob(dirpath + '/*.' + extension)
88    for elem in sub_set:
89        image = Image.open(elem)
90        image_array = np.array(image)
91        data_subset.append(image_array)
92    return data_subset  

Takes in a directory containing images and returns a list of numpy arrays representing those images. Args: - dirpath: path to directory - extension: image extension type (e.g. png) (string)

def image_dir_to_data_norm(dirpath, extension):
 95def image_dir_to_data_norm(dirpath, extension):
 96    """
 97    (Same as image_dir_to_data but with max value 
 98    (255) normalization). 
 99    Takes in a directory containing images
100    and returns a list of numpy arrays representing
101    those images. 
102    Args:
103        - dirpath: path to directory 
104        - extension: image extension type (e.g. png) (string)
105    """
106    data_subset = []
107    sub_set = glob(dirpath + '/*.' + extension)
108    for elem in sub_set:
109        image = Image.open(elem)
110        image_array = np.array(image)
111        image_array = image_array.astype(float)
112        image_array = image_array/255.0
113        data_subset.append(image_array)
114    return data_subset    

(Same as image_dir_to_data but with max value (255) normalization). Takes in a directory containing images and returns a list of numpy arrays representing those images. Args: - dirpath: path to directory - extension: image extension type (e.g. png) (string)

def gen_label_pair(data_samples, label):
117def gen_label_pair(data_samples, label):
118	"""
119	Takes in a list of data samples (i.e. images, x)
120	and a corresponding label and returns a list of tuples
121	where each tuple is an (x, y) pair. 
122	"""
123	d_set = []
124	for elem in data_samples:
125	    sample_pair = (elem, label)
126	    d_set.append(sample_pair)
127	return d_set 

Takes in a list of data samples (i.e. images, x) and a corresponding label and returns a list of tuples where each tuple is an (x, y) pair.

def gen_distro(master_list):
130def gen_distro(master_list):
131    """
132    Takes in a list of lists who each contain
133    (x, y) tuple samples for that class and returns 
134    a randomly concatenated version. 
135    """
136    generated_distro = []
137    for class_list in master_list:
138        generated_distro = generated_distro + class_list
139    random.shuffle(generated_distro)
140    return generated_distro

Takes in a list of lists who each contain (x, y) tuple samples for that class and returns a randomly concatenated version.

def get_img( url='https://stanford.edu/~rsikand/assets/images/seal.png', resize=True, size=(128, 128)):
143def get_img(url='https://stanford.edu/~rsikand/assets/images/seal.png', resize=True, size=(128, 128)):
144    """
145    Returns a sample numpy image to play with. 
146    Arguments:
147    -----------
148    - url: Can pass in custom url if you want a different image. 
149    Defaults to a baby seal!  
150    - resize: by default, all images are resized to 128x128. If you'd
151    like to keep the default size, specify False. 
152    - size: size to resize to. Default is 128x128. 
153    """
154
155    image = np.array(Image.open(requests.get(url, stream=True).raw))
156
157
158    if resize:
159        if len(image.shape) == 3:
160            image = np.array(T.Resize(size=size)(torch.movedim(torch.tensor(image), -1, 0)))
161        else:
162            image = np.array(T.Resize(size=size)(torch.tensor(image)))
163    else:
164        if len(image.shape) == 3:
165            if image.shape[0] != 3 and image.shape[2] == 3:
166                image = np.moveaxis(image, -1, 0)
167            elif image.shape[0] != 1 and image.shape[2] == 1:
168                image = np.moveaxis(image, -1, 0)
169            else:
170                image = image
171        else:
172            image = image
173
174    return image

Returns a sample numpy image to play with.

Arguments:

  • url: Can pass in custom url if you want a different image. Defaults to a baby seal!
  • resize: by default, all images are resized to 128x128. If you'd like to keep the default size, specify False.
  • size: size to resize to. Default is 128x128.
def img_dataset_from_dir(dir_path):
177def img_dataset_from_dir(dir_path):
178    """
179    Given a directory containing folders
180    representing classes of images, this
181    functions builds a valid numpy
182    dataset distribution. 
183    Input (dir_path) structure: 
184    dir_path/class_1, class_n/1.png 
185    Note: 'dir_path' must be the raw
186    dir name (no trailing dash) 
187    Output: [(x,y), ..., (x,y)]
188    """
189
190    dir_path = dir_path + "/*/"
191    class_list = glob(dir_path, recursive = True)
192    
193    master_list = []
194    idx = 0
195    for class_ in class_list:
196        curr_class = image_dir_to_data_norm(class_, "png")
197        new_arrays = []
198        for elem in curr_class:
199            if len(elem.shape) == 2:
200                elem = np.expand_dims(elem, axis=0)
201            assert len(elem.shape) == 3
202            if elem.shape[0] != 3 and elem.shape[2] == 3:
203                elem = np.moveaxis(elem, -1, 0)
204            elif elem.shape[0] != 1 and elem.shape[2] == 1:
205                elem = np.moveaxis(elem, -1, 0)
206            new_arrays.append(elem)
207
208        labeled_list = gen_label_pair(new_arrays, idx)
209        master_list.append(labeled_list)
210        idx += 1
211
212    return gen_distro(master_list)

Given a directory containing folders representing classes of images, this functions builds a valid numpy dataset distribution. Input (dir_path) structure: dir_path/class_1, class_n/1.png Note: 'dir_path' must be the raw dir name (no trailing dash) Output: [(x,y), ..., (x,y)]

class MeanMetric:
240class MeanMetric:
241  """
242  Scalar metric designed to use on a per-epoch basis 
243  and updated on per-batch basis. For getting average across
244  the epoch. 
245  """
246
247  def __init__(self):
248    self.vals = []
249
250  def update(self, new_val):
251    self.vals.append(new_val)
252
253  def reset(self):
254    self.vals = []
255
256  def get(self):
257    mean_value = sum(self.vals)/len(self.vals)
258    return mean_value

Scalar metric designed to use on a per-epoch basis and updated on per-batch basis. For getting average across the epoch.

def update(self, new_val):
250  def update(self, new_val):
251    self.vals.append(new_val)
def reset(self):
253  def reset(self):
254    self.vals = []
def get(self):
256  def get(self):
257    mean_value = sum(self.vals)/len(self.vals)
258    return mean_value
def numpy_collate(batch):
262def numpy_collate(batch):
263    """batch collate function but keep as numpy array instead 
264    of converting to torch tensor like pytorch default does. inputs
265    must be np.arrays 
266    https://github.com/pytorch/pytorch/blob/35c8f93fd238d42aaea8fd6e730c3da9e18257cc/torch/utils/data/dataloader.py#L218
267    """
268
269    r_tuple = []
270
271    for i in range(len(batch[0])):
272        arrays_to_stack = []
273        for j in range(len(batch)):
274            arrays_to_stack.append(batch[j][i])
275        stacked = np.stack(arrays_to_stack, axis=0)
276        r_tuple.append(stacked)
277    
278    return tuple(r_tuple)

batch collate function but keep as numpy array instead of converting to torch tensor like pytorch default does. inputs must be np.arrays https://github.com/pytorch/pytorch/blob/35c8f93fd238d42aaea8fd6e730c3da9e18257cc/torch/utils/data/dataloader.py#L218

def load_image(img_path, resize=None, normalize=True):
281def load_image(img_path, resize=None, normalize=True):
282    """
283    Loads an image file into a numpy array in (C, H, W) form. 
284    Arguments:
285    -----------
286    - img_path (str): image filename (relative) 
287    - resize (tuple): (x, y) size to resize to. If None, won't resize. Default = None. 
288    - normalize: if True, divide by 255. 
289    Returns:
290    -----------
291    - image_array: loaded numpy array of the image file     
292    """
293    
294    x = Image.open(img_path)
295    image_array = np.array(x)
296
297    # remove transparency dimension if it exists 
298    if image_array.shape[-1] == 4 and len(image_array.shape) == 3:
299        image_array = image_array[:, :, :3]
300    elif image_array.shape[0] == 4 and len(image_array.shape) == 3:
301        image_array = image_array[:3, :, :]
302    
303    # if image has only 2 channels, add a third channel
304    if len(image_array.shape) == 3 and image_array.shape[-1] == 2:
305        image_array = np.concatenate([np.expand_dims(image_array[:, :, -1], axis=-1), image_array], axis=-1)
306    elif len(image_array.shape) == 3 and image_array.shape[0] == 2:
307        image_array = np.concatenate([np.expand_dims(image_array[-1, :, :], axis=0), image_array], axis=0)
308
309    if normalize:
310        image_array = image_array / 255.0
311
312    # if image is grayscale, add a channel dimension
313    if len(image_array.shape) == 2:
314        image_array = np.expand_dims(image_array, axis=0)
315    
316    assert len(image_array.shape) == 3
317
318    # switch dim 
319    if (image_array.shape[0] != 3 and image_array.shape[2] == 3) or (image_array.shape[0] != 1 and image_array.shape[2] == 1):
320        image_array = np.moveaxis(image_array, -1, 0)
321
322    assert image_array.shape[0] == 3 or image_array.shape[0] == 1
323
324    # resize 
325    if resize is not None:
326        image_array = np.array(T.Resize(size=resize)(torch.tensor(image_array)))
327
328    return image_array

Loads an image file into a numpy array in (C, H, W) form.

Arguments:

  • img_path (str): image filename (relative)
  • resize (tuple): (x, y) size to resize to. If None, won't resize. Default = None.
  • normalize: if True, divide by 255.

    Returns:

  • image_array: loaded numpy array of the image file

def img_dir_to_data(dirpath, resize=None, normalize=True, extension=None):
334def img_dir_to_data(dirpath, resize=None, normalize=True, extension=None):
335    """
336    (New version of image_dir_to_data). 
337    Takes in a directory containing images
338    and returns a list of numpy arrays representing
339    those images. 
340    Args:
341        - dirpath: path to directory 
342        - extension: include only files with this extension. Default = None. 
343        - resize: tuple of (h, w) for what to resize the images to. If None, won't resize. Default = None. 
344        - normalize: if True, divide by 255. 
345    """
346    data_subset = []
347    if extension is not None:
348        dirpath = dirpath + "/*." + extension
349    else:
350        dirpath = dirpath + "/*"
351    sub_set = glob(dirpath)
352
353    for elem in sub_set:
354        image = load_image(elem, resize=resize, normalize=normalize)
355        data_subset.append(image)
356
357    return data_subset  

(New version of image_dir_to_data). Takes in a directory containing images and returns a list of numpy arrays representing those images. Args: - dirpath: path to directory - extension: include only files with this extension. Default = None. - resize: tuple of (h, w) for what to resize the images to. If None, won't resize. Default = None. - normalize: if True, divide by 255.

def classification_dataset(dir_path, resize=None, normalize=True, extension=None):
361def classification_dataset(dir_path, resize=None, normalize=True, extension=None):
362    """
363    (New version of img_dataset_from_dir).  
364    Given a directory containing folders
365    representing classes of images, this
366    functions builds a valid numpy
367    dataset distribution. 
368    Input (dir_path) structure: 
369    dir_path/class_1, class_n/1.png 
370    Note: 'dir_path' must be the raw
371    dir name (no trailing dash) 
372    Output: [(x,y), ..., (x,y)]
373    Arguments:
374    - dir_path (str): path to the directory containing the class folders. 
375    - resize: tuple of (h, w) for what to resize the images to. If None, won't resize. Default = None. 
376    - normalize: if True, divide by 255. Default = True. 
377    - extension: include only files with this extension. Default = None. 
378    """
379
380    dir_path = dir_path + "/*/"
381    class_list = glob(dir_path, recursive = True)
382    
383    master_list = []
384    idx = 0
385    tqdm_class_idx = 1
386    tqdm_class_list = tqdm(class_list)
387    for class_ in tqdm_class_list:
388        tqdm_class_list.set_description(f"Loading class {tqdm_class_idx}")
389        tqdm_class_idx += 1
390        curr_class = img_dir_to_data(class_, resize, normalize, extension)
391        new_arrays = []
392        for elem in curr_class:
393            if len(elem.shape) == 2:
394                elem = np.expand_dims(elem, axis=0)
395            assert len(elem.shape) == 3
396            if elem.shape[0] != 3 and elem.shape[2] == 3:
397                elem = np.moveaxis(elem, -1, 0)
398            elif elem.shape[0] != 1 and elem.shape[2] == 1:
399                elem = np.moveaxis(elem, -1, 0)
400            new_arrays.append(elem)
401
402        labeled_list = gen_label_pair(new_arrays, idx)
403        master_list.append(labeled_list)
404        idx += 1
405
406    return gen_distro(master_list)

(New version of img_dataset_from_dir).
Given a directory containing folders representing classes of images, this functions builds a valid numpy dataset distribution. Input (dir_path) structure: dir_path/class_1, class_n/1.png Note: 'dir_path' must be the raw dir name (no trailing dash) Output: [(x,y), ..., (x,y)] Arguments:

  • dir_path (str): path to the directory containing the class folders.
  • resize: tuple of (h, w) for what to resize the images to. If None, won't resize. Default = None.
  • normalize: if True, divide by 255. Default = True.
  • extension: include only files with this extension. Default = None.