test_datasets.py 131 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409
  1. import bz2
  2. import contextlib
  3. import csv
  4. import io
  5. import itertools
  6. import json
  7. import os
  8. import pathlib
  9. import pickle
  10. import random
  11. import re
  12. import shutil
  13. import string
  14. import unittest
  15. import xml.etree.ElementTree as ET
  16. import zipfile
  17. from typing import Callable, Tuple, Union
  18. import datasets_utils
  19. import numpy as np
  20. import PIL
  21. import pytest
  22. import torch
  23. import torch.nn.functional as F
  24. from common_utils import combinations_grid
  25. from torchvision import datasets
  26. class STL10TestCase(datasets_utils.ImageDatasetTestCase):
  27. DATASET_CLASS = datasets.STL10
  28. ADDITIONAL_CONFIGS = combinations_grid(split=("train", "test", "unlabeled", "train+unlabeled"))
  29. @staticmethod
  30. def _make_binary_file(num_elements, root, name):
  31. file_name = os.path.join(root, name)
  32. np.zeros(num_elements, dtype=np.uint8).tofile(file_name)
  33. @staticmethod
  34. def _make_image_file(num_images, root, name, num_channels=3, height=96, width=96):
  35. STL10TestCase._make_binary_file(num_images * num_channels * height * width, root, name)
  36. @staticmethod
  37. def _make_label_file(num_images, root, name):
  38. STL10TestCase._make_binary_file(num_images, root, name)
  39. @staticmethod
  40. def _make_class_names_file(root, name="class_names.txt"):
  41. with open(os.path.join(root, name), "w") as fh:
  42. for cname in ("airplane", "bird"):
  43. fh.write(f"{cname}\n")
  44. @staticmethod
  45. def _make_fold_indices_file(root):
  46. num_folds = 10
  47. offset = 0
  48. with open(os.path.join(root, "fold_indices.txt"), "w") as fh:
  49. for fold in range(num_folds):
  50. line = " ".join([str(idx) for idx in range(offset, offset + fold + 1)])
  51. fh.write(f"{line}\n")
  52. offset += fold + 1
  53. return tuple(range(1, num_folds + 1))
  54. @staticmethod
  55. def _make_train_files(root, num_unlabeled_images=1):
  56. num_images_in_fold = STL10TestCase._make_fold_indices_file(root)
  57. num_train_images = sum(num_images_in_fold)
  58. STL10TestCase._make_image_file(num_train_images, root, "train_X.bin")
  59. STL10TestCase._make_label_file(num_train_images, root, "train_y.bin")
  60. STL10TestCase._make_image_file(1, root, "unlabeled_X.bin")
  61. return dict(train=num_train_images, unlabeled=num_unlabeled_images)
  62. @staticmethod
  63. def _make_test_files(root, num_images=2):
  64. STL10TestCase._make_image_file(num_images, root, "test_X.bin")
  65. STL10TestCase._make_label_file(num_images, root, "test_y.bin")
  66. return dict(test=num_images)
  67. def inject_fake_data(self, tmpdir, config):
  68. root_folder = os.path.join(tmpdir, "stl10_binary")
  69. os.mkdir(root_folder)
  70. num_images_in_split = self._make_train_files(root_folder)
  71. num_images_in_split.update(self._make_test_files(root_folder))
  72. self._make_class_names_file(root_folder)
  73. return sum(num_images_in_split[part] for part in config["split"].split("+"))
  74. def test_folds(self):
  75. for fold in range(10):
  76. with self.create_dataset(split="train", folds=fold) as (dataset, _):
  77. assert len(dataset) == fold + 1
  78. def test_unlabeled(self):
  79. with self.create_dataset(split="unlabeled") as (dataset, _):
  80. labels = [dataset[idx][1] for idx in range(len(dataset))]
  81. assert all(label == -1 for label in labels)
  82. def test_invalid_folds1(self):
  83. with pytest.raises(ValueError):
  84. with self.create_dataset(folds=10):
  85. pass
  86. def test_invalid_folds2(self):
  87. with pytest.raises(ValueError):
  88. with self.create_dataset(folds="0"):
  89. pass
  90. class Caltech101TestCase(datasets_utils.ImageDatasetTestCase):
  91. DATASET_CLASS = datasets.Caltech101
  92. FEATURE_TYPES = (PIL.Image.Image, (int, np.ndarray, tuple))
  93. ADDITIONAL_CONFIGS = combinations_grid(target_type=("category", "annotation", ["category", "annotation"]))
  94. REQUIRED_PACKAGES = ("scipy",)
  95. def inject_fake_data(self, tmpdir, config):
  96. root = pathlib.Path(tmpdir) / "caltech101"
  97. images = root / "101_ObjectCategories"
  98. annotations = root / "Annotations"
  99. categories = (("Faces", "Faces_2"), ("helicopter", "helicopter"), ("ying_yang", "ying_yang"))
  100. num_images_per_category = 2
  101. for image_category, annotation_category in categories:
  102. datasets_utils.create_image_folder(
  103. root=images,
  104. name=image_category,
  105. file_name_fn=lambda idx: f"image_{idx + 1:04d}.jpg",
  106. num_examples=num_images_per_category,
  107. )
  108. self._create_annotation_folder(
  109. root=annotations,
  110. name=annotation_category,
  111. file_name_fn=lambda idx: f"annotation_{idx + 1:04d}.mat",
  112. num_examples=num_images_per_category,
  113. )
  114. # This is included in the original archive, but is removed by the dataset. Thus, an empty directory suffices.
  115. os.makedirs(images / "BACKGROUND_Google")
  116. return num_images_per_category * len(categories)
  117. def _create_annotation_folder(self, root, name, file_name_fn, num_examples):
  118. root = pathlib.Path(root) / name
  119. os.makedirs(root)
  120. for idx in range(num_examples):
  121. self._create_annotation_file(root, file_name_fn(idx))
  122. def _create_annotation_file(self, root, name):
  123. mdict = dict(obj_contour=torch.rand((2, torch.randint(3, 6, size=())), dtype=torch.float64).numpy())
  124. datasets_utils.lazy_importer.scipy.io.savemat(str(pathlib.Path(root) / name), mdict)
  125. def test_combined_targets(self):
  126. target_types = ["category", "annotation"]
  127. individual_targets = []
  128. for target_type in target_types:
  129. with self.create_dataset(target_type=target_type) as (dataset, _):
  130. _, target = dataset[0]
  131. individual_targets.append(target)
  132. with self.create_dataset(target_type=target_types) as (dataset, _):
  133. _, combined_targets = dataset[0]
  134. actual = len(individual_targets)
  135. expected = len(combined_targets)
  136. assert (
  137. actual == expected
  138. ), "The number of the returned combined targets does not match the the number targets if requested "
  139. f"individually: {actual} != {expected}",
  140. for target_type, combined_target, individual_target in zip(target_types, combined_targets, individual_targets):
  141. with self.subTest(target_type=target_type):
  142. actual = type(combined_target)
  143. expected = type(individual_target)
  144. assert (
  145. actual is expected
  146. ), "Type of the combined target does not match the type of the corresponding individual target: "
  147. f"{actual} is not {expected}",
  148. def test_transforms_v2_wrapper_spawn(self):
  149. with self.create_dataset(target_type="category") as (dataset, _):
  150. datasets_utils.check_transforms_v2_wrapper_spawn(dataset)
  151. class Caltech256TestCase(datasets_utils.ImageDatasetTestCase):
  152. DATASET_CLASS = datasets.Caltech256
  153. def inject_fake_data(self, tmpdir, config):
  154. tmpdir = pathlib.Path(tmpdir) / "caltech256" / "256_ObjectCategories"
  155. categories = ((1, "ak47"), (2, "american-flag"), (3, "backpack"))
  156. num_images_per_category = 2
  157. for idx, category in categories:
  158. datasets_utils.create_image_folder(
  159. tmpdir,
  160. name=f"{idx:03d}.{category}",
  161. file_name_fn=lambda image_idx: f"{idx:03d}_{image_idx + 1:04d}.jpg",
  162. num_examples=num_images_per_category,
  163. )
  164. return num_images_per_category * len(categories)
  165. class WIDERFaceTestCase(datasets_utils.ImageDatasetTestCase):
  166. DATASET_CLASS = datasets.WIDERFace
  167. FEATURE_TYPES = (PIL.Image.Image, (dict, type(None))) # test split returns None as target
  168. ADDITIONAL_CONFIGS = combinations_grid(split=("train", "val", "test"))
  169. def inject_fake_data(self, tmpdir, config):
  170. widerface_dir = pathlib.Path(tmpdir) / "widerface"
  171. annotations_dir = widerface_dir / "wider_face_split"
  172. os.makedirs(annotations_dir)
  173. split_to_idx = split_to_num_examples = {
  174. "train": 1,
  175. "val": 2,
  176. "test": 3,
  177. }
  178. # We need to create all folders regardless of the split in config
  179. for split in ("train", "val", "test"):
  180. split_idx = split_to_idx[split]
  181. num_examples = split_to_num_examples[split]
  182. datasets_utils.create_image_folder(
  183. root=tmpdir,
  184. name=widerface_dir / f"WIDER_{split}" / "images" / "0--Parade",
  185. file_name_fn=lambda image_idx: f"0_Parade_marchingband_1_{split_idx + image_idx}.jpg",
  186. num_examples=num_examples,
  187. )
  188. annotation_file_name = {
  189. "train": annotations_dir / "wider_face_train_bbx_gt.txt",
  190. "val": annotations_dir / "wider_face_val_bbx_gt.txt",
  191. "test": annotations_dir / "wider_face_test_filelist.txt",
  192. }[split]
  193. annotation_content = {
  194. "train": "".join(
  195. f"0--Parade/0_Parade_marchingband_1_{split_idx + image_idx}.jpg\n1\n449 330 122 149 0 0 0 0 0 0\n"
  196. for image_idx in range(num_examples)
  197. ),
  198. "val": "".join(
  199. f"0--Parade/0_Parade_marchingband_1_{split_idx + image_idx}.jpg\n1\n501 160 285 443 0 0 0 0 0 0\n"
  200. for image_idx in range(num_examples)
  201. ),
  202. "test": "".join(
  203. f"0--Parade/0_Parade_marchingband_1_{split_idx + image_idx}.jpg\n"
  204. for image_idx in range(num_examples)
  205. ),
  206. }[split]
  207. with open(annotation_file_name, "w") as annotation_file:
  208. annotation_file.write(annotation_content)
  209. return split_to_num_examples[config["split"]]
  210. def test_transforms_v2_wrapper_spawn(self):
  211. with self.create_dataset() as (dataset, _):
  212. datasets_utils.check_transforms_v2_wrapper_spawn(dataset)
  213. class CityScapesTestCase(datasets_utils.ImageDatasetTestCase):
  214. DATASET_CLASS = datasets.Cityscapes
  215. TARGET_TYPES = (
  216. "instance",
  217. "semantic",
  218. "polygon",
  219. "color",
  220. )
  221. ADDITIONAL_CONFIGS = (
  222. *combinations_grid(mode=("fine",), split=("train", "test", "val"), target_type=TARGET_TYPES),
  223. *combinations_grid(
  224. mode=("coarse",),
  225. split=("train", "train_extra", "val"),
  226. target_type=TARGET_TYPES,
  227. ),
  228. )
  229. FEATURE_TYPES = (PIL.Image.Image, (dict, PIL.Image.Image))
  230. def inject_fake_data(self, tmpdir, config):
  231. tmpdir = pathlib.Path(tmpdir)
  232. mode_to_splits = {
  233. "Coarse": ["train", "train_extra", "val"],
  234. "Fine": ["train", "test", "val"],
  235. }
  236. if config["split"] == "train": # just for coverage of the number of samples
  237. cities = ["bochum", "bremen"]
  238. else:
  239. cities = ["bochum"]
  240. polygon_target = {
  241. "imgHeight": 1024,
  242. "imgWidth": 2048,
  243. "objects": [
  244. {
  245. "label": "sky",
  246. "polygon": [
  247. [1241, 0],
  248. [1234, 156],
  249. [1478, 197],
  250. [1611, 172],
  251. [1606, 0],
  252. ],
  253. },
  254. {
  255. "label": "road",
  256. "polygon": [
  257. [0, 448],
  258. [1331, 274],
  259. [1473, 265],
  260. [2047, 605],
  261. [2047, 1023],
  262. [0, 1023],
  263. ],
  264. },
  265. ],
  266. }
  267. for mode in ["Coarse", "Fine"]:
  268. gt_dir = tmpdir / f"gt{mode}"
  269. for split in mode_to_splits[mode]:
  270. for city in cities:
  271. def make_image(name, size=10):
  272. datasets_utils.create_image_folder(
  273. root=gt_dir / split,
  274. name=city,
  275. file_name_fn=lambda _: name,
  276. size=size,
  277. num_examples=1,
  278. )
  279. make_image(f"{city}_000000_000000_gt{mode}_instanceIds.png")
  280. make_image(f"{city}_000000_000000_gt{mode}_labelIds.png")
  281. make_image(f"{city}_000000_000000_gt{mode}_color.png", size=(4, 10, 10))
  282. polygon_target_name = gt_dir / split / city / f"{city}_000000_000000_gt{mode}_polygons.json"
  283. with open(polygon_target_name, "w") as outfile:
  284. json.dump(polygon_target, outfile)
  285. # Create leftImg8bit folder
  286. for split in ["test", "train_extra", "train", "val"]:
  287. for city in cities:
  288. datasets_utils.create_image_folder(
  289. root=tmpdir / "leftImg8bit" / split,
  290. name=city,
  291. file_name_fn=lambda _: f"{city}_000000_000000_leftImg8bit.png",
  292. num_examples=1,
  293. )
  294. info = {"num_examples": len(cities)}
  295. if config["target_type"] == "polygon":
  296. info["expected_polygon_target"] = polygon_target
  297. return info
  298. def test_combined_targets(self):
  299. target_types = ["semantic", "polygon", "color"]
  300. with self.create_dataset(target_type=target_types) as (dataset, _):
  301. output = dataset[0]
  302. assert isinstance(output, tuple)
  303. assert len(output) == 2
  304. assert isinstance(output[0], PIL.Image.Image)
  305. assert isinstance(output[1], tuple)
  306. assert len(output[1]) == 3
  307. assert isinstance(output[1][0], PIL.Image.Image) # semantic
  308. assert isinstance(output[1][1], dict) # polygon
  309. assert isinstance(output[1][2], PIL.Image.Image) # color
  310. def test_feature_types_target_color(self):
  311. with self.create_dataset(target_type="color") as (dataset, _):
  312. color_img, color_target = dataset[0]
  313. assert isinstance(color_img, PIL.Image.Image)
  314. assert np.array(color_target).shape[2] == 4
  315. def test_feature_types_target_polygon(self):
  316. with self.create_dataset(target_type="polygon") as (dataset, info):
  317. polygon_img, polygon_target = dataset[0]
  318. assert isinstance(polygon_img, PIL.Image.Image)
  319. (polygon_target, info["expected_polygon_target"])
  320. def test_transforms_v2_wrapper_spawn(self):
  321. for target_type in ["instance", "semantic", ["instance", "semantic"]]:
  322. with self.create_dataset(target_type=target_type) as (dataset, _):
  323. datasets_utils.check_transforms_v2_wrapper_spawn(dataset)
  324. class ImageNetTestCase(datasets_utils.ImageDatasetTestCase):
  325. DATASET_CLASS = datasets.ImageNet
  326. REQUIRED_PACKAGES = ("scipy",)
  327. ADDITIONAL_CONFIGS = combinations_grid(split=("train", "val"))
  328. def inject_fake_data(self, tmpdir, config):
  329. tmpdir = pathlib.Path(tmpdir)
  330. wnid = "n01234567"
  331. if config["split"] == "train":
  332. num_examples = 3
  333. datasets_utils.create_image_folder(
  334. root=tmpdir,
  335. name=tmpdir / "train" / wnid / wnid,
  336. file_name_fn=lambda image_idx: f"{wnid}_{image_idx}.JPEG",
  337. num_examples=num_examples,
  338. )
  339. else:
  340. num_examples = 1
  341. datasets_utils.create_image_folder(
  342. root=tmpdir,
  343. name=tmpdir / "val" / wnid,
  344. file_name_fn=lambda image_ifx: "ILSVRC2012_val_0000000{image_idx}.JPEG",
  345. num_examples=num_examples,
  346. )
  347. wnid_to_classes = {wnid: [1]}
  348. torch.save((wnid_to_classes, None), tmpdir / "meta.bin")
  349. return num_examples
  350. def test_transforms_v2_wrapper_spawn(self):
  351. with self.create_dataset() as (dataset, _):
  352. datasets_utils.check_transforms_v2_wrapper_spawn(dataset)
  353. class CIFAR10TestCase(datasets_utils.ImageDatasetTestCase):
  354. DATASET_CLASS = datasets.CIFAR10
  355. ADDITIONAL_CONFIGS = combinations_grid(train=(True, False))
  356. _VERSION_CONFIG = dict(
  357. base_folder="cifar-10-batches-py",
  358. train_files=tuple(f"data_batch_{idx}" for idx in range(1, 6)),
  359. test_files=("test_batch",),
  360. labels_key="labels",
  361. meta_file="batches.meta",
  362. num_categories=10,
  363. categories_key="label_names",
  364. )
  365. def inject_fake_data(self, tmpdir, config):
  366. tmpdir = pathlib.Path(tmpdir) / self._VERSION_CONFIG["base_folder"]
  367. os.makedirs(tmpdir)
  368. num_images_per_file = 1
  369. for name in itertools.chain(self._VERSION_CONFIG["train_files"], self._VERSION_CONFIG["test_files"]):
  370. self._create_batch_file(tmpdir, name, num_images_per_file)
  371. categories = self._create_meta_file(tmpdir)
  372. return dict(
  373. num_examples=num_images_per_file
  374. * len(self._VERSION_CONFIG["train_files"] if config["train"] else self._VERSION_CONFIG["test_files"]),
  375. categories=categories,
  376. )
  377. def _create_batch_file(self, root, name, num_images):
  378. np_rng = np.random.RandomState(0)
  379. data = datasets_utils.create_image_or_video_tensor((num_images, 32 * 32 * 3))
  380. labels = np_rng.randint(0, self._VERSION_CONFIG["num_categories"], size=num_images).tolist()
  381. self._create_binary_file(root, name, {"data": data, self._VERSION_CONFIG["labels_key"]: labels})
  382. def _create_meta_file(self, root):
  383. categories = [
  384. f"{idx:0{len(str(self._VERSION_CONFIG['num_categories'] - 1))}d}"
  385. for idx in range(self._VERSION_CONFIG["num_categories"])
  386. ]
  387. self._create_binary_file(
  388. root, self._VERSION_CONFIG["meta_file"], {self._VERSION_CONFIG["categories_key"]: categories}
  389. )
  390. return categories
  391. def _create_binary_file(self, root, name, content):
  392. with open(pathlib.Path(root) / name, "wb") as fh:
  393. pickle.dump(content, fh)
  394. def test_class_to_idx(self):
  395. with self.create_dataset() as (dataset, info):
  396. expected = {category: label for label, category in enumerate(info["categories"])}
  397. actual = dataset.class_to_idx
  398. assert actual == expected
  399. class CIFAR100(CIFAR10TestCase):
  400. DATASET_CLASS = datasets.CIFAR100
  401. _VERSION_CONFIG = dict(
  402. base_folder="cifar-100-python",
  403. train_files=("train",),
  404. test_files=("test",),
  405. labels_key="fine_labels",
  406. meta_file="meta",
  407. num_categories=100,
  408. categories_key="fine_label_names",
  409. )
  410. class CelebATestCase(datasets_utils.ImageDatasetTestCase):
  411. DATASET_CLASS = datasets.CelebA
  412. FEATURE_TYPES = (PIL.Image.Image, (torch.Tensor, int, tuple, type(None)))
  413. ADDITIONAL_CONFIGS = combinations_grid(
  414. split=("train", "valid", "test", "all"),
  415. target_type=("attr", "identity", "bbox", "landmarks", ["attr", "identity"]),
  416. )
  417. _SPLIT_TO_IDX = dict(train=0, valid=1, test=2)
  418. def inject_fake_data(self, tmpdir, config):
  419. base_folder = pathlib.Path(tmpdir) / "celeba"
  420. os.makedirs(base_folder)
  421. num_images, num_images_per_split = self._create_split_txt(base_folder)
  422. datasets_utils.create_image_folder(
  423. base_folder, "img_align_celeba", lambda idx: f"{idx + 1:06d}.jpg", num_images
  424. )
  425. attr_names = self._create_attr_txt(base_folder, num_images)
  426. self._create_identity_txt(base_folder, num_images)
  427. self._create_bbox_txt(base_folder, num_images)
  428. self._create_landmarks_txt(base_folder, num_images)
  429. return dict(num_examples=num_images_per_split[config["split"]], attr_names=attr_names)
  430. def _create_split_txt(self, root):
  431. num_images_per_split = dict(train=4, valid=3, test=2)
  432. data = [
  433. [self._SPLIT_TO_IDX[split]] for split, num_images in num_images_per_split.items() for _ in range(num_images)
  434. ]
  435. self._create_txt(root, "list_eval_partition.txt", data)
  436. num_images_per_split["all"] = num_images = sum(num_images_per_split.values())
  437. return num_images, num_images_per_split
  438. def _create_attr_txt(self, root, num_images):
  439. header = ("5_o_Clock_Shadow", "Young")
  440. data = torch.rand((num_images, len(header))).ge(0.5).int().mul(2).sub(1).tolist()
  441. self._create_txt(root, "list_attr_celeba.txt", data, header=header, add_num_examples=True)
  442. return header
  443. def _create_identity_txt(self, root, num_images):
  444. data = torch.randint(1, 4, size=(num_images, 1)).tolist()
  445. self._create_txt(root, "identity_CelebA.txt", data)
  446. def _create_bbox_txt(self, root, num_images):
  447. header = ("x_1", "y_1", "width", "height")
  448. data = torch.randint(10, size=(num_images, len(header))).tolist()
  449. self._create_txt(
  450. root, "list_bbox_celeba.txt", data, header=header, add_num_examples=True, add_image_id_to_header=True
  451. )
  452. def _create_landmarks_txt(self, root, num_images):
  453. header = ("lefteye_x", "rightmouth_y")
  454. data = torch.randint(10, size=(num_images, len(header))).tolist()
  455. self._create_txt(root, "list_landmarks_align_celeba.txt", data, header=header, add_num_examples=True)
  456. def _create_txt(self, root, name, data, header=None, add_num_examples=False, add_image_id_to_header=False):
  457. with open(pathlib.Path(root) / name, "w") as fh:
  458. if add_num_examples:
  459. fh.write(f"{len(data)}\n")
  460. if header:
  461. if add_image_id_to_header:
  462. header = ("image_id", *header)
  463. fh.write(f"{' '.join(header)}\n")
  464. for idx, line in enumerate(data, 1):
  465. fh.write(f"{' '.join((f'{idx:06d}.jpg', *[str(value) for value in line]))}\n")
  466. def test_combined_targets(self):
  467. target_types = ["attr", "identity", "bbox", "landmarks"]
  468. individual_targets = []
  469. for target_type in target_types:
  470. with self.create_dataset(target_type=target_type) as (dataset, _):
  471. _, target = dataset[0]
  472. individual_targets.append(target)
  473. with self.create_dataset(target_type=target_types) as (dataset, _):
  474. _, combined_targets = dataset[0]
  475. actual = len(individual_targets)
  476. expected = len(combined_targets)
  477. assert (
  478. actual == expected
  479. ), "The number of the returned combined targets does not match the the number targets if requested "
  480. f"individually: {actual} != {expected}",
  481. for target_type, combined_target, individual_target in zip(target_types, combined_targets, individual_targets):
  482. with self.subTest(target_type=target_type):
  483. actual = type(combined_target)
  484. expected = type(individual_target)
  485. assert (
  486. actual is expected
  487. ), "Type of the combined target does not match the type of the corresponding individual target: "
  488. f"{actual} is not {expected}",
  489. def test_no_target(self):
  490. with self.create_dataset(target_type=[]) as (dataset, _):
  491. _, target = dataset[0]
  492. assert target is None
  493. def test_attr_names(self):
  494. with self.create_dataset() as (dataset, info):
  495. assert tuple(dataset.attr_names) == info["attr_names"]
  496. def test_images_names_split(self):
  497. with self.create_dataset(split="all") as (dataset, _):
  498. all_imgs_names = set(dataset.filename)
  499. merged_imgs_names = set()
  500. for split in ["train", "valid", "test"]:
  501. with self.create_dataset(split=split) as (dataset, _):
  502. merged_imgs_names.update(dataset.filename)
  503. assert merged_imgs_names == all_imgs_names
  504. def test_transforms_v2_wrapper_spawn(self):
  505. for target_type in ["identity", "bbox", ["identity", "bbox"]]:
  506. with self.create_dataset(target_type=target_type) as (dataset, _):
  507. datasets_utils.check_transforms_v2_wrapper_spawn(dataset)
  508. class VOCSegmentationTestCase(datasets_utils.ImageDatasetTestCase):
  509. DATASET_CLASS = datasets.VOCSegmentation
  510. FEATURE_TYPES = (PIL.Image.Image, PIL.Image.Image)
  511. ADDITIONAL_CONFIGS = (
  512. *combinations_grid(year=[f"20{year:02d}" for year in range(7, 13)], image_set=("train", "val", "trainval")),
  513. dict(year="2007", image_set="test"),
  514. )
  515. def inject_fake_data(self, tmpdir, config):
  516. year, is_test_set = config["year"], config["image_set"] == "test"
  517. image_set = config["image_set"]
  518. base_dir = pathlib.Path(tmpdir)
  519. if year == "2011":
  520. base_dir /= "TrainVal"
  521. base_dir = base_dir / "VOCdevkit" / f"VOC{year}"
  522. os.makedirs(base_dir)
  523. num_images, num_images_per_image_set = self._create_image_set_files(base_dir, "ImageSets", is_test_set)
  524. datasets_utils.create_image_folder(base_dir, "JPEGImages", lambda idx: f"{idx:06d}.jpg", num_images)
  525. datasets_utils.create_image_folder(base_dir, "SegmentationClass", lambda idx: f"{idx:06d}.png", num_images)
  526. annotation = self._create_annotation_files(base_dir, "Annotations", num_images)
  527. return dict(num_examples=num_images_per_image_set[image_set], annotation=annotation)
  528. def _create_image_set_files(self, root, name, is_test_set):
  529. root = pathlib.Path(root) / name
  530. src = pathlib.Path(root) / "Main"
  531. os.makedirs(src, exist_ok=True)
  532. idcs = dict(train=(0, 1, 2), val=(3, 4), test=(5,))
  533. idcs["trainval"] = (*idcs["train"], *idcs["val"])
  534. for image_set in ("test",) if is_test_set else ("train", "val", "trainval"):
  535. self._create_image_set_file(src, image_set, idcs[image_set])
  536. shutil.copytree(src, root / "Segmentation")
  537. num_images = max(itertools.chain(*idcs.values())) + 1
  538. num_images_per_image_set = {image_set: len(idcs_) for image_set, idcs_ in idcs.items()}
  539. return num_images, num_images_per_image_set
  540. def _create_image_set_file(self, root, image_set, idcs):
  541. with open(pathlib.Path(root) / f"{image_set}.txt", "w") as fh:
  542. fh.writelines([f"{idx:06d}\n" for idx in idcs])
  543. def _create_annotation_files(self, root, name, num_images):
  544. root = pathlib.Path(root) / name
  545. os.makedirs(root)
  546. for idx in range(num_images):
  547. annotation = self._create_annotation_file(root, f"{idx:06d}.xml")
  548. return annotation
  549. def _create_annotation_file(self, root, name):
  550. def add_child(parent, name, text=None):
  551. child = ET.SubElement(parent, name)
  552. child.text = text
  553. return child
  554. def add_name(obj, name="dog"):
  555. add_child(obj, "name", name)
  556. return name
  557. def add_bndbox(obj, bndbox=None):
  558. if bndbox is None:
  559. bndbox = {"xmin": "1", "xmax": "2", "ymin": "3", "ymax": "4"}
  560. obj = add_child(obj, "bndbox")
  561. for name, text in bndbox.items():
  562. add_child(obj, name, text)
  563. return bndbox
  564. annotation = ET.Element("annotation")
  565. obj = add_child(annotation, "object")
  566. data = dict(name=add_name(obj), bndbox=add_bndbox(obj))
  567. with open(pathlib.Path(root) / name, "wb") as fh:
  568. fh.write(ET.tostring(annotation))
  569. return data
  570. def test_transforms_v2_wrapper_spawn(self):
  571. with self.create_dataset() as (dataset, _):
  572. datasets_utils.check_transforms_v2_wrapper_spawn(dataset)
  573. class VOCDetectionTestCase(VOCSegmentationTestCase):
  574. DATASET_CLASS = datasets.VOCDetection
  575. FEATURE_TYPES = (PIL.Image.Image, dict)
  576. def test_annotations(self):
  577. with self.create_dataset() as (dataset, info):
  578. _, target = dataset[0]
  579. assert "annotation" in target
  580. annotation = target["annotation"]
  581. assert "object" in annotation
  582. objects = annotation["object"]
  583. assert len(objects) == 1
  584. object = objects[0]
  585. assert object == info["annotation"]
  586. def test_transforms_v2_wrapper_spawn(self):
  587. with self.create_dataset() as (dataset, _):
  588. datasets_utils.check_transforms_v2_wrapper_spawn(dataset)
  589. class CocoDetectionTestCase(datasets_utils.ImageDatasetTestCase):
  590. DATASET_CLASS = datasets.CocoDetection
  591. FEATURE_TYPES = (PIL.Image.Image, list)
  592. REQUIRED_PACKAGES = ("pycocotools",)
  593. _IMAGE_FOLDER = "images"
  594. _ANNOTATIONS_FOLDER = "annotations"
  595. _ANNOTATIONS_FILE = "annotations.json"
  596. def dataset_args(self, tmpdir, config):
  597. tmpdir = pathlib.Path(tmpdir)
  598. root = tmpdir / self._IMAGE_FOLDER
  599. annotation_file = tmpdir / self._ANNOTATIONS_FOLDER / self._ANNOTATIONS_FILE
  600. return root, annotation_file
  601. def inject_fake_data(self, tmpdir, config):
  602. tmpdir = pathlib.Path(tmpdir)
  603. num_images = 3
  604. num_annotations_per_image = 2
  605. files = datasets_utils.create_image_folder(
  606. tmpdir, name=self._IMAGE_FOLDER, file_name_fn=lambda idx: f"{idx:012d}.jpg", num_examples=num_images
  607. )
  608. file_names = [file.relative_to(tmpdir / self._IMAGE_FOLDER) for file in files]
  609. annotation_folder = tmpdir / self._ANNOTATIONS_FOLDER
  610. os.makedirs(annotation_folder)
  611. info = self._create_annotation_file(
  612. annotation_folder, self._ANNOTATIONS_FILE, file_names, num_annotations_per_image
  613. )
  614. info["num_examples"] = num_images
  615. return info
  616. def _create_annotation_file(self, root, name, file_names, num_annotations_per_image):
  617. image_ids = [int(file_name.stem) for file_name in file_names]
  618. images = [dict(file_name=str(file_name), id=id) for file_name, id in zip(file_names, image_ids)]
  619. annotations, info = self._create_annotations(image_ids, num_annotations_per_image)
  620. self._create_json(root, name, dict(images=images, annotations=annotations))
  621. return info
  622. def _create_annotations(self, image_ids, num_annotations_per_image):
  623. annotations = []
  624. annotion_id = 0
  625. for image_id in itertools.islice(itertools.cycle(image_ids), len(image_ids) * num_annotations_per_image):
  626. annotations.append(
  627. dict(
  628. image_id=image_id,
  629. id=annotion_id,
  630. bbox=torch.rand(4).tolist(),
  631. segmentation=[torch.rand(8).tolist()],
  632. category_id=int(torch.randint(91, ())),
  633. area=float(torch.rand(1)),
  634. iscrowd=int(torch.randint(2, size=(1,))),
  635. )
  636. )
  637. annotion_id += 1
  638. return annotations, dict()
  639. def _create_json(self, root, name, content):
  640. file = pathlib.Path(root) / name
  641. with open(file, "w") as fh:
  642. json.dump(content, fh)
  643. return file
  644. def test_transforms_v2_wrapper_spawn(self):
  645. with self.create_dataset() as (dataset, _):
  646. datasets_utils.check_transforms_v2_wrapper_spawn(dataset)
  647. class CocoCaptionsTestCase(CocoDetectionTestCase):
  648. DATASET_CLASS = datasets.CocoCaptions
  649. def _create_annotations(self, image_ids, num_annotations_per_image):
  650. captions = [str(idx) for idx in range(num_annotations_per_image)]
  651. annotations = combinations_grid(image_id=image_ids, caption=captions)
  652. for id, annotation in enumerate(annotations):
  653. annotation["id"] = id
  654. return annotations, dict(captions=captions)
  655. def test_captions(self):
  656. with self.create_dataset() as (dataset, info):
  657. _, captions = dataset[0]
  658. assert tuple(captions) == tuple(info["captions"])
  659. def test_transforms_v2_wrapper_spawn(self):
  660. # We need to define this method, because otherwise the test from the super class will
  661. # be run
  662. pytest.skip("CocoCaptions is currently not supported by the v2 wrapper.")
  663. class UCF101TestCase(datasets_utils.VideoDatasetTestCase):
  664. DATASET_CLASS = datasets.UCF101
  665. ADDITIONAL_CONFIGS = combinations_grid(fold=(1, 2, 3), train=(True, False))
  666. _VIDEO_FOLDER = "videos"
  667. _ANNOTATIONS_FOLDER = "annotations"
  668. def dataset_args(self, tmpdir, config):
  669. tmpdir = pathlib.Path(tmpdir)
  670. root = tmpdir / self._VIDEO_FOLDER
  671. annotation_path = tmpdir / self._ANNOTATIONS_FOLDER
  672. return root, annotation_path
  673. def inject_fake_data(self, tmpdir, config):
  674. tmpdir = pathlib.Path(tmpdir)
  675. video_folder = tmpdir / self._VIDEO_FOLDER
  676. os.makedirs(video_folder)
  677. video_files = self._create_videos(video_folder)
  678. annotations_folder = tmpdir / self._ANNOTATIONS_FOLDER
  679. os.makedirs(annotations_folder)
  680. num_examples = self._create_annotation_files(annotations_folder, video_files, config["fold"], config["train"])
  681. return num_examples
  682. def _create_videos(self, root, num_examples_per_class=3):
  683. def file_name_fn(cls, idx, clips_per_group=2):
  684. return f"v_{cls}_g{(idx // clips_per_group) + 1:02d}_c{(idx % clips_per_group) + 1:02d}.avi"
  685. video_files = [
  686. datasets_utils.create_video_folder(root, cls, lambda idx: file_name_fn(cls, idx), num_examples_per_class)
  687. for cls in ("ApplyEyeMakeup", "YoYo")
  688. ]
  689. return [path.relative_to(root) for path in itertools.chain(*video_files)]
  690. def _create_annotation_files(self, root, video_files, fold, train):
  691. current_videos = random.sample(video_files, random.randrange(1, len(video_files) - 1))
  692. current_annotation = self._annotation_file_name(fold, train)
  693. self._create_annotation_file(root, current_annotation, current_videos)
  694. other_videos = set(video_files) - set(current_videos)
  695. other_annotations = [
  696. self._annotation_file_name(fold, train) for fold, train in itertools.product((1, 2, 3), (True, False))
  697. ]
  698. other_annotations.remove(current_annotation)
  699. for name in other_annotations:
  700. self._create_annotation_file(root, name, other_videos)
  701. return len(current_videos)
  702. def _annotation_file_name(self, fold, train):
  703. return f"{'train' if train else 'test'}list{fold:02d}.txt"
  704. def _create_annotation_file(self, root, name, video_files):
  705. with open(pathlib.Path(root) / name, "w") as fh:
  706. fh.writelines(f"{str(file).replace(os.sep, '/')}\n" for file in sorted(video_files))
  707. class LSUNTestCase(datasets_utils.ImageDatasetTestCase):
  708. DATASET_CLASS = datasets.LSUN
  709. REQUIRED_PACKAGES = ("lmdb",)
  710. ADDITIONAL_CONFIGS = combinations_grid(classes=("train", "test", "val", ["bedroom_train", "church_outdoor_train"]))
  711. _CATEGORIES = (
  712. "bedroom",
  713. "bridge",
  714. "church_outdoor",
  715. "classroom",
  716. "conference_room",
  717. "dining_room",
  718. "kitchen",
  719. "living_room",
  720. "restaurant",
  721. "tower",
  722. )
  723. def inject_fake_data(self, tmpdir, config):
  724. root = pathlib.Path(tmpdir)
  725. num_images = 0
  726. for cls in self._parse_classes(config["classes"]):
  727. num_images += self._create_lmdb(root, cls)
  728. return num_images
  729. @contextlib.contextmanager
  730. def create_dataset(self, *args, **kwargs):
  731. with super().create_dataset(*args, **kwargs) as output:
  732. yield output
  733. # Currently datasets.LSUN caches the keys in the current directory rather than in the root directory. Thus,
  734. # this creates a number of _cache_* files in the current directory that will not be removed together
  735. # with the temporary directory
  736. for file in os.listdir(os.getcwd()):
  737. if file.startswith("_cache_"):
  738. try:
  739. os.remove(file)
  740. except FileNotFoundError:
  741. # When the same test is run in parallel (in fb internal tests), a thread may remove another
  742. # thread's file. We should be able to remove the try/except when
  743. # https://github.com/pytorch/vision/issues/825 is fixed.
  744. pass
  745. def _parse_classes(self, classes):
  746. if not isinstance(classes, str):
  747. return classes
  748. split = classes
  749. if split == "test":
  750. return [split]
  751. return [f"{category}_{split}" for category in self._CATEGORIES]
  752. def _create_lmdb(self, root, cls):
  753. lmdb = datasets_utils.lazy_importer.lmdb
  754. hexdigits_lowercase = string.digits + string.ascii_lowercase[:6]
  755. folder = f"{cls}_lmdb"
  756. num_images = torch.randint(1, 4, size=()).item()
  757. format = "png"
  758. files = datasets_utils.create_image_folder(root, folder, lambda idx: f"{idx}.{format}", num_images)
  759. with lmdb.open(str(root / folder)) as env, env.begin(write=True) as txn:
  760. for file in files:
  761. key = "".join(random.choice(hexdigits_lowercase) for _ in range(40)).encode()
  762. buffer = io.BytesIO()
  763. PIL.Image.open(file).save(buffer, format)
  764. buffer.seek(0)
  765. value = buffer.read()
  766. txn.put(key, value)
  767. os.remove(file)
  768. return num_images
  769. def test_not_found_or_corrupted(self):
  770. # LSUN does not raise built-in exception, but a custom one. It is expressive enough to not 'cast' it to
  771. # RuntimeError or FileNotFoundError that are normally checked by this test.
  772. with pytest.raises(datasets_utils.lazy_importer.lmdb.Error):
  773. super().test_not_found_or_corrupted()
  774. class KineticsTestCase(datasets_utils.VideoDatasetTestCase):
  775. DATASET_CLASS = datasets.Kinetics
  776. ADDITIONAL_CONFIGS = combinations_grid(split=("train", "val"), num_classes=("400", "600", "700"))
  777. def inject_fake_data(self, tmpdir, config):
  778. classes = ("Abseiling", "Zumba")
  779. num_videos_per_class = 2
  780. tmpdir = pathlib.Path(tmpdir) / config["split"]
  781. digits = string.ascii_letters + string.digits + "-_"
  782. for cls in classes:
  783. datasets_utils.create_video_folder(
  784. tmpdir,
  785. cls,
  786. lambda _: f"{datasets_utils.create_random_string(11, digits)}.mp4",
  787. num_videos_per_class,
  788. )
  789. return num_videos_per_class * len(classes)
  790. def test_transforms_v2_wrapper_spawn(self):
  791. with self.create_dataset(output_format="TCHW") as (dataset, _):
  792. datasets_utils.check_transforms_v2_wrapper_spawn(dataset)
  793. class HMDB51TestCase(datasets_utils.VideoDatasetTestCase):
  794. DATASET_CLASS = datasets.HMDB51
  795. ADDITIONAL_CONFIGS = combinations_grid(fold=(1, 2, 3), train=(True, False))
  796. _VIDEO_FOLDER = "videos"
  797. _SPLITS_FOLDER = "splits"
  798. _CLASSES = ("brush_hair", "wave")
  799. def dataset_args(self, tmpdir, config):
  800. tmpdir = pathlib.Path(tmpdir)
  801. root = tmpdir / self._VIDEO_FOLDER
  802. annotation_path = tmpdir / self._SPLITS_FOLDER
  803. return root, annotation_path
  804. def inject_fake_data(self, tmpdir, config):
  805. tmpdir = pathlib.Path(tmpdir)
  806. video_folder = tmpdir / self._VIDEO_FOLDER
  807. os.makedirs(video_folder)
  808. video_files = self._create_videos(video_folder)
  809. splits_folder = tmpdir / self._SPLITS_FOLDER
  810. os.makedirs(splits_folder)
  811. num_examples = self._create_split_files(splits_folder, video_files, config["fold"], config["train"])
  812. return num_examples
  813. def _create_videos(self, root, num_examples_per_class=3):
  814. def file_name_fn(cls, idx, clips_per_group=2):
  815. return f"{cls}_{(idx // clips_per_group) + 1:d}_{(idx % clips_per_group) + 1:d}.avi"
  816. return [
  817. (
  818. cls,
  819. datasets_utils.create_video_folder(
  820. root,
  821. cls,
  822. lambda idx: file_name_fn(cls, idx),
  823. num_examples_per_class,
  824. ),
  825. )
  826. for cls in self._CLASSES
  827. ]
  828. def _create_split_files(self, root, video_files, fold, train):
  829. num_videos = num_train_videos = 0
  830. for cls, videos in video_files:
  831. num_videos += len(videos)
  832. train_videos = set(random.sample(videos, random.randrange(1, len(videos) - 1)))
  833. num_train_videos += len(train_videos)
  834. with open(pathlib.Path(root) / f"{cls}_test_split{fold}.txt", "w") as fh:
  835. fh.writelines(f"{file.name} {1 if file in train_videos else 2}\n" for file in videos)
  836. return num_train_videos if train else (num_videos - num_train_videos)
  837. class OmniglotTestCase(datasets_utils.ImageDatasetTestCase):
  838. DATASET_CLASS = datasets.Omniglot
  839. ADDITIONAL_CONFIGS = combinations_grid(background=(True, False))
  840. def inject_fake_data(self, tmpdir, config):
  841. target_folder = (
  842. pathlib.Path(tmpdir) / "omniglot-py" / f"images_{'background' if config['background'] else 'evaluation'}"
  843. )
  844. os.makedirs(target_folder)
  845. num_images = 0
  846. for name in ("Alphabet_of_the_Magi", "Tifinagh"):
  847. num_images += self._create_alphabet_folder(target_folder, name)
  848. return num_images
  849. def _create_alphabet_folder(self, root, name):
  850. num_images_total = 0
  851. for idx in range(torch.randint(1, 4, size=()).item()):
  852. num_images = torch.randint(1, 4, size=()).item()
  853. num_images_total += num_images
  854. datasets_utils.create_image_folder(
  855. root / name, f"character{idx:02d}", lambda image_idx: f"{image_idx:02d}.png", num_images
  856. )
  857. return num_images_total
  858. class SBUTestCase(datasets_utils.ImageDatasetTestCase):
  859. DATASET_CLASS = datasets.SBU
  860. FEATURE_TYPES = (PIL.Image.Image, str)
  861. def inject_fake_data(self, tmpdir, config):
  862. num_images = 3
  863. dataset_folder = pathlib.Path(tmpdir) / "dataset"
  864. images = datasets_utils.create_image_folder(tmpdir, "dataset", self._create_file_name, num_images)
  865. self._create_urls_txt(dataset_folder, images)
  866. self._create_captions_txt(dataset_folder, num_images)
  867. return num_images
  868. def _create_file_name(self, idx):
  869. part1 = datasets_utils.create_random_string(10, string.digits)
  870. part2 = datasets_utils.create_random_string(10, string.ascii_lowercase, string.digits[:6])
  871. return f"{part1}_{part2}.jpg"
  872. def _create_urls_txt(self, root, images):
  873. with open(root / "SBU_captioned_photo_dataset_urls.txt", "w") as fh:
  874. for image in images:
  875. fh.write(
  876. f"http://static.flickr.com/{datasets_utils.create_random_string(4, string.digits)}/{image.name}\n"
  877. )
  878. def _create_captions_txt(self, root, num_images):
  879. with open(root / "SBU_captioned_photo_dataset_captions.txt", "w") as fh:
  880. for _ in range(num_images):
  881. fh.write(f"{datasets_utils.create_random_string(10)}\n")
  882. class SEMEIONTestCase(datasets_utils.ImageDatasetTestCase):
  883. DATASET_CLASS = datasets.SEMEION
  884. def inject_fake_data(self, tmpdir, config):
  885. num_images = 3
  886. images = torch.rand(num_images, 256)
  887. labels = F.one_hot(torch.randint(10, size=(num_images,)))
  888. with open(pathlib.Path(tmpdir) / "semeion.data", "w") as fh:
  889. for image, one_hot_labels in zip(images, labels):
  890. image_columns = " ".join([f"{pixel.item():.4f}" for pixel in image])
  891. labels_columns = " ".join([str(label.item()) for label in one_hot_labels])
  892. fh.write(f"{image_columns} {labels_columns}\n")
  893. return num_images
  894. class USPSTestCase(datasets_utils.ImageDatasetTestCase):
  895. DATASET_CLASS = datasets.USPS
  896. ADDITIONAL_CONFIGS = combinations_grid(train=(True, False))
  897. def inject_fake_data(self, tmpdir, config):
  898. num_images = 2 if config["train"] else 1
  899. images = torch.rand(num_images, 256) * 2 - 1
  900. labels = torch.randint(1, 11, size=(num_images,))
  901. with bz2.open(pathlib.Path(tmpdir) / f"usps{'.t' if not config['train'] else ''}.bz2", "w") as fh:
  902. for image, label in zip(images, labels):
  903. line = " ".join((str(label.item()), *[f"{idx}:{pixel:.6f}" for idx, pixel in enumerate(image, 1)]))
  904. fh.write(f"{line}\n".encode())
  905. return num_images
  906. class SBDatasetTestCase(datasets_utils.ImageDatasetTestCase):
  907. DATASET_CLASS = datasets.SBDataset
  908. FEATURE_TYPES = (PIL.Image.Image, (np.ndarray, PIL.Image.Image))
  909. REQUIRED_PACKAGES = ("scipy.io", "scipy.sparse")
  910. ADDITIONAL_CONFIGS = combinations_grid(
  911. image_set=("train", "val", "train_noval"), mode=("boundaries", "segmentation")
  912. )
  913. _NUM_CLASSES = 20
  914. def inject_fake_data(self, tmpdir, config):
  915. num_images, num_images_per_image_set = self._create_split_files(tmpdir)
  916. sizes = self._create_target_folder(tmpdir, "cls", num_images)
  917. datasets_utils.create_image_folder(
  918. tmpdir, "img", lambda idx: f"{self._file_stem(idx)}.jpg", num_images, size=lambda idx: sizes[idx]
  919. )
  920. return num_images_per_image_set[config["image_set"]]
  921. def _create_split_files(self, root):
  922. root = pathlib.Path(root)
  923. splits = dict(train=(0, 1, 2), train_noval=(0, 2), val=(3,))
  924. for split, idcs in splits.items():
  925. self._create_split_file(root, split, idcs)
  926. num_images = max(itertools.chain(*splits.values())) + 1
  927. num_images_per_split = {split: len(idcs) for split, idcs in splits.items()}
  928. return num_images, num_images_per_split
  929. def _create_split_file(self, root, name, idcs):
  930. with open(root / f"{name}.txt", "w") as fh:
  931. fh.writelines(f"{self._file_stem(idx)}\n" for idx in idcs)
  932. def _create_target_folder(self, root, name, num_images):
  933. io = datasets_utils.lazy_importer.scipy.io
  934. target_folder = pathlib.Path(root) / name
  935. os.makedirs(target_folder)
  936. sizes = [torch.randint(1, 4, size=(2,)).tolist() for _ in range(num_images)]
  937. for idx, size in enumerate(sizes):
  938. content = dict(
  939. GTcls=dict(Boundaries=self._create_boundaries(size), Segmentation=self._create_segmentation(size))
  940. )
  941. io.savemat(target_folder / f"{self._file_stem(idx)}.mat", content)
  942. return sizes
  943. def _create_boundaries(self, size):
  944. sparse = datasets_utils.lazy_importer.scipy.sparse
  945. return [
  946. [sparse.csc_matrix(torch.randint(0, 2, size=size, dtype=torch.uint8).numpy())]
  947. for _ in range(self._NUM_CLASSES)
  948. ]
  949. def _create_segmentation(self, size):
  950. return torch.randint(0, self._NUM_CLASSES + 1, size=size, dtype=torch.uint8).numpy()
  951. def _file_stem(self, idx):
  952. return f"2008_{idx:06d}"
  953. def test_transforms_v2_wrapper_spawn(self):
  954. with self.create_dataset(mode="segmentation") as (dataset, _):
  955. datasets_utils.check_transforms_v2_wrapper_spawn(dataset)
  956. class FakeDataTestCase(datasets_utils.ImageDatasetTestCase):
  957. DATASET_CLASS = datasets.FakeData
  958. FEATURE_TYPES = (PIL.Image.Image, int)
  959. def dataset_args(self, tmpdir, config):
  960. return ()
  961. def inject_fake_data(self, tmpdir, config):
  962. return config["size"]
  963. def test_not_found_or_corrupted(self):
  964. self.skipTest("The data is generated at creation and thus cannot be non-existent or corrupted.")
  965. class PhotoTourTestCase(datasets_utils.ImageDatasetTestCase):
  966. DATASET_CLASS = datasets.PhotoTour
  967. # The PhotoTour dataset returns examples with different features with respect to the 'train' parameter. Thus,
  968. # we overwrite 'FEATURE_TYPES' with a dummy value to satisfy the initial checks of the base class. Furthermore, we
  969. # overwrite the 'test_feature_types()' method to select the correct feature types before the test is run.
  970. FEATURE_TYPES = ()
  971. _TRAIN_FEATURE_TYPES = (torch.Tensor,)
  972. _TEST_FEATURE_TYPES = (torch.Tensor, torch.Tensor, torch.Tensor)
  973. combinations_grid(train=(True, False))
  974. _NAME = "liberty"
  975. def dataset_args(self, tmpdir, config):
  976. return tmpdir, self._NAME
  977. def inject_fake_data(self, tmpdir, config):
  978. tmpdir = pathlib.Path(tmpdir)
  979. # In contrast to the original data, the fake images injected here comprise only a single patch. Thus,
  980. # num_images == num_patches.
  981. num_patches = 5
  982. image_files = self._create_images(tmpdir, self._NAME, num_patches)
  983. point_ids, info_file = self._create_info_file(tmpdir / self._NAME, num_patches)
  984. num_matches, matches_file = self._create_matches_file(tmpdir / self._NAME, num_patches, point_ids)
  985. self._create_archive(tmpdir, self._NAME, *image_files, info_file, matches_file)
  986. return num_patches if config["train"] else num_matches
  987. def _create_images(self, root, name, num_images):
  988. # The images in the PhotoTour dataset comprises of multiple grayscale patches of 64 x 64 pixels. Thus, the
  989. # smallest fake image is 64 x 64 pixels and comprises a single patch.
  990. return datasets_utils.create_image_folder(
  991. root, name, lambda idx: f"patches{idx:04d}.bmp", num_images, size=(1, 64, 64)
  992. )
  993. def _create_info_file(self, root, num_images):
  994. point_ids = torch.randint(num_images, size=(num_images,)).tolist()
  995. file = root / "info.txt"
  996. with open(file, "w") as fh:
  997. fh.writelines([f"{point_id} 0\n" for point_id in point_ids])
  998. return point_ids, file
  999. def _create_matches_file(self, root, num_patches, point_ids):
  1000. lines = [
  1001. f"{patch_id1} {point_ids[patch_id1]} 0 {patch_id2} {point_ids[patch_id2]} 0\n"
  1002. for patch_id1, patch_id2 in itertools.combinations(range(num_patches), 2)
  1003. ]
  1004. file = root / "m50_100000_100000_0.txt"
  1005. with open(file, "w") as fh:
  1006. fh.writelines(lines)
  1007. return len(lines), file
  1008. def _create_archive(self, root, name, *files):
  1009. archive = root / f"{name}.zip"
  1010. with zipfile.ZipFile(archive, "w") as zip:
  1011. for file in files:
  1012. zip.write(file, arcname=file.relative_to(root))
  1013. return archive
  1014. @datasets_utils.test_all_configs
  1015. def test_feature_types(self, config):
  1016. feature_types = self.FEATURE_TYPES
  1017. self.FEATURE_TYPES = self._TRAIN_FEATURE_TYPES if config["train"] else self._TEST_FEATURE_TYPES
  1018. try:
  1019. super().test_feature_types.__wrapped__(self, config)
  1020. finally:
  1021. self.FEATURE_TYPES = feature_types
  1022. class Flickr8kTestCase(datasets_utils.ImageDatasetTestCase):
  1023. DATASET_CLASS = datasets.Flickr8k
  1024. FEATURE_TYPES = (PIL.Image.Image, list)
  1025. _IMAGES_FOLDER = "images"
  1026. _ANNOTATIONS_FILE = "captions.html"
  1027. def dataset_args(self, tmpdir, config):
  1028. tmpdir = pathlib.Path(tmpdir)
  1029. root = tmpdir / self._IMAGES_FOLDER
  1030. ann_file = tmpdir / self._ANNOTATIONS_FILE
  1031. return str(root), str(ann_file)
  1032. def inject_fake_data(self, tmpdir, config):
  1033. num_images = 3
  1034. num_captions_per_image = 3
  1035. tmpdir = pathlib.Path(tmpdir)
  1036. images = self._create_images(tmpdir, self._IMAGES_FOLDER, num_images)
  1037. self._create_annotations_file(tmpdir, self._ANNOTATIONS_FILE, images, num_captions_per_image)
  1038. return dict(num_examples=num_images, captions=self._create_captions(num_captions_per_image))
  1039. def _create_images(self, root, name, num_images):
  1040. return datasets_utils.create_image_folder(root, name, self._image_file_name, num_images)
  1041. def _image_file_name(self, idx):
  1042. id = datasets_utils.create_random_string(10, string.digits)
  1043. checksum = datasets_utils.create_random_string(10, string.digits, string.ascii_lowercase[:6])
  1044. size = datasets_utils.create_random_string(1, "qwcko")
  1045. return f"{id}_{checksum}_{size}.jpg"
  1046. def _create_annotations_file(self, root, name, images, num_captions_per_image):
  1047. with open(root / name, "w") as fh:
  1048. fh.write("<table>")
  1049. for image in (None, *images):
  1050. self._add_image(fh, image, num_captions_per_image)
  1051. fh.write("</table>")
  1052. def _add_image(self, fh, image, num_captions_per_image):
  1053. fh.write("<tr>")
  1054. self._add_image_header(fh, image)
  1055. fh.write("</tr><tr><td><ul>")
  1056. self._add_image_captions(fh, num_captions_per_image)
  1057. fh.write("</ul></td></tr>")
  1058. def _add_image_header(self, fh, image=None):
  1059. if image:
  1060. url = f"http://www.flickr.com/photos/user/{image.name.split('_')[0]}/"
  1061. data = f'<a href="{url}">{url}</a>'
  1062. else:
  1063. data = "Image Not Found"
  1064. fh.write(f"<td>{data}</td>")
  1065. def _add_image_captions(self, fh, num_captions_per_image):
  1066. for caption in self._create_captions(num_captions_per_image):
  1067. fh.write(f"<li>{caption}")
  1068. def _create_captions(self, num_captions_per_image):
  1069. return [str(idx) for idx in range(num_captions_per_image)]
  1070. def test_captions(self):
  1071. with self.create_dataset() as (dataset, info):
  1072. _, captions = dataset[0]
  1073. assert len(captions) == len(info["captions"])
  1074. assert all([a == b for a, b in zip(captions, info["captions"])])
  1075. class Flickr30kTestCase(Flickr8kTestCase):
  1076. DATASET_CLASS = datasets.Flickr30k
  1077. FEATURE_TYPES = (PIL.Image.Image, list)
  1078. _ANNOTATIONS_FILE = "captions.token"
  1079. def _image_file_name(self, idx):
  1080. return f"{idx}.jpg"
  1081. def _create_annotations_file(self, root, name, images, num_captions_per_image):
  1082. with open(root / name, "w") as fh:
  1083. for image, (idx, caption) in itertools.product(
  1084. images, enumerate(self._create_captions(num_captions_per_image))
  1085. ):
  1086. fh.write(f"{image.name}#{idx}\t{caption}\n")
  1087. class MNISTTestCase(datasets_utils.ImageDatasetTestCase):
  1088. DATASET_CLASS = datasets.MNIST
  1089. ADDITIONAL_CONFIGS = combinations_grid(train=(True, False))
  1090. _MAGIC_DTYPES = {
  1091. torch.uint8: 8,
  1092. torch.int8: 9,
  1093. torch.int16: 11,
  1094. torch.int32: 12,
  1095. torch.float32: 13,
  1096. torch.float64: 14,
  1097. }
  1098. _IMAGES_SIZE = (28, 28)
  1099. _IMAGES_DTYPE = torch.uint8
  1100. _LABELS_SIZE = ()
  1101. _LABELS_DTYPE = torch.uint8
  1102. def inject_fake_data(self, tmpdir, config):
  1103. raw_dir = pathlib.Path(tmpdir) / self.DATASET_CLASS.__name__ / "raw"
  1104. os.makedirs(raw_dir, exist_ok=True)
  1105. num_images = self._num_images(config)
  1106. self._create_binary_file(
  1107. raw_dir, self._images_file(config), (num_images, *self._IMAGES_SIZE), self._IMAGES_DTYPE
  1108. )
  1109. self._create_binary_file(
  1110. raw_dir, self._labels_file(config), (num_images, *self._LABELS_SIZE), self._LABELS_DTYPE
  1111. )
  1112. return num_images
  1113. def _num_images(self, config):
  1114. return 2 if config["train"] else 1
  1115. def _images_file(self, config):
  1116. return f"{self._prefix(config)}-images-idx3-ubyte"
  1117. def _labels_file(self, config):
  1118. return f"{self._prefix(config)}-labels-idx1-ubyte"
  1119. def _prefix(self, config):
  1120. return "train" if config["train"] else "t10k"
  1121. def _create_binary_file(self, root, filename, size, dtype):
  1122. with open(pathlib.Path(root) / filename, "wb") as fh:
  1123. for meta in (self._magic(dtype, len(size)), *size):
  1124. fh.write(self._encode(meta))
  1125. # If ever an MNIST variant is added that uses floating point data, this should be adapted.
  1126. data = torch.randint(0, torch.iinfo(dtype).max + 1, size, dtype=dtype)
  1127. fh.write(data.numpy().tobytes())
  1128. def _magic(self, dtype, dims):
  1129. return self._MAGIC_DTYPES[dtype] * 256 + dims
  1130. def _encode(self, v):
  1131. return torch.tensor(v, dtype=torch.int32).numpy().tobytes()[::-1]
  1132. class FashionMNISTTestCase(MNISTTestCase):
  1133. DATASET_CLASS = datasets.FashionMNIST
  1134. class KMNISTTestCase(MNISTTestCase):
  1135. DATASET_CLASS = datasets.KMNIST
  1136. class EMNISTTestCase(MNISTTestCase):
  1137. DATASET_CLASS = datasets.EMNIST
  1138. DEFAULT_CONFIG = dict(split="byclass")
  1139. ADDITIONAL_CONFIGS = combinations_grid(
  1140. split=("byclass", "bymerge", "balanced", "letters", "digits", "mnist"), train=(True, False)
  1141. )
  1142. def _prefix(self, config):
  1143. return f"emnist-{config['split']}-{'train' if config['train'] else 'test'}"
  1144. class QMNISTTestCase(MNISTTestCase):
  1145. DATASET_CLASS = datasets.QMNIST
  1146. ADDITIONAL_CONFIGS = combinations_grid(what=("train", "test", "test10k", "nist"))
  1147. _LABELS_SIZE = (8,)
  1148. _LABELS_DTYPE = torch.int32
  1149. def _num_images(self, config):
  1150. if config["what"] == "nist":
  1151. return 3
  1152. elif config["what"] == "train":
  1153. return 2
  1154. elif config["what"] == "test50k":
  1155. # The split 'test50k' is defined as the last 50k images beginning at index 10000. Thus, we need to create
  1156. # more than 10000 images for the dataset to not be empty. Since this takes significantly longer than the
  1157. # creation of all other splits, this is excluded from the 'ADDITIONAL_CONFIGS' and is tested only once in
  1158. # 'test_num_examples_test50k'.
  1159. return 10001
  1160. else:
  1161. return 1
  1162. def _labels_file(self, config):
  1163. return f"{self._prefix(config)}-labels-idx2-int"
  1164. def _prefix(self, config):
  1165. if config["what"] == "nist":
  1166. return "xnist"
  1167. if config["what"] is None:
  1168. what = "train" if config["train"] else "test"
  1169. elif config["what"].startswith("test"):
  1170. what = "test"
  1171. else:
  1172. what = config["what"]
  1173. return f"qmnist-{what}"
  1174. def test_num_examples_test50k(self):
  1175. with self.create_dataset(what="test50k") as (dataset, info):
  1176. # Since the split 'test50k' selects all images beginning from the index 10000, we subtract the number of
  1177. # created examples by this.
  1178. assert len(dataset) == info["num_examples"] - 10000
  1179. class MovingMNISTTestCase(datasets_utils.DatasetTestCase):
  1180. DATASET_CLASS = datasets.MovingMNIST
  1181. FEATURE_TYPES = (torch.Tensor,)
  1182. ADDITIONAL_CONFIGS = combinations_grid(split=(None, "train", "test"), split_ratio=(10, 1, 19))
  1183. _NUM_FRAMES = 20
  1184. def inject_fake_data(self, tmpdir, config):
  1185. base_folder = os.path.join(tmpdir, self.DATASET_CLASS.__name__)
  1186. os.makedirs(base_folder, exist_ok=True)
  1187. num_samples = 5
  1188. data = np.concatenate(
  1189. [
  1190. np.zeros((config["split_ratio"], num_samples, 64, 64)),
  1191. np.ones((self._NUM_FRAMES - config["split_ratio"], num_samples, 64, 64)),
  1192. ]
  1193. )
  1194. np.save(os.path.join(base_folder, "mnist_test_seq.npy"), data)
  1195. return num_samples
  1196. @datasets_utils.test_all_configs
  1197. def test_split(self, config):
  1198. with self.create_dataset(config) as (dataset, _):
  1199. if config["split"] == "train":
  1200. assert (dataset.data == 0).all()
  1201. elif config["split"] == "test":
  1202. assert (dataset.data == 1).all()
  1203. else:
  1204. assert dataset.data.size()[1] == self._NUM_FRAMES
  1205. class DatasetFolderTestCase(datasets_utils.ImageDatasetTestCase):
  1206. DATASET_CLASS = datasets.DatasetFolder
  1207. _EXTENSIONS = ("jpg", "png")
  1208. # DatasetFolder has two mutually exclusive parameters: 'extensions' and 'is_valid_file'. One of both is required.
  1209. # We only iterate over different 'extensions' here and handle the tests for 'is_valid_file' in the
  1210. # 'test_is_valid_file()' method.
  1211. DEFAULT_CONFIG = dict(extensions=_EXTENSIONS)
  1212. ADDITIONAL_CONFIGS = combinations_grid(extensions=[(ext,) for ext in _EXTENSIONS])
  1213. def dataset_args(self, tmpdir, config):
  1214. return tmpdir, datasets.folder.pil_loader
  1215. def inject_fake_data(self, tmpdir, config):
  1216. extensions = config["extensions"] or self._is_valid_file_to_extensions(config["is_valid_file"])
  1217. num_examples_total = 0
  1218. classes = []
  1219. for ext, cls in zip(self._EXTENSIONS, string.ascii_letters):
  1220. if ext not in extensions:
  1221. continue
  1222. num_examples = torch.randint(1, 3, size=()).item()
  1223. datasets_utils.create_image_folder(tmpdir, cls, lambda idx: self._file_name_fn(cls, ext, idx), num_examples)
  1224. num_examples_total += num_examples
  1225. classes.append(cls)
  1226. return dict(num_examples=num_examples_total, classes=classes)
  1227. def _file_name_fn(self, cls, ext, idx):
  1228. return f"{cls}_{idx}.{ext}"
  1229. def _is_valid_file_to_extensions(self, is_valid_file):
  1230. return {ext for ext in self._EXTENSIONS if is_valid_file(f"foo.{ext}")}
  1231. @datasets_utils.test_all_configs
  1232. def test_is_valid_file(self, config):
  1233. extensions = config.pop("extensions")
  1234. # We need to explicitly pass extensions=None here or otherwise it would be filled by the value from the
  1235. # DEFAULT_CONFIG.
  1236. with self.create_dataset(
  1237. config, extensions=None, is_valid_file=lambda file: pathlib.Path(file).suffix[1:] in extensions
  1238. ) as (dataset, info):
  1239. assert len(dataset) == info["num_examples"]
  1240. @datasets_utils.test_all_configs
  1241. def test_classes(self, config):
  1242. with self.create_dataset(config) as (dataset, info):
  1243. assert len(dataset.classes) == len(info["classes"])
  1244. assert all([a == b for a, b in zip(dataset.classes, info["classes"])])
  1245. class ImageFolderTestCase(datasets_utils.ImageDatasetTestCase):
  1246. DATASET_CLASS = datasets.ImageFolder
  1247. def inject_fake_data(self, tmpdir, config):
  1248. num_examples_total = 0
  1249. classes = ("a", "b")
  1250. for cls in classes:
  1251. num_examples = torch.randint(1, 3, size=()).item()
  1252. num_examples_total += num_examples
  1253. datasets_utils.create_image_folder(tmpdir, cls, lambda idx: f"{cls}_{idx}.png", num_examples)
  1254. return dict(num_examples=num_examples_total, classes=classes)
  1255. @datasets_utils.test_all_configs
  1256. def test_classes(self, config):
  1257. with self.create_dataset(config) as (dataset, info):
  1258. assert len(dataset.classes) == len(info["classes"])
  1259. assert all([a == b for a, b in zip(dataset.classes, info["classes"])])
  1260. class KittiTestCase(datasets_utils.ImageDatasetTestCase):
  1261. DATASET_CLASS = datasets.Kitti
  1262. FEATURE_TYPES = (PIL.Image.Image, (list, type(None))) # test split returns None as target
  1263. ADDITIONAL_CONFIGS = combinations_grid(train=(True, False))
  1264. def inject_fake_data(self, tmpdir, config):
  1265. kitti_dir = os.path.join(tmpdir, "Kitti", "raw")
  1266. os.makedirs(kitti_dir)
  1267. split_to_num_examples = {
  1268. True: 1,
  1269. False: 2,
  1270. }
  1271. # We need to create all folders(training and testing).
  1272. for is_training in (True, False):
  1273. num_examples = split_to_num_examples[is_training]
  1274. datasets_utils.create_image_folder(
  1275. root=kitti_dir,
  1276. name=os.path.join("training" if is_training else "testing", "image_2"),
  1277. file_name_fn=lambda image_idx: f"{image_idx:06d}.png",
  1278. num_examples=num_examples,
  1279. )
  1280. if is_training:
  1281. for image_idx in range(num_examples):
  1282. target_file_dir = os.path.join(kitti_dir, "training", "label_2")
  1283. os.makedirs(target_file_dir)
  1284. target_file_name = os.path.join(target_file_dir, f"{image_idx:06d}.txt")
  1285. target_contents = "Pedestrian 0.00 0 -0.20 712.40 143.00 810.73 307.92 1.89 0.48 1.20 1.84 1.47 8.41 0.01\n" # noqa
  1286. with open(target_file_name, "w") as target_file:
  1287. target_file.write(target_contents)
  1288. return split_to_num_examples[config["train"]]
  1289. def test_transforms_v2_wrapper_spawn(self):
  1290. with self.create_dataset() as (dataset, _):
  1291. datasets_utils.check_transforms_v2_wrapper_spawn(dataset)
  1292. class SvhnTestCase(datasets_utils.ImageDatasetTestCase):
  1293. DATASET_CLASS = datasets.SVHN
  1294. REQUIRED_PACKAGES = ("scipy",)
  1295. ADDITIONAL_CONFIGS = combinations_grid(split=("train", "test", "extra"))
  1296. def inject_fake_data(self, tmpdir, config):
  1297. import scipy.io as sio
  1298. split = config["split"]
  1299. num_examples = {
  1300. "train": 2,
  1301. "test": 3,
  1302. "extra": 4,
  1303. }.get(split)
  1304. file = f"{split}_32x32.mat"
  1305. images = np.zeros((32, 32, 3, num_examples), dtype=np.uint8)
  1306. targets = np.zeros((num_examples,), dtype=np.uint8)
  1307. sio.savemat(os.path.join(tmpdir, file), {"X": images, "y": targets})
  1308. return num_examples
  1309. class Places365TestCase(datasets_utils.ImageDatasetTestCase):
  1310. DATASET_CLASS = datasets.Places365
  1311. ADDITIONAL_CONFIGS = combinations_grid(
  1312. split=("train-standard", "train-challenge", "val"),
  1313. small=(False, True),
  1314. )
  1315. _CATEGORIES = "categories_places365.txt"
  1316. # {split: file}
  1317. _FILE_LISTS = {
  1318. "train-standard": "places365_train_standard.txt",
  1319. "train-challenge": "places365_train_challenge.txt",
  1320. "val": "places365_val.txt",
  1321. }
  1322. # {(split, small): folder_name}
  1323. _IMAGES = {
  1324. ("train-standard", False): "data_large_standard",
  1325. ("train-challenge", False): "data_large_challenge",
  1326. ("val", False): "val_large",
  1327. ("train-standard", True): "data_256_standard",
  1328. ("train-challenge", True): "data_256_challenge",
  1329. ("val", True): "val_256",
  1330. }
  1331. # (class, idx)
  1332. _CATEGORIES_CONTENT = (
  1333. ("/a/airfield", 0),
  1334. ("/a/apartment_building/outdoor", 8),
  1335. ("/b/badlands", 30),
  1336. )
  1337. # (file, idx)
  1338. _FILE_LIST_CONTENT = (
  1339. ("Places365_val_00000001.png", 0),
  1340. *((f"{category}/Places365_train_00000001.png", idx) for category, idx in _CATEGORIES_CONTENT),
  1341. )
  1342. @staticmethod
  1343. def _make_txt(root, name, seq):
  1344. file = os.path.join(root, name)
  1345. with open(file, "w") as fh:
  1346. for text, idx in seq:
  1347. fh.write(f"{text} {idx}\n")
  1348. @staticmethod
  1349. def _make_categories_txt(root, name):
  1350. Places365TestCase._make_txt(root, name, Places365TestCase._CATEGORIES_CONTENT)
  1351. @staticmethod
  1352. def _make_file_list_txt(root, name):
  1353. Places365TestCase._make_txt(root, name, Places365TestCase._FILE_LIST_CONTENT)
  1354. @staticmethod
  1355. def _make_image(file_name, size):
  1356. os.makedirs(os.path.dirname(file_name), exist_ok=True)
  1357. PIL.Image.fromarray(np.zeros((*size, 3), dtype=np.uint8)).save(file_name)
  1358. @staticmethod
  1359. def _make_devkit_archive(root, split):
  1360. Places365TestCase._make_categories_txt(root, Places365TestCase._CATEGORIES)
  1361. Places365TestCase._make_file_list_txt(root, Places365TestCase._FILE_LISTS[split])
  1362. @staticmethod
  1363. def _make_images_archive(root, split, small):
  1364. folder_name = Places365TestCase._IMAGES[(split, small)]
  1365. image_size = (256, 256) if small else (512, random.randint(512, 1024))
  1366. files, idcs = zip(*Places365TestCase._FILE_LIST_CONTENT)
  1367. images = [f.lstrip("/").replace("/", os.sep) for f in files]
  1368. for image in images:
  1369. Places365TestCase._make_image(os.path.join(root, folder_name, image), image_size)
  1370. return [(os.path.join(root, folder_name, image), idx) for image, idx in zip(images, idcs)]
  1371. def inject_fake_data(self, tmpdir, config):
  1372. self._make_devkit_archive(tmpdir, config["split"])
  1373. return len(self._make_images_archive(tmpdir, config["split"], config["small"]))
  1374. def test_classes(self):
  1375. classes = list(map(lambda x: x[0], self._CATEGORIES_CONTENT))
  1376. with self.create_dataset() as (dataset, _):
  1377. assert dataset.classes == classes
  1378. def test_class_to_idx(self):
  1379. class_to_idx = dict(self._CATEGORIES_CONTENT)
  1380. with self.create_dataset() as (dataset, _):
  1381. assert dataset.class_to_idx == class_to_idx
  1382. def test_images_download_preexisting(self):
  1383. with pytest.raises(RuntimeError):
  1384. with self.create_dataset({"download": True}):
  1385. pass
  1386. class INaturalistTestCase(datasets_utils.ImageDatasetTestCase):
  1387. DATASET_CLASS = datasets.INaturalist
  1388. FEATURE_TYPES = (PIL.Image.Image, (int, tuple))
  1389. ADDITIONAL_CONFIGS = combinations_grid(
  1390. target_type=("kingdom", "full", "genus", ["kingdom", "phylum", "class", "order", "family", "genus", "full"]),
  1391. version=("2021_train",),
  1392. )
  1393. def inject_fake_data(self, tmpdir, config):
  1394. categories = [
  1395. "00000_Akingdom_0phylum_Aclass_Aorder_Afamily_Agenus_Aspecies",
  1396. "00001_Akingdom_1phylum_Aclass_Border_Afamily_Bgenus_Aspecies",
  1397. "00002_Akingdom_2phylum_Cclass_Corder_Cfamily_Cgenus_Cspecies",
  1398. ]
  1399. num_images_per_category = 3
  1400. for category in categories:
  1401. datasets_utils.create_image_folder(
  1402. root=os.path.join(tmpdir, config["version"]),
  1403. name=category,
  1404. file_name_fn=lambda idx: f"image_{idx + 1:04d}.jpg",
  1405. num_examples=num_images_per_category,
  1406. )
  1407. return num_images_per_category * len(categories)
  1408. def test_targets(self):
  1409. target_types = ["kingdom", "phylum", "class", "order", "family", "genus", "full"]
  1410. with self.create_dataset(target_type=target_types, version="2021_valid") as (dataset, _):
  1411. items = [d[1] for d in dataset]
  1412. for i, item in enumerate(items):
  1413. assert dataset.category_name("kingdom", item[0]) == "Akingdom"
  1414. assert dataset.category_name("phylum", item[1]) == f"{i // 3}phylum"
  1415. assert item[6] == i // 3
  1416. class LFWPeopleTestCase(datasets_utils.DatasetTestCase):
  1417. DATASET_CLASS = datasets.LFWPeople
  1418. FEATURE_TYPES = (PIL.Image.Image, int)
  1419. ADDITIONAL_CONFIGS = combinations_grid(
  1420. split=("10fold", "train", "test"), image_set=("original", "funneled", "deepfunneled")
  1421. )
  1422. _IMAGES_DIR = {"original": "lfw", "funneled": "lfw_funneled", "deepfunneled": "lfw-deepfunneled"}
  1423. _file_id = {"10fold": "", "train": "DevTrain", "test": "DevTest"}
  1424. def inject_fake_data(self, tmpdir, config):
  1425. tmpdir = pathlib.Path(tmpdir) / "lfw-py"
  1426. os.makedirs(tmpdir, exist_ok=True)
  1427. return dict(
  1428. num_examples=self._create_images_dir(tmpdir, self._IMAGES_DIR[config["image_set"]], config["split"]),
  1429. split=config["split"],
  1430. )
  1431. def _create_images_dir(self, root, idir, split):
  1432. idir = os.path.join(root, idir)
  1433. os.makedirs(idir, exist_ok=True)
  1434. n, flines = (10, ["10\n"]) if split == "10fold" else (1, [])
  1435. num_examples = 0
  1436. names = []
  1437. for _ in range(n):
  1438. num_people = random.randint(2, 5)
  1439. flines.append(f"{num_people}\n")
  1440. for i in range(num_people):
  1441. name = self._create_random_id()
  1442. no = random.randint(1, 10)
  1443. flines.append(f"{name}\t{no}\n")
  1444. names.append(f"{name}\t{no}\n")
  1445. datasets_utils.create_image_folder(idir, name, lambda n: f"{name}_{n+1:04d}.jpg", no, 250)
  1446. num_examples += no
  1447. with open(pathlib.Path(root) / f"people{self._file_id[split]}.txt", "w") as f:
  1448. f.writelines(flines)
  1449. with open(pathlib.Path(root) / "lfw-names.txt", "w") as f:
  1450. f.writelines(sorted(names))
  1451. return num_examples
  1452. def _create_random_id(self):
  1453. part1 = datasets_utils.create_random_string(random.randint(5, 7))
  1454. part2 = datasets_utils.create_random_string(random.randint(4, 7))
  1455. return f"{part1}_{part2}"
  1456. class LFWPairsTestCase(LFWPeopleTestCase):
  1457. DATASET_CLASS = datasets.LFWPairs
  1458. FEATURE_TYPES = (PIL.Image.Image, PIL.Image.Image, int)
  1459. def _create_images_dir(self, root, idir, split):
  1460. idir = os.path.join(root, idir)
  1461. os.makedirs(idir, exist_ok=True)
  1462. num_pairs = 7 # effectively 7*2*n = 14*n
  1463. n, self.flines = (10, [f"10\t{num_pairs}"]) if split == "10fold" else (1, [str(num_pairs)])
  1464. for _ in range(n):
  1465. self._inject_pairs(idir, num_pairs, True)
  1466. self._inject_pairs(idir, num_pairs, False)
  1467. with open(pathlib.Path(root) / f"pairs{self._file_id[split]}.txt", "w") as f:
  1468. f.writelines(self.flines)
  1469. return num_pairs * 2 * n
  1470. def _inject_pairs(self, root, num_pairs, same):
  1471. for i in range(num_pairs):
  1472. name1 = self._create_random_id()
  1473. name2 = name1 if same else self._create_random_id()
  1474. no1, no2 = random.randint(1, 100), random.randint(1, 100)
  1475. if same:
  1476. self.flines.append(f"\n{name1}\t{no1}\t{no2}")
  1477. else:
  1478. self.flines.append(f"\n{name1}\t{no1}\t{name2}\t{no2}")
  1479. datasets_utils.create_image_folder(root, name1, lambda _: f"{name1}_{no1:04d}.jpg", 1, 250)
  1480. datasets_utils.create_image_folder(root, name2, lambda _: f"{name2}_{no2:04d}.jpg", 1, 250)
  1481. class SintelTestCase(datasets_utils.ImageDatasetTestCase):
  1482. DATASET_CLASS = datasets.Sintel
  1483. ADDITIONAL_CONFIGS = combinations_grid(split=("train", "test"), pass_name=("clean", "final", "both"))
  1484. FEATURE_TYPES = (PIL.Image.Image, PIL.Image.Image, (np.ndarray, type(None)))
  1485. FLOW_H, FLOW_W = 3, 4
  1486. def inject_fake_data(self, tmpdir, config):
  1487. root = pathlib.Path(tmpdir) / "Sintel"
  1488. num_images_per_scene = 3 if config["split"] == "train" else 4
  1489. num_scenes = 2
  1490. for split_dir in ("training", "test"):
  1491. for pass_name in ("clean", "final"):
  1492. image_root = root / split_dir / pass_name
  1493. for scene_id in range(num_scenes):
  1494. scene_dir = image_root / f"scene_{scene_id}"
  1495. datasets_utils.create_image_folder(
  1496. image_root,
  1497. name=str(scene_dir),
  1498. file_name_fn=lambda image_idx: f"frame_000{image_idx}.png",
  1499. num_examples=num_images_per_scene,
  1500. )
  1501. flow_root = root / "training" / "flow"
  1502. for scene_id in range(num_scenes):
  1503. scene_dir = flow_root / f"scene_{scene_id}"
  1504. os.makedirs(scene_dir)
  1505. for i in range(num_images_per_scene - 1):
  1506. file_name = str(scene_dir / f"frame_000{i}.flo")
  1507. datasets_utils.make_fake_flo_file(h=self.FLOW_H, w=self.FLOW_W, file_name=file_name)
  1508. # with e.g. num_images_per_scene = 3, for a single scene with have 3 images
  1509. # which are frame_0000, frame_0001 and frame_0002
  1510. # They will be consecutively paired as (frame_0000, frame_0001), (frame_0001, frame_0002),
  1511. # that is 3 - 1 = 2 examples. Hence the formula below
  1512. num_passes = 2 if config["pass_name"] == "both" else 1
  1513. num_examples = (num_images_per_scene - 1) * num_scenes * num_passes
  1514. return num_examples
  1515. def test_flow(self):
  1516. # Make sure flow exists for train split, and make sure there are as many flow values as (pairs of) images
  1517. h, w = self.FLOW_H, self.FLOW_W
  1518. expected_flow = np.arange(2 * h * w).reshape(h, w, 2).transpose(2, 0, 1)
  1519. with self.create_dataset(split="train") as (dataset, _):
  1520. assert dataset._flow_list and len(dataset._flow_list) == len(dataset._image_list)
  1521. for _, _, flow in dataset:
  1522. assert flow.shape == (2, h, w)
  1523. np.testing.assert_allclose(flow, expected_flow)
  1524. # Make sure flow is always None for test split
  1525. with self.create_dataset(split="test") as (dataset, _):
  1526. assert dataset._image_list and not dataset._flow_list
  1527. for _, _, flow in dataset:
  1528. assert flow is None
  1529. def test_bad_input(self):
  1530. with pytest.raises(ValueError, match="Unknown value 'bad' for argument split"):
  1531. with self.create_dataset(split="bad"):
  1532. pass
  1533. with pytest.raises(ValueError, match="Unknown value 'bad' for argument pass_name"):
  1534. with self.create_dataset(pass_name="bad"):
  1535. pass
  1536. class KittiFlowTestCase(datasets_utils.ImageDatasetTestCase):
  1537. DATASET_CLASS = datasets.KittiFlow
  1538. ADDITIONAL_CONFIGS = combinations_grid(split=("train", "test"))
  1539. FEATURE_TYPES = (PIL.Image.Image, PIL.Image.Image, (np.ndarray, type(None)), (np.ndarray, type(None)))
  1540. def inject_fake_data(self, tmpdir, config):
  1541. root = pathlib.Path(tmpdir) / "KittiFlow"
  1542. num_examples = 2 if config["split"] == "train" else 3
  1543. for split_dir in ("training", "testing"):
  1544. datasets_utils.create_image_folder(
  1545. root / split_dir,
  1546. name="image_2",
  1547. file_name_fn=lambda image_idx: f"{image_idx}_10.png",
  1548. num_examples=num_examples,
  1549. )
  1550. datasets_utils.create_image_folder(
  1551. root / split_dir,
  1552. name="image_2",
  1553. file_name_fn=lambda image_idx: f"{image_idx}_11.png",
  1554. num_examples=num_examples,
  1555. )
  1556. # For kitti the ground truth flows are encoded as 16-bits pngs.
  1557. # create_image_folder() will actually create 8-bits pngs, but it doesn't
  1558. # matter much: the flow reader will still be able to read the files, it
  1559. # will just be garbage flow value - but we don't care about that here.
  1560. datasets_utils.create_image_folder(
  1561. root / "training",
  1562. name="flow_occ",
  1563. file_name_fn=lambda image_idx: f"{image_idx}_10.png",
  1564. num_examples=num_examples,
  1565. )
  1566. return num_examples
  1567. def test_flow_and_valid(self):
  1568. # Make sure flow exists for train split, and make sure there are as many flow values as (pairs of) images
  1569. # Also assert flow and valid are of the expected shape
  1570. with self.create_dataset(split="train") as (dataset, _):
  1571. assert dataset._flow_list and len(dataset._flow_list) == len(dataset._image_list)
  1572. for _, _, flow, valid in dataset:
  1573. two, h, w = flow.shape
  1574. assert two == 2
  1575. assert valid.shape == (h, w)
  1576. # Make sure flow and valid are always None for test split
  1577. with self.create_dataset(split="test") as (dataset, _):
  1578. assert dataset._image_list and not dataset._flow_list
  1579. for _, _, flow, valid in dataset:
  1580. assert flow is None
  1581. assert valid is None
  1582. def test_bad_input(self):
  1583. with pytest.raises(ValueError, match="Unknown value 'bad' for argument split"):
  1584. with self.create_dataset(split="bad"):
  1585. pass
  1586. class FlyingChairsTestCase(datasets_utils.ImageDatasetTestCase):
  1587. DATASET_CLASS = datasets.FlyingChairs
  1588. ADDITIONAL_CONFIGS = combinations_grid(split=("train", "val"))
  1589. FEATURE_TYPES = (PIL.Image.Image, PIL.Image.Image, (np.ndarray, type(None)))
  1590. FLOW_H, FLOW_W = 3, 4
  1591. def _make_split_file(self, root, num_examples):
  1592. # We create a fake split file here, but users are asked to download the real one from the authors website
  1593. split_ids = [1] * num_examples["train"] + [2] * num_examples["val"]
  1594. random.shuffle(split_ids)
  1595. with open(str(root / "FlyingChairs_train_val.txt"), "w+") as split_file:
  1596. for split_id in split_ids:
  1597. split_file.write(f"{split_id}\n")
  1598. def inject_fake_data(self, tmpdir, config):
  1599. root = pathlib.Path(tmpdir) / "FlyingChairs"
  1600. num_examples = {"train": 5, "val": 3}
  1601. num_examples_total = sum(num_examples.values())
  1602. datasets_utils.create_image_folder( # img1
  1603. root,
  1604. name="data",
  1605. file_name_fn=lambda image_idx: f"00{image_idx}_img1.ppm",
  1606. num_examples=num_examples_total,
  1607. )
  1608. datasets_utils.create_image_folder( # img2
  1609. root,
  1610. name="data",
  1611. file_name_fn=lambda image_idx: f"00{image_idx}_img2.ppm",
  1612. num_examples=num_examples_total,
  1613. )
  1614. for i in range(num_examples_total):
  1615. file_name = str(root / "data" / f"00{i}_flow.flo")
  1616. datasets_utils.make_fake_flo_file(h=self.FLOW_H, w=self.FLOW_W, file_name=file_name)
  1617. self._make_split_file(root, num_examples)
  1618. return num_examples[config["split"]]
  1619. @datasets_utils.test_all_configs
  1620. def test_flow(self, config):
  1621. # Make sure flow always exists, and make sure there are as many flow values as (pairs of) images
  1622. # Also make sure the flow is properly decoded
  1623. h, w = self.FLOW_H, self.FLOW_W
  1624. expected_flow = np.arange(2 * h * w).reshape(h, w, 2).transpose(2, 0, 1)
  1625. with self.create_dataset(config=config) as (dataset, _):
  1626. assert dataset._flow_list and len(dataset._flow_list) == len(dataset._image_list)
  1627. for _, _, flow in dataset:
  1628. assert flow.shape == (2, h, w)
  1629. np.testing.assert_allclose(flow, expected_flow)
  1630. class FlyingThings3DTestCase(datasets_utils.ImageDatasetTestCase):
  1631. DATASET_CLASS = datasets.FlyingThings3D
  1632. ADDITIONAL_CONFIGS = combinations_grid(
  1633. split=("train", "test"), pass_name=("clean", "final", "both"), camera=("left", "right", "both")
  1634. )
  1635. FEATURE_TYPES = (PIL.Image.Image, PIL.Image.Image, (np.ndarray, type(None)))
  1636. FLOW_H, FLOW_W = 3, 4
  1637. def inject_fake_data(self, tmpdir, config):
  1638. root = pathlib.Path(tmpdir) / "FlyingThings3D"
  1639. num_images_per_camera = 3 if config["split"] == "train" else 4
  1640. passes = ("frames_cleanpass", "frames_finalpass")
  1641. splits = ("TRAIN", "TEST")
  1642. letters = ("A", "B", "C")
  1643. subfolders = ("0000", "0001")
  1644. cameras = ("left", "right")
  1645. for pass_name, split, letter, subfolder, camera in itertools.product(
  1646. passes, splits, letters, subfolders, cameras
  1647. ):
  1648. current_folder = root / pass_name / split / letter / subfolder
  1649. datasets_utils.create_image_folder(
  1650. current_folder,
  1651. name=camera,
  1652. file_name_fn=lambda image_idx: f"00{image_idx}.png",
  1653. num_examples=num_images_per_camera,
  1654. )
  1655. directions = ("into_future", "into_past")
  1656. for split, letter, subfolder, direction, camera in itertools.product(
  1657. splits, letters, subfolders, directions, cameras
  1658. ):
  1659. current_folder = root / "optical_flow" / split / letter / subfolder / direction / camera
  1660. os.makedirs(str(current_folder), exist_ok=True)
  1661. for i in range(num_images_per_camera):
  1662. datasets_utils.make_fake_pfm_file(self.FLOW_H, self.FLOW_W, file_name=str(current_folder / f"{i}.pfm"))
  1663. num_cameras = 2 if config["camera"] == "both" else 1
  1664. num_passes = 2 if config["pass_name"] == "both" else 1
  1665. num_examples = (
  1666. (num_images_per_camera - 1) * num_cameras * len(subfolders) * len(letters) * len(splits) * num_passes
  1667. )
  1668. return num_examples
  1669. @datasets_utils.test_all_configs
  1670. def test_flow(self, config):
  1671. h, w = self.FLOW_H, self.FLOW_W
  1672. expected_flow = np.arange(3 * h * w).reshape(h, w, 3).transpose(2, 0, 1)
  1673. expected_flow = np.flip(expected_flow, axis=1)
  1674. expected_flow = expected_flow[:2, :, :]
  1675. with self.create_dataset(config=config) as (dataset, _):
  1676. assert dataset._flow_list and len(dataset._flow_list) == len(dataset._image_list)
  1677. for _, _, flow in dataset:
  1678. assert flow.shape == (2, self.FLOW_H, self.FLOW_W)
  1679. np.testing.assert_allclose(flow, expected_flow)
  1680. def test_bad_input(self):
  1681. with pytest.raises(ValueError, match="Unknown value 'bad' for argument split"):
  1682. with self.create_dataset(split="bad"):
  1683. pass
  1684. with pytest.raises(ValueError, match="Unknown value 'bad' for argument pass_name"):
  1685. with self.create_dataset(pass_name="bad"):
  1686. pass
  1687. with pytest.raises(ValueError, match="Unknown value 'bad' for argument camera"):
  1688. with self.create_dataset(camera="bad"):
  1689. pass
  1690. class HD1KTestCase(KittiFlowTestCase):
  1691. DATASET_CLASS = datasets.HD1K
  1692. def inject_fake_data(self, tmpdir, config):
  1693. root = pathlib.Path(tmpdir) / "hd1k"
  1694. num_sequences = 4 if config["split"] == "train" else 3
  1695. num_examples_per_train_sequence = 3
  1696. for seq_idx in range(num_sequences):
  1697. # Training data
  1698. datasets_utils.create_image_folder(
  1699. root / "hd1k_input",
  1700. name="image_2",
  1701. file_name_fn=lambda image_idx: f"{seq_idx:06d}_{image_idx}.png",
  1702. num_examples=num_examples_per_train_sequence,
  1703. )
  1704. datasets_utils.create_image_folder(
  1705. root / "hd1k_flow_gt",
  1706. name="flow_occ",
  1707. file_name_fn=lambda image_idx: f"{seq_idx:06d}_{image_idx}.png",
  1708. num_examples=num_examples_per_train_sequence,
  1709. )
  1710. # Test data
  1711. datasets_utils.create_image_folder(
  1712. root / "hd1k_challenge",
  1713. name="image_2",
  1714. file_name_fn=lambda _: f"{seq_idx:06d}_10.png",
  1715. num_examples=1,
  1716. )
  1717. datasets_utils.create_image_folder(
  1718. root / "hd1k_challenge",
  1719. name="image_2",
  1720. file_name_fn=lambda _: f"{seq_idx:06d}_11.png",
  1721. num_examples=1,
  1722. )
  1723. num_examples_per_sequence = num_examples_per_train_sequence if config["split"] == "train" else 2
  1724. return num_sequences * (num_examples_per_sequence - 1)
  1725. class EuroSATTestCase(datasets_utils.ImageDatasetTestCase):
  1726. DATASET_CLASS = datasets.EuroSAT
  1727. FEATURE_TYPES = (PIL.Image.Image, int)
  1728. def inject_fake_data(self, tmpdir, config):
  1729. data_folder = os.path.join(tmpdir, "eurosat", "2750")
  1730. os.makedirs(data_folder)
  1731. num_examples_per_class = 3
  1732. classes = ("AnnualCrop", "Forest")
  1733. for cls in classes:
  1734. datasets_utils.create_image_folder(
  1735. root=data_folder,
  1736. name=cls,
  1737. file_name_fn=lambda idx: f"{cls}_{idx}.jpg",
  1738. num_examples=num_examples_per_class,
  1739. )
  1740. return len(classes) * num_examples_per_class
  1741. class Food101TestCase(datasets_utils.ImageDatasetTestCase):
  1742. DATASET_CLASS = datasets.Food101
  1743. FEATURE_TYPES = (PIL.Image.Image, int)
  1744. ADDITIONAL_CONFIGS = combinations_grid(split=("train", "test"))
  1745. def inject_fake_data(self, tmpdir: str, config):
  1746. root_folder = pathlib.Path(tmpdir) / "food-101"
  1747. image_folder = root_folder / "images"
  1748. meta_folder = root_folder / "meta"
  1749. image_folder.mkdir(parents=True)
  1750. meta_folder.mkdir()
  1751. num_images_per_class = 5
  1752. metadata = {}
  1753. n_samples_per_class = 3 if config["split"] == "train" else 2
  1754. sampled_classes = ("apple_pie", "crab_cakes", "gyoza")
  1755. for cls in sampled_classes:
  1756. im_fnames = datasets_utils.create_image_folder(
  1757. image_folder,
  1758. cls,
  1759. file_name_fn=lambda idx: f"{idx}.jpg",
  1760. num_examples=num_images_per_class,
  1761. )
  1762. metadata[cls] = [
  1763. "/".join(fname.relative_to(image_folder).with_suffix("").parts)
  1764. for fname in random.choices(im_fnames, k=n_samples_per_class)
  1765. ]
  1766. with open(meta_folder / f"{config['split']}.json", "w") as file:
  1767. file.write(json.dumps(metadata))
  1768. return len(sampled_classes * n_samples_per_class)
  1769. class FGVCAircraftTestCase(datasets_utils.ImageDatasetTestCase):
  1770. DATASET_CLASS = datasets.FGVCAircraft
  1771. ADDITIONAL_CONFIGS = combinations_grid(
  1772. split=("train", "val", "trainval", "test"), annotation_level=("variant", "family", "manufacturer")
  1773. )
  1774. def inject_fake_data(self, tmpdir: str, config):
  1775. split = config["split"]
  1776. annotation_level = config["annotation_level"]
  1777. annotation_level_to_file = {
  1778. "variant": "variants.txt",
  1779. "family": "families.txt",
  1780. "manufacturer": "manufacturers.txt",
  1781. }
  1782. root_folder = pathlib.Path(tmpdir) / "fgvc-aircraft-2013b"
  1783. data_folder = root_folder / "data"
  1784. classes = ["707-320", "Hawk T1", "Tornado"]
  1785. num_images_per_class = 5
  1786. datasets_utils.create_image_folder(
  1787. data_folder,
  1788. "images",
  1789. file_name_fn=lambda idx: f"{idx}.jpg",
  1790. num_examples=num_images_per_class * len(classes),
  1791. )
  1792. annotation_file = data_folder / annotation_level_to_file[annotation_level]
  1793. with open(annotation_file, "w") as file:
  1794. file.write("\n".join(classes))
  1795. num_samples_per_class = 4 if split == "trainval" else 2
  1796. images_classes = []
  1797. for i in range(len(classes)):
  1798. images_classes.extend(
  1799. [
  1800. f"{idx} {classes[i]}"
  1801. for idx in random.sample(
  1802. range(i * num_images_per_class, (i + 1) * num_images_per_class), num_samples_per_class
  1803. )
  1804. ]
  1805. )
  1806. images_annotation_file = data_folder / f"images_{annotation_level}_{split}.txt"
  1807. with open(images_annotation_file, "w") as file:
  1808. file.write("\n".join(images_classes))
  1809. return len(classes * num_samples_per_class)
  1810. class SUN397TestCase(datasets_utils.ImageDatasetTestCase):
  1811. DATASET_CLASS = datasets.SUN397
  1812. def inject_fake_data(self, tmpdir: str, config):
  1813. data_dir = pathlib.Path(tmpdir) / "SUN397"
  1814. data_dir.mkdir()
  1815. num_images_per_class = 5
  1816. sampled_classes = ("abbey", "airplane_cabin", "airport_terminal")
  1817. im_paths = []
  1818. for cls in sampled_classes:
  1819. image_folder = data_dir / cls[0]
  1820. im_paths.extend(
  1821. datasets_utils.create_image_folder(
  1822. image_folder,
  1823. image_folder / cls,
  1824. file_name_fn=lambda idx: f"sun_{idx}.jpg",
  1825. num_examples=num_images_per_class,
  1826. )
  1827. )
  1828. with open(data_dir / "ClassName.txt", "w") as file:
  1829. file.writelines("\n".join(f"/{cls[0]}/{cls}" for cls in sampled_classes))
  1830. num_samples = len(im_paths)
  1831. return num_samples
  1832. class DTDTestCase(datasets_utils.ImageDatasetTestCase):
  1833. DATASET_CLASS = datasets.DTD
  1834. FEATURE_TYPES = (PIL.Image.Image, int)
  1835. ADDITIONAL_CONFIGS = combinations_grid(
  1836. split=("train", "test", "val"),
  1837. # There is no need to test the whole matrix here, since each fold is treated exactly the same
  1838. partition=(1, 5, 10),
  1839. )
  1840. def inject_fake_data(self, tmpdir: str, config):
  1841. data_folder = pathlib.Path(tmpdir) / "dtd" / "dtd"
  1842. num_images_per_class = 3
  1843. image_folder = data_folder / "images"
  1844. image_files = []
  1845. for cls in ("banded", "marbled", "zigzagged"):
  1846. image_files.extend(
  1847. datasets_utils.create_image_folder(
  1848. image_folder,
  1849. cls,
  1850. file_name_fn=lambda idx: f"{cls}_{idx:04d}.jpg",
  1851. num_examples=num_images_per_class,
  1852. )
  1853. )
  1854. meta_folder = data_folder / "labels"
  1855. meta_folder.mkdir()
  1856. image_ids = [str(path.relative_to(path.parents[1])).replace(os.sep, "/") for path in image_files]
  1857. image_ids_in_config = random.choices(image_ids, k=len(image_files) // 2)
  1858. with open(meta_folder / f"{config['split']}{config['partition']}.txt", "w") as file:
  1859. file.write("\n".join(image_ids_in_config) + "\n")
  1860. return len(image_ids_in_config)
  1861. class FER2013TestCase(datasets_utils.ImageDatasetTestCase):
  1862. DATASET_CLASS = datasets.FER2013
  1863. ADDITIONAL_CONFIGS = combinations_grid(split=("train", "test"))
  1864. FEATURE_TYPES = (PIL.Image.Image, (int, type(None)))
  1865. def inject_fake_data(self, tmpdir, config):
  1866. base_folder = os.path.join(tmpdir, "fer2013")
  1867. os.makedirs(base_folder)
  1868. num_samples = 5
  1869. with open(os.path.join(base_folder, f"{config['split']}.csv"), "w", newline="") as file:
  1870. writer = csv.DictWriter(
  1871. file,
  1872. fieldnames=("emotion", "pixels") if config["split"] == "train" else ("pixels",),
  1873. quoting=csv.QUOTE_NONNUMERIC,
  1874. quotechar='"',
  1875. )
  1876. writer.writeheader()
  1877. for _ in range(num_samples):
  1878. row = dict(
  1879. pixels=" ".join(
  1880. str(pixel) for pixel in datasets_utils.create_image_or_video_tensor((48, 48)).view(-1).tolist()
  1881. )
  1882. )
  1883. if config["split"] == "train":
  1884. row["emotion"] = str(int(torch.randint(0, 7, ())))
  1885. writer.writerow(row)
  1886. return num_samples
  1887. class GTSRBTestCase(datasets_utils.ImageDatasetTestCase):
  1888. DATASET_CLASS = datasets.GTSRB
  1889. FEATURE_TYPES = (PIL.Image.Image, int)
  1890. ADDITIONAL_CONFIGS = combinations_grid(split=("train", "test"))
  1891. def inject_fake_data(self, tmpdir: str, config):
  1892. root_folder = os.path.join(tmpdir, "gtsrb")
  1893. os.makedirs(root_folder, exist_ok=True)
  1894. # Train data
  1895. train_folder = os.path.join(root_folder, "GTSRB", "Training")
  1896. os.makedirs(train_folder, exist_ok=True)
  1897. num_examples = 3 if config["split"] == "train" else 4
  1898. classes = ("00000", "00042", "00012")
  1899. for class_idx in classes:
  1900. datasets_utils.create_image_folder(
  1901. train_folder,
  1902. name=class_idx,
  1903. file_name_fn=lambda image_idx: f"{class_idx}_{image_idx:05d}.ppm",
  1904. num_examples=num_examples,
  1905. )
  1906. total_number_of_examples = num_examples * len(classes)
  1907. # Test data
  1908. test_folder = os.path.join(root_folder, "GTSRB", "Final_Test", "Images")
  1909. os.makedirs(test_folder, exist_ok=True)
  1910. with open(os.path.join(root_folder, "GT-final_test.csv"), "w") as csv_file:
  1911. csv_file.write("Filename;Width;Height;Roi.X1;Roi.Y1;Roi.X2;Roi.Y2;ClassId\n")
  1912. for _ in range(total_number_of_examples):
  1913. image_file = datasets_utils.create_random_string(5, string.digits) + ".ppm"
  1914. datasets_utils.create_image_file(test_folder, image_file)
  1915. row = [
  1916. image_file,
  1917. torch.randint(1, 100, size=()).item(),
  1918. torch.randint(1, 100, size=()).item(),
  1919. torch.randint(1, 100, size=()).item(),
  1920. torch.randint(1, 100, size=()).item(),
  1921. torch.randint(1, 100, size=()).item(),
  1922. torch.randint(1, 100, size=()).item(),
  1923. torch.randint(0, 43, size=()).item(),
  1924. ]
  1925. csv_file.write(";".join(map(str, row)) + "\n")
  1926. return total_number_of_examples
  1927. class CLEVRClassificationTestCase(datasets_utils.ImageDatasetTestCase):
  1928. DATASET_CLASS = datasets.CLEVRClassification
  1929. FEATURE_TYPES = (PIL.Image.Image, (int, type(None)))
  1930. ADDITIONAL_CONFIGS = combinations_grid(split=("train", "val", "test"))
  1931. def inject_fake_data(self, tmpdir, config):
  1932. data_folder = pathlib.Path(tmpdir) / "clevr" / "CLEVR_v1.0"
  1933. images_folder = data_folder / "images"
  1934. image_files = datasets_utils.create_image_folder(
  1935. images_folder, config["split"], lambda idx: f"CLEVR_{config['split']}_{idx:06d}.png", num_examples=5
  1936. )
  1937. scenes_folder = data_folder / "scenes"
  1938. scenes_folder.mkdir()
  1939. if config["split"] != "test":
  1940. with open(scenes_folder / f"CLEVR_{config['split']}_scenes.json", "w") as file:
  1941. json.dump(
  1942. dict(
  1943. info=dict(),
  1944. scenes=[
  1945. dict(image_filename=image_file.name, objects=[dict()] * int(torch.randint(10, ())))
  1946. for image_file in image_files
  1947. ],
  1948. ),
  1949. file,
  1950. )
  1951. return len(image_files)
  1952. class OxfordIIITPetTestCase(datasets_utils.ImageDatasetTestCase):
  1953. DATASET_CLASS = datasets.OxfordIIITPet
  1954. FEATURE_TYPES = (PIL.Image.Image, (int, PIL.Image.Image, tuple, type(None)))
  1955. ADDITIONAL_CONFIGS = combinations_grid(
  1956. split=("trainval", "test"),
  1957. target_types=("category", "segmentation", ["category", "segmentation"], []),
  1958. )
  1959. def inject_fake_data(self, tmpdir, config):
  1960. base_folder = os.path.join(tmpdir, "oxford-iiit-pet")
  1961. classification_anns_meta = (
  1962. dict(cls="Abyssinian", label=0, species="cat"),
  1963. dict(cls="Keeshond", label=18, species="dog"),
  1964. dict(cls="Yorkshire Terrier", label=37, species="dog"),
  1965. )
  1966. split_and_classification_anns = [
  1967. self._meta_to_split_and_classification_ann(meta, idx)
  1968. for meta, idx in itertools.product(classification_anns_meta, (1, 2, 10))
  1969. ]
  1970. image_ids, *_ = zip(*split_and_classification_anns)
  1971. image_files = datasets_utils.create_image_folder(
  1972. base_folder, "images", file_name_fn=lambda idx: f"{image_ids[idx]}.jpg", num_examples=len(image_ids)
  1973. )
  1974. anns_folder = os.path.join(base_folder, "annotations")
  1975. os.makedirs(anns_folder)
  1976. split_and_classification_anns_in_split = random.choices(split_and_classification_anns, k=len(image_ids) // 2)
  1977. with open(os.path.join(anns_folder, f"{config['split']}.txt"), "w", newline="") as file:
  1978. writer = csv.writer(file, delimiter=" ")
  1979. for split_and_classification_ann in split_and_classification_anns_in_split:
  1980. writer.writerow(split_and_classification_ann)
  1981. segmentation_files = datasets_utils.create_image_folder(
  1982. anns_folder, "trimaps", file_name_fn=lambda idx: f"{image_ids[idx]}.png", num_examples=len(image_ids)
  1983. )
  1984. # The dataset has some rogue files
  1985. for path in image_files[:2]:
  1986. path.with_suffix(".mat").touch()
  1987. for path in segmentation_files:
  1988. path.with_name(f".{path.name}").touch()
  1989. return len(split_and_classification_anns_in_split)
  1990. def _meta_to_split_and_classification_ann(self, meta, idx):
  1991. image_id = "_".join(
  1992. [
  1993. *[(str.title if meta["species"] == "cat" else str.lower)(part) for part in meta["cls"].split()],
  1994. str(idx),
  1995. ]
  1996. )
  1997. class_id = str(meta["label"] + 1)
  1998. species = "1" if meta["species"] == "cat" else "2"
  1999. breed_id = "-1"
  2000. return (image_id, class_id, species, breed_id)
  2001. def test_transforms_v2_wrapper_spawn(self):
  2002. with self.create_dataset() as (dataset, _):
  2003. datasets_utils.check_transforms_v2_wrapper_spawn(dataset)
  2004. class StanfordCarsTestCase(datasets_utils.ImageDatasetTestCase):
  2005. DATASET_CLASS = datasets.StanfordCars
  2006. REQUIRED_PACKAGES = ("scipy",)
  2007. ADDITIONAL_CONFIGS = combinations_grid(split=("train", "test"))
  2008. def inject_fake_data(self, tmpdir, config):
  2009. import scipy.io as io
  2010. from numpy.core.records import fromarrays
  2011. num_examples = {"train": 5, "test": 7}[config["split"]]
  2012. num_classes = 3
  2013. base_folder = pathlib.Path(tmpdir) / "stanford_cars"
  2014. devkit = base_folder / "devkit"
  2015. devkit.mkdir(parents=True)
  2016. if config["split"] == "train":
  2017. images_folder_name = "cars_train"
  2018. annotations_mat_path = devkit / "cars_train_annos.mat"
  2019. else:
  2020. images_folder_name = "cars_test"
  2021. annotations_mat_path = base_folder / "cars_test_annos_withlabels.mat"
  2022. datasets_utils.create_image_folder(
  2023. root=base_folder,
  2024. name=images_folder_name,
  2025. file_name_fn=lambda image_index: f"{image_index:5d}.jpg",
  2026. num_examples=num_examples,
  2027. )
  2028. classes = np.random.randint(1, num_classes + 1, num_examples, dtype=np.uint8)
  2029. fnames = [f"{i:5d}.jpg" for i in range(num_examples)]
  2030. rec_array = fromarrays(
  2031. [classes, fnames],
  2032. names=["class", "fname"],
  2033. )
  2034. io.savemat(annotations_mat_path, {"annotations": rec_array})
  2035. random_class_names = ["random_name"] * num_classes
  2036. io.savemat(devkit / "cars_meta.mat", {"class_names": random_class_names})
  2037. return num_examples
  2038. class Country211TestCase(datasets_utils.ImageDatasetTestCase):
  2039. DATASET_CLASS = datasets.Country211
  2040. ADDITIONAL_CONFIGS = combinations_grid(split=("train", "valid", "test"))
  2041. def inject_fake_data(self, tmpdir: str, config):
  2042. split_folder = pathlib.Path(tmpdir) / "country211" / config["split"]
  2043. split_folder.mkdir(parents=True, exist_ok=True)
  2044. num_examples = {
  2045. "train": 3,
  2046. "valid": 4,
  2047. "test": 5,
  2048. }[config["split"]]
  2049. classes = ("AD", "BS", "GR")
  2050. for cls in classes:
  2051. datasets_utils.create_image_folder(
  2052. split_folder,
  2053. name=cls,
  2054. file_name_fn=lambda idx: f"{idx}.jpg",
  2055. num_examples=num_examples,
  2056. )
  2057. return num_examples * len(classes)
  2058. class Flowers102TestCase(datasets_utils.ImageDatasetTestCase):
  2059. DATASET_CLASS = datasets.Flowers102
  2060. ADDITIONAL_CONFIGS = combinations_grid(split=("train", "val", "test"))
  2061. REQUIRED_PACKAGES = ("scipy",)
  2062. def inject_fake_data(self, tmpdir: str, config):
  2063. base_folder = pathlib.Path(tmpdir) / "flowers-102"
  2064. num_classes = 3
  2065. num_images_per_split = dict(train=5, val=4, test=3)
  2066. num_images_total = sum(num_images_per_split.values())
  2067. datasets_utils.create_image_folder(
  2068. base_folder,
  2069. "jpg",
  2070. file_name_fn=lambda idx: f"image_{idx + 1:05d}.jpg",
  2071. num_examples=num_images_total,
  2072. )
  2073. label_dict = dict(
  2074. labels=np.random.randint(1, num_classes + 1, size=(1, num_images_total), dtype=np.uint8),
  2075. )
  2076. datasets_utils.lazy_importer.scipy.io.savemat(str(base_folder / "imagelabels.mat"), label_dict)
  2077. setid_mat = np.arange(1, num_images_total + 1, dtype=np.uint16)
  2078. np.random.shuffle(setid_mat)
  2079. setid_dict = dict(
  2080. trnid=setid_mat[: num_images_per_split["train"]].reshape(1, -1),
  2081. valid=setid_mat[num_images_per_split["train"] : -num_images_per_split["test"]].reshape(1, -1),
  2082. tstid=setid_mat[-num_images_per_split["test"] :].reshape(1, -1),
  2083. )
  2084. datasets_utils.lazy_importer.scipy.io.savemat(str(base_folder / "setid.mat"), setid_dict)
  2085. return num_images_per_split[config["split"]]
  2086. class PCAMTestCase(datasets_utils.ImageDatasetTestCase):
  2087. DATASET_CLASS = datasets.PCAM
  2088. ADDITIONAL_CONFIGS = combinations_grid(split=("train", "val", "test"))
  2089. REQUIRED_PACKAGES = ("h5py",)
  2090. def inject_fake_data(self, tmpdir: str, config):
  2091. base_folder = pathlib.Path(tmpdir) / "pcam"
  2092. base_folder.mkdir()
  2093. num_images = {"train": 2, "test": 3, "val": 4}[config["split"]]
  2094. images_file = datasets.PCAM._FILES[config["split"]]["images"][0]
  2095. with datasets_utils.lazy_importer.h5py.File(str(base_folder / images_file), "w") as f:
  2096. f["x"] = np.random.randint(0, 256, size=(num_images, 10, 10, 3), dtype=np.uint8)
  2097. targets_file = datasets.PCAM._FILES[config["split"]]["targets"][0]
  2098. with datasets_utils.lazy_importer.h5py.File(str(base_folder / targets_file), "w") as f:
  2099. f["y"] = np.random.randint(0, 2, size=(num_images, 1, 1, 1), dtype=np.uint8)
  2100. return num_images
  2101. class RenderedSST2TestCase(datasets_utils.ImageDatasetTestCase):
  2102. DATASET_CLASS = datasets.RenderedSST2
  2103. ADDITIONAL_CONFIGS = combinations_grid(split=("train", "val", "test"))
  2104. SPLIT_TO_FOLDER = {"train": "train", "val": "valid", "test": "test"}
  2105. def inject_fake_data(self, tmpdir: str, config):
  2106. root_folder = pathlib.Path(tmpdir) / "rendered-sst2"
  2107. image_folder = root_folder / self.SPLIT_TO_FOLDER[config["split"]]
  2108. num_images_per_class = {"train": 5, "test": 6, "val": 7}
  2109. sampled_classes = ["positive", "negative"]
  2110. for cls in sampled_classes:
  2111. datasets_utils.create_image_folder(
  2112. image_folder,
  2113. cls,
  2114. file_name_fn=lambda idx: f"{idx}.png",
  2115. num_examples=num_images_per_class[config["split"]],
  2116. )
  2117. return len(sampled_classes) * num_images_per_class[config["split"]]
  2118. class Kitti2012StereoTestCase(datasets_utils.ImageDatasetTestCase):
  2119. DATASET_CLASS = datasets.Kitti2012Stereo
  2120. ADDITIONAL_CONFIGS = combinations_grid(split=("train", "test"))
  2121. FEATURE_TYPES = (PIL.Image.Image, PIL.Image.Image, (np.ndarray, type(None)), (np.ndarray, type(None)))
  2122. def inject_fake_data(self, tmpdir, config):
  2123. kitti_dir = pathlib.Path(tmpdir) / "Kitti2012"
  2124. os.makedirs(kitti_dir, exist_ok=True)
  2125. split_dir = kitti_dir / (config["split"] + "ing")
  2126. os.makedirs(split_dir, exist_ok=True)
  2127. num_examples = {"train": 4, "test": 3}.get(config["split"], 0)
  2128. datasets_utils.create_image_folder(
  2129. root=split_dir,
  2130. name="colored_0",
  2131. file_name_fn=lambda i: f"{i:06d}_10.png",
  2132. num_examples=num_examples,
  2133. size=(3, 100, 200),
  2134. )
  2135. datasets_utils.create_image_folder(
  2136. root=split_dir,
  2137. name="colored_1",
  2138. file_name_fn=lambda i: f"{i:06d}_10.png",
  2139. num_examples=num_examples,
  2140. size=(3, 100, 200),
  2141. )
  2142. if config["split"] == "train":
  2143. datasets_utils.create_image_folder(
  2144. root=split_dir,
  2145. name="disp_noc",
  2146. file_name_fn=lambda i: f"{i:06d}.png",
  2147. num_examples=num_examples,
  2148. # Kitti2012 uses a single channel image for disparities
  2149. size=(1, 100, 200),
  2150. )
  2151. return num_examples
  2152. def test_train_splits(self):
  2153. for split in ["train"]:
  2154. with self.create_dataset(split=split) as (dataset, _):
  2155. for left, right, disparity, mask in dataset:
  2156. assert mask is None
  2157. datasets_utils.shape_test_for_stereo(left, right, disparity)
  2158. def test_test_split(self):
  2159. for split in ["test"]:
  2160. with self.create_dataset(split=split) as (dataset, _):
  2161. for left, right, disparity, mask in dataset:
  2162. assert mask is None
  2163. assert disparity is None
  2164. datasets_utils.shape_test_for_stereo(left, right)
  2165. def test_bad_input(self):
  2166. with pytest.raises(ValueError, match="Unknown value 'bad' for argument split"):
  2167. with self.create_dataset(split="bad"):
  2168. pass
  2169. class Kitti2015StereoTestCase(datasets_utils.ImageDatasetTestCase):
  2170. DATASET_CLASS = datasets.Kitti2015Stereo
  2171. ADDITIONAL_CONFIGS = combinations_grid(split=("train", "test"))
  2172. FEATURE_TYPES = (PIL.Image.Image, PIL.Image.Image, (np.ndarray, type(None)), (np.ndarray, type(None)))
  2173. def inject_fake_data(self, tmpdir, config):
  2174. kitti_dir = pathlib.Path(tmpdir) / "Kitti2015"
  2175. os.makedirs(kitti_dir, exist_ok=True)
  2176. split_dir = kitti_dir / (config["split"] + "ing")
  2177. os.makedirs(split_dir, exist_ok=True)
  2178. num_examples = {"train": 4, "test": 6}.get(config["split"], 0)
  2179. datasets_utils.create_image_folder(
  2180. root=split_dir,
  2181. name="image_2",
  2182. file_name_fn=lambda i: f"{i:06d}_10.png",
  2183. num_examples=num_examples,
  2184. size=(3, 100, 200),
  2185. )
  2186. datasets_utils.create_image_folder(
  2187. root=split_dir,
  2188. name="image_3",
  2189. file_name_fn=lambda i: f"{i:06d}_10.png",
  2190. num_examples=num_examples,
  2191. size=(3, 100, 200),
  2192. )
  2193. if config["split"] == "train":
  2194. datasets_utils.create_image_folder(
  2195. root=split_dir,
  2196. name="disp_occ_0",
  2197. file_name_fn=lambda i: f"{i:06d}.png",
  2198. num_examples=num_examples,
  2199. # Kitti2015 uses a single channel image for disparities
  2200. size=(1, 100, 200),
  2201. )
  2202. datasets_utils.create_image_folder(
  2203. root=split_dir,
  2204. name="disp_occ_1",
  2205. file_name_fn=lambda i: f"{i:06d}.png",
  2206. num_examples=num_examples,
  2207. # Kitti2015 uses a single channel image for disparities
  2208. size=(1, 100, 200),
  2209. )
  2210. return num_examples
  2211. def test_train_splits(self):
  2212. for split in ["train"]:
  2213. with self.create_dataset(split=split) as (dataset, _):
  2214. for left, right, disparity, mask in dataset:
  2215. assert mask is None
  2216. datasets_utils.shape_test_for_stereo(left, right, disparity)
  2217. def test_test_split(self):
  2218. for split in ["test"]:
  2219. with self.create_dataset(split=split) as (dataset, _):
  2220. for left, right, disparity, mask in dataset:
  2221. assert mask is None
  2222. assert disparity is None
  2223. datasets_utils.shape_test_for_stereo(left, right)
  2224. def test_bad_input(self):
  2225. with pytest.raises(ValueError, match="Unknown value 'bad' for argument split"):
  2226. with self.create_dataset(split="bad"):
  2227. pass
  2228. class CarlaStereoTestCase(datasets_utils.ImageDatasetTestCase):
  2229. DATASET_CLASS = datasets.CarlaStereo
  2230. FEATURE_TYPES = (PIL.Image.Image, PIL.Image.Image, (np.ndarray, None))
  2231. @staticmethod
  2232. def _create_scene_folders(num_examples: int, root_dir: Union[str, pathlib.Path]):
  2233. # make the root_dir if it does not exits
  2234. os.makedirs(root_dir, exist_ok=True)
  2235. for i in range(num_examples):
  2236. scene_dir = pathlib.Path(root_dir) / f"scene_{i}"
  2237. os.makedirs(scene_dir, exist_ok=True)
  2238. # populate with left right images
  2239. datasets_utils.create_image_file(root=scene_dir, name="im0.png", size=(100, 100))
  2240. datasets_utils.create_image_file(root=scene_dir, name="im1.png", size=(100, 100))
  2241. datasets_utils.make_fake_pfm_file(100, 100, file_name=str(scene_dir / "disp0GT.pfm"))
  2242. datasets_utils.make_fake_pfm_file(100, 100, file_name=str(scene_dir / "disp1GT.pfm"))
  2243. def inject_fake_data(self, tmpdir, config):
  2244. carla_dir = pathlib.Path(tmpdir) / "carla-highres"
  2245. os.makedirs(carla_dir, exist_ok=True)
  2246. split_dir = pathlib.Path(carla_dir) / "trainingF"
  2247. os.makedirs(split_dir, exist_ok=True)
  2248. num_examples = 6
  2249. self._create_scene_folders(num_examples=num_examples, root_dir=split_dir)
  2250. return num_examples
  2251. def test_train_splits(self):
  2252. with self.create_dataset() as (dataset, _):
  2253. for left, right, disparity in dataset:
  2254. datasets_utils.shape_test_for_stereo(left, right, disparity)
  2255. class CREStereoTestCase(datasets_utils.ImageDatasetTestCase):
  2256. DATASET_CLASS = datasets.CREStereo
  2257. FEATURE_TYPES = (PIL.Image.Image, PIL.Image.Image, np.ndarray, type(None))
  2258. def inject_fake_data(self, tmpdir, config):
  2259. crestereo_dir = pathlib.Path(tmpdir) / "CREStereo"
  2260. os.makedirs(crestereo_dir, exist_ok=True)
  2261. examples = {"tree": 2, "shapenet": 3, "reflective": 6, "hole": 5}
  2262. for category_name in ["shapenet", "reflective", "tree", "hole"]:
  2263. split_dir = crestereo_dir / category_name
  2264. os.makedirs(split_dir, exist_ok=True)
  2265. num_examples = examples[category_name]
  2266. for idx in range(num_examples):
  2267. datasets_utils.create_image_file(root=split_dir, name=f"{idx}_left.jpg", size=(100, 100))
  2268. datasets_utils.create_image_file(root=split_dir, name=f"{idx}_right.jpg", size=(100, 100))
  2269. # these are going to end up being gray scale images
  2270. datasets_utils.create_image_file(root=split_dir, name=f"{idx}_left.disp.png", size=(1, 100, 100))
  2271. datasets_utils.create_image_file(root=split_dir, name=f"{idx}_right.disp.png", size=(1, 100, 100))
  2272. return sum(examples.values())
  2273. def test_splits(self):
  2274. with self.create_dataset() as (dataset, _):
  2275. for left, right, disparity, mask in dataset:
  2276. assert mask is None
  2277. datasets_utils.shape_test_for_stereo(left, right, disparity)
  2278. class FallingThingsStereoTestCase(datasets_utils.ImageDatasetTestCase):
  2279. DATASET_CLASS = datasets.FallingThingsStereo
  2280. ADDITIONAL_CONFIGS = combinations_grid(variant=("single", "mixed", "both"))
  2281. FEATURE_TYPES = (PIL.Image.Image, PIL.Image.Image, (np.ndarray, type(None)))
  2282. @staticmethod
  2283. def _make_dummy_depth_map(root: str, name: str, size: Tuple[int, int]):
  2284. file = pathlib.Path(root) / name
  2285. image = np.ones((size[0], size[1]), dtype=np.uint8)
  2286. PIL.Image.fromarray(image).save(file)
  2287. @staticmethod
  2288. def _make_scene_folder(root: str, scene_name: str, size: Tuple[int, int]) -> None:
  2289. root = pathlib.Path(root) / scene_name
  2290. os.makedirs(root, exist_ok=True)
  2291. # jpg images
  2292. datasets_utils.create_image_file(root, "image1.left.jpg", size=(3, size[1], size[0]))
  2293. datasets_utils.create_image_file(root, "image1.right.jpg", size=(3, size[1], size[0]))
  2294. # single channel depth maps
  2295. FallingThingsStereoTestCase._make_dummy_depth_map(root, "image1.left.depth.png", size=(size[0], size[1]))
  2296. FallingThingsStereoTestCase._make_dummy_depth_map(root, "image1.right.depth.png", size=(size[0], size[1]))
  2297. # camera settings json. Minimal example for _read_disparity function testing
  2298. settings_json = {"camera_settings": [{"intrinsic_settings": {"fx": 1}}]}
  2299. with open(root / "_camera_settings.json", "w") as f:
  2300. json.dump(settings_json, f)
  2301. def inject_fake_data(self, tmpdir, config):
  2302. fallingthings_dir = pathlib.Path(tmpdir) / "FallingThings"
  2303. os.makedirs(fallingthings_dir, exist_ok=True)
  2304. num_examples = {"single": 2, "mixed": 3, "both": 4}.get(config["variant"], 0)
  2305. variants = {
  2306. "single": ["single"],
  2307. "mixed": ["mixed"],
  2308. "both": ["single", "mixed"],
  2309. }.get(config["variant"], [])
  2310. variant_dir_prefixes = {
  2311. "single": 1,
  2312. "mixed": 0,
  2313. }
  2314. for variant_name in variants:
  2315. variant_dir = pathlib.Path(fallingthings_dir) / variant_name
  2316. os.makedirs(variant_dir, exist_ok=True)
  2317. for i in range(variant_dir_prefixes[variant_name]):
  2318. variant_dir = variant_dir / f"{i:02d}"
  2319. os.makedirs(variant_dir, exist_ok=True)
  2320. for i in range(num_examples):
  2321. self._make_scene_folder(
  2322. root=variant_dir,
  2323. scene_name=f"scene_{i:06d}",
  2324. size=(100, 200),
  2325. )
  2326. if config["variant"] == "both":
  2327. num_examples *= 2
  2328. return num_examples
  2329. def test_splits(self):
  2330. for variant_name in ["single", "mixed"]:
  2331. with self.create_dataset(variant=variant_name) as (dataset, _):
  2332. for left, right, disparity in dataset:
  2333. datasets_utils.shape_test_for_stereo(left, right, disparity)
  2334. def test_bad_input(self):
  2335. with pytest.raises(ValueError, match="Unknown value 'bad' for argument variant"):
  2336. with self.create_dataset(variant="bad"):
  2337. pass
  2338. class SceneFlowStereoTestCase(datasets_utils.ImageDatasetTestCase):
  2339. DATASET_CLASS = datasets.SceneFlowStereo
  2340. ADDITIONAL_CONFIGS = combinations_grid(
  2341. variant=("FlyingThings3D", "Driving", "Monkaa"), pass_name=("clean", "final", "both")
  2342. )
  2343. FEATURE_TYPES = (PIL.Image.Image, PIL.Image.Image, (np.ndarray, type(None)))
  2344. @staticmethod
  2345. def _create_pfm_folder(
  2346. root: str, name: str, file_name_fn: Callable[..., str], num_examples: int, size: Tuple[int, int]
  2347. ) -> None:
  2348. root = pathlib.Path(root) / name
  2349. os.makedirs(root, exist_ok=True)
  2350. for i in range(num_examples):
  2351. datasets_utils.make_fake_pfm_file(size[0], size[1], root / file_name_fn(i))
  2352. def inject_fake_data(self, tmpdir, config):
  2353. scene_flow_dir = pathlib.Path(tmpdir) / "SceneFlow"
  2354. os.makedirs(scene_flow_dir, exist_ok=True)
  2355. variant_dir = scene_flow_dir / config["variant"]
  2356. variant_dir_prefixes = {
  2357. "Monkaa": 0,
  2358. "Driving": 2,
  2359. "FlyingThings3D": 2,
  2360. }
  2361. os.makedirs(variant_dir, exist_ok=True)
  2362. num_examples = {"FlyingThings3D": 4, "Driving": 6, "Monkaa": 5}.get(config["variant"], 0)
  2363. passes = {
  2364. "clean": ["frames_cleanpass"],
  2365. "final": ["frames_finalpass"],
  2366. "both": ["frames_cleanpass", "frames_finalpass"],
  2367. }.get(config["pass_name"], [])
  2368. for pass_dir_name in passes:
  2369. # create pass directories
  2370. pass_dir = variant_dir / pass_dir_name
  2371. disp_dir = variant_dir / "disparity"
  2372. os.makedirs(pass_dir, exist_ok=True)
  2373. os.makedirs(disp_dir, exist_ok=True)
  2374. for i in range(variant_dir_prefixes.get(config["variant"], 0)):
  2375. pass_dir = pass_dir / str(i)
  2376. disp_dir = disp_dir / str(i)
  2377. os.makedirs(pass_dir, exist_ok=True)
  2378. os.makedirs(disp_dir, exist_ok=True)
  2379. for direction in ["left", "right"]:
  2380. for scene_idx in range(num_examples):
  2381. os.makedirs(pass_dir / f"scene_{scene_idx:06d}", exist_ok=True)
  2382. datasets_utils.create_image_folder(
  2383. root=pass_dir / f"scene_{scene_idx:06d}",
  2384. name=direction,
  2385. file_name_fn=lambda i: f"{i:06d}.png",
  2386. num_examples=1,
  2387. size=(3, 200, 100),
  2388. )
  2389. os.makedirs(disp_dir / f"scene_{scene_idx:06d}", exist_ok=True)
  2390. self._create_pfm_folder(
  2391. root=disp_dir / f"scene_{scene_idx:06d}",
  2392. name=direction,
  2393. file_name_fn=lambda i: f"{i:06d}.pfm",
  2394. num_examples=1,
  2395. size=(100, 200),
  2396. )
  2397. if config["pass_name"] == "both":
  2398. num_examples *= 2
  2399. return num_examples
  2400. def test_splits(self):
  2401. for variant_name, pass_name in itertools.product(["FlyingThings3D", "Driving", "Monkaa"], ["clean", "final"]):
  2402. with self.create_dataset(variant=variant_name, pass_name=pass_name) as (dataset, _):
  2403. for left, right, disparity in dataset:
  2404. datasets_utils.shape_test_for_stereo(left, right, disparity)
  2405. def test_bad_input(self):
  2406. with pytest.raises(ValueError, match="Unknown value 'bad' for argument variant"):
  2407. with self.create_dataset(variant="bad"):
  2408. pass
  2409. class InStereo2k(datasets_utils.ImageDatasetTestCase):
  2410. DATASET_CLASS = datasets.InStereo2k
  2411. FEATURE_TYPES = (PIL.Image.Image, PIL.Image.Image, (np.ndarray, type(None)))
  2412. ADDITIONAL_CONFIGS = combinations_grid(split=("train", "test"))
  2413. @staticmethod
  2414. def _make_scene_folder(root: str, name: str, size: Tuple[int, int]):
  2415. root = pathlib.Path(root) / name
  2416. os.makedirs(root, exist_ok=True)
  2417. datasets_utils.create_image_file(root=root, name="left.png", size=(3, size[0], size[1]))
  2418. datasets_utils.create_image_file(root=root, name="right.png", size=(3, size[0], size[1]))
  2419. datasets_utils.create_image_file(root=root, name="left_disp.png", size=(1, size[0], size[1]))
  2420. datasets_utils.create_image_file(root=root, name="right_disp.png", size=(1, size[0], size[1]))
  2421. def inject_fake_data(self, tmpdir, config):
  2422. in_stereo_dir = pathlib.Path(tmpdir) / "InStereo2k"
  2423. os.makedirs(in_stereo_dir, exist_ok=True)
  2424. split_dir = pathlib.Path(in_stereo_dir) / config["split"]
  2425. os.makedirs(split_dir, exist_ok=True)
  2426. num_examples = {"train": 4, "test": 5}.get(config["split"], 0)
  2427. for i in range(num_examples):
  2428. self._make_scene_folder(split_dir, f"scene_{i:06d}", (100, 200))
  2429. return num_examples
  2430. def test_splits(self):
  2431. for split_name in ["train", "test"]:
  2432. with self.create_dataset(split=split_name) as (dataset, _):
  2433. for left, right, disparity in dataset:
  2434. datasets_utils.shape_test_for_stereo(left, right, disparity)
  2435. def test_bad_input(self):
  2436. with pytest.raises(
  2437. ValueError, match="Unknown value 'bad' for argument split. Valid values are {'train', 'test'}."
  2438. ):
  2439. with self.create_dataset(split="bad"):
  2440. pass
  2441. class SintelStereoTestCase(datasets_utils.ImageDatasetTestCase):
  2442. DATASET_CLASS = datasets.SintelStereo
  2443. ADDITIONAL_CONFIGS = combinations_grid(pass_name=("final", "clean", "both"))
  2444. FEATURE_TYPES = (PIL.Image.Image, PIL.Image.Image, (np.ndarray, type(None)), (np.ndarray, type(None)))
  2445. def inject_fake_data(self, tmpdir, config):
  2446. sintel_dir = pathlib.Path(tmpdir) / "Sintel"
  2447. os.makedirs(sintel_dir, exist_ok=True)
  2448. split_dir = pathlib.Path(sintel_dir) / "training"
  2449. os.makedirs(split_dir, exist_ok=True)
  2450. # a single setting, since there are no splits
  2451. num_examples = {"final": 2, "clean": 3}
  2452. pass_names = {
  2453. "final": ["final"],
  2454. "clean": ["clean"],
  2455. "both": ["final", "clean"],
  2456. }.get(config["pass_name"], [])
  2457. for p in pass_names:
  2458. for view in [f"{p}_left", f"{p}_right"]:
  2459. root = split_dir / view
  2460. os.makedirs(root, exist_ok=True)
  2461. datasets_utils.create_image_folder(
  2462. root=root,
  2463. name="scene1",
  2464. file_name_fn=lambda i: f"{i:06d}.png",
  2465. num_examples=num_examples[p],
  2466. size=(3, 100, 200),
  2467. )
  2468. datasets_utils.create_image_folder(
  2469. root=split_dir / "occlusions",
  2470. name="scene1",
  2471. file_name_fn=lambda i: f"{i:06d}.png",
  2472. num_examples=max(num_examples.values()),
  2473. size=(1, 100, 200),
  2474. )
  2475. datasets_utils.create_image_folder(
  2476. root=split_dir / "outofframe",
  2477. name="scene1",
  2478. file_name_fn=lambda i: f"{i:06d}.png",
  2479. num_examples=max(num_examples.values()),
  2480. size=(1, 100, 200),
  2481. )
  2482. datasets_utils.create_image_folder(
  2483. root=split_dir / "disparities",
  2484. name="scene1",
  2485. file_name_fn=lambda i: f"{i:06d}.png",
  2486. num_examples=max(num_examples.values()),
  2487. size=(3, 100, 200),
  2488. )
  2489. if config["pass_name"] == "both":
  2490. num_examples = sum(num_examples.values())
  2491. else:
  2492. num_examples = num_examples.get(config["pass_name"], 0)
  2493. return num_examples
  2494. def test_splits(self):
  2495. for pass_name in ["final", "clean", "both"]:
  2496. with self.create_dataset(pass_name=pass_name) as (dataset, _):
  2497. for left, right, disparity, valid_mask in dataset:
  2498. datasets_utils.shape_test_for_stereo(left, right, disparity, valid_mask)
  2499. def test_bad_input(self):
  2500. with pytest.raises(ValueError, match="Unknown value 'bad' for argument pass_name"):
  2501. with self.create_dataset(pass_name="bad"):
  2502. pass
  2503. class ETH3DStereoestCase(datasets_utils.ImageDatasetTestCase):
  2504. DATASET_CLASS = datasets.ETH3DStereo
  2505. ADDITIONAL_CONFIGS = combinations_grid(split=("train", "test"))
  2506. FEATURE_TYPES = (PIL.Image.Image, PIL.Image.Image, (np.ndarray, type(None)), (np.ndarray, type(None)))
  2507. @staticmethod
  2508. def _create_scene_folder(num_examples: int, root_dir: str):
  2509. # make the root_dir if it does not exits
  2510. root_dir = pathlib.Path(root_dir)
  2511. os.makedirs(root_dir, exist_ok=True)
  2512. for i in range(num_examples):
  2513. scene_dir = root_dir / f"scene_{i}"
  2514. os.makedirs(scene_dir, exist_ok=True)
  2515. # populate with left right images
  2516. datasets_utils.create_image_file(root=scene_dir, name="im0.png", size=(100, 100))
  2517. datasets_utils.create_image_file(root=scene_dir, name="im1.png", size=(100, 100))
  2518. @staticmethod
  2519. def _create_annotation_folder(num_examples: int, root_dir: str):
  2520. # make the root_dir if it does not exits
  2521. root_dir = pathlib.Path(root_dir)
  2522. os.makedirs(root_dir, exist_ok=True)
  2523. # create scene directories
  2524. for i in range(num_examples):
  2525. scene_dir = root_dir / f"scene_{i}"
  2526. os.makedirs(scene_dir, exist_ok=True)
  2527. # populate with a random png file for occlusion mask, and a pfm file for disparity
  2528. datasets_utils.create_image_file(root=scene_dir, name="mask0nocc.png", size=(1, 100, 100))
  2529. pfm_path = scene_dir / "disp0GT.pfm"
  2530. datasets_utils.make_fake_pfm_file(h=100, w=100, file_name=pfm_path)
  2531. def inject_fake_data(self, tmpdir, config):
  2532. eth3d_dir = pathlib.Path(tmpdir) / "ETH3D"
  2533. num_examples = 2 if config["split"] == "train" else 3
  2534. split_name = "two_view_training" if config["split"] == "train" else "two_view_test"
  2535. split_dir = eth3d_dir / split_name
  2536. self._create_scene_folder(num_examples, split_dir)
  2537. if config["split"] == "train":
  2538. annot_dir = eth3d_dir / "two_view_training_gt"
  2539. self._create_annotation_folder(num_examples, annot_dir)
  2540. return num_examples
  2541. def test_training_splits(self):
  2542. with self.create_dataset(split="train") as (dataset, _):
  2543. for left, right, disparity, valid_mask in dataset:
  2544. datasets_utils.shape_test_for_stereo(left, right, disparity, valid_mask)
  2545. def test_testing_splits(self):
  2546. with self.create_dataset(split="test") as (dataset, _):
  2547. assert all(d == (None, None) for d in dataset._disparities)
  2548. for left, right, disparity, valid_mask in dataset:
  2549. assert valid_mask is None
  2550. datasets_utils.shape_test_for_stereo(left, right, disparity)
  2551. def test_bad_input(self):
  2552. with pytest.raises(ValueError, match="Unknown value 'bad' for argument split"):
  2553. with self.create_dataset(split="bad"):
  2554. pass
  2555. class Middlebury2014StereoTestCase(datasets_utils.ImageDatasetTestCase):
  2556. DATASET_CLASS = datasets.Middlebury2014Stereo
  2557. ADDITIONAL_CONFIGS = combinations_grid(
  2558. split=("train", "additional"),
  2559. calibration=("perfect", "imperfect", "both"),
  2560. use_ambient_views=(True, False),
  2561. )
  2562. FEATURE_TYPES = (PIL.Image.Image, PIL.Image.Image, (np.ndarray, type(None)), (np.ndarray, type(None)))
  2563. @staticmethod
  2564. def _make_scene_folder(root_dir: str, scene_name: str, split: str) -> None:
  2565. calibrations = [None] if split == "test" else ["-perfect", "-imperfect"]
  2566. root_dir = pathlib.Path(root_dir)
  2567. for c in calibrations:
  2568. scene_dir = root_dir / f"{scene_name}{c}"
  2569. os.makedirs(scene_dir, exist_ok=True)
  2570. # make normal images first
  2571. datasets_utils.create_image_file(root=scene_dir, name="im0.png", size=(3, 100, 100))
  2572. datasets_utils.create_image_file(root=scene_dir, name="im1.png", size=(3, 100, 100))
  2573. datasets_utils.create_image_file(root=scene_dir, name="im1E.png", size=(3, 100, 100))
  2574. datasets_utils.create_image_file(root=scene_dir, name="im1L.png", size=(3, 100, 100))
  2575. # these are going to end up being gray scale images
  2576. datasets_utils.make_fake_pfm_file(h=100, w=100, file_name=scene_dir / "disp0.pfm")
  2577. datasets_utils.make_fake_pfm_file(h=100, w=100, file_name=scene_dir / "disp1.pfm")
  2578. def inject_fake_data(self, tmpdir, config):
  2579. split_scene_map = {
  2580. "train": ["Adirondack", "Jadeplant", "Motorcycle", "Piano"],
  2581. "additional": ["Backpack", "Bicycle1", "Cable", "Classroom1"],
  2582. "test": ["Plants", "Classroom2E", "Classroom2", "Australia"],
  2583. }
  2584. middlebury_dir = pathlib.Path(tmpdir, "Middlebury2014")
  2585. os.makedirs(middlebury_dir, exist_ok=True)
  2586. split_dir = middlebury_dir / config["split"]
  2587. os.makedirs(split_dir, exist_ok=True)
  2588. num_examples = {"train": 2, "additional": 3, "test": 4}.get(config["split"], 0)
  2589. for idx in range(num_examples):
  2590. scene_name = split_scene_map[config["split"]][idx]
  2591. self._make_scene_folder(root_dir=split_dir, scene_name=scene_name, split=config["split"])
  2592. if config["calibration"] == "both":
  2593. num_examples *= 2
  2594. return num_examples
  2595. def test_train_splits(self):
  2596. for split, calibration in itertools.product(["train", "additional"], ["perfect", "imperfect", "both"]):
  2597. with self.create_dataset(split=split, calibration=calibration) as (dataset, _):
  2598. for left, right, disparity, mask in dataset:
  2599. datasets_utils.shape_test_for_stereo(left, right, disparity, mask)
  2600. def test_test_split(self):
  2601. for split in ["test"]:
  2602. with self.create_dataset(split=split, calibration=None) as (dataset, _):
  2603. for left, right, disparity, mask in dataset:
  2604. datasets_utils.shape_test_for_stereo(left, right)
  2605. def test_augmented_view_usage(self):
  2606. with self.create_dataset(split="train", use_ambient_views=True) as (dataset, _):
  2607. for left, right, disparity, mask in dataset:
  2608. datasets_utils.shape_test_for_stereo(left, right, disparity, mask)
  2609. def test_value_err_train(self):
  2610. # train set invalid
  2611. split = "train"
  2612. calibration = None
  2613. with pytest.raises(
  2614. ValueError,
  2615. match=f"Split '{split}' has calibration settings, however None was provided as an argument."
  2616. f"\nSetting calibration to 'perfect' for split '{split}'. Available calibration settings are: 'perfect', 'imperfect', 'both'.",
  2617. ):
  2618. with self.create_dataset(split=split, calibration=calibration):
  2619. pass
  2620. def test_value_err_test(self):
  2621. # test set invalid
  2622. split = "test"
  2623. calibration = "perfect"
  2624. with pytest.raises(
  2625. ValueError, match="Split 'test' has only no calibration settings, please set `calibration=None`."
  2626. ):
  2627. with self.create_dataset(split=split, calibration=calibration):
  2628. pass
  2629. def test_bad_input(self):
  2630. with pytest.raises(ValueError, match="Unknown value 'bad' for argument split"):
  2631. with self.create_dataset(split="bad"):
  2632. pass
  2633. class TestDatasetWrapper:
  2634. def test_unknown_type(self):
  2635. unknown_object = object()
  2636. with pytest.raises(
  2637. TypeError, match=re.escape("is meant for subclasses of `torchvision.datasets.VisionDataset`")
  2638. ):
  2639. datasets.wrap_dataset_for_transforms_v2(unknown_object)
  2640. def test_unknown_dataset(self):
  2641. class MyVisionDataset(datasets.VisionDataset):
  2642. pass
  2643. dataset = MyVisionDataset("root")
  2644. with pytest.raises(TypeError, match="No wrapper exist"):
  2645. datasets.wrap_dataset_for_transforms_v2(dataset)
  2646. def test_missing_wrapper(self):
  2647. dataset = datasets.FakeData()
  2648. with pytest.raises(TypeError, match="please open an issue"):
  2649. datasets.wrap_dataset_for_transforms_v2(dataset)
  2650. def test_subclass(self, mocker):
  2651. from torchvision import tv_tensors
  2652. sentinel = object()
  2653. mocker.patch.dict(
  2654. tv_tensors._dataset_wrapper.WRAPPER_FACTORIES,
  2655. clear=False,
  2656. values={datasets.FakeData: lambda dataset, target_keys: lambda idx, sample: sentinel},
  2657. )
  2658. class MyFakeData(datasets.FakeData):
  2659. pass
  2660. dataset = MyFakeData()
  2661. wrapped_dataset = datasets.wrap_dataset_for_transforms_v2(dataset)
  2662. assert wrapped_dataset[0] is sentinel
  2663. if __name__ == "__main__":
  2664. unittest.main()