DaSE-Computer-Vision-2021
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

262 lines
9.0 KiB

  1. from __future__ import print_function
  2. from builtins import range
  3. from six.moves import cPickle as pickle
  4. import numpy as np
  5. import os
  6. from imageio import imread
  7. import platform
  8. def load_pickle(f):
  9. version = platform.python_version_tuple()
  10. if version[0] == '2':
  11. return pickle.load(f)
  12. elif version[0] == '3':
  13. return pickle.load(f, encoding='latin1')
  14. raise ValueError("invalid python version: {}".format(version))
  15. def load_CIFAR_batch(filename):
  16. """ load single batch of cifar """
  17. with open(filename, 'rb') as f:
  18. datadict = load_pickle(f)
  19. X = datadict['data']
  20. Y = datadict['labels']
  21. X = X.reshape(10000, 3, 32, 32).transpose(0,2,3,1).astype("float")
  22. Y = np.array(Y)
  23. return X, Y
  24. def load_CIFAR10(ROOT):
  25. """ load all of cifar """
  26. xs = []
  27. ys = []
  28. for b in range(1,6):
  29. f = os.path.join(ROOT, 'data_batch_%d' % (b, ))
  30. X, Y = load_CIFAR_batch(f)
  31. xs.append(X)
  32. ys.append(Y)
  33. Xtr = np.concatenate(xs)
  34. Ytr = np.concatenate(ys)
  35. del X, Y
  36. Xte, Yte = load_CIFAR_batch(os.path.join(ROOT, 'test_batch'))
  37. return Xtr, Ytr, Xte, Yte
  38. def get_CIFAR10_data(num_training=49000, num_validation=1000, num_test=1000,
  39. subtract_mean=True):
  40. """
  41. Load the CIFAR-10 dataset from disk and perform preprocessing to prepare
  42. it for classifiers. These are the same steps as we used for the SVM, but
  43. condensed to a single function.
  44. """
  45. # Load the raw CIFAR-10 data
  46. cifar10_dir = 'daseCV/datasets/cifar-10-batches-py'
  47. X_train, y_train, X_test, y_test = load_CIFAR10(cifar10_dir)
  48. # Subsample the data
  49. mask = list(range(num_training, num_training + num_validation))
  50. X_val = X_train[mask]
  51. y_val = y_train[mask]
  52. mask = list(range(num_training))
  53. X_train = X_train[mask]
  54. y_train = y_train[mask]
  55. mask = list(range(num_test))
  56. X_test = X_test[mask]
  57. y_test = y_test[mask]
  58. # Normalize the data: subtract the mean image
  59. if subtract_mean:
  60. mean_image = np.mean(X_train, axis=0)
  61. X_train -= mean_image
  62. X_val -= mean_image
  63. X_test -= mean_image
  64. # Transpose so that channels come first
  65. X_train = X_train.transpose(0, 3, 1, 2).copy()
  66. X_val = X_val.transpose(0, 3, 1, 2).copy()
  67. X_test = X_test.transpose(0, 3, 1, 2).copy()
  68. # Package data into a dictionary
  69. return {
  70. 'X_train': X_train, 'y_train': y_train,
  71. 'X_val': X_val, 'y_val': y_val,
  72. 'X_test': X_test, 'y_test': y_test,
  73. }
  74. def load_tiny_imagenet(path, dtype=np.float32, subtract_mean=True):
  75. """
  76. Load TinyImageNet. Each of TinyImageNet-100-A, TinyImageNet-100-B, and
  77. TinyImageNet-200 have the same directory structure, so this can be used
  78. to load any of them.
  79. Inputs:
  80. - path: String giving path to the directory to load.
  81. - dtype: numpy datatype used to load the data.
  82. - subtract_mean: Whether to subtract the mean training image.
  83. Returns: A dictionary with the following entries:
  84. - class_names: A list where class_names[i] is a list of strings giving the
  85. WordNet names for class i in the loaded dataset.
  86. - X_train: (N_tr, 3, 64, 64) array of training images
  87. - y_train: (N_tr,) array of training labels
  88. - X_val: (N_val, 3, 64, 64) array of validation images
  89. - y_val: (N_val,) array of validation labels
  90. - X_test: (N_test, 3, 64, 64) array of testing images.
  91. - y_test: (N_test,) array of test labels; if test labels are not available
  92. (such as in student code) then y_test will be None.
  93. - mean_image: (3, 64, 64) array giving mean training image
  94. """
  95. # First load wnids
  96. with open(os.path.join(path, 'wnids.txt'), 'r') as f:
  97. wnids = [x.strip() for x in f]
  98. # Map wnids to integer labels
  99. wnid_to_label = {wnid: i for i, wnid in enumerate(wnids)}
  100. # Use words.txt to get names for each class
  101. with open(os.path.join(path, 'words.txt'), 'r') as f:
  102. wnid_to_words = dict(line.split('\t') for line in f)
  103. for wnid, words in wnid_to_words.items():
  104. wnid_to_words[wnid] = [w.strip() for w in words.split(',')]
  105. class_names = [wnid_to_words[wnid] for wnid in wnids]
  106. # Next load training data.
  107. X_train = []
  108. y_train = []
  109. for i, wnid in enumerate(wnids):
  110. if (i + 1) % 20 == 0:
  111. print('loading training data for synset %d / %d'
  112. % (i + 1, len(wnids)))
  113. # To figure out the filenames we need to open the boxes file
  114. boxes_file = os.path.join(path, 'train', wnid, '%s_boxes.txt' % wnid)
  115. with open(boxes_file, 'r') as f:
  116. filenames = [x.split('\t')[0] for x in f]
  117. num_images = len(filenames)
  118. X_train_block = np.zeros((num_images, 3, 64, 64), dtype=dtype)
  119. y_train_block = wnid_to_label[wnid] * \
  120. np.ones(num_images, dtype=np.int64)
  121. for j, img_file in enumerate(filenames):
  122. img_file = os.path.join(path, 'train', wnid, 'images', img_file)
  123. img = imread(img_file)
  124. if img.ndim == 2:
  125. ## grayscale file
  126. img.shape = (64, 64, 1)
  127. X_train_block[j] = img.transpose(2, 0, 1)
  128. X_train.append(X_train_block)
  129. y_train.append(y_train_block)
  130. # We need to concatenate all training data
  131. X_train = np.concatenate(X_train, axis=0)
  132. y_train = np.concatenate(y_train, axis=0)
  133. # Next load validation data
  134. with open(os.path.join(path, 'val', 'val_annotations.txt'), 'r') as f:
  135. img_files = []
  136. val_wnids = []
  137. for line in f:
  138. img_file, wnid = line.split('\t')[:2]
  139. img_files.append(img_file)
  140. val_wnids.append(wnid)
  141. num_val = len(img_files)
  142. y_val = np.array([wnid_to_label[wnid] for wnid in val_wnids])
  143. X_val = np.zeros((num_val, 3, 64, 64), dtype=dtype)
  144. for i, img_file in enumerate(img_files):
  145. img_file = os.path.join(path, 'val', 'images', img_file)
  146. img = imread(img_file)
  147. if img.ndim == 2:
  148. img.shape = (64, 64, 1)
  149. X_val[i] = img.transpose(2, 0, 1)
  150. # Next load test images
  151. # Students won't have test labels, so we need to iterate over files in the
  152. # images directory.
  153. img_files = os.listdir(os.path.join(path, 'test', 'images'))
  154. X_test = np.zeros((len(img_files), 3, 64, 64), dtype=dtype)
  155. for i, img_file in enumerate(img_files):
  156. img_file = os.path.join(path, 'test', 'images', img_file)
  157. img = imread(img_file)
  158. if img.ndim == 2:
  159. img.shape = (64, 64, 1)
  160. X_test[i] = img.transpose(2, 0, 1)
  161. y_test = None
  162. y_test_file = os.path.join(path, 'test', 'test_annotations.txt')
  163. if os.path.isfile(y_test_file):
  164. with open(y_test_file, 'r') as f:
  165. img_file_to_wnid = {}
  166. for line in f:
  167. line = line.split('\t')
  168. img_file_to_wnid[line[0]] = line[1]
  169. y_test = [wnid_to_label[img_file_to_wnid[img_file]]
  170. for img_file in img_files]
  171. y_test = np.array(y_test)
  172. mean_image = X_train.mean(axis=0)
  173. if subtract_mean:
  174. X_train -= mean_image[None]
  175. X_val -= mean_image[None]
  176. X_test -= mean_image[None]
  177. return {
  178. 'class_names': class_names,
  179. 'X_train': X_train,
  180. 'y_train': y_train,
  181. 'X_val': X_val,
  182. 'y_val': y_val,
  183. 'X_test': X_test,
  184. 'y_test': y_test,
  185. 'class_names': class_names,
  186. 'mean_image': mean_image,
  187. }
  188. def load_models(models_dir):
  189. """
  190. Load saved models from disk. This will attempt to unpickle all files in a
  191. directory; any files that give errors on unpickling (such as README.txt)
  192. will be skipped.
  193. Inputs:
  194. - models_dir: String giving the path to a directory containing model files.
  195. Each model file is a pickled dictionary with a 'model' field.
  196. Returns:
  197. A dictionary mapping model file names to models.
  198. """
  199. models = {}
  200. for model_file in os.listdir(models_dir):
  201. with open(os.path.join(models_dir, model_file), 'rb') as f:
  202. try:
  203. models[model_file] = load_pickle(f)['model']
  204. except pickle.UnpicklingError:
  205. continue
  206. return models
  207. def load_imagenet_val(num=None):
  208. """Load a handful of validation images from ImageNet.
  209. Inputs:
  210. - num: Number of images to load (max of 25)
  211. Returns:
  212. - X: numpy array with shape [num, 224, 224, 3]
  213. - y: numpy array of integer image labels, shape [num]
  214. - class_names: dict mapping integer label to class name
  215. """
  216. imagenet_fn = 'daseCV/datasets/imagenet_val_25.npz'
  217. if not os.path.isfile(imagenet_fn):
  218. print('file %s not found' % imagenet_fn)
  219. print('Run the following:')
  220. print('cd daseCV/datasets')
  221. print('bash get_imagenet_val.sh')
  222. assert False, 'Need to download imagenet_val_25.npz'
  223. f = np.load(imagenet_fn)
  224. X = f['X']
  225. y = f['y']
  226. class_names = f['label_map'].item()
  227. if num is not None:
  228. X = X[:num]
  229. y = y[:num]
  230. return X, y, class_names