imagenet.py 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394
  1. import os, yaml, pickle, shutil, tarfile, glob
  2. import cv2
  3. import albumentations
  4. import PIL
  5. import numpy as np
  6. import torchvision.transforms.functional as TF
  7. from omegaconf import OmegaConf
  8. from functools import partial
  9. from PIL import Image
  10. from tqdm import tqdm
  11. from torch.utils.data import Dataset, Subset
  12. import taming.data.utils as tdu
  13. from taming.data.imagenet import str_to_indices, give_synsets_from_indices, download, retrieve
  14. from taming.data.imagenet import ImagePaths
  15. from ldm.modules.image_degradation import degradation_fn_bsr, degradation_fn_bsr_light
  16. def synset2idx(path_to_yaml="data/index_synset.yaml"):
  17. with open(path_to_yaml) as f:
  18. di2s = yaml.load(f)
  19. return dict((v,k) for k,v in di2s.items())
  20. class ImageNetBase(Dataset):
  21. def __init__(self, config=None):
  22. self.config = config or OmegaConf.create()
  23. if not type(self.config)==dict:
  24. self.config = OmegaConf.to_container(self.config)
  25. self.keep_orig_class_label = self.config.get("keep_orig_class_label", False)
  26. self.process_images = True # if False we skip loading & processing images and self.data contains filepaths
  27. self._prepare()
  28. self._prepare_synset_to_human()
  29. self._prepare_idx_to_synset()
  30. self._prepare_human_to_integer_label()
  31. self._load()
  32. def __len__(self):
  33. return len(self.data)
  34. def __getitem__(self, i):
  35. return self.data[i]
  36. def _prepare(self):
  37. raise NotImplementedError()
  38. def _filter_relpaths(self, relpaths):
  39. ignore = set([
  40. "n06596364_9591.JPEG",
  41. ])
  42. relpaths = [rpath for rpath in relpaths if not rpath.split("/")[-1] in ignore]
  43. if "sub_indices" in self.config:
  44. indices = str_to_indices(self.config["sub_indices"])
  45. synsets = give_synsets_from_indices(indices, path_to_yaml=self.idx2syn) # returns a list of strings
  46. self.synset2idx = synset2idx(path_to_yaml=self.idx2syn)
  47. files = []
  48. for rpath in relpaths:
  49. syn = rpath.split("/")[0]
  50. if syn in synsets:
  51. files.append(rpath)
  52. return files
  53. else:
  54. return relpaths
  55. def _prepare_synset_to_human(self):
  56. SIZE = 2655750
  57. URL = "https://heibox.uni-heidelberg.de/f/9f28e956cd304264bb82/?dl=1"
  58. self.human_dict = os.path.join(self.root, "synset_human.txt")
  59. if (not os.path.exists(self.human_dict) or
  60. not os.path.getsize(self.human_dict)==SIZE):
  61. download(URL, self.human_dict)
  62. def _prepare_idx_to_synset(self):
  63. URL = "https://heibox.uni-heidelberg.de/f/d835d5b6ceda4d3aa910/?dl=1"
  64. self.idx2syn = os.path.join(self.root, "index_synset.yaml")
  65. if (not os.path.exists(self.idx2syn)):
  66. download(URL, self.idx2syn)
  67. def _prepare_human_to_integer_label(self):
  68. URL = "https://heibox.uni-heidelberg.de/f/2362b797d5be43b883f6/?dl=1"
  69. self.human2integer = os.path.join(self.root, "imagenet1000_clsidx_to_labels.txt")
  70. if (not os.path.exists(self.human2integer)):
  71. download(URL, self.human2integer)
  72. with open(self.human2integer, "r") as f:
  73. lines = f.read().splitlines()
  74. assert len(lines) == 1000
  75. self.human2integer_dict = dict()
  76. for line in lines:
  77. value, key = line.split(":")
  78. self.human2integer_dict[key] = int(value)
  79. def _load(self):
  80. with open(self.txt_filelist, "r") as f:
  81. self.relpaths = f.read().splitlines()
  82. l1 = len(self.relpaths)
  83. self.relpaths = self._filter_relpaths(self.relpaths)
  84. print("Removed {} files from filelist during filtering.".format(l1 - len(self.relpaths)))
  85. self.synsets = [p.split("/")[0] for p in self.relpaths]
  86. self.abspaths = [os.path.join(self.datadir, p) for p in self.relpaths]
  87. unique_synsets = np.unique(self.synsets)
  88. class_dict = dict((synset, i) for i, synset in enumerate(unique_synsets))
  89. if not self.keep_orig_class_label:
  90. self.class_labels = [class_dict[s] for s in self.synsets]
  91. else:
  92. self.class_labels = [self.synset2idx[s] for s in self.synsets]
  93. with open(self.human_dict, "r") as f:
  94. human_dict = f.read().splitlines()
  95. human_dict = dict(line.split(maxsplit=1) for line in human_dict)
  96. self.human_labels = [human_dict[s] for s in self.synsets]
  97. labels = {
  98. "relpath": np.array(self.relpaths),
  99. "synsets": np.array(self.synsets),
  100. "class_label": np.array(self.class_labels),
  101. "human_label": np.array(self.human_labels),
  102. }
  103. if self.process_images:
  104. self.size = retrieve(self.config, "size", default=256)
  105. self.data = ImagePaths(self.abspaths,
  106. labels=labels,
  107. size=self.size,
  108. random_crop=self.random_crop,
  109. )
  110. else:
  111. self.data = self.abspaths
  112. class ImageNetTrain(ImageNetBase):
  113. NAME = "ILSVRC2012_train"
  114. URL = "http://www.image-net.org/challenges/LSVRC/2012/"
  115. AT_HASH = "a306397ccf9c2ead27155983c254227c0fd938e2"
  116. FILES = [
  117. "ILSVRC2012_img_train.tar",
  118. ]
  119. SIZES = [
  120. 147897477120,
  121. ]
  122. def __init__(self, process_images=True, data_root=None, **kwargs):
  123. self.process_images = process_images
  124. self.data_root = data_root
  125. super().__init__(**kwargs)
  126. def _prepare(self):
  127. if self.data_root:
  128. self.root = os.path.join(self.data_root, self.NAME)
  129. else:
  130. cachedir = os.environ.get("XDG_CACHE_HOME", os.path.expanduser("~/.cache"))
  131. self.root = os.path.join(cachedir, "autoencoders/data", self.NAME)
  132. self.datadir = os.path.join(self.root, "data")
  133. self.txt_filelist = os.path.join(self.root, "filelist.txt")
  134. self.expected_length = 1281167
  135. self.random_crop = retrieve(self.config, "ImageNetTrain/random_crop",
  136. default=True)
  137. if not tdu.is_prepared(self.root):
  138. # prep
  139. print("Preparing dataset {} in {}".format(self.NAME, self.root))
  140. datadir = self.datadir
  141. if not os.path.exists(datadir):
  142. path = os.path.join(self.root, self.FILES[0])
  143. if not os.path.exists(path) or not os.path.getsize(path)==self.SIZES[0]:
  144. import academictorrents as at
  145. atpath = at.get(self.AT_HASH, datastore=self.root)
  146. assert atpath == path
  147. print("Extracting {} to {}".format(path, datadir))
  148. os.makedirs(datadir, exist_ok=True)
  149. with tarfile.open(path, "r:") as tar:
  150. tar.extractall(path=datadir)
  151. print("Extracting sub-tars.")
  152. subpaths = sorted(glob.glob(os.path.join(datadir, "*.tar")))
  153. for subpath in tqdm(subpaths):
  154. subdir = subpath[:-len(".tar")]
  155. os.makedirs(subdir, exist_ok=True)
  156. with tarfile.open(subpath, "r:") as tar:
  157. tar.extractall(path=subdir)
  158. filelist = glob.glob(os.path.join(datadir, "**", "*.JPEG"))
  159. filelist = [os.path.relpath(p, start=datadir) for p in filelist]
  160. filelist = sorted(filelist)
  161. filelist = "\n".join(filelist)+"\n"
  162. with open(self.txt_filelist, "w") as f:
  163. f.write(filelist)
  164. tdu.mark_prepared(self.root)
  165. class ImageNetValidation(ImageNetBase):
  166. NAME = "ILSVRC2012_validation"
  167. URL = "http://www.image-net.org/challenges/LSVRC/2012/"
  168. AT_HASH = "5d6d0df7ed81efd49ca99ea4737e0ae5e3a5f2e5"
  169. VS_URL = "https://heibox.uni-heidelberg.de/f/3e0f6e9c624e45f2bd73/?dl=1"
  170. FILES = [
  171. "ILSVRC2012_img_val.tar",
  172. "validation_synset.txt",
  173. ]
  174. SIZES = [
  175. 6744924160,
  176. 1950000,
  177. ]
  178. def __init__(self, process_images=True, data_root=None, **kwargs):
  179. self.data_root = data_root
  180. self.process_images = process_images
  181. super().__init__(**kwargs)
  182. def _prepare(self):
  183. if self.data_root:
  184. self.root = os.path.join(self.data_root, self.NAME)
  185. else:
  186. cachedir = os.environ.get("XDG_CACHE_HOME", os.path.expanduser("~/.cache"))
  187. self.root = os.path.join(cachedir, "autoencoders/data", self.NAME)
  188. self.datadir = os.path.join(self.root, "data")
  189. self.txt_filelist = os.path.join(self.root, "filelist.txt")
  190. self.expected_length = 50000
  191. self.random_crop = retrieve(self.config, "ImageNetValidation/random_crop",
  192. default=False)
  193. if not tdu.is_prepared(self.root):
  194. # prep
  195. print("Preparing dataset {} in {}".format(self.NAME, self.root))
  196. datadir = self.datadir
  197. if not os.path.exists(datadir):
  198. path = os.path.join(self.root, self.FILES[0])
  199. if not os.path.exists(path) or not os.path.getsize(path)==self.SIZES[0]:
  200. import academictorrents as at
  201. atpath = at.get(self.AT_HASH, datastore=self.root)
  202. assert atpath == path
  203. print("Extracting {} to {}".format(path, datadir))
  204. os.makedirs(datadir, exist_ok=True)
  205. with tarfile.open(path, "r:") as tar:
  206. tar.extractall(path=datadir)
  207. vspath = os.path.join(self.root, self.FILES[1])
  208. if not os.path.exists(vspath) or not os.path.getsize(vspath)==self.SIZES[1]:
  209. download(self.VS_URL, vspath)
  210. with open(vspath, "r") as f:
  211. synset_dict = f.read().splitlines()
  212. synset_dict = dict(line.split() for line in synset_dict)
  213. print("Reorganizing into synset folders")
  214. synsets = np.unique(list(synset_dict.values()))
  215. for s in synsets:
  216. os.makedirs(os.path.join(datadir, s), exist_ok=True)
  217. for k, v in synset_dict.items():
  218. src = os.path.join(datadir, k)
  219. dst = os.path.join(datadir, v)
  220. shutil.move(src, dst)
  221. filelist = glob.glob(os.path.join(datadir, "**", "*.JPEG"))
  222. filelist = [os.path.relpath(p, start=datadir) for p in filelist]
  223. filelist = sorted(filelist)
  224. filelist = "\n".join(filelist)+"\n"
  225. with open(self.txt_filelist, "w") as f:
  226. f.write(filelist)
  227. tdu.mark_prepared(self.root)
  228. class ImageNetSR(Dataset):
  229. def __init__(self, size=None,
  230. degradation=None, downscale_f=4, min_crop_f=0.5, max_crop_f=1.,
  231. random_crop=True):
  232. """
  233. Imagenet Superresolution Dataloader
  234. Performs following ops in order:
  235. 1. crops a crop of size s from image either as random or center crop
  236. 2. resizes crop to size with cv2.area_interpolation
  237. 3. degrades resized crop with degradation_fn
  238. :param size: resizing to size after cropping
  239. :param degradation: degradation_fn, e.g. cv_bicubic or bsrgan_light
  240. :param downscale_f: Low Resolution Downsample factor
  241. :param min_crop_f: determines crop size s,
  242. where s = c * min_img_side_len with c sampled from interval (min_crop_f, max_crop_f)
  243. :param max_crop_f: ""
  244. :param data_root:
  245. :param random_crop:
  246. """
  247. self.base = self.get_base()
  248. assert size
  249. assert (size / downscale_f).is_integer()
  250. self.size = size
  251. self.LR_size = int(size / downscale_f)
  252. self.min_crop_f = min_crop_f
  253. self.max_crop_f = max_crop_f
  254. assert(max_crop_f <= 1.)
  255. self.center_crop = not random_crop
  256. self.image_rescaler = albumentations.SmallestMaxSize(max_size=size, interpolation=cv2.INTER_AREA)
  257. self.pil_interpolation = False # gets reset later if incase interp_op is from pillow
  258. if degradation == "bsrgan":
  259. self.degradation_process = partial(degradation_fn_bsr, sf=downscale_f)
  260. elif degradation == "bsrgan_light":
  261. self.degradation_process = partial(degradation_fn_bsr_light, sf=downscale_f)
  262. else:
  263. interpolation_fn = {
  264. "cv_nearest": cv2.INTER_NEAREST,
  265. "cv_bilinear": cv2.INTER_LINEAR,
  266. "cv_bicubic": cv2.INTER_CUBIC,
  267. "cv_area": cv2.INTER_AREA,
  268. "cv_lanczos": cv2.INTER_LANCZOS4,
  269. "pil_nearest": PIL.Image.NEAREST,
  270. "pil_bilinear": PIL.Image.BILINEAR,
  271. "pil_bicubic": PIL.Image.BICUBIC,
  272. "pil_box": PIL.Image.BOX,
  273. "pil_hamming": PIL.Image.HAMMING,
  274. "pil_lanczos": PIL.Image.LANCZOS,
  275. }[degradation]
  276. self.pil_interpolation = degradation.startswith("pil_")
  277. if self.pil_interpolation:
  278. self.degradation_process = partial(TF.resize, size=self.LR_size, interpolation=interpolation_fn)
  279. else:
  280. self.degradation_process = albumentations.SmallestMaxSize(max_size=self.LR_size,
  281. interpolation=interpolation_fn)
  282. def __len__(self):
  283. return len(self.base)
  284. def __getitem__(self, i):
  285. example = self.base[i]
  286. image = Image.open(example["file_path_"])
  287. if not image.mode == "RGB":
  288. image = image.convert("RGB")
  289. image = np.array(image).astype(np.uint8)
  290. min_side_len = min(image.shape[:2])
  291. crop_side_len = min_side_len * np.random.uniform(self.min_crop_f, self.max_crop_f, size=None)
  292. crop_side_len = int(crop_side_len)
  293. if self.center_crop:
  294. self.cropper = albumentations.CenterCrop(height=crop_side_len, width=crop_side_len)
  295. else:
  296. self.cropper = albumentations.RandomCrop(height=crop_side_len, width=crop_side_len)
  297. image = self.cropper(image=image)["image"]
  298. image = self.image_rescaler(image=image)["image"]
  299. if self.pil_interpolation:
  300. image_pil = PIL.Image.fromarray(image)
  301. LR_image = self.degradation_process(image_pil)
  302. LR_image = np.array(LR_image).astype(np.uint8)
  303. else:
  304. LR_image = self.degradation_process(image=image)["image"]
  305. example["image"] = (image/127.5 - 1.0).astype(np.float32)
  306. example["LR_image"] = (LR_image/127.5 - 1.0).astype(np.float32)
  307. return example
  308. class ImageNetSRTrain(ImageNetSR):
  309. def __init__(self, **kwargs):
  310. super().__init__(**kwargs)
  311. def get_base(self):
  312. with open("data/imagenet_train_hr_indices.p", "rb") as f:
  313. indices = pickle.load(f)
  314. dset = ImageNetTrain(process_images=False,)
  315. return Subset(dset, indices)
  316. class ImageNetSRValidation(ImageNetSR):
  317. def __init__(self, **kwargs):
  318. super().__init__(**kwargs)
  319. def get_base(self):
  320. with open("data/imagenet_val_hr_indices.p", "rb") as f:
  321. indices = pickle.load(f)
  322. dset = ImageNetValidation(process_images=False,)
  323. return Subset(dset, indices)