meta.py 215 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455445644574458445944604461446244634464446544664467446844694470447144724473447444754476447744784479448044814482448344844485448644874488448944904491449244934494449544964497449844994500450145024503450445054506450745084509451045114512451345144515451645174518451945204521452245234524452545264527452845294530453145324533453445354536453745384539454045414542454345444545454645474548454945504551455245534554455545564557455845594560456145624563456445654566456745684569457045714572457345744575457645774578457945804581458245834584458545864587458845894590459145924593459445954596459745984599460046014602460346044605460646074608460946104611461246134614461546164617461846194620462146224623462446254626462746284629463046314632463346344635463646374638463946404641464246434644464546464647464846494650465146524653465446554656465746584659466046614662466346644665466646674668466946704671467246734674467546764677467846794680468146824683468446854686468746884689469046914692469346944695469646974698469947004701470247034704470547064707470847094710471147124713471447154716471747184719472047214722472347244725472647274728472947304731473247334734473547364737473847394740474147424743474447454746474747484749475047514752475347544755475647574758475947604761476247634764476547664767476847694770477147724773477447754776477747784779478047814782478347844785478647874788478947904791479247934794479547964797479847994800480148024803480448054806480748084809481048114812481348144815481648174818481948204821482248234824482548264827482848294830483148324833483448354836483748384839484048414842484348444845484648474848484948504851485248534854485548564857485848594860486148624863486448654866486748684869487048714872487348744875487648774878487948804881488248834884488548864887488848894890489148924893489448954896489748984899490049014902490349044905490649074908490949104911491249134914491549164917491849194920492149224923492449254926492749284929493049314932493349344935493649374938493949404941494249434944494549464947494849494950495149524953495449554956495749584959496049614962496349644965496649674968496949704971497249734974497549764977497849794980498149824983498449854986498749884989499049914992499349944995499649974998499950005001500250035004500550065007500850095010501150125013501450155016501750185019502050215022502350245025502650275028502950305031503250335034503550365037503850395040504150425043504450455046504750485049505050515052505350545055505650575058505950605061506250635064506550665067506850695070507150725073507450755076507750785079508050815082508350845085508650875088508950905091509250935094509550965097509850995100510151025103510451055106510751085109511051115112511351145115511651175118511951205121512251235124512551265127512851295130513151325133513451355136513751385139514051415142514351445145514651475148514951505151515251535154515551565157515851595160516151625163516451655166516751685169517051715172517351745175517651775178517951805181518251835184518551865187518851895190519151925193
  1. """
  2. Augmenters that don't apply augmentations themselves, but are needed
  3. for meta usage.
  4. List of augmenters:
  5. * :class:`Augmenter` (base class for all augmenters)
  6. * :class:`Sequential`
  7. * :class:`SomeOf`
  8. * :class:`OneOf`
  9. * :class:`Sometimes`
  10. * :class:`WithChannels`
  11. * :class:`Identity`
  12. * :class:`Noop`
  13. * :class:`Lambda`
  14. * :class:`AssertLambda`
  15. * :class:`AssertShape`
  16. * :class:`ChannelShuffle`
  17. Note: :class:`~imgaug.augmenters.color.WithColorspace` is in ``color.py``.
  18. """
  19. from __future__ import print_function, division, absolute_import
  20. from abc import ABCMeta, abstractmethod
  21. import copy as copy_module
  22. import re
  23. import itertools
  24. import functools
  25. import sys
  26. import numpy as np
  27. import six
  28. import six.moves as sm
  29. import imgaug as ia
  30. from imgaug.augmentables.batches import (Batch, UnnormalizedBatch,
  31. _BatchInAugmentation)
  32. from .. import parameters as iap
  33. from .. import random as iarandom
  34. from . import base as iabase
  35. @ia.deprecated("imgaug.dtypes.clip_")
  36. def clip_augmented_image_(image, min_value, max_value):
  37. """Clip image in-place."""
  38. return clip_augmented_images_(image, min_value, max_value)
  39. @ia.deprecated("imgaug.dtypes.clip_")
  40. def clip_augmented_image(image, min_value, max_value):
  41. """Clip image."""
  42. return clip_augmented_images(image, min_value, max_value)
  43. @ia.deprecated("imgaug.dtypes.clip_")
  44. def clip_augmented_images_(images, min_value, max_value):
  45. """Clip images in-place."""
  46. if ia.is_np_array(images):
  47. return np.clip(images, min_value, max_value, out=images)
  48. return [np.clip(image, min_value, max_value, out=image)
  49. for image in images]
  50. @ia.deprecated("imgaug.dtypes.clip_")
  51. def clip_augmented_images(images, min_value, max_value):
  52. """Clip images."""
  53. if ia.is_np_array(images):
  54. images = np.copy(images)
  55. else:
  56. images = [np.copy(image) for image in images]
  57. return clip_augmented_images_(images, min_value, max_value)
  58. def handle_children_list(lst, augmenter_name, lst_name, default="sequential"):
  59. """Normalize an augmenter list provided by a user."""
  60. if lst is None:
  61. if default == "sequential":
  62. return Sequential([], name="%s-%s" % (augmenter_name, lst_name))
  63. return default
  64. if isinstance(lst, Augmenter):
  65. if ia.is_iterable(lst):
  66. # TODO why was this assert added here? seems to make no sense
  67. only_augmenters = all([isinstance(child, Augmenter)
  68. for child in lst])
  69. assert only_augmenters, (
  70. "Expected all children to be augmenters, got types %s." % (
  71. ", ".join([str(type(v)) for v in lst])))
  72. return lst
  73. return Sequential(lst, name="%s-%s" % (augmenter_name, lst_name))
  74. if ia.is_iterable(lst):
  75. if len(lst) == 0 and default != "sequential":
  76. return default
  77. only_augmenters = all([isinstance(child, Augmenter)
  78. for child in lst])
  79. assert only_augmenters, (
  80. "Expected all children to be augmenters, got types %s." % (
  81. ", ".join([str(type(v)) for v in lst])))
  82. return Sequential(lst, name="%s-%s" % (augmenter_name, lst_name))
  83. raise Exception(
  84. "Expected None, Augmenter or list/tuple as children list %s "
  85. "for augmenter with name %s, got %s." % (
  86. lst_name, augmenter_name, type(lst),))
  87. def reduce_to_nonempty(objs):
  88. """Remove from a list all objects that don't follow ``obj.empty==True``."""
  89. objs_reduced = []
  90. ids = []
  91. for i, obj in enumerate(objs):
  92. assert hasattr(obj, "empty"), (
  93. "Expected object with property 'empty'. Got type %s." % (
  94. type(obj),))
  95. if not obj.empty:
  96. objs_reduced.append(obj)
  97. ids.append(i)
  98. return objs_reduced, ids
  99. def invert_reduce_to_nonempty(objs, ids, objs_reduced):
  100. """Inverse of :func:`reduce_to_nonempty`."""
  101. objs_inv = list(objs)
  102. for idx, obj_from_reduced in zip(ids, objs_reduced):
  103. objs_inv[idx] = obj_from_reduced
  104. return objs_inv
  105. def estimate_max_number_of_channels(images):
  106. """Compute the maximum number of image channels among a list of images."""
  107. if ia.is_np_array(images):
  108. assert images.ndim == 4, (
  109. "Expected 'images' to be 4-dimensional if provided as array. "
  110. "Got %d dimensions." % (images.ndim,))
  111. return images.shape[3]
  112. assert ia.is_iterable(images), (
  113. "Expected 'images' to be an array or iterable, got %s." % (
  114. type(images),))
  115. if len(images) == 0:
  116. return None
  117. channels = [el.shape[2] if len(el.shape) >= 3 else 1 for el in images]
  118. return max(channels)
  119. def copy_arrays(arrays):
  120. """Copy the arrays of a single input array or list of input arrays."""
  121. if ia.is_np_array(arrays):
  122. return np.copy(arrays)
  123. return [np.copy(array) for array in arrays]
  124. def _add_channel_axis(arrs):
  125. if ia.is_np_array(arrs):
  126. if arrs.ndim == 3: # (N,H,W)
  127. return arrs[..., np.newaxis] # (N,H,W) -> (N,H,W,1)
  128. return arrs
  129. return [
  130. arr[..., np.newaxis] # (H,W) -> (H,W,1)
  131. if arr.ndim == 2
  132. else arr
  133. for arr in arrs
  134. ]
  135. def _remove_added_channel_axis(arrs_added, arrs_orig):
  136. if ia.is_np_array(arrs_orig):
  137. if arrs_orig.ndim == 3: # (N,H,W)
  138. if ia.is_np_array(arrs_added):
  139. return arrs_added[..., 0] # (N,H,W,1) -> (N,H,W)
  140. # (N,H,W) -> (N,H,W,1) -> <augmentation> -> list of (H,W,1)
  141. return [arr[..., 0] for arr in arrs_added]
  142. return arrs_added
  143. return [
  144. arr_added[..., 0]
  145. if arr_orig.ndim == 2
  146. else arr_added # (H,W,1) -> (H,W)
  147. for arr_added, arr_orig
  148. in zip(arrs_added, arrs_orig)
  149. ]
  150. class _maybe_deterministic_ctx(object): # pylint: disable=invalid-name
  151. """Context that resets an RNG to its initial state upon exit.
  152. This allows to execute some sampling functions and leave the code block
  153. with the used RNG in the same state as before.
  154. Parameters
  155. ----------
  156. random_state : imgaug.random.RNG or imgaug.augmenters.meta.Augmenter
  157. The RNG to reset. If this is an augmenter, then the augmenter's
  158. RNG will be used.
  159. deterministic : None or bool
  160. Whether to reset the RNG upon exit (``True``) or not (``False``).
  161. Allowed to be ``None`` iff `random_state` was an augmenter, in which
  162. case that augmenter's ``deterministic`` attribute will be used.
  163. """
  164. def __init__(self, random_state, deterministic=None):
  165. if deterministic is None:
  166. augmenter = random_state
  167. self.random_state = augmenter.random_state
  168. self.deterministic = augmenter.deterministic
  169. else:
  170. assert deterministic is not None, (
  171. "Expected boolean as `deterministic`, got None.")
  172. self.random_state = random_state
  173. self.deterministic = deterministic
  174. self.old_state = None
  175. def __enter__(self):
  176. if self.deterministic:
  177. self.old_state = self.random_state.state
  178. def __exit__(self, exception_type, exception_value, exception_traceback):
  179. if self.old_state is not None:
  180. self.random_state.state = self.old_state
  181. @six.add_metaclass(ABCMeta)
  182. class Augmenter(object):
  183. """
  184. Base class for Augmenter objects.
  185. All augmenters derive from this class.
  186. Parameters
  187. ----------
  188. seed : None or int or imgaug.random.RNG or numpy.random.Generator or numpy.random.BitGenerator or numpy.random.SeedSequence or numpy.random.RandomState, optional
  189. Seed to use for this augmenter's random number generator (RNG) or
  190. alternatively an RNG itself. Setting this parameter allows to
  191. control/influence the random number sampling of this specific
  192. augmenter without affecting other augmenters. Usually, there is no
  193. need to set this parameter.
  194. * If ``None``: The global RNG is used (shared by all
  195. augmenters).
  196. * If ``int``: The value will be used as a seed for a new
  197. :class:`~imgaug.random.RNG` instance.
  198. * If :class:`~imgaug.random.RNG`: The ``RNG`` instance will be
  199. used without changes.
  200. * If :class:`~imgaug.random.Generator`: A new
  201. :class:`~imgaug.random.RNG` instance will be
  202. created, containing that generator.
  203. * If :class:`~imgaug.random.bit_generator.BitGenerator`: Will
  204. be wrapped in a :class:`~imgaug.random.Generator`. Then
  205. similar behaviour to :class:`~imgaug.random.Generator`
  206. parameters.
  207. * If :class:`~imgaug.random.SeedSequence`: Will
  208. be wrapped in a new bit generator and
  209. :class:`~imgaug.random.Generator`. Then
  210. similar behaviour to :class:`~imgaug.random.Generator`
  211. parameters.
  212. * If :class:`~imgaug.random.RandomState`: Similar behaviour to
  213. :class:`~imgaug.random.Generator`. Outdated in numpy 1.17+.
  214. If a new bit generator has to be created, it will be an instance
  215. of :class:`numpy.random.SFC64`.
  216. Added in 0.4.0.
  217. name : None or str, optional
  218. Name given to the Augmenter instance. This name is used when
  219. converting the instance to a string, e.g. for ``print`` statements.
  220. It is also used for ``find``, ``remove`` or similar operations
  221. on augmenters with children.
  222. If ``None``, ``UnnamedX`` will be used as the name, where ``X``
  223. is the Augmenter's class name.
  224. random_state : None or int or imgaug.random.RNG or numpy.random.Generator or numpy.random.BitGenerator or numpy.random.SeedSequence or numpy.random.RandomState, optional
  225. Old name for parameter `seed`.
  226. Its usage will not yet cause a deprecation warning,
  227. but it is still recommended to use `seed` now.
  228. Outdated since 0.4.0.
  229. deterministic : bool, optional
  230. Deprecated since 0.4.0.
  231. See method ``to_deterministic()`` for an alternative and for
  232. details about what the "deterministic mode" actually does.
  233. """
  234. def __init__(self, seed=None, name=None,
  235. random_state="deprecated",
  236. deterministic="deprecated"):
  237. """Create a new Augmenter instance."""
  238. super(Augmenter, self).__init__()
  239. assert name is None or ia.is_string(name), (
  240. "Expected name to be None or string-like, got %s." % (
  241. type(name),))
  242. if name is None:
  243. self.name = "Unnamed%s" % (self.__class__.__name__,)
  244. else:
  245. self.name = name
  246. if deterministic != "deprecated":
  247. ia.warn_deprecated(
  248. "The parameter `deterministic` is deprecated "
  249. "in `imgaug.augmenters.meta.Augmenter`. Use "
  250. "`.to_deterministic()` to switch into deterministic mode.",
  251. stacklevel=4)
  252. assert ia.is_single_bool(deterministic), (
  253. "Expected deterministic to be a boolean, got %s." % (
  254. type(deterministic),))
  255. else:
  256. deterministic = False
  257. self.deterministic = deterministic
  258. if random_state != "deprecated":
  259. assert seed is None, "Cannot set both `seed` and `random_state`."
  260. seed = random_state
  261. if deterministic and seed is None:
  262. # Usually if None is provided, the global RNG will be used.
  263. # In case of deterministic mode we most likely rather want a local
  264. # RNG, which is here created.
  265. self.random_state = iarandom.RNG.create_pseudo_random_()
  266. else:
  267. # self.random_state = iarandom.normalize_rng_(random_state)
  268. self.random_state = iarandom.RNG(seed)
  269. self.activated = True
  270. def augment_batches(self, batches, hooks=None, background=False):
  271. """Augment multiple batches.
  272. In contrast to other ``augment_*`` method, this one **yields**
  273. batches instead of returning a full list. This is more suited
  274. for most training loops.
  275. This method also also supports augmentation on multiple cpu cores,
  276. activated via the `background` flag. If the `background` flag
  277. is activated, an instance of :class:`~imgaug.multicore.Pool` will
  278. be spawned using all available logical CPU cores and an
  279. ``output_buffer_size`` of ``C*10``, where ``C`` is the number of
  280. logical CPU cores. I.e. a maximum of ``C*10`` batches will be somewhere
  281. in the augmentation pipeline (or waiting to be retrieved by downstream
  282. functions) before this method temporarily stops the loading of new
  283. batches from `batches`.
  284. Parameters
  285. ----------
  286. batches : imgaug.augmentables.batches.Batch or imgaug.augmentables.batches.UnnormalizedBatch or iterable of imgaug.augmentables.batches.Batch or iterable of imgaug.augmentables.batches.UnnormalizedBatch
  287. A single batch or a list of batches to augment.
  288. hooks : None or imgaug.HooksImages, optional
  289. HooksImages object to dynamically interfere with the augmentation
  290. process.
  291. background : bool, optional
  292. Whether to augment the batches in background processes.
  293. If ``True``, hooks can currently not be used as that would require
  294. pickling functions.
  295. Note that multicore augmentation distributes the batches onto
  296. different CPU cores. It does *not* split the data *within* batches.
  297. It is therefore *not* sensible to use ``background=True`` to
  298. augment a single batch. Only use it for multiple batches.
  299. Note also that multicore augmentation needs some time to start. It
  300. is therefore not recommended to use it for very few batches.
  301. Yields
  302. -------
  303. imgaug.augmentables.batches.Batch or imgaug.augmentables.batches.UnnormalizedBatch or iterable of imgaug.augmentables.batches.Batch or iterable of imgaug.augmentables.batches.UnnormalizedBatch
  304. Augmented batches.
  305. """
  306. if isinstance(batches, (Batch, UnnormalizedBatch)):
  307. batches = [batches]
  308. assert (
  309. (ia.is_iterable(batches)
  310. and not ia.is_np_array(batches)
  311. and not ia.is_string(batches))
  312. or ia.is_generator(batches)), (
  313. "Expected either (a) an iterable that is not an array or a "
  314. "string or (b) a generator. Got: %s" % (type(batches),))
  315. if background:
  316. assert hooks is None, (
  317. "Hooks can not be used when background augmentation is "
  318. "activated.")
  319. def _normalize_batch(idx, batch):
  320. if isinstance(batch, Batch):
  321. batch_copy = batch.deepcopy()
  322. batch_copy.data = (idx, batch_copy.data)
  323. batch_normalized = batch_copy
  324. batch_orig_dt = "imgaug.Batch"
  325. elif isinstance(batch, UnnormalizedBatch):
  326. batch_copy = batch.to_normalized_batch()
  327. batch_copy.data = (idx, batch_copy.data)
  328. batch_normalized = batch_copy
  329. batch_orig_dt = "imgaug.UnnormalizedBatch"
  330. elif ia.is_np_array(batch):
  331. assert batch.ndim in (3, 4), (
  332. "Expected numpy array to have shape (N, H, W) or "
  333. "(N, H, W, C), got %s." % (batch.shape,))
  334. batch_normalized = Batch(images=batch, data=(idx,))
  335. batch_orig_dt = "numpy_array"
  336. elif isinstance(batch, list):
  337. if len(batch) == 0:
  338. batch_normalized = Batch(data=(idx,))
  339. batch_orig_dt = "empty_list"
  340. elif ia.is_np_array(batch[0]):
  341. batch_normalized = Batch(images=batch, data=(idx,))
  342. batch_orig_dt = "list_of_numpy_arrays"
  343. elif isinstance(batch[0], ia.HeatmapsOnImage):
  344. batch_normalized = Batch(heatmaps=batch, data=(idx,))
  345. batch_orig_dt = "list_of_imgaug.HeatmapsOnImage"
  346. elif isinstance(batch[0], ia.SegmentationMapsOnImage):
  347. batch_normalized = Batch(segmentation_maps=batch,
  348. data=(idx,))
  349. batch_orig_dt = "list_of_imgaug.SegmentationMapsOnImage"
  350. elif isinstance(batch[0], ia.KeypointsOnImage):
  351. batch_normalized = Batch(keypoints=batch, data=(idx,))
  352. batch_orig_dt = "list_of_imgaug.KeypointsOnImage"
  353. elif isinstance(batch[0], ia.BoundingBoxesOnImage):
  354. batch_normalized = Batch(bounding_boxes=batch, data=(idx,))
  355. batch_orig_dt = "list_of_imgaug.BoundingBoxesOnImage"
  356. elif isinstance(batch[0], ia.PolygonsOnImage):
  357. batch_normalized = Batch(polygons=batch, data=(idx,))
  358. batch_orig_dt = "list_of_imgaug.PolygonsOnImage"
  359. else:
  360. raise Exception(
  361. "Unknown datatype in batch[0]. Expected numpy array "
  362. "or imgaug.HeatmapsOnImage or "
  363. "imgaug.SegmentationMapsOnImage or "
  364. "imgaug.KeypointsOnImage or "
  365. "imgaug.BoundingBoxesOnImage, "
  366. "or imgaug.PolygonsOnImage, "
  367. "got %s." % (type(batch[0]),))
  368. else:
  369. raise Exception(
  370. "Unknown datatype of batch. Expected imgaug.Batch or "
  371. "imgaug.UnnormalizedBatch or "
  372. "numpy array or list of (numpy array or "
  373. "imgaug.HeatmapsOnImage or "
  374. "imgaug.SegmentationMapsOnImage "
  375. "or imgaug.KeypointsOnImage or "
  376. "imgaug.BoundingBoxesOnImage or "
  377. "imgaug.PolygonsOnImage). Got %s." % (type(batch),))
  378. if batch_orig_dt not in ["imgaug.Batch",
  379. "imgaug.UnnormalizedBatch"]:
  380. ia.warn_deprecated(
  381. "Received an input in augment_batches() that was not an "
  382. "instance of imgaug.augmentables.batches.Batch "
  383. "or imgaug.augmentables.batches.UnnormalizedBatch, but "
  384. "instead %s. This is deprecated. Use augment() for such "
  385. "data or wrap it in a Batch instance." % (
  386. batch_orig_dt,))
  387. return batch_normalized, batch_orig_dt
  388. # unnormalization of non-Batch/UnnormalizedBatch is for legacy support
  389. def _unnormalize_batch(batch_aug, batch_orig, batch_orig_dt):
  390. if batch_orig_dt == "imgaug.Batch":
  391. batch_unnormalized = batch_aug
  392. # change (i, .data) back to just .data
  393. batch_unnormalized.data = batch_unnormalized.data[1]
  394. elif batch_orig_dt == "imgaug.UnnormalizedBatch":
  395. # change (i, .data) back to just .data
  396. batch_aug.data = batch_aug.data[1]
  397. batch_unnormalized = \
  398. batch_orig.fill_from_augmented_normalized_batch(batch_aug)
  399. elif batch_orig_dt == "numpy_array":
  400. batch_unnormalized = batch_aug.images_aug
  401. elif batch_orig_dt == "empty_list":
  402. batch_unnormalized = []
  403. elif batch_orig_dt == "list_of_numpy_arrays":
  404. batch_unnormalized = batch_aug.images_aug
  405. elif batch_orig_dt == "list_of_imgaug.HeatmapsOnImage":
  406. batch_unnormalized = batch_aug.heatmaps_aug
  407. elif batch_orig_dt == "list_of_imgaug.SegmentationMapsOnImage":
  408. batch_unnormalized = batch_aug.segmentation_maps_aug
  409. elif batch_orig_dt == "list_of_imgaug.KeypointsOnImage":
  410. batch_unnormalized = batch_aug.keypoints_aug
  411. elif batch_orig_dt == "list_of_imgaug.BoundingBoxesOnImage":
  412. batch_unnormalized = batch_aug.bounding_boxes_aug
  413. else: # only option left
  414. assert batch_orig_dt == "list_of_imgaug.PolygonsOnImage", (
  415. "Got an unexpected type %s." % (type(batch_orig_dt),))
  416. batch_unnormalized = batch_aug.polygons_aug
  417. return batch_unnormalized
  418. if not background:
  419. # singlecore augmentation
  420. for idx, batch in enumerate(batches):
  421. batch_normalized, batch_orig_dt = _normalize_batch(idx, batch)
  422. batch_normalized = self.augment_batch_(
  423. batch_normalized, hooks=hooks)
  424. batch_unnormalized = _unnormalize_batch(
  425. batch_normalized, batch, batch_orig_dt)
  426. yield batch_unnormalized
  427. else:
  428. # multicore augmentation
  429. import imgaug.multicore as multicore
  430. id_to_batch_orig = dict()
  431. def load_batches():
  432. for idx, batch in enumerate(batches):
  433. batch_normalized, batch_orig_dt = _normalize_batch(
  434. idx, batch)
  435. id_to_batch_orig[idx] = (batch, batch_orig_dt)
  436. yield batch_normalized
  437. with multicore.Pool(self) as pool:
  438. # pylint:disable=protected-access
  439. # note that pool.processes is None here
  440. output_buffer_size = pool.pool._processes * 10
  441. for batch_aug in pool.imap_batches(
  442. load_batches(), output_buffer_size=output_buffer_size):
  443. idx = batch_aug.data[0]
  444. assert idx in id_to_batch_orig, (
  445. "Got idx %d from Pool, which is not known." % (
  446. idx))
  447. batch_orig, batch_orig_dt = id_to_batch_orig[idx]
  448. batch_unnormalized = _unnormalize_batch(
  449. batch_aug, batch_orig, batch_orig_dt)
  450. del id_to_batch_orig[idx]
  451. yield batch_unnormalized
  452. # we deprecate here so that users switch to `augment_batch_()` and in the
  453. # future we can add a `parents` parameter here without having to consider
  454. # that a breaking change
  455. @ia.deprecated("augment_batch_()",
  456. comment="`augment_batch()` was renamed to "
  457. "`augment_batch_()` as it changes all `*_unaug` "
  458. "attributes of batches in-place. Note that "
  459. "`augment_batch_()` has now a `parents` parameter. "
  460. "Calls of the style `augment_batch(batch, hooks)` "
  461. "must be changed to "
  462. "`augment_batch(batch, hooks=hooks)`.")
  463. def augment_batch(self, batch, hooks=None):
  464. """Augment a single batch.
  465. Deprecated since 0.4.0.
  466. """
  467. # We call augment_batch_() directly here without copy, because this
  468. # method never copies. Would make sense to add a copy here if the
  469. # method is un-deprecated at some point.
  470. return self.augment_batch_(batch, hooks=hooks)
  471. # TODO add more tests
  472. def augment_batch_(self, batch, parents=None, hooks=None):
  473. """
  474. Augment a single batch in-place.
  475. Added in 0.4.0.
  476. Parameters
  477. ----------
  478. batch : imgaug.augmentables.batches.Batch or imgaug.augmentables.batches.UnnormalizedBatch or imgaug.augmentables.batch._BatchInAugmentation
  479. A single batch to augment.
  480. If :class:`imgaug.augmentables.batches.UnnormalizedBatch`
  481. or :class:`imgaug.augmentables.batches.Batch`, then the ``*_aug``
  482. attributes may be modified in-place, while the ``*_unaug``
  483. attributes will not be modified.
  484. If :class:`imgaug.augmentables.batches._BatchInAugmentation`,
  485. then all attributes may be modified in-place.
  486. parents : None or list of imgaug.augmenters.Augmenter, optional
  487. Parent augmenters that have previously been called before the
  488. call to this function. Usually you can leave this parameter as
  489. ``None``. It is set automatically for child augmenters.
  490. hooks : None or imgaug.HooksImages, optional
  491. HooksImages object to dynamically interfere with the augmentation
  492. process.
  493. Returns
  494. -------
  495. imgaug.augmentables.batches.Batch or imgaug.augmentables.batches.UnnormalizedBatch
  496. Augmented batch.
  497. """
  498. # this chain of if/elses would be more beautiful if it was
  499. # (1st) UnnormalizedBatch, (2nd) Batch, (3rd) BatchInAugmenation.
  500. # We check for _BatchInAugmentation first as it is expected to be the
  501. # most common input (due to child calls).
  502. batch_unnorm = None
  503. batch_norm = None
  504. if isinstance(batch, _BatchInAugmentation):
  505. batch_inaug = batch
  506. elif isinstance(batch, UnnormalizedBatch):
  507. batch_unnorm = batch
  508. batch_norm = batch.to_normalized_batch()
  509. batch_inaug = batch_norm.to_batch_in_augmentation()
  510. elif isinstance(batch, Batch):
  511. batch_norm = batch
  512. batch_inaug = batch_norm.to_batch_in_augmentation()
  513. else:
  514. raise ValueError(
  515. "Expected UnnormalizedBatch, Batch or _BatchInAugmentation, "
  516. "got %s." % (type(batch).__name__,))
  517. columns = batch_inaug.columns
  518. # hooks preprocess
  519. if hooks is not None:
  520. for column in columns:
  521. value = hooks.preprocess(
  522. column.value, augmenter=self, parents=parents)
  523. setattr(batch_inaug, column.attr_name, value)
  524. # refresh so that values are updated for later functions
  525. columns = batch_inaug.columns
  526. # set augmentables to None if this augmenter is deactivated or hooks
  527. # demands it
  528. set_to_none = []
  529. if not self.activated:
  530. for column in columns:
  531. set_to_none.append(column)
  532. setattr(batch_inaug, column.attr_name, None)
  533. elif hooks is not None:
  534. for column in columns:
  535. activated = hooks.is_activated(
  536. column.value, augmenter=self, parents=parents,
  537. default=self.activated)
  538. if not activated:
  539. set_to_none.append(column)
  540. setattr(batch_inaug, column.attr_name, None)
  541. # If _augment_batch_() follows legacy-style and ends up calling
  542. # _augment_images() and similar methods, we don't need the
  543. # deterministic context here. But if there is a custom implementation
  544. # of _augment_batch_(), then we should have this here. It causes very
  545. # little overhead.
  546. with _maybe_deterministic_ctx(self):
  547. if not batch_inaug.empty:
  548. batch_inaug = self._augment_batch_(
  549. batch_inaug,
  550. random_state=self.random_state,
  551. parents=parents if parents is not None else [],
  552. hooks=hooks)
  553. # revert augmentables being set to None for non-activated augmenters
  554. for column in set_to_none:
  555. setattr(batch_inaug, column.attr_name, column.value)
  556. # hooks postprocess
  557. if hooks is not None:
  558. # refresh as contents may have been changed in _augment_batch_()
  559. columns = batch_inaug.columns
  560. for column in columns:
  561. augm_value = hooks.postprocess(
  562. column.value, augmenter=self, parents=parents)
  563. setattr(batch_inaug, column.attr_name, augm_value)
  564. if batch_unnorm is not None:
  565. batch_norm = batch_norm.fill_from_batch_in_augmentation_(
  566. batch_inaug)
  567. batch_unnorm = batch_unnorm.fill_from_augmented_normalized_batch_(
  568. batch_norm)
  569. return batch_unnorm
  570. if batch_norm is not None:
  571. batch_norm = batch_norm.fill_from_batch_in_augmentation_(
  572. batch_inaug)
  573. return batch_norm
  574. return batch_inaug
  575. def _augment_batch_(self, batch, random_state, parents, hooks):
  576. """Augment a single batch in-place.
  577. This is the internal version of :func:`Augmenter.augment_batch_`.
  578. It is called from :func:`Augmenter.augment_batch_` and should usually
  579. not be called directly.
  580. This method may transform the batches in-place.
  581. This method does not have to care about determinism or the
  582. Augmenter instance's ``random_state`` variable. The parameter
  583. ``random_state`` takes care of both of these.
  584. Added in 0.4.0.
  585. Parameters
  586. ----------
  587. batch : imgaug.augmentables.batches._BatchInAugmentation
  588. The normalized batch to augment. May be changed in-place.
  589. random_state : imgaug.random.RNG
  590. The random state to use for all sampling tasks during the
  591. augmentation.
  592. parents : list of imgaug.augmenters.meta.Augmenter
  593. See :func:`~imgaug.augmenters.meta.Augmenter.augment_batch_`.
  594. hooks : imgaug.imgaug.HooksImages or None
  595. See :func:`~imgaug.augmenters.meta.Augmenter.augment_batch_`.
  596. Returns
  597. ----------
  598. imgaug.augmentables.batches._BatchInAugmentation
  599. The augmented batch.
  600. """
  601. # The code below covers the case of older augmenters that still have
  602. # _augment_images(), _augment_keypoints(), ... methods that augment
  603. # each input type on its own (including re-sampling from random
  604. # variables). The code block can be safely overwritten by a method
  605. # augmenting a whole batch of data in one step.
  606. columns = batch.columns
  607. multiple_columns = len(columns) > 1
  608. # For multi-column data (e.g. images + BBs) we need deterministic mode
  609. # within this batch, otherwise the datatypes within this batch would
  610. # get different samples.
  611. deterministic = self.deterministic or multiple_columns
  612. # set attribute batch.T_aug with result of self.augment_T() for each
  613. # batch.T_unaug (that had any content)
  614. for column in columns:
  615. with _maybe_deterministic_ctx(random_state, deterministic):
  616. value = getattr(self, "_augment_" + column.name)(
  617. column.value, random_state=random_state,
  618. parents=parents, hooks=hooks)
  619. setattr(batch, column.attr_name, value)
  620. # If the augmenter was alread in deterministic mode, we can expect
  621. # that to_deterministic() was called, which advances the RNG. But
  622. # if it wasn't and we had to auto-switch for the batch, there was not
  623. # advancement yet.
  624. if multiple_columns and not self.deterministic:
  625. random_state.advance_()
  626. return batch
  627. def augment_image(self, image, hooks=None):
  628. """Augment a single image.
  629. Parameters
  630. ----------
  631. image : (H,W,C) ndarray or (H,W) ndarray
  632. The image to augment.
  633. Channel-axis is optional, but expected to be the last axis if
  634. present. In most cases, this array should be of dtype ``uint8``,
  635. which is supported by all augmenters. Support for other dtypes
  636. varies by augmenter -- see the respective augmenter-specific
  637. documentation for more details.
  638. hooks : None or imgaug.HooksImages, optional
  639. HooksImages object to dynamically interfere with the augmentation
  640. process.
  641. Returns
  642. -------
  643. ndarray
  644. The corresponding augmented image.
  645. """
  646. assert ia.is_np_array(image), (
  647. "Expected to get a single numpy array of shape (H,W) or (H,W,C) "
  648. "for `image`. Got instead type %d. Use `augment_images(images)` "
  649. "to augment a list of multiple images." % (
  650. type(image).__name__),)
  651. assert image.ndim in [2, 3], (
  652. "Expected image to have shape (height, width, [channels]), "
  653. "got shape %s." % (image.shape,))
  654. iabase._warn_on_suspicious_single_image_shape(image)
  655. return self.augment_images([image], hooks=hooks)[0]
  656. def augment_images(self, images, parents=None, hooks=None):
  657. """Augment a batch of images.
  658. Parameters
  659. ----------
  660. images : (N,H,W,C) ndarray or (N,H,W) ndarray or list of (H,W,C) ndarray or list of (H,W) ndarray
  661. Images to augment.
  662. The input can be a list of numpy arrays or a single array. Each
  663. array is expected to have shape ``(H, W, C)`` or ``(H, W)``,
  664. where ``H`` is the height, ``W`` is the width and ``C`` are the
  665. channels. The number of channels may differ between images.
  666. If a list is provided, the height, width and channels may differ
  667. between images within the provided batch.
  668. In most cases, the image array(s) should be of dtype ``uint8``,
  669. which is supported by all augmenters. Support for other dtypes
  670. varies by augmenter -- see the respective augmenter-specific
  671. documentation for more details.
  672. parents : None or list of imgaug.augmenters.Augmenter, optional
  673. Parent augmenters that have previously been called before the
  674. call to this function. Usually you can leave this parameter as
  675. ``None``. It is set automatically for child augmenters.
  676. hooks : None or imgaug.imgaug.HooksImages, optional
  677. :class:`~imgaug.imgaug.HooksImages` object to dynamically
  678. interfere with the augmentation process.
  679. Returns
  680. -------
  681. ndarray or list
  682. Corresponding augmented images.
  683. If the input was an ``ndarray``, the output is also an ``ndarray``,
  684. unless the used augmentations have led to different output image
  685. sizes (as can happen in e.g. cropping).
  686. Examples
  687. --------
  688. >>> import imgaug.augmenters as iaa
  689. >>> import numpy as np
  690. >>> aug = iaa.GaussianBlur((0.0, 3.0))
  691. >>> # create empty example images
  692. >>> images = np.zeros((2, 64, 64, 3), dtype=np.uint8)
  693. >>> images_aug = aug.augment_images(images)
  694. Create ``2`` empty (i.e. black) example numpy images and apply
  695. gaussian blurring to them.
  696. """
  697. iabase._warn_on_suspicious_multi_image_shapes(images)
  698. return self.augment_batch_(
  699. UnnormalizedBatch(images=images),
  700. parents=parents,
  701. hooks=hooks
  702. ).images_aug
  703. def _augment_images(self, images, random_state, parents, hooks):
  704. """Augment a batch of images in-place.
  705. This is the internal version of :func:`Augmenter.augment_images`.
  706. It is called from :func:`Augmenter.augment_images` and should usually
  707. not be called directly.
  708. It has to be implemented by every augmenter.
  709. This method may transform the images in-place.
  710. This method does not have to care about determinism or the
  711. Augmenter instance's ``random_state`` variable. The parameter
  712. ``random_state`` takes care of both of these.
  713. .. note::
  714. This method exists mostly for legacy-support.
  715. Overwriting :func:`~imgaug.augmenters.meta.Augmenter._augment_batch`
  716. is now the preferred way of implementing custom augmentation
  717. routines.
  718. Parameters
  719. ----------
  720. images : (N,H,W,C) ndarray or list of (H,W,C) ndarray
  721. Images to augment.
  722. They may be changed in-place.
  723. Either a list of ``(H, W, C)`` arrays or a single ``(N, H, W, C)``
  724. array, where ``N`` is the number of images, ``H`` is the height of
  725. images, ``W`` is the width of images and ``C`` is the number of
  726. channels of images. In the case of a list as input, ``H``, ``W``
  727. and ``C`` may change per image.
  728. random_state : imgaug.random.RNG
  729. The random state to use for all sampling tasks during the
  730. augmentation.
  731. parents : list of imgaug.augmenters.meta.Augmenter
  732. See :func:`~imgaug.augmenters.meta.Augmenter.augment_images`.
  733. hooks : imgaug.imgaug.HooksImages or None
  734. See :func:`~imgaug.augmenters.meta.Augmenter.augment_images`.
  735. Returns
  736. ----------
  737. (N,H,W,C) ndarray or list of (H,W,C) ndarray
  738. The augmented images.
  739. """
  740. return images
  741. def augment_heatmaps(self, heatmaps, parents=None, hooks=None):
  742. """Augment a batch of heatmaps.
  743. Parameters
  744. ----------
  745. heatmaps : imgaug.augmentables.heatmaps.HeatmapsOnImage or list of imgaug.augmentables.heatmaps.HeatmapsOnImage
  746. Heatmap(s) to augment. Either a single heatmap or a list of
  747. heatmaps.
  748. parents : None or list of imgaug.augmenters.meta.Augmenter, optional
  749. Parent augmenters that have previously been called before the
  750. call to this function. Usually you can leave this parameter as
  751. ``None``.
  752. It is set automatically for child augmenters.
  753. hooks : None or imaug.imgaug.HooksHeatmaps, optional
  754. :class:`~imgaug.imgaug.HooksHeatmaps` object to dynamically
  755. interfere with the augmentation process.
  756. Returns
  757. -------
  758. imgaug.augmentables.heatmaps.HeatmapsOnImage or list of imgaug.augmentables.heatmaps.HeatmapsOnImage
  759. Corresponding augmented heatmap(s).
  760. """
  761. return self.augment_batch_(
  762. UnnormalizedBatch(heatmaps=heatmaps), parents=parents, hooks=hooks
  763. ).heatmaps_aug
  764. def _augment_heatmaps(self, heatmaps, random_state, parents, hooks):
  765. """Augment a batch of heatmaps in-place.
  766. This is the internal version of :func:`Augmenter.augment_heatmaps`.
  767. It is called from :func:`Augmenter.augment_heatmaps` and should
  768. usually not be called directly.
  769. This method may augment heatmaps in-place.
  770. This method does not have to care about determinism or the
  771. Augmenter instance's ``random_state`` variable. The parameter
  772. ``random_state`` takes care of both of these.
  773. .. note::
  774. This method exists mostly for legacy-support.
  775. Overwriting :func:`~imgaug.augmenters.meta.Augmenter._augment_batch`
  776. is now the preferred way of implementing custom augmentation
  777. routines.
  778. Parameters
  779. ----------
  780. heatmaps : list of imgaug.augmentables.heatmaps.HeatmapsOnImage
  781. Heatmaps to augment. They may be changed in-place.
  782. parents : list of imgaug.augmenters.meta.Augmenter
  783. See :func:`~imgaug.augmenters.meta.Augmenter.augment_heatmaps`.
  784. hooks : imgaug.imgaug.HooksHeatmaps or None
  785. See :func:`~imgaug.augmenters.meta.Augmenter.augment_heatmaps`.
  786. Returns
  787. ----------
  788. images : list of imgaug.augmentables.heatmaps.HeatmapsOnImage
  789. The augmented heatmaps.
  790. """
  791. return heatmaps
  792. def augment_segmentation_maps(self, segmaps, parents=None, hooks=None):
  793. """Augment a batch of segmentation maps.
  794. Parameters
  795. ----------
  796. segmaps : imgaug.augmentables.segmaps.SegmentationMapsOnImage or list of imgaug.augmentables.segmaps.SegmentationMapsOnImage
  797. Segmentation map(s) to augment. Either a single segmentation map
  798. or a list of segmentation maps.
  799. parents : None or list of imgaug.augmenters.meta.Augmenter, optional
  800. Parent augmenters that have previously been called before the
  801. call to this function. Usually you can leave this parameter as
  802. ``None``. It is set automatically for child augmenters.
  803. hooks : None or imgaug.HooksHeatmaps, optional
  804. :class:`~imgaug.imgaug.HooksHeatmaps` object to dynamically
  805. interfere with the augmentation process.
  806. Returns
  807. -------
  808. imgaug.augmentables.segmaps.SegmentationMapsOnImage or list of imgaug.augmentables.segmaps.SegmentationMapsOnImage
  809. Corresponding augmented segmentation map(s).
  810. """
  811. return self.augment_batch_(
  812. UnnormalizedBatch(segmentation_maps=segmaps),
  813. parents=parents,
  814. hooks=hooks
  815. ).segmentation_maps_aug
  816. def _augment_segmentation_maps(self, segmaps, random_state, parents, hooks):
  817. """Augment a batch of segmentation in-place.
  818. This is the internal version of
  819. :func:`Augmenter.augment_segmentation_maps`.
  820. It is called from :func:`Augmenter.augment_segmentation_maps` and
  821. should usually not be called directly.
  822. This method may augment segmentation maps in-place.
  823. This method does not have to care about determinism or the
  824. Augmenter instance's ``random_state`` variable. The parameter
  825. ``random_state`` takes care of both of these.
  826. .. note::
  827. This method exists mostly for legacy-support.
  828. Overwriting :func:`~imgaug.augmenters.meta.Augmenter._augment_batch`
  829. is now the preferred way of implementing custom augmentation
  830. routines.
  831. Parameters
  832. ----------
  833. segmaps : list of imgaug.augmentables.segmaps.SegmentationMapsOnImage
  834. Segmentation maps to augment. They may be changed in-place.
  835. parents : list of imgaug.augmenters.meta.Augmenter
  836. See
  837. :func:`~imgaug.augmenters.meta.Augmenter.augment_segmentation_maps`.
  838. hooks : imgaug.imgaug.HooksHeatmaps or None
  839. See
  840. :func:`~imgaug.augmenters.meta.Augmenter.augment_segmentation_maps`.
  841. Returns
  842. ----------
  843. images : list of imgaug.augmentables.segmaps.SegmentationMapsOnImage
  844. The augmented segmentation maps.
  845. """
  846. return segmaps
  847. def augment_keypoints(self, keypoints_on_images, parents=None, hooks=None):
  848. """Augment a batch of keypoints/landmarks.
  849. This is the corresponding function to :func:`Augmenter.augment_images`,
  850. just for keypoints/landmarks (i.e. points on images).
  851. Usually you will want to call :func:`Augmenter.augment_images` with
  852. a list of images, e.g. ``augment_images([A, B, C])`` and then
  853. ``augment_keypoints()`` with the corresponding list of keypoints on
  854. these images, e.g. ``augment_keypoints([Ak, Bk, Ck])``, where ``Ak``
  855. are the keypoints on image ``A``.
  856. Make sure to first convert the augmenter(s) to deterministic states
  857. before augmenting images and their corresponding keypoints,
  858. e.g. by
  859. >>> import imgaug.augmenters as iaa
  860. >>> from imgaug.augmentables.kps import Keypoint
  861. >>> from imgaug.augmentables.kps import KeypointsOnImage
  862. >>> A = B = C = np.zeros((10, 10), dtype=np.uint8)
  863. >>> Ak = Bk = Ck = KeypointsOnImage([Keypoint(2, 2)], (10, 10))
  864. >>> seq = iaa.Fliplr(0.5)
  865. >>> seq_det = seq.to_deterministic()
  866. >>> imgs_aug = seq_det.augment_images([A, B, C])
  867. >>> kps_aug = seq_det.augment_keypoints([Ak, Bk, Ck])
  868. Otherwise, different random values will be sampled for the image
  869. and keypoint augmentations, resulting in different augmentations (e.g.
  870. images might be rotated by ``30deg`` and keypoints by ``-10deg``).
  871. Also make sure to call :func:`Augmenter.to_deterministic` again for
  872. each new batch, otherwise you would augment all batches in the same
  873. way.
  874. Note that there is also :func:`Augmenter.augment`, which automatically
  875. handles the random state alignment.
  876. Parameters
  877. ----------
  878. keypoints_on_images : imgaug.augmentables.kps.KeypointsOnImage or list of imgaug.augmentables.kps.KeypointsOnImage
  879. The keypoints/landmarks to augment.
  880. Either a single instance of
  881. :class:`~imgaug.augmentables.kps.KeypointsOnImage` or a list of
  882. such instances. Each instance must contain the keypoints of a
  883. single image.
  884. parents : None or list of imgaug.augmenters.meta.Augmenter, optional
  885. Parent augmenters that have previously been called before the
  886. call to this function. Usually you can leave this parameter as
  887. ``None``. It is set automatically for child augmenters.
  888. hooks : None or imgaug.imgaug.HooksKeypoints, optional
  889. :class:`~imgaug.imgaug.HooksKeypoints` object to dynamically
  890. interfere with the augmentation process.
  891. Returns
  892. -------
  893. imgaug.augmentables.kps.KeypointsOnImage or list of imgaug.augmentables.kps.KeypointsOnImage
  894. Augmented keypoints.
  895. """
  896. return self.augment_batch_(
  897. UnnormalizedBatch(keypoints=keypoints_on_images),
  898. parents=parents,
  899. hooks=hooks
  900. ).keypoints_aug
  901. def _augment_keypoints(self, keypoints_on_images, random_state, parents,
  902. hooks):
  903. """Augment a batch of keypoints in-place.
  904. This is the internal version of :func:`Augmenter.augment_keypoints`.
  905. It is called from :func:`Augmenter.augment_keypoints` and should
  906. usually not be called directly.
  907. This method may transform the keypoints in-place.
  908. This method does not have to care about determinism or the
  909. Augmenter instance's ``random_state`` variable. The parameter
  910. ``random_state`` takes care of both of these.
  911. .. note::
  912. This method exists mostly for legacy-support.
  913. Overwriting :func:`~imgaug.augmenters.meta.Augmenter._augment_batch`
  914. is now the preferred way of implementing custom augmentation
  915. routines.
  916. Parameters
  917. ----------
  918. keypoints_on_images : list of imgaug.augmentables.kps.KeypointsOnImage
  919. Keypoints to augment. They may be changed in-place.
  920. random_state : imgaug.random.RNG
  921. The random state to use for all sampling tasks during the augmentation.
  922. parents : list of imgaug.augmenters.meta.Augmenter
  923. See :func:`~imgaug.augmenters.meta.Augmenter.augment_keypoints`.
  924. hooks : imgaug.imgaug.HooksKeypoints or None
  925. See :func:`~imgaug.augmenters.meta.Augmenter.augment_keypoints`.
  926. Returns
  927. ----------
  928. list of imgaug.augmentables.kps.KeypointsOnImage
  929. The augmented keypoints.
  930. """
  931. return keypoints_on_images
  932. def augment_bounding_boxes(self, bounding_boxes_on_images, parents=None,
  933. hooks=None):
  934. """Augment a batch of bounding boxes.
  935. This is the corresponding function to
  936. :func:`Augmenter.augment_images`, just for bounding boxes.
  937. Usually you will want to call :func:`Augmenter.augment_images` with
  938. a list of images, e.g. ``augment_images([A, B, C])`` and then
  939. ``augment_bounding_boxes()`` with the corresponding list of bounding
  940. boxes on these images, e.g.
  941. ``augment_bounding_boxes([Abb, Bbb, Cbb])``, where ``Abb`` are the
  942. bounding boxes on image ``A``.
  943. Make sure to first convert the augmenter(s) to deterministic states
  944. before augmenting images and their corresponding bounding boxes,
  945. e.g. by
  946. >>> import imgaug.augmenters as iaa
  947. >>> from imgaug.augmentables.bbs import BoundingBox
  948. >>> from imgaug.augmentables.bbs import BoundingBoxesOnImage
  949. >>> A = B = C = np.ones((10, 10), dtype=np.uint8)
  950. >>> Abb = Bbb = Cbb = BoundingBoxesOnImage([
  951. >>> BoundingBox(1, 1, 9, 9)], (10, 10))
  952. >>> seq = iaa.Fliplr(0.5)
  953. >>> seq_det = seq.to_deterministic()
  954. >>> imgs_aug = seq_det.augment_images([A, B, C])
  955. >>> bbs_aug = seq_det.augment_bounding_boxes([Abb, Bbb, Cbb])
  956. Otherwise, different random values will be sampled for the image
  957. and bounding box augmentations, resulting in different augmentations
  958. (e.g. images might be rotated by ``30deg`` and bounding boxes by
  959. ``-10deg``). Also make sure to call :func:`Augmenter.to_deterministic`
  960. again for each new batch, otherwise you would augment all batches in
  961. the same way.
  962. Note that there is also :func:`Augmenter.augment`, which automatically
  963. handles the random state alignment.
  964. Parameters
  965. ----------
  966. bounding_boxes_on_images : imgaug.augmentables.bbs.BoundingBoxesOnImage or list of imgaug.augmentables.bbs.BoundingBoxesOnImage
  967. The bounding boxes to augment.
  968. Either a single instance of
  969. :class:`~imgaug.augmentables.bbs.BoundingBoxesOnImage` or a list of
  970. such instances, with each one of them containing the bounding
  971. boxes of a single image.
  972. parents : None or list of imgaug.augmenters.meta.Augmenter, optional
  973. Parent augmenters that have previously been called before the
  974. call to this function. Usually you can leave this parameter as
  975. ``None``. It is set automatically for child augmenters.
  976. hooks : None or imgaug.imgaug.HooksKeypoints, optional
  977. :class:`~imgaug.imgaug.HooksKeypoints` object to dynamically
  978. interfere with the augmentation process.
  979. Returns
  980. -------
  981. imgaug.augmentables.bbs.BoundingBoxesOnImage or list of imgaug.augmentables.bbs.BoundingBoxesOnImage
  982. Augmented bounding boxes.
  983. """
  984. return self.augment_batch_(
  985. UnnormalizedBatch(bounding_boxes=bounding_boxes_on_images),
  986. parents=parents,
  987. hooks=hooks
  988. ).bounding_boxes_aug
  989. def augment_polygons(self, polygons_on_images, parents=None, hooks=None):
  990. """Augment a batch of polygons.
  991. This is the corresponding function to :func:`Augmenter.augment_images`,
  992. just for polygons.
  993. Usually you will want to call :func:`Augmenter.augment_images`` with
  994. a list of images, e.g. ``augment_images([A, B, C])`` and then
  995. ``augment_polygons()`` with the corresponding list of polygons on these
  996. images, e.g. ``augment_polygons([A_poly, B_poly, C_poly])``, where
  997. ``A_poly`` are the polygons on image ``A``.
  998. Make sure to first convert the augmenter(s) to deterministic states
  999. before augmenting images and their corresponding polygons,
  1000. e.g. by
  1001. >>> import imgaug.augmenters as iaa
  1002. >>> from imgaug.augmentables.polys import Polygon, PolygonsOnImage
  1003. >>> A = B = C = np.ones((10, 10), dtype=np.uint8)
  1004. >>> Apoly = Bpoly = Cpoly = PolygonsOnImage(
  1005. >>> [Polygon([(0, 0), (1, 0), (1, 1), (0, 1)])],
  1006. >>> shape=(10, 10))
  1007. >>> seq = iaa.Fliplr(0.5)
  1008. >>> seq_det = seq.to_deterministic()
  1009. >>> imgs_aug = seq_det.augment_images([A, B, C])
  1010. >>> polys_aug = seq_det.augment_polygons([Apoly, Bpoly, Cpoly])
  1011. Otherwise, different random values will be sampled for the image
  1012. and polygon augmentations, resulting in different augmentations
  1013. (e.g. images might be rotated by ``30deg`` and polygons by
  1014. ``-10deg``). Also make sure to call ``to_deterministic()`` again for
  1015. each new batch, otherwise you would augment all batches in the same
  1016. way.
  1017. Note that there is also :func:`Augmenter.augment`, which automatically
  1018. handles the random state alignment.
  1019. Parameters
  1020. ----------
  1021. polygons_on_images : imgaug.augmentables.polys.PolygonsOnImage or list of imgaug.augmentables.polys.PolygonsOnImage
  1022. The polygons to augment.
  1023. Either a single instance of
  1024. :class:`~imgaug.augmentables.polys.PolygonsOnImage` or a list of
  1025. such instances, with each one of them containing the polygons of
  1026. a single image.
  1027. parents : None or list of imgaug.augmenters.meta.Augmenter, optional
  1028. Parent augmenters that have previously been called before the
  1029. call to this function. Usually you can leave this parameter as
  1030. ``None``. It is set automatically for child augmenters.
  1031. hooks : None or imgaug.imgaug.HooksKeypoints, optional
  1032. :class:`~imgaug.imgaug.HooksKeypoints` object to dynamically
  1033. interfere with the augmentation process.
  1034. Returns
  1035. -------
  1036. imgaug.augmentables.polys.PolygonsOnImage or list of imgaug.augmentables.polys.PolygonsOnImage
  1037. Augmented polygons.
  1038. """
  1039. return self.augment_batch_(
  1040. UnnormalizedBatch(polygons=polygons_on_images),
  1041. parents=parents,
  1042. hooks=hooks
  1043. ).polygons_aug
  1044. def augment_line_strings(self, line_strings_on_images, parents=None,
  1045. hooks=None):
  1046. """Augment a batch of line strings.
  1047. This is the corresponding function to
  1048. :func:`Augmenter.augment_images``, just for line strings.
  1049. Usually you will want to call :func:`Augmenter.augment_images` with
  1050. a list of images, e.g. ``augment_images([A, B, C])`` and then
  1051. ``augment_line_strings()`` with the corresponding list of line
  1052. strings on these images, e.g.
  1053. ``augment_line_strings([A_line, B_line, C_line])``, where ``A_line``
  1054. are the line strings on image ``A``.
  1055. Make sure to first convert the augmenter(s) to deterministic states
  1056. before augmenting images and their corresponding line strings,
  1057. e.g. by
  1058. >>> import imgaug.augmenters as iaa
  1059. >>> from imgaug.augmentables.lines import LineString
  1060. >>> from imgaug.augmentables.lines import LineStringsOnImage
  1061. >>> A = B = C = np.ones((10, 10), dtype=np.uint8)
  1062. >>> A_line = B_line = C_line = LineStringsOnImage(
  1063. >>> [LineString([(0, 0), (1, 0), (1, 1), (0, 1)])],
  1064. >>> shape=(10, 10))
  1065. >>> seq = iaa.Fliplr(0.5)
  1066. >>> seq_det = seq.to_deterministic()
  1067. >>> imgs_aug = seq_det.augment_images([A, B, C])
  1068. >>> lines_aug = seq_det.augment_line_strings([A_line, B_line, C_line])
  1069. Otherwise, different random values will be sampled for the image
  1070. and line string augmentations, resulting in different augmentations
  1071. (e.g. images might be rotated by ``30deg`` and line strings by
  1072. ``-10deg``). Also make sure to call ``to_deterministic()`` again for
  1073. each new batch, otherwise you would augment all batches in the same
  1074. way.
  1075. Note that there is also :func:`Augmenter.augment`, which automatically
  1076. handles the random state alignment.
  1077. Parameters
  1078. ----------
  1079. line_strings_on_images : imgaug.augmentables.lines.LineStringsOnImage or list of imgaug.augmentables.lines.LineStringsOnImage
  1080. The line strings to augment.
  1081. Either a single instance of
  1082. :class:`~imgaug.augmentables.lines.LineStringsOnImage` or a list of
  1083. such instances, with each one of them containing the line strings
  1084. of a single image.
  1085. parents : None or list of imgaug.augmenters.meta.Augmenter, optional
  1086. Parent augmenters that have previously been called before the
  1087. call to this function. Usually you can leave this parameter as None.
  1088. It is set automatically for child augmenters.
  1089. hooks : None or imgaug.imgaug.HooksKeypoints, optional
  1090. :class:`~imgaug.imgaug.HooksKeypoints` object to dynamically
  1091. interfere with the augmentation process.
  1092. Returns
  1093. -------
  1094. imgaug.augmentables.lines.LineStringsOnImage or list of imgaug.augmentables.lines.LineStringsOnImage
  1095. Augmented line strings.
  1096. """
  1097. return self.augment_batch_(
  1098. UnnormalizedBatch(line_strings=line_strings_on_images),
  1099. parents=parents,
  1100. hooks=hooks
  1101. ).line_strings_aug
  1102. def _augment_bounding_boxes(self, bounding_boxes_on_images, random_state,
  1103. parents, hooks):
  1104. """Augment a batch of bounding boxes on images in-place.
  1105. This is the internal version of
  1106. :func:`Augmenter.augment_bounding_boxes`.
  1107. It is called from :func:`Augmenter.augment_bounding_boxes` and should
  1108. usually not be called directly.
  1109. This method may transform the bounding boxes in-place.
  1110. This method does not have to care about determinism or the
  1111. Augmenter instance's ``random_state`` variable. The parameter
  1112. ``random_state`` takes care of both of these.
  1113. .. note::
  1114. This method exists mostly for legacy-support.
  1115. Overwriting :func:`~imgaug.augmenters.meta.Augmenter._augment_batch`
  1116. is now the preferred way of implementing custom augmentation
  1117. routines.
  1118. Added in 0.4.0.
  1119. Parameters
  1120. ----------
  1121. bounding_boxes_on_images : list of imgaug.augmentables.bbs.BoundingBoxesOnImage
  1122. Polygons to augment. They may be changed in-place.
  1123. random_state : imgaug.random.RNG
  1124. The random state to use for all sampling tasks during the
  1125. augmentation.
  1126. parents : list of imgaug.augmenters.meta.Augmenter
  1127. See :func:`~imgaug.augmenters.meta.Augmenter.augment_bounding_boxes`.
  1128. hooks : imgaug.imgaug.HooksKeypoints or None
  1129. See :func:`~imgaug.augmenters.meta.Augmenter.augment_bounding_boxes`.
  1130. Returns
  1131. -------
  1132. list of imgaug.augmentables.bbs.BoundingBoxesOnImage
  1133. The augmented bounding boxes.
  1134. """
  1135. return bounding_boxes_on_images
  1136. def _augment_polygons(self, polygons_on_images, random_state, parents,
  1137. hooks):
  1138. """Augment a batch of polygons on images in-place.
  1139. This is the internal version of :func:`Augmenter.augment_polygons`.
  1140. It is called from :func:`Augmenter.augment_polygons` and should
  1141. usually not be called directly.
  1142. This method may transform the polygons in-place.
  1143. This method does not have to care about determinism or the
  1144. Augmenter instance's ``random_state`` variable. The parameter
  1145. ``random_state`` takes care of both of these.
  1146. .. note::
  1147. This method exists mostly for legacy-support.
  1148. Overwriting :func:`~imgaug.augmenters.meta.Augmenter._augment_batch`
  1149. is now the preferred way of implementing custom augmentation
  1150. routines.
  1151. Parameters
  1152. ----------
  1153. polygons_on_images : list of imgaug.augmentables.polys.PolygonsOnImage
  1154. Polygons to augment. They may be changed in-place.
  1155. random_state : imgaug.random.RNG
  1156. The random state to use for all sampling tasks during the
  1157. augmentation.
  1158. parents : list of imgaug.augmenters.meta.Augmenter
  1159. See :func:`~imgaug.augmenters.meta.Augmenter.augment_polygons`.
  1160. hooks : imgaug.imgaug.HooksKeypoints or None
  1161. See :func:`~imgaug.augmenters.meta.Augmenter.augment_polygons`.
  1162. Returns
  1163. -------
  1164. list of imgaug.augmentables.polys.PolygonsOnImage
  1165. The augmented polygons.
  1166. """
  1167. return polygons_on_images
  1168. def _augment_line_strings(self, line_strings_on_images, random_state,
  1169. parents, hooks):
  1170. """Augment a batch of line strings in-place.
  1171. This is the internal version of
  1172. :func:`Augmenter.augment_line_strings`.
  1173. It is called from :func:`Augmenter.augment_line_strings` and should
  1174. usually not be called directly.
  1175. This method may transform the line strings in-place.
  1176. This method does not have to care about determinism or the
  1177. Augmenter instance's ``random_state`` variable. The parameter
  1178. ``random_state`` takes care of both of these.
  1179. .. note::
  1180. This method exists mostly for legacy-support.
  1181. Overwriting :func:`~imgaug.augmenters.meta.Augmenter._augment_batch`
  1182. is now the preferred way of implementing custom augmentation
  1183. routines.
  1184. Parameters
  1185. ----------
  1186. line_strings_on_images : list of imgaug.augmentables.lines.LineStringsOnImage
  1187. Line strings to augment. They may be changed in-place.
  1188. random_state : imgaug.random.RNG
  1189. The random state to use for all sampling tasks during the
  1190. augmentation.
  1191. parents : list of imgaug.augmenters.meta.Augmenter
  1192. See :func:`~imgaug.augmenters.meta.Augmenter.augment_line_strings`.
  1193. hooks : imgaug.imgaug.HooksKeypoints or None
  1194. See :func:`~imgaug.augmenters.meta.Augmenter.augment_line_strings`.
  1195. Returns
  1196. -------
  1197. list of imgaug.augmentables.lines.LineStringsOnImage
  1198. The augmented line strings.
  1199. """
  1200. return line_strings_on_images
  1201. def _augment_bounding_boxes_as_keypoints(self, bounding_boxes_on_images,
  1202. random_state, parents, hooks):
  1203. """
  1204. Augment BBs by applying keypoint augmentation to their corners.
  1205. Added in 0.4.0.
  1206. Parameters
  1207. ----------
  1208. bounding_boxes_on_images : list of imgaug.augmentables.bbs.BoundingBoxesOnImages or imgaug.augmentables.bbs.BoundingBoxesOnImages
  1209. Bounding boxes to augment. They may be changed in-place.
  1210. random_state : imgaug.random.RNG
  1211. The random state to use for all sampling tasks during the
  1212. augmentation.
  1213. parents : list of imgaug.augmenters.meta.Augmenter
  1214. See :func:`~imgaug.augmenters.meta.Augmenter.augment_polygons`.
  1215. hooks : imgaug.imgaug.HooksKeypoints or None
  1216. See :func:`~imgaug.augmenters.meta.Augmenter.augment_polygons`.
  1217. Returns
  1218. -------
  1219. list of imgaug.augmentables.bbs.BoundingBoxesOnImage or imgaug.augmentables.bbs.BoundingBoxesOnImage
  1220. The augmented bounding boxes.
  1221. """
  1222. return self._augment_cbaois_as_keypoints(bounding_boxes_on_images,
  1223. random_state=random_state,
  1224. parents=parents,
  1225. hooks=hooks)
  1226. def _augment_polygons_as_keypoints(self, polygons_on_images, random_state,
  1227. parents, hooks, recoverer=None):
  1228. """
  1229. Augment polygons by applying keypoint augmentation to their vertices.
  1230. .. warning::
  1231. This method calls
  1232. :func:`~imgaug.augmenters.meta.Augmenter._augment_keypoints` and
  1233. expects it to do keypoint augmentation. The default for that
  1234. method is to do nothing. It must therefore be overwritten,
  1235. otherwise the polygon augmentation will also do nothing.
  1236. Parameters
  1237. ----------
  1238. polygons_on_images : list of imgaug.augmentables.polys.PolygonsOnImage or imgaug.augmentables.polys.PolygonsOnImage
  1239. Polygons to augment. They may be changed in-place.
  1240. random_state : imgaug.random.RNG
  1241. The random state to use for all sampling tasks during the
  1242. augmentation.
  1243. parents : list of imgaug.augmenters.meta.Augmenter
  1244. See :func:`~imgaug.augmenters.meta.Augmenter.augment_polygons`.
  1245. hooks : imgaug.imgaug.HooksKeypoints or None
  1246. See :func:`~imgaug.augmenters.meta.Augmenter.augment_polygons`.
  1247. recoverer : None or imgaug.augmentables.polys._ConcavePolygonRecoverer
  1248. An instance used to repair invalid polygons after augmentation.
  1249. Must offer the method
  1250. ``recover_from(new_exterior, old_polygon, random_state=0)``.
  1251. If ``None`` then invalid polygons are not repaired.
  1252. Returns
  1253. -------
  1254. list of imgaug.augmentables.polys.PolygonsOnImage or imgaug.augmentables.polys.PolygonsOnImage
  1255. The augmented polygons.
  1256. """
  1257. func = functools.partial(self._augment_keypoints,
  1258. random_state=random_state,
  1259. parents=parents,
  1260. hooks=hooks)
  1261. return self._apply_to_polygons_as_keypoints(polygons_on_images, func,
  1262. recoverer, random_state)
  1263. def _augment_line_strings_as_keypoints(self, line_strings_on_images,
  1264. random_state, parents, hooks):
  1265. """
  1266. Augment BBs by applying keypoint augmentation to their corners.
  1267. Parameters
  1268. ----------
  1269. line_strings_on_images : list of imgaug.augmentables.lines.LineStringsOnImages or imgaug.augmentables.lines.LineStringsOnImages
  1270. Line strings to augment. They may be changed in-place.
  1271. random_state : imgaug.random.RNG
  1272. The random state to use for all sampling tasks during the
  1273. augmentation.
  1274. parents : list of imgaug.augmenters.meta.Augmenter
  1275. See :func:`~imgaug.augmenters.meta.Augmenter.augment_polygons`.
  1276. hooks : imgaug.imgaug.HooksKeypoints or None
  1277. See :func:`~imgaug.augmenters.meta.Augmenter.augment_polygons`.
  1278. Returns
  1279. -------
  1280. list of imgaug.augmentables.lines.LineStringsOnImages or imgaug.augmentables.lines.LineStringsOnImages
  1281. The augmented line strings.
  1282. """
  1283. return self._augment_cbaois_as_keypoints(line_strings_on_images,
  1284. random_state=random_state,
  1285. parents=parents,
  1286. hooks=hooks)
  1287. def _augment_cbaois_as_keypoints(
  1288. self, cbaois, random_state, parents, hooks):
  1289. """
  1290. Augment bounding boxes by applying KP augmentation to their corners.
  1291. Added in 0.4.0.
  1292. Parameters
  1293. ----------
  1294. cbaois : list of imgaug.augmentables.bbs.BoundingBoxesOnImage or list of imgaug.augmentables.polys.PolygonsOnImage or list of imgaug.augmentables.lines.LineStringsOnImage or imgaug.augmentables.bbs.BoundingBoxesOnImage or imgaug.augmentables.polys.PolygonsOnImage or imgaug.augmentables.lines.LineStringsOnImage
  1295. Coordinate-based augmentables to augment. They may be changed
  1296. in-place.
  1297. random_state : imgaug.random.RNG
  1298. The random state to use for all sampling tasks during the
  1299. augmentation.
  1300. parents : list of imgaug.augmenters.meta.Augmenter
  1301. See :func:`~imgaug.augmenters.meta.Augmenter.augment_batch`.
  1302. hooks : imgaug.imgaug.HooksKeypoints or None
  1303. See :func:`~imgaug.augmenters.meta.Augmenter.augment_batch`.
  1304. Returns
  1305. -------
  1306. list of imgaug.augmentables.bbs.BoundingBoxesOnImage or list of imgaug.augmentables.polys.PolygonsOnImage or list of imgaug.augmentables.lines.LineStringsOnImage or imgaug.augmentables.bbs.BoundingBoxesOnImage or imgaug.augmentables.polys.PolygonsOnImage or imgaug.augmentables.lines.LineStringsOnImage
  1307. The augmented coordinate-based augmentables.
  1308. """
  1309. func = functools.partial(self._augment_keypoints,
  1310. random_state=random_state,
  1311. parents=parents,
  1312. hooks=hooks)
  1313. return self._apply_to_cbaois_as_keypoints(cbaois, func)
  1314. @classmethod
  1315. def _apply_to_polygons_as_keypoints(cls, polygons_on_images, func,
  1316. recoverer=None, random_state=None):
  1317. """
  1318. Apply a callback to polygons in keypoint-representation.
  1319. Added in 0.4.0.
  1320. Parameters
  1321. ----------
  1322. polygons_on_images : list of imgaug.augmentables.polys.PolygonsOnImage or imgaug.augmentables.polys.PolygonsOnImage
  1323. Polygons to augment. They may be changed in-place.
  1324. func : callable
  1325. The function to apply. Receives a list of
  1326. :class:`~imgaug.augmentables.kps.KeypointsOnImage` instances as its
  1327. only parameter.
  1328. recoverer : None or imgaug.augmentables.polys._ConcavePolygonRecoverer
  1329. An instance used to repair invalid polygons after augmentation.
  1330. Must offer the method
  1331. ``recover_from(new_exterior, old_polygon, random_state=0)``.
  1332. If ``None`` then invalid polygons are not repaired.
  1333. random_state : None or imgaug.random.RNG
  1334. The random state to use for the recoverer.
  1335. Returns
  1336. -------
  1337. list of imgaug.augmentables.polys.PolygonsOnImage or imgaug.augmentables.polys.PolygonsOnImage
  1338. The augmented polygons.
  1339. """
  1340. from ..augmentables.polys import recover_psois_
  1341. psois_orig = None
  1342. if recoverer is not None:
  1343. if isinstance(polygons_on_images, list):
  1344. psois_orig = [psoi.deepcopy() for psoi in polygons_on_images]
  1345. else:
  1346. psois_orig = polygons_on_images.deepcopy()
  1347. psois = cls._apply_to_cbaois_as_keypoints(polygons_on_images, func)
  1348. if recoverer is None:
  1349. return psois
  1350. # Its not really necessary to create an RNG copy for the recoverer
  1351. # here, as the augmentation of the polygons is already finished and
  1352. # used the same samples as the image augmentation. The recoverer might
  1353. # advance the RNG state, but the next call to e.g. augment() will then
  1354. # still use the same (advanced) RNG state for images and polygons.
  1355. # We copy here anyways as it seems cleaner.
  1356. random_state_recoverer = (random_state.copy()
  1357. if random_state is not None else None)
  1358. psois = recover_psois_(psois, psois_orig, recoverer,
  1359. random_state_recoverer)
  1360. return psois
  1361. @classmethod
  1362. def _apply_to_cbaois_as_keypoints(cls, cbaois, func):
  1363. """
  1364. Augment bounding boxes by applying KP augmentation to their corners.
  1365. Added in 0.4.0.
  1366. Parameters
  1367. ----------
  1368. cbaois : list of imgaug.augmentables.bbs.BoundingBoxesOnImage or list of imgaug.augmentables.polys.PolygonsOnImage or list of imgaug.augmentables.lines.LineStringsOnImage or imgaug.augmentables.bbs.BoundingBoxesOnImage or imgaug.augmentables.polys.PolygonsOnImage or imgaug.augmentables.lines.LineStringsOnImage
  1369. Coordinate-based augmentables to augment. They may be changed
  1370. in-place.
  1371. func : callable
  1372. The function to apply. Receives a list of
  1373. :class:`~imgaug.augmentables.kps.KeypointsOnImage` instances as its
  1374. only parameter.
  1375. Returns
  1376. -------
  1377. list of imgaug.augmentables.bbs.BoundingBoxesOnImage or list of imgaug.augmentables.polys.PolygonsOnImage or list of imgaug.augmentables.lines.LineStringsOnImage or imgaug.augmentables.bbs.BoundingBoxesOnImage or imgaug.augmentables.polys.PolygonsOnImage or imgaug.augmentables.lines.LineStringsOnImage
  1378. The augmented coordinate-based augmentables.
  1379. """
  1380. from ..augmentables.utils import (convert_cbaois_to_kpsois,
  1381. invert_convert_cbaois_to_kpsois_)
  1382. kpsois = convert_cbaois_to_kpsois(cbaois)
  1383. kpsois_aug = func(kpsois)
  1384. return invert_convert_cbaois_to_kpsois_(cbaois, kpsois_aug)
  1385. def augment(self, return_batch=False, hooks=None, **kwargs):
  1386. """Augment a batch.
  1387. This method is a wrapper around
  1388. :class:`~imgaug.augmentables.batches.UnnormalizedBatch` and
  1389. :func:`~imgaug.augmenters.meta.Augmenter.augment_batch`. Hence, it
  1390. supports the same datatypes as
  1391. :class:`~imgaug.augmentables.batches.UnnormalizedBatch`.
  1392. If `return_batch` was set to ``False`` (the default), the method will
  1393. return a tuple of augmentables. It will return the same types of
  1394. augmentables (but in augmented form) as input into the method. This
  1395. behaviour is partly specific to the python version:
  1396. * In **python 3.6+** (if ``return_batch=False``):
  1397. * Any number of augmentables may be provided as input.
  1398. * None of the provided named arguments *has to be* `image` or
  1399. `images` (but of coarse you *may* provide them).
  1400. * The return order matches the order of the named arguments, e.g.
  1401. ``x_aug, y_aug, z_aug = augment(X=x, Y=y, Z=z)``.
  1402. * In **python <3.6** (if ``return_batch=False``):
  1403. * One or two augmentables may be used as input, not more than that.
  1404. * One of the input arguments has to be `image` or `images`.
  1405. * The augmented images are *always* returned first, independent
  1406. of the input argument order, e.g.
  1407. ``a_aug, b_aug = augment(b=b, images=a)``. This also means
  1408. that the output of the function can only be one of the
  1409. following three cases: a batch, list/array of images,
  1410. tuple of images and something (like images + segmentation maps).
  1411. If `return_batch` was set to ``True``, an instance of
  1412. :class:`~imgaug.augmentables.batches.UnnormalizedBatch` will be
  1413. returned. The output is the same for all python version and any
  1414. number or combination of augmentables may be provided.
  1415. So, to keep code downward compatible for python <3.6, use one of the
  1416. following three options:
  1417. * Use ``batch = augment(images=X, ..., return_batch=True)``.
  1418. * Call ``images = augment(images=X)``.
  1419. * Call ``images, other = augment(images=X, <something_else>=Y)``.
  1420. All augmentables must be provided as named arguments.
  1421. E.g. ``augment(<array>)`` will crash, but ``augment(images=<array>)``
  1422. will work.
  1423. Parameters
  1424. ----------
  1425. image : None or (H,W,C) ndarray or (H,W) ndarray, optional
  1426. The image to augment. Only this or `images` can be set, not both.
  1427. If `return_batch` is ``False`` and the python version is below 3.6,
  1428. either this or `images` **must** be provided.
  1429. images : None or (N,H,W,C) ndarray or (N,H,W) ndarray or iterable of (H,W,C) ndarray or iterable of (H,W) ndarray, optional
  1430. The images to augment. Only this or `image` can be set, not both.
  1431. If `return_batch` is ``False`` and the python version is below 3.6,
  1432. either this or `image` **must** be provided.
  1433. heatmaps : None or (N,H,W,C) ndarray or imgaug.augmentables.heatmaps.HeatmapsOnImage or iterable of (H,W,C) ndarray or iterable of imgaug.augmentables.heatmaps.HeatmapsOnImage, optional
  1434. The heatmaps to augment.
  1435. If anything else than
  1436. :class:`~imgaug.augmentables.heatmaps.HeatmapsOnImage`, then the
  1437. number of heatmaps must match the number of images provided via
  1438. parameter `images`. The number is contained either in ``N`` or the
  1439. first iterable's size.
  1440. segmentation_maps : None or (N,H,W) ndarray or imgaug.augmentables.segmaps.SegmentationMapsOnImage or iterable of (H,W) ndarray or iterable of imgaug.augmentables.segmaps.SegmentationMapsOnImage, optional
  1441. The segmentation maps to augment.
  1442. If anything else than
  1443. :class:`~imgaug.augmentables.segmaps.SegmentationMapsOnImage`, then
  1444. the number of segmaps must match the number of images provided via
  1445. parameter `images`. The number is contained either in ``N`` or the
  1446. first iterable's size.
  1447. keypoints : None or list of (N,K,2) ndarray or tuple of number or imgaug.augmentables.kps.Keypoint or iterable of (K,2) ndarray or iterable of tuple of number or iterable of imgaug.augmentables.kps.Keypoint or iterable of imgaug.augmentables.kps.KeypointOnImage or iterable of iterable of tuple of number or iterable of iterable of imgaug.augmentables.kps.Keypoint, optional
  1448. The keypoints to augment.
  1449. If a tuple (or iterable(s) of tuple), then iterpreted as ``(x,y)``
  1450. coordinates and must hence contain two numbers.
  1451. A single tuple represents a single coordinate on one image, an
  1452. iterable of tuples the coordinates on one image and an iterable of
  1453. iterable of tuples the coordinates on several images. Analogous if
  1454. :class:`~imgaug.augmentables.kps.Keypoint` instances are used
  1455. instead of tuples.
  1456. If an ndarray, then ``N`` denotes the number of images and ``K``
  1457. the number of keypoints on each image.
  1458. If anything else than
  1459. :class:`~imgaug.augmentables.kps.KeypointsOnImage` is provided, then
  1460. the number of keypoint groups must match the number of images
  1461. provided via parameter `images`. The number is contained e.g. in
  1462. ``N`` or in case of "iterable of iterable of tuples" in the first
  1463. iterable's size.
  1464. bounding_boxes : None or (N,B,4) ndarray or tuple of number or imgaug.augmentables.bbs.BoundingBox or imgaug.augmentables.bbs.BoundingBoxesOnImage or iterable of (B,4) ndarray or iterable of tuple of number or iterable of imgaug.augmentables.bbs.BoundingBox or iterable of imgaug.augmentables.bbs.BoundingBoxesOnImage or iterable of iterable of tuple of number or iterable of iterable imgaug.augmentables.bbs.BoundingBox, optional
  1465. The bounding boxes to augment.
  1466. This is analogous to the `keypoints` parameter. However, each
  1467. tuple -- and also the last index in case of arrays -- has size
  1468. ``4``, denoting the bounding box coordinates ``x1``, ``y1``,
  1469. ``x2`` and ``y2``.
  1470. polygons : None or (N,#polys,#points,2) ndarray or imgaug.augmentables.polys.Polygon or imgaug.augmentables.polys.PolygonsOnImage or iterable of (#polys,#points,2) ndarray or iterable of tuple of number or iterable of imgaug.augmentables.kps.Keypoint or iterable of imgaug.augmentables.polys.Polygon or iterable of imgaug.augmentables.polys.PolygonsOnImage or iterable of iterable of (#points,2) ndarray or iterable of iterable of tuple of number or iterable of iterable of imgaug.augmentables.kps.Keypoint or iterable of iterable of imgaug.augmentables.polys.Polygon or iterable of iterable of iterable of tuple of number or iterable of iterable of iterable of tuple of imgaug.augmentables.kps.Keypoint, optional
  1471. The polygons to augment.
  1472. This is similar to the `keypoints` parameter. However, each polygon
  1473. may be made up of several ``(x,y) ``coordinates (three or more are
  1474. required for valid polygons).
  1475. The following datatypes will be interpreted as a single polygon on
  1476. a single image:
  1477. * ``imgaug.augmentables.polys.Polygon``
  1478. * ``iterable of tuple of number``
  1479. * ``iterable of imgaug.augmentables.kps.Keypoint``
  1480. The following datatypes will be interpreted as multiple polygons
  1481. on a single image:
  1482. * ``imgaug.augmentables.polys.PolygonsOnImage``
  1483. * ``iterable of imgaug.augmentables.polys.Polygon``
  1484. * ``iterable of iterable of tuple of number``
  1485. * ``iterable of iterable of imgaug.augmentables.kps.Keypoint``
  1486. * ``iterable of iterable of imgaug.augmentables.polys.Polygon``
  1487. The following datatypes will be interpreted as multiple polygons on
  1488. multiple images:
  1489. * ``(N,#polys,#points,2) ndarray``
  1490. * ``iterable of (#polys,#points,2) ndarray``
  1491. * ``iterable of iterable of (#points,2) ndarray``
  1492. * ``iterable of iterable of iterable of tuple of number``
  1493. * ``iterable of iterable of iterable of tuple of imgaug.augmentables.kps.Keypoint``
  1494. line_strings : None or (N,#lines,#points,2) ndarray or imgaug.augmentables.lines.LineString or imgaug.augmentables.lines.LineStringOnImage or iterable of (#polys,#points,2) ndarray or iterable of tuple of number or iterable of imgaug.augmentables.kps.Keypoint or iterable of imgaug.augmentables.lines.LineString or iterable of imgaug.augmentables.lines.LineStringOnImage or iterable of iterable of (#points,2) ndarray or iterable of iterable of tuple of number or iterable of iterable of imgaug.augmentables.kps.Keypoint or iterable of iterable of imgaug.augmentables.lines.LineString or iterable of iterable of iterable of tuple of number or iterable of iterable of iterable of tuple of imgaug.augmentables.kps.Keypoint, optional
  1495. The line strings to augment.
  1496. See `polygons`, which behaves similarly.
  1497. return_batch : bool, optional
  1498. Whether to return an instance of
  1499. :class:`~imgaug.augmentables.batches.UnnormalizedBatch`. If the
  1500. python version is below 3.6 and more than two augmentables were
  1501. provided (e.g. images, keypoints and polygons), then this must be
  1502. set to ``True``. Otherwise an error will be raised.
  1503. hooks : None or imgaug.imgaug.HooksImages, optional
  1504. Hooks object to dynamically interfere with the augmentation process.
  1505. Returns
  1506. -------
  1507. tuple or imgaug.augmentables.batches.UnnormalizedBatch
  1508. If `return_batch` was set to ``True``, a instance of
  1509. ``UnnormalizedBatch`` will be returned.
  1510. If `return_batch` was set to ``False``, a tuple of augmentables
  1511. will be returned, e.g. ``(augmented images, augmented keypoints)``.
  1512. The datatypes match the input datatypes of the corresponding named
  1513. arguments. In python <3.6, augmented images are always the first
  1514. entry in the returned tuple. In python 3.6+ the order matches the
  1515. order of the named arguments.
  1516. Examples
  1517. --------
  1518. >>> import numpy as np
  1519. >>> import imgaug as ia
  1520. >>> import imgaug.augmenters as iaa
  1521. >>> aug = iaa.Affine(rotate=(-25, 25))
  1522. >>> image = np.zeros((64, 64, 3), dtype=np.uint8)
  1523. >>> keypoints = [(10, 20), (30, 32)] # (x,y) coordinates
  1524. >>> images_aug, keypoints_aug = aug.augment(
  1525. >>> image=image, keypoints=keypoints)
  1526. Create a single image and a set of two keypoints on it, then
  1527. augment both by applying a random rotation between ``-25`` deg and
  1528. ``+25`` deg. The sampled rotation value is automatically aligned
  1529. between image and keypoints. Note that in python <3.6, augmented
  1530. images will always be returned first, independent of the order of
  1531. the named input arguments. So
  1532. ``keypoints_aug, images_aug = aug.augment(keypoints=keypoints,
  1533. image=image)`` would **not** be correct (but in python 3.6+ it would
  1534. be).
  1535. >>> import numpy as np
  1536. >>> import imgaug as ia
  1537. >>> import imgaug.augmenters as iaa
  1538. >>> from imgaug.augmentables.bbs import BoundingBox
  1539. >>> aug = iaa.Affine(rotate=(-25, 25))
  1540. >>> images = [np.zeros((64, 64, 3), dtype=np.uint8),
  1541. >>> np.zeros((32, 32, 3), dtype=np.uint8)]
  1542. >>> keypoints = [[(10, 20), (30, 32)], # KPs on first image
  1543. >>> [(22, 10), (12, 14)]] # KPs on second image
  1544. >>> bbs = [
  1545. >>> [BoundingBox(x1=5, y1=5, x2=50, y2=45)],
  1546. >>> [BoundingBox(x1=4, y1=6, x2=10, y2=15),
  1547. >>> BoundingBox(x1=8, y1=9, x2=16, y2=30)]
  1548. >>> ] # one BB on first image, two BBs on second image
  1549. >>> batch_aug = aug.augment(
  1550. >>> images=images, keypoints=keypoints, bounding_boxes=bbs,
  1551. >>> return_batch=True)
  1552. Create two images of size ``64x64`` and ``32x32``, two sets of
  1553. keypoints (each containing two keypoints) and two sets of bounding
  1554. boxes (the first containing one bounding box, the second two bounding
  1555. boxes). These augmentables are then augmented by applying random
  1556. rotations between ``-25`` deg and ``+25`` deg to them. The rotation
  1557. values are sampled by image and aligned between all augmentables on
  1558. the same image. The method finally returns an instance of
  1559. :class:`~imgaug.augmentables.batches.UnnormalizedBatch` from which the
  1560. augmented data can be retrieved via ``batch_aug.images_aug``,
  1561. ``batch_aug.keypoints_aug``, and ``batch_aug.bounding_boxes_aug``.
  1562. In python 3.6+, `return_batch` can be kept at ``False`` and the
  1563. augmented data can be retrieved as
  1564. ``images_aug, keypoints_aug, bbs_aug = augment(...)``.
  1565. """
  1566. assert ia.is_single_bool(return_batch), (
  1567. "Expected boolean as argument for 'return_batch', got type %s. "
  1568. "Call augment() only with named arguments, e.g. "
  1569. "augment(images=<array>)." % (str(type(return_batch)),))
  1570. expected_keys = ["images", "heatmaps", "segmentation_maps",
  1571. "keypoints", "bounding_boxes", "polygons",
  1572. "line_strings"]
  1573. expected_keys_call = ["image"] + expected_keys
  1574. # at least one augmentable provided?
  1575. assert any([key in kwargs for key in expected_keys_call]), (
  1576. "Expected augment() to be called with one of the following named "
  1577. "arguments: %s. Got none of these." % (
  1578. ", ".join(expected_keys_call),))
  1579. # all keys in kwargs actually known?
  1580. unknown_args = [key for key in kwargs if key not in expected_keys_call]
  1581. assert len(unknown_args) == 0, (
  1582. "Got the following unknown keyword argument(s) in augment(): %s" % (
  1583. ", ".join(unknown_args)
  1584. ))
  1585. # normalize image=... input to images=...
  1586. # this is not done by Batch.to_normalized_batch()
  1587. if "image" in kwargs:
  1588. assert "images" not in kwargs, (
  1589. "You may only provide the argument 'image' OR 'images' to "
  1590. "augment(), not both of them.")
  1591. images = [kwargs["image"]]
  1592. iabase._warn_on_suspicious_single_image_shape(images[0])
  1593. else:
  1594. images = kwargs.get("images", None)
  1595. iabase._warn_on_suspicious_multi_image_shapes(images)
  1596. # Decide whether to return the final tuple in the order of the kwargs
  1597. # keys or the default order based on python version. Only 3.6+ uses
  1598. # an ordered dict implementation for kwargs.
  1599. order = "standard"
  1600. nb_keys = len(list(kwargs.keys()))
  1601. vinfo = sys.version_info
  1602. is_py36_or_newer = vinfo[0] > 3 or (vinfo[0] == 3 and vinfo[1] >= 6)
  1603. if is_py36_or_newer:
  1604. order = "kwargs_keys"
  1605. elif not return_batch and nb_keys > 2:
  1606. raise ValueError(
  1607. "Requested more than two outputs in augment(), but detected "
  1608. "python version is below 3.6. More than two outputs are only "
  1609. "supported for 3.6+ as earlier python versions offer no way "
  1610. "to retrieve the order of the provided named arguments. To "
  1611. "still use more than two outputs, add 'return_batch=True' as "
  1612. "an argument and retrieve the outputs manually from the "
  1613. "returned UnnormalizedBatch instance, e.g. via "
  1614. "'batch.images_aug' to get augmented images."
  1615. )
  1616. elif not return_batch and nb_keys == 2 and images is None:
  1617. raise ValueError(
  1618. "Requested two outputs from augment() that were not 'images', "
  1619. "but detected python version is below 3.6. For security "
  1620. "reasons, only single-output requests or requests with two "
  1621. "outputs of which one is 'images' are allowed in <3.6. "
  1622. "'images' will then always be returned first. If you don't "
  1623. "want this, use 'return_batch=True' mode in augment(), which "
  1624. "returns a single UnnormalizedBatch instance instead and "
  1625. "supports any combination of outputs."
  1626. )
  1627. # augment batch
  1628. batch = UnnormalizedBatch(
  1629. images=images,
  1630. heatmaps=kwargs.get("heatmaps", None),
  1631. segmentation_maps=kwargs.get("segmentation_maps", None),
  1632. keypoints=kwargs.get("keypoints", None),
  1633. bounding_boxes=kwargs.get("bounding_boxes", None),
  1634. polygons=kwargs.get("polygons", None),
  1635. line_strings=kwargs.get("line_strings", None)
  1636. )
  1637. batch_aug = self.augment_batch_(batch, hooks=hooks)
  1638. # return either batch or tuple of augmentables, depending on what
  1639. # was requested by user
  1640. if return_batch:
  1641. return batch_aug
  1642. result = []
  1643. if order == "kwargs_keys":
  1644. for key in kwargs:
  1645. if key == "image":
  1646. attr = getattr(batch_aug, "images_aug")
  1647. result.append(attr[0])
  1648. else:
  1649. result.append(getattr(batch_aug, "%s_aug" % (key,)))
  1650. else:
  1651. for key in expected_keys:
  1652. if key == "images" and "image" in kwargs:
  1653. attr = getattr(batch_aug, "images_aug")
  1654. result.append(attr[0])
  1655. elif key in kwargs:
  1656. result.append(getattr(batch_aug, "%s_aug" % (key,)))
  1657. if len(result) == 1:
  1658. return result[0]
  1659. return tuple(result)
  1660. def __call__(self, *args, **kwargs):
  1661. """Alias for :func:`~imgaug.augmenters.meta.Augmenter.augment`."""
  1662. return self.augment(*args, **kwargs)
  1663. def pool(self, processes=None, maxtasksperchild=None, seed=None):
  1664. """Create a pool used for multicore augmentation.
  1665. Parameters
  1666. ----------
  1667. processes : None or int, optional
  1668. Same as in :func:`~imgaug.multicore.Pool.__init__`.
  1669. The number of background workers. If ``None``, the number of the
  1670. machine's CPU cores will be used (this counts hyperthreads as CPU
  1671. cores). If this is set to a negative value ``p``, then
  1672. ``P - abs(p)`` will be used, where ``P`` is the number of CPU
  1673. cores. E.g. ``-1`` would use all cores except one (this is useful
  1674. to e.g. reserve one core to feed batches to the GPU).
  1675. maxtasksperchild : None or int, optional
  1676. Same as for :func:`~imgaug.multicore.Pool.__init__`.
  1677. The number of tasks done per worker process before the process
  1678. is killed and restarted. If ``None``, worker processes will not
  1679. be automatically restarted.
  1680. seed : None or int, optional
  1681. Same as for :func:`~imgaug.multicore.Pool.__init__`.
  1682. The seed to use for child processes. If ``None``, a random seed
  1683. will be used.
  1684. Returns
  1685. -------
  1686. imgaug.multicore.Pool
  1687. Pool for multicore augmentation.
  1688. Examples
  1689. --------
  1690. >>> import numpy as np
  1691. >>> import imgaug as ia
  1692. >>> import imgaug.augmenters as iaa
  1693. >>> from imgaug.augmentables.batches import Batch
  1694. >>>
  1695. >>> aug = iaa.Add(1)
  1696. >>> images = np.zeros((16, 128, 128, 3), dtype=np.uint8)
  1697. >>> batches = [Batch(images=np.copy(images)) for _ in range(100)]
  1698. >>> with aug.pool(processes=-1, seed=2) as pool:
  1699. >>> batches_aug = pool.map_batches(batches, chunksize=8)
  1700. >>> print(np.sum(batches_aug[0].images_aug[0]))
  1701. 49152
  1702. Create ``100`` batches of empty images. Each batch contains
  1703. ``16`` images of size ``128x128``. The batches are then augmented on
  1704. all CPU cores except one (``processes=-1``). After augmentation, the
  1705. sum of pixel values from the first augmented image is printed.
  1706. >>> import numpy as np
  1707. >>> import imgaug as ia
  1708. >>> import imgaug.augmenters as iaa
  1709. >>> from imgaug.augmentables.batches import Batch
  1710. >>>
  1711. >>> aug = iaa.Add(1)
  1712. >>> images = np.zeros((16, 128, 128, 3), dtype=np.uint8)
  1713. >>> def generate_batches():
  1714. >>> for _ in range(100):
  1715. >>> yield Batch(images=np.copy(images))
  1716. >>>
  1717. >>> with aug.pool(processes=-1, seed=2) as pool:
  1718. >>> batches_aug = pool.imap_batches(generate_batches(), chunksize=8)
  1719. >>> batch_aug = next(batches_aug)
  1720. >>> print(np.sum(batch_aug.images_aug[0]))
  1721. 49152
  1722. Same as above. This time, a generator is used to generate batches
  1723. of images. Again, the first augmented image's sum of pixels is printed.
  1724. """
  1725. import imgaug.multicore as multicore
  1726. return multicore.Pool(self, processes=processes,
  1727. maxtasksperchild=maxtasksperchild, seed=seed)
  1728. # TODO most of the code of this function could be replaced with
  1729. # ia.draw_grid()
  1730. # TODO add parameter for handling multiple images ((a) next to each other
  1731. # in each row or (b) multiply row count by number of images and put
  1732. # each one in a new row)
  1733. # TODO "images" parameter deviates from augment_images (3d array is here
  1734. # treated as one 3d image, in augment_images as (N, H, W))
  1735. # TODO according to the docstring, this can handle (H,W) images, but not
  1736. # (H,W,1)
  1737. def draw_grid(self, images, rows, cols):
  1738. """Augment images and draw the results as a single grid-like image.
  1739. This method applies this augmenter to the provided images and returns
  1740. a grid image of the results. Each cell in the grid contains a single
  1741. augmented version of an input image.
  1742. If multiple input images are provided, the row count is multiplied by
  1743. the number of images and each image gets its own row.
  1744. E.g. for ``images = [A, B]``, ``rows=2``, ``cols=3``::
  1745. A A A
  1746. B B B
  1747. A A A
  1748. B B B
  1749. for ``images = [A]``, ``rows=2``, ``cols=3``::
  1750. A A A
  1751. A A A
  1752. Parameters
  1753. -------
  1754. images : (N,H,W,3) ndarray or (H,W,3) ndarray or (H,W) ndarray or list of (H,W,3) ndarray or list of (H,W) ndarray
  1755. List of images to augment and draw in the grid.
  1756. If a list, then each element is expected to have shape ``(H, W)``
  1757. or ``(H, W, 3)``. If a single array, then it is expected to have
  1758. shape ``(N, H, W, 3)`` or ``(H, W, 3)`` or ``(H, W)``.
  1759. rows : int
  1760. Number of rows in the grid.
  1761. If ``N`` input images are given, this value will automatically be
  1762. multiplied by ``N`` to create rows for each image.
  1763. cols : int
  1764. Number of columns in the grid.
  1765. Returns
  1766. -------
  1767. (Hg, Wg, 3) ndarray
  1768. The generated grid image with augmented versions of the input
  1769. images. Here, ``Hg`` and ``Wg`` reference the output size of the
  1770. grid, and *not* the sizes of the input images.
  1771. """
  1772. if ia.is_np_array(images):
  1773. if len(images.shape) == 4:
  1774. images = [images[i] for i in range(images.shape[0])]
  1775. elif len(images.shape) == 3:
  1776. images = [images]
  1777. elif len(images.shape) == 2:
  1778. images = [images[:, :, np.newaxis]]
  1779. else:
  1780. raise Exception(
  1781. "Unexpected images shape, expected 2-, 3- or "
  1782. "4-dimensional array, got shape %s." % (images.shape,))
  1783. else:
  1784. assert isinstance(images, list), (
  1785. "Expected 'images' to be an ndarray or list of ndarrays. "
  1786. "Got %s." % (type(images),))
  1787. for i, image in enumerate(images):
  1788. if len(image.shape) == 3:
  1789. continue
  1790. if len(image.shape) == 2:
  1791. images[i] = image[:, :, np.newaxis]
  1792. else:
  1793. raise Exception(
  1794. "Unexpected image shape at index %d, expected 2- or "
  1795. "3-dimensional array, got shape %s." % (
  1796. i, image.shape,))
  1797. det = self if self.deterministic else self.to_deterministic()
  1798. augs = []
  1799. for image in images:
  1800. augs.append(det.augment_images([image] * (rows * cols)))
  1801. augs_flat = list(itertools.chain(*augs))
  1802. cell_height = max([image.shape[0] for image in augs_flat])
  1803. cell_width = max([image.shape[1] for image in augs_flat])
  1804. width = cell_width * cols
  1805. height = cell_height * (rows * len(images))
  1806. grid = np.zeros((height, width, 3), dtype=augs[0][0].dtype)
  1807. for row_idx in range(rows):
  1808. for img_idx, image in enumerate(images):
  1809. for col_idx in range(cols):
  1810. image_aug = augs[img_idx][(row_idx * cols) + col_idx]
  1811. cell_y1 = cell_height * (row_idx * len(images) + img_idx)
  1812. cell_y2 = cell_y1 + image_aug.shape[0]
  1813. cell_x1 = cell_width * col_idx
  1814. cell_x2 = cell_x1 + image_aug.shape[1]
  1815. grid[cell_y1:cell_y2, cell_x1:cell_x2, :] = image_aug
  1816. return grid
  1817. # TODO test for 2D images
  1818. # TODO test with C = 1
  1819. def show_grid(self, images, rows, cols):
  1820. """Augment images and plot the results as a single grid-like image.
  1821. This calls :func:`~imgaug.augmenters.meta.Augmenter.draw_grid` and
  1822. simply shows the results. See that method for details.
  1823. Parameters
  1824. ----------
  1825. images : (N,H,W,3) ndarray or (H,W,3) ndarray or (H,W) ndarray or list of (H,W,3) ndarray or list of (H,W) ndarray
  1826. List of images to augment and draw in the grid.
  1827. If a list, then each element is expected to have shape ``(H, W)``
  1828. or ``(H, W, 3)``. If a single array, then it is expected to have
  1829. shape ``(N, H, W, 3)`` or ``(H, W, 3)`` or ``(H, W)``.
  1830. rows : int
  1831. Number of rows in the grid.
  1832. If ``N`` input images are given, this value will automatically be
  1833. multiplied by ``N`` to create rows for each image.
  1834. cols : int
  1835. Number of columns in the grid.
  1836. """
  1837. grid = self.draw_grid(images, rows, cols)
  1838. ia.imshow(grid)
  1839. def to_deterministic(self, n=None):
  1840. """Convert this augmenter from a stochastic to a deterministic one.
  1841. A stochastic augmenter samples pseudo-random values for each parameter,
  1842. image and batch.
  1843. A deterministic augmenter also samples new values for each parameter
  1844. and image, but not batch. Instead, for consecutive batches it will
  1845. sample the same values (provided the number of images and their sizes
  1846. don't change).
  1847. From a technical perspective this means that a deterministic augmenter
  1848. starts each batch's augmentation with a random number generator in
  1849. the same state (i.e. same seed), instead of advancing that state from
  1850. batch to batch.
  1851. Using determinism is useful to (a) get the same augmentations for
  1852. two or more image batches (e.g. for stereo cameras), (b) to augment
  1853. images and corresponding data on them (e.g. segmentation maps or
  1854. bounding boxes) in the same way.
  1855. Parameters
  1856. ----------
  1857. n : None or int, optional
  1858. Number of deterministic augmenters to return.
  1859. If ``None`` then only one :class:`~imgaug.augmenters.meta.Augmenter`
  1860. instance will be returned.
  1861. If ``1`` or higher, a list containing ``n``
  1862. :class:`~imgaug.augmenters.meta.Augmenter` instances will be
  1863. returned.
  1864. Returns
  1865. -------
  1866. imgaug.augmenters.meta.Augmenter or list of imgaug.augmenters.meta.Augmenter
  1867. A single Augmenter object if `n` was None,
  1868. otherwise a list of Augmenter objects (even if `n` was ``1``).
  1869. """
  1870. assert n is None or n >= 1, (
  1871. "Expected 'n' to be None or >=1, got %s." % (n,))
  1872. if n is None:
  1873. return self.to_deterministic(1)[0]
  1874. return [self._to_deterministic() for _ in sm.xrange(n)]
  1875. def _to_deterministic(self):
  1876. """Convert this augmenter from a stochastic to a deterministic one.
  1877. Augmenter-specific implementation of
  1878. :func:`~imgaug.augmenters.meta.to_deterministic`. This function is
  1879. expected to return a single new deterministic
  1880. :class:`~imgaug.augmenters.meta.Augmenter` instance of this augmenter.
  1881. Returns
  1882. -------
  1883. det : imgaug.augmenters.meta.Augmenter
  1884. Deterministic variation of this Augmenter object.
  1885. """
  1886. aug = self.copy()
  1887. # This was changed for 0.2.8 from deriving a new random state based on
  1888. # the global random state to deriving it from the augmenter's local
  1889. # random state. This should reduce the risk that re-runs of scripts
  1890. # lead to different results upon small changes somewhere. It also
  1891. # decreases the likelihood of problems when using multiprocessing
  1892. # (the child processes might use the same global random state as the
  1893. # parent process). Note for the latter point that augment_batches()
  1894. # might call to_deterministic() if the batch contains multiply types
  1895. # of augmentables.
  1896. # aug.random_state = iarandom.create_random_rng()
  1897. aug.random_state = self.random_state.derive_rng_()
  1898. aug.deterministic = True
  1899. return aug
  1900. @ia.deprecated("imgaug.augmenters.meta.Augmenter.seed_")
  1901. def reseed(self, random_state=None, deterministic_too=False):
  1902. """Old name of :func:`~imgaug.augmenters.meta.Augmenter.seed_`.
  1903. Deprecated since 0.4.0.
  1904. """
  1905. self.seed_(entropy=random_state, deterministic_too=deterministic_too)
  1906. # TODO mark this as in-place
  1907. def seed_(self, entropy=None, deterministic_too=False):
  1908. """Seed this augmenter and all of its children.
  1909. This method assigns a new random number generator to the
  1910. augmenter and all of its children (if it has any). The new random
  1911. number generator is *derived* from the provided seed or RNG -- or from
  1912. the global random number generator if ``None`` was provided.
  1913. Note that as child RNGs are *derived*, they do not all use the same
  1914. seed.
  1915. If this augmenter or any child augmenter had a random number generator
  1916. that pointed to the global random state, it will automatically be
  1917. replaced with a local random state. This is similar to what
  1918. :func:`~imgaug.augmenters.meta.Augmenter.localize_random_state`
  1919. does.
  1920. This method is useful when augmentations are run in the
  1921. background (i.e. on multiple cores).
  1922. It should be called before sending this
  1923. :class:`~imgaug.augmenters.meta.Augmenter` instance to a
  1924. background worker or once within each worker with different seeds
  1925. (i.e., if ``N`` workers are used, the function should be called
  1926. ``N`` times). Otherwise, all background workers will
  1927. use the same seeds and therefore apply the same augmentations.
  1928. Note that :func:`Augmenter.augment_batches` and :func:`Augmenter.pool`
  1929. already do this automatically.
  1930. Added in 0.4.0.
  1931. Parameters
  1932. ----------
  1933. entropy : None or int or imgaug.random.RNG or numpy.random.Generator or numpy.random.BitGenerator or numpy.random.SeedSequence or numpy.random.RandomState, optional
  1934. A seed or random number generator that is used to derive new
  1935. random number generators for this augmenter and its children.
  1936. If an ``int`` is provided, it will be interpreted as a seed.
  1937. If ``None`` is provided, the global random number generator will
  1938. be used.
  1939. deterministic_too : bool, optional
  1940. Whether to also change the seed of an augmenter ``A``, if ``A``
  1941. is deterministic. This is the case both when this augmenter
  1942. object is ``A`` or one of its children is ``A``.
  1943. Examples
  1944. --------
  1945. >>> import imgaug.augmenters as iaa
  1946. >>> aug = iaa.Sequential([
  1947. >>> iaa.Crop(px=(0, 10)),
  1948. >>> iaa.Crop(px=(0, 10))
  1949. >>> ])
  1950. >>> aug.seed_(1)
  1951. Seed an augmentation sequence containing two crop operations. Even
  1952. though the same seed was used, the two operations will still sample
  1953. different pixel amounts to crop as the child-specific seed is merely
  1954. derived from the provided seed.
  1955. """
  1956. assert isinstance(deterministic_too, bool), (
  1957. "Expected 'deterministic_too' to be a boolean, got type %s." % (
  1958. deterministic_too))
  1959. if entropy is None:
  1960. random_state = iarandom.RNG.create_pseudo_random_()
  1961. else:
  1962. random_state = iarandom.RNG(entropy)
  1963. if not self.deterministic or deterministic_too:
  1964. # note that derive_rng_() (used below) advances the RNG, so
  1965. # child augmenters get a different RNG state
  1966. self.random_state = random_state.copy()
  1967. for lst in self.get_children_lists():
  1968. for aug in lst:
  1969. aug.seed_(entropy=random_state.derive_rng_(),
  1970. deterministic_too=deterministic_too)
  1971. def localize_random_state(self, recursive=True):
  1972. """Assign augmenter-specific RNGs to this augmenter and its children.
  1973. See :func:`Augmenter.localize_random_state_` for more details.
  1974. Parameters
  1975. ----------
  1976. recursive : bool, optional
  1977. See
  1978. :func:`~imgaug.augmenters.meta.Augmenter.localize_random_state_`.
  1979. Returns
  1980. -------
  1981. imgaug.augmenters.meta.Augmenter
  1982. Copy of the augmenter and its children, with localized RNGs.
  1983. """
  1984. aug = self.deepcopy()
  1985. aug.localize_random_state_(
  1986. recursive=recursive
  1987. )
  1988. return aug
  1989. # TODO rename random_state -> rng
  1990. def localize_random_state_(self, recursive=True):
  1991. """Assign augmenter-specific RNGs to this augmenter and its children.
  1992. This method iterates over this augmenter and all of its children and
  1993. replaces any pointer to the global RNG with a new local (i.e.
  1994. augmenter-specific) RNG.
  1995. A random number generator (RNG) is used for the sampling of random
  1996. values.
  1997. The global random number generator exists exactly once throughout
  1998. the library and is shared by many augmenters.
  1999. A local RNG (usually) exists within exactly one augmenter and is
  2000. only used by that augmenter.
  2001. Usually there is no need to change global into local RNGs.
  2002. The only noteworthy exceptions are
  2003. * Whenever you want to use determinism (so that the global RNG is
  2004. not accidentally reverted).
  2005. * Whenever you want to copy RNGs from one augmenter to
  2006. another. (Copying the global RNG would usually not be useful.
  2007. Copying the global RNG from augmenter A to B, then executing A
  2008. and then B would result in B's (global) RNG's state having
  2009. already changed because of A's sampling. So the samples of
  2010. A and B would differ.)
  2011. The case of determinism is handled automatically by
  2012. :func:`~imgaug.augmenters.meta.Augmenter.to_deterministic`.
  2013. Only when you copy RNGs (via
  2014. :func:`~imgaug.augmenters.meta.Augmenter.copy_random_state`),
  2015. you need to call this function first.
  2016. Parameters
  2017. ----------
  2018. recursive : bool, optional
  2019. Whether to localize the RNGs of the augmenter's children too.
  2020. Returns
  2021. -------
  2022. imgaug.augmenters.meta.Augmenter
  2023. Returns itself (with localized RNGs).
  2024. """
  2025. if self.random_state.is_global_rng():
  2026. self.random_state = self.random_state.derive_rng_()
  2027. if recursive:
  2028. for lst in self.get_children_lists():
  2029. for child in lst:
  2030. child.localize_random_state_(recursive=recursive)
  2031. return self
  2032. # TODO adapt random_state -> rng
  2033. def copy_random_state(self, source, recursive=True, matching="position",
  2034. matching_tolerant=True, copy_determinism=False):
  2035. """Copy the RNGs from a source augmenter sequence.
  2036. Parameters
  2037. ----------
  2038. source : imgaug.augmenters.meta.Augmenter
  2039. See :func:`~imgaug.augmenters.meta.Augmenter.copy_random_state_`.
  2040. recursive : bool, optional
  2041. See :func:`~imgaug.augmenters.meta.Augmenter.copy_random_state_`.
  2042. matching : {'position', 'name'}, optional
  2043. See :func:`~imgaug.augmenters.meta.Augmenter.copy_random_state_`.
  2044. matching_tolerant : bool, optional
  2045. See :func:`~imgaug.augmenters.meta.Augmenter.copy_random_state_`.
  2046. copy_determinism : bool, optional
  2047. See :func:`~imgaug.augmenters.meta.Augmenter.copy_random_state_`.
  2048. Returns
  2049. -------
  2050. imgaug.augmenters.meta.Augmenter
  2051. Copy of the augmenter itself (with copied RNGs).
  2052. """
  2053. aug = self.deepcopy()
  2054. aug.copy_random_state_(
  2055. source,
  2056. recursive=recursive,
  2057. matching=matching,
  2058. matching_tolerant=matching_tolerant,
  2059. copy_determinism=copy_determinism
  2060. )
  2061. return aug
  2062. def copy_random_state_(self, source, recursive=True, matching="position",
  2063. matching_tolerant=True, copy_determinism=False):
  2064. """Copy the RNGs from a source augmenter sequence (in-place).
  2065. .. note::
  2066. The source augmenters are not allowed to use the global RNG.
  2067. Call
  2068. :func:`~imgaug.augmenters.meta.Augmenter.localize_random_state_`
  2069. once on the source to localize all random states.
  2070. Parameters
  2071. ----------
  2072. source : imgaug.augmenters.meta.Augmenter
  2073. The source augmenter(s) from where to copy the RNG(s).
  2074. The source may have children (e.g. the source can be a
  2075. :class:`~imgaug.augmenters.meta.Sequential`).
  2076. recursive : bool, optional
  2077. Whether to copy the RNGs of the source augmenter *and*
  2078. all of its children (``True``) or just the source
  2079. augmenter (``False``).
  2080. matching : {'position', 'name'}, optional
  2081. Defines the matching mode to use during recursive copy.
  2082. This is used to associate source augmenters with target augmenters.
  2083. If ``position`` then the target and source sequences of augmenters
  2084. are turned into flattened lists and are associated based on
  2085. their list indices. If ``name`` then the target and source
  2086. augmenters are matched based on their names (i.e.
  2087. ``augmenter.name``).
  2088. matching_tolerant : bool, optional
  2089. Whether to use tolerant matching between source and target
  2090. augmenters. If set to ``False``: Name matching will raise an
  2091. exception for any target augmenter which's name does not appear
  2092. among the source augmenters. Position matching will raise an
  2093. exception if source and target augmenter have an unequal number
  2094. of children.
  2095. copy_determinism : bool, optional
  2096. Whether to copy the ``deterministic`` attributes from source to
  2097. target augmenters too.
  2098. Returns
  2099. -------
  2100. imgaug.augmenters.meta.Augmenter
  2101. The augmenter itself.
  2102. """
  2103. # Note: the target random states are localized, but the source random
  2104. # states don't have to be localized. That means that they can be
  2105. # the global random state. Worse, if copy_random_state() was called,
  2106. # the target random states would have different identities, but
  2107. # same states. If multiple target random states were the global random
  2108. # state, then after deepcopying them, they would all share the same
  2109. # identity that is different to the global random state. I.e., if the
  2110. # state of any random state of them is set in-place, it modifies the
  2111. # state of all other target random states (that were once global),
  2112. # but not the global random state.
  2113. # Summary: Use target = source.copy() here, instead of
  2114. # target.use_state_of_(source).
  2115. source_augs = (
  2116. [source] + source.get_all_children(flat=True)
  2117. if recursive
  2118. else [source])
  2119. target_augs = (
  2120. [self] + self.get_all_children(flat=True)
  2121. if recursive
  2122. else [self])
  2123. global_rs_exc_msg = (
  2124. "You called copy_random_state_() with a source that uses global "
  2125. "RNGs. Call localize_random_state_() on the source "
  2126. "first or initialize your augmenters with local random states, "
  2127. "e.g. via Dropout(..., random_state=1234).")
  2128. if matching == "name":
  2129. source_augs_dict = {aug.name: aug for aug in source_augs}
  2130. target_augs_dict = {aug.name: aug for aug in target_augs}
  2131. different_lengths = (
  2132. len(source_augs_dict) < len(source_augs)
  2133. or len(target_augs_dict) < len(target_augs))
  2134. if different_lengths:
  2135. ia.warn(
  2136. "Matching mode 'name' with recursive=True was chosen in "
  2137. "copy_random_state_, but either the source or target "
  2138. "augmentation sequence contains multiple augmenters with "
  2139. "the same name."
  2140. )
  2141. for name in target_augs_dict:
  2142. if name in source_augs_dict:
  2143. if source_augs_dict[name].random_state.is_global_rng():
  2144. raise Exception(global_rs_exc_msg)
  2145. # has to be copy(), see above
  2146. target_augs_dict[name].random_state = \
  2147. source_augs_dict[name].random_state.copy()
  2148. if copy_determinism:
  2149. target_augs_dict[name].deterministic = \
  2150. source_augs_dict[name].deterministic
  2151. elif not matching_tolerant:
  2152. raise Exception(
  2153. "Augmenter name '%s' not found among source "
  2154. "augmenters." % (name,))
  2155. elif matching == "position":
  2156. if len(source_augs) != len(target_augs) and not matching_tolerant:
  2157. raise Exception(
  2158. "Source and target augmentation sequences have different "
  2159. "lengths.")
  2160. for source_aug, target_aug in zip(source_augs, target_augs):
  2161. if source_aug.random_state.is_global_rng():
  2162. raise Exception(global_rs_exc_msg)
  2163. # has to be copy(), see above
  2164. target_aug.random_state = source_aug.random_state.copy()
  2165. if copy_determinism:
  2166. target_aug.deterministic = source_aug.deterministic
  2167. else:
  2168. raise Exception(
  2169. "Unknown matching method '%s'. Valid options are 'name' "
  2170. "and 'position'." % (matching,))
  2171. return self
  2172. @abstractmethod
  2173. def get_parameters(self):
  2174. """Get the parameters of this augmenter.
  2175. Returns
  2176. -------
  2177. list
  2178. List of parameters of arbitrary types (usually child class
  2179. of :class:`~imgaug.parameters.StochasticParameter`, but not
  2180. guaranteed to be).
  2181. """
  2182. raise NotImplementedError()
  2183. def get_children_lists(self):
  2184. """Get a list of lists of children of this augmenter.
  2185. For most augmenters, the result will be a single empty list.
  2186. For augmenters with children it will often be a list with one
  2187. sublist containing all children. In some cases the augmenter will
  2188. contain multiple distinct lists of children, e.g. an if-list and an
  2189. else-list. This will lead to a result consisting of a single list
  2190. with multiple sublists, each representing the respective sublist of
  2191. children.
  2192. E.g. for an if/else-augmenter that executes the children ``A1``,
  2193. ``A2`` if a condition is met and otherwise executes the children
  2194. ``B1``, ``B2``, ``B3`` the result will be
  2195. ``[[A1, A2], [B1, B2, B3]]``.
  2196. IMPORTANT: While the topmost list may be newly created, each of the
  2197. sublist must be editable inplace resulting in a changed children list
  2198. of the augmenter. E.g. if an Augmenter
  2199. ``IfElse(condition, [A1, A2], [B1, B2, B3])`` returns
  2200. ``[[A1, A2], [B1, B2, B3]]``
  2201. for a call to
  2202. :func:`~imgaug.augmenters.meta.Augmenter.get_children_lists` and
  2203. ``A2`` is removed inplace from ``[A1, A2]``, then the children lists
  2204. of ``IfElse(...)`` must also change to ``[A1], [B1, B2, B3]``. This
  2205. is used in
  2206. :func:`~imgaug.augmeneters.meta.Augmenter.remove_augmenters_`.
  2207. Returns
  2208. -------
  2209. list of list of imgaug.augmenters.meta.Augmenter
  2210. One or more lists of child augmenter.
  2211. Can also be a single empty list.
  2212. """
  2213. return []
  2214. # TODO why does this exist? it seems to be identical to
  2215. # get_children_lists() for flat=False, aside from returning list
  2216. # copies instead of the same instances as used by the augmenters.
  2217. # TODO this can be simplified using imgaug.imgaug.flatten()?
  2218. def get_all_children(self, flat=False):
  2219. """Get all children of this augmenter as a list.
  2220. If the augmenter has no children, the returned list is empty.
  2221. Parameters
  2222. ----------
  2223. flat : bool
  2224. If set to ``True``, the returned list will be flat.
  2225. Returns
  2226. -------
  2227. list of imgaug.augmenters.meta.Augmenter
  2228. The children as a nested or flat list.
  2229. """
  2230. result = []
  2231. for lst in self.get_children_lists():
  2232. for aug in lst:
  2233. result.append(aug)
  2234. children = aug.get_all_children(flat=flat)
  2235. if len(children) > 0:
  2236. if flat:
  2237. result.extend(children)
  2238. else:
  2239. result.append(children)
  2240. return result
  2241. def find_augmenters(self, func, parents=None, flat=True):
  2242. """Find augmenters that match a condition.
  2243. This function will compare this augmenter and all of its children
  2244. with a condition. The condition is a lambda function.
  2245. Parameters
  2246. ----------
  2247. func : callable
  2248. A function that receives a
  2249. :class:`~imgaug.augmenters.meta.Augmenter` instance and a list of
  2250. parent :class:`~imgaug.augmenters.meta.Augmenter` instances and
  2251. must return ``True``, if that augmenter is valid match or
  2252. ``False`` otherwise.
  2253. parents : None or list of imgaug.augmenters.meta.Augmenter, optional
  2254. List of parent augmenters.
  2255. Intended for nested calls and can usually be left as ``None``.
  2256. flat : bool, optional
  2257. Whether to return the result as a flat list (``True``)
  2258. or a nested list (``False``). In the latter case, the nesting
  2259. matches each augmenters position among the children.
  2260. Returns
  2261. ----------
  2262. list of imgaug.augmenters.meta.Augmenter
  2263. Nested list if `flat` was set to ``False``.
  2264. Flat list if `flat` was set to ``True``.
  2265. Examples
  2266. --------
  2267. >>> import imgaug.augmenters as iaa
  2268. >>> aug = iaa.Sequential([
  2269. >>> iaa.Fliplr(0.5, name="fliplr"),
  2270. >>> iaa.Flipud(0.5, name="flipud")
  2271. >>> ])
  2272. >>> print(aug.find_augmenters(lambda a, parents: a.name == "fliplr"))
  2273. Return the first child augmenter (``Fliplr`` instance).
  2274. """
  2275. if parents is None:
  2276. parents = []
  2277. result = []
  2278. if func(self, parents):
  2279. result.append(self)
  2280. subparents = parents + [self]
  2281. for lst in self.get_children_lists():
  2282. for aug in lst:
  2283. found = aug.find_augmenters(func, parents=subparents,
  2284. flat=flat)
  2285. if len(found) > 0:
  2286. if flat:
  2287. result.extend(found)
  2288. else:
  2289. result.append(found)
  2290. return result
  2291. def find_augmenters_by_name(self, name, regex=False, flat=True):
  2292. """Find augmenter(s) by name.
  2293. Parameters
  2294. ----------
  2295. name : str
  2296. Name of the augmenter(s) to search for.
  2297. regex : bool, optional
  2298. Whether `name` parameter is a regular expression.
  2299. flat : bool, optional
  2300. See :func:`~imgaug.augmenters.meta.Augmenter.find_augmenters`.
  2301. Returns
  2302. -------
  2303. augmenters : list of imgaug.augmenters.meta.Augmenter
  2304. Nested list if `flat` was set to ``False``.
  2305. Flat list if `flat` was set to ``True``.
  2306. """
  2307. return self.find_augmenters_by_names([name], regex=regex, flat=flat)
  2308. def find_augmenters_by_names(self, names, regex=False, flat=True):
  2309. """Find augmenter(s) by names.
  2310. Parameters
  2311. ----------
  2312. names : list of str
  2313. Names of the augmenter(s) to search for.
  2314. regex : bool, optional
  2315. Whether `names` is a list of regular expressions.
  2316. If it is, an augmenter is considered a match if *at least* one
  2317. of these expressions is a match.
  2318. flat : boolean, optional
  2319. See :func:`~imgaug.augmenters.meta.Augmenter.find_augmenters`.
  2320. Returns
  2321. -------
  2322. augmenters : list of imgaug.augmenters.meta.Augmenter
  2323. Nested list if `flat` was set to ``False``.
  2324. Flat list if `flat` was set to ``True``.
  2325. """
  2326. if regex:
  2327. def comparer(aug, _parents):
  2328. for pattern in names:
  2329. if re.match(pattern, aug.name):
  2330. return True
  2331. return False
  2332. return self.find_augmenters(comparer, flat=flat)
  2333. return self.find_augmenters(
  2334. lambda aug, parents: aug.name in names, flat=flat)
  2335. # TODO remove copy arg
  2336. # TODO allow first arg to be string name, class type or func
  2337. def remove_augmenters(self, func, copy=True, identity_if_topmost=True,
  2338. noop_if_topmost=None):
  2339. """Remove this augmenter or children that match a condition.
  2340. Parameters
  2341. ----------
  2342. func : callable
  2343. Condition to match per augmenter.
  2344. The function must expect the augmenter itself and a list of parent
  2345. augmenters and returns ``True`` if that augmenter is supposed to
  2346. be removed, or ``False`` otherwise.
  2347. E.g. ``lambda a, parents: a.name == "fliplr" and len(parents) == 1``
  2348. removes an augmenter with name ``fliplr`` if it is the direct child
  2349. of the augmenter upon which ``remove_augmenters()`` was initially
  2350. called.
  2351. copy : bool, optional
  2352. Whether to copy this augmenter and all if its children before
  2353. removing. If ``False``, removal is performed in-place.
  2354. identity_if_topmost : bool, optional
  2355. If ``True`` and the condition (lambda function) leads to the
  2356. removal of the topmost augmenter (the one this function is called
  2357. on initially), then that topmost augmenter will be replaced by an
  2358. instance of :class:`~imgaug.augmenters.meta.Noop` (i.e. an
  2359. augmenter that doesn't change its inputs). If ``False``, ``None``
  2360. will be returned in these cases.
  2361. This can only be ``False`` if copy is set to ``True``.
  2362. noop_if_topmost : bool, optional
  2363. Deprecated since 0.4.0.
  2364. Returns
  2365. -------
  2366. imgaug.augmenters.meta.Augmenter or None
  2367. This augmenter after the removal was performed.
  2368. ``None`` is returned if the condition was matched for the
  2369. topmost augmenter, `copy` was set to ``True`` and `noop_if_topmost`
  2370. was set to ``False``.
  2371. Examples
  2372. --------
  2373. >>> import imgaug.augmenters as iaa
  2374. >>> seq = iaa.Sequential([
  2375. >>> iaa.Fliplr(0.5, name="fliplr"),
  2376. >>> iaa.Flipud(0.5, name="flipud"),
  2377. >>> ])
  2378. >>> seq = seq.remove_augmenters(lambda a, parents: a.name == "fliplr")
  2379. This removes the augmenter ``Fliplr`` from the ``Sequential``
  2380. object's children.
  2381. """
  2382. if noop_if_topmost is not None:
  2383. ia.warn_deprecated("Parameter 'noop_if_topmost' is deprecated. "
  2384. "Use 'identity_if_topmost' instead.")
  2385. identity_if_topmost = noop_if_topmost
  2386. if func(self, []):
  2387. if not copy:
  2388. raise Exception(
  2389. "Inplace removal of topmost augmenter requested, "
  2390. "which is currently not possible. Set 'copy' to True.")
  2391. if identity_if_topmost:
  2392. return Identity()
  2393. return None
  2394. aug = self if not copy else self.deepcopy()
  2395. aug.remove_augmenters_(func, parents=[])
  2396. return aug
  2397. @ia.deprecated("remove_augmenters_")
  2398. def remove_augmenters_inplace(self, func, parents=None):
  2399. """Old name for :func:`~imgaug.meta.Augmenter.remove_augmenters_`.
  2400. Deprecated since 0.4.0.
  2401. """
  2402. self.remove_augmenters_(func=func, parents=parents)
  2403. # TODO allow first arg to be string name, class type or func
  2404. # TODO remove parents arg + add _remove_augmenters_() with parents arg
  2405. def remove_augmenters_(self, func, parents=None):
  2406. """Remove in-place children of this augmenter that match a condition.
  2407. This is functionally identical to
  2408. :func:`~imgaug.augmenters.meta.remove_augmenters` with
  2409. ``copy=False``, except that it does not affect the topmost augmenter
  2410. (the one on which this function is initially called on).
  2411. Added in 0.4.0.
  2412. Parameters
  2413. ----------
  2414. func : callable
  2415. See :func:`~imgaug.augmenters.meta.Augmenter.remove_augmenters`.
  2416. parents : None or list of imgaug.augmenters.meta.Augmenter, optional
  2417. List of parent :class:`~imgaug.augmenters.meta.Augmenter` instances
  2418. that lead to this augmenter. If ``None``, an empty list will be
  2419. used. This parameter can usually be left empty and will be set
  2420. automatically for children.
  2421. Examples
  2422. --------
  2423. >>> import imgaug.augmenters as iaa
  2424. >>> seq = iaa.Sequential([
  2425. >>> iaa.Fliplr(0.5, name="fliplr"),
  2426. >>> iaa.Flipud(0.5, name="flipud"),
  2427. >>> ])
  2428. >>> seq.remove_augmenters_(lambda a, parents: a.name == "fliplr")
  2429. This removes the augmenter ``Fliplr`` from the ``Sequential``
  2430. object's children.
  2431. """
  2432. parents = [] if parents is None else parents
  2433. subparents = parents + [self]
  2434. for lst in self.get_children_lists():
  2435. to_remove = []
  2436. for i, aug in enumerate(lst):
  2437. if func(aug, subparents):
  2438. to_remove.append((i, aug))
  2439. for count_removed, (i, aug) in enumerate(to_remove):
  2440. del lst[i - count_removed]
  2441. for aug in lst:
  2442. aug.remove_augmenters_(func, subparents)
  2443. def copy(self):
  2444. """Create a shallow copy of this Augmenter instance.
  2445. Returns
  2446. -------
  2447. imgaug.augmenters.meta.Augmenter
  2448. Shallow copy of this Augmenter instance.
  2449. """
  2450. return copy_module.copy(self)
  2451. def deepcopy(self):
  2452. """Create a deep copy of this Augmenter instance.
  2453. Returns
  2454. -------
  2455. imgaug.augmenters.meta.Augmenter
  2456. Deep copy of this Augmenter instance.
  2457. """
  2458. # TODO if this augmenter has child augmenters and multiple of them
  2459. # use the global random state, then after copying, these
  2460. # augmenters share a single new random state that is a copy of
  2461. # the global random state (i.e. all use the same *instance*,
  2462. # not just state). This can lead to confusing bugs.
  2463. # TODO write a custom copying routine?
  2464. return copy_module.deepcopy(self)
  2465. def __repr__(self):
  2466. return self.__str__()
  2467. def __str__(self):
  2468. params = self.get_parameters()
  2469. params_str = ", ".join([param.__str__() for param in params])
  2470. return "%s(name=%s, parameters=[%s], deterministic=%s)" % (
  2471. self.__class__.__name__, self.name, params_str, self.deterministic)
  2472. class Sequential(Augmenter, list):
  2473. """List augmenter containing child augmenters to apply to inputs.
  2474. This augmenter is simply a list of other augmenters. To augment an image
  2475. or any other data, it iterates over its children and applies each one
  2476. of them independently to the data. (This also means that the second
  2477. applied augmenter will already receive augmented input data and augment
  2478. it further.)
  2479. This augmenter offers the option to apply its children in random order
  2480. using the `random_order` parameter. This should often be activated as
  2481. it greatly increases the space of possible augmentations.
  2482. .. note::
  2483. You are *not* forced to use :class:`~imgaug.augmenters.meta.Sequential`
  2484. in order to use other augmenters. Each augmenter can be used on its
  2485. own, e.g the following defines an augmenter for horizontal flips and
  2486. then augments a single image:
  2487. >>> import numpy as np
  2488. >>> import imgaug.augmenters as iaa
  2489. >>> image = np.zeros((32, 32, 3), dtype=np.uint8)
  2490. >>> aug = iaa.Fliplr(0.5)
  2491. >>> image_aug = aug.augment_image(image)
  2492. **Supported dtypes**:
  2493. * ``uint8``: yes; fully tested
  2494. * ``uint16``: yes; tested
  2495. * ``uint32``: yes; tested
  2496. * ``uint64``: yes; tested
  2497. * ``int8``: yes; tested
  2498. * ``int16``: yes; tested
  2499. * ``int32``: yes; tested
  2500. * ``int64``: yes; tested
  2501. * ``float16``: yes; tested
  2502. * ``float32``: yes; tested
  2503. * ``float64``: yes; tested
  2504. * ``float128``: yes; tested
  2505. * ``bool``: yes; tested
  2506. Parameters
  2507. ----------
  2508. children : imgaug.augmenters.meta.Augmenter or list of imgaug.augmenters.meta.Augmenter or None, optional
  2509. The augmenters to apply to images.
  2510. random_order : bool, optional
  2511. Whether to apply the child augmenters in random order.
  2512. If ``True``, the order will be randomly sampled once per batch.
  2513. seed : None or int or imgaug.random.RNG or numpy.random.Generator or numpy.random.BitGenerator or numpy.random.SeedSequence or numpy.random.RandomState, optional
  2514. See :func:`~imgaug.augmenters.meta.Augmenter.__init__`.
  2515. name : None or str, optional
  2516. See :func:`~imgaug.augmenters.meta.Augmenter.__init__`.
  2517. random_state : None or int or imgaug.random.RNG or numpy.random.Generator or numpy.random.BitGenerator or numpy.random.SeedSequence or numpy.random.RandomState, optional
  2518. Old name for parameter `seed`.
  2519. Its usage will not yet cause a deprecation warning,
  2520. but it is still recommended to use `seed` now.
  2521. Outdated since 0.4.0.
  2522. deterministic : bool, optional
  2523. Deprecated since 0.4.0.
  2524. See method ``to_deterministic()`` for an alternative and for
  2525. details about what the "deterministic mode" actually does.
  2526. Examples
  2527. --------
  2528. >>> import numpy as np
  2529. >>> import imgaug.augmenters as iaa
  2530. >>> imgs = [np.random.rand(10, 10)]
  2531. >>> seq = iaa.Sequential([
  2532. >>> iaa.Fliplr(0.5),
  2533. >>> iaa.Flipud(0.5)
  2534. >>> ])
  2535. >>> imgs_aug = seq.augment_images(imgs)
  2536. Create a :class:`~imgaug.augmenters.meta.Sequential` that always first
  2537. applies a horizontal flip augmenter and then a vertical flip augmenter.
  2538. Each of these two augmenters has a ``50%`` probability of actually
  2539. flipping the image.
  2540. >>> seq = iaa.Sequential([
  2541. >>> iaa.Fliplr(0.5),
  2542. >>> iaa.Flipud(0.5)
  2543. >>> ], random_order=True)
  2544. >>> imgs_aug = seq.augment_images(imgs)
  2545. Create a :class:`~imgaug.augmenters.meta.Sequential` that sometimes first
  2546. applies a horizontal flip augmenter (followed by a vertical flip
  2547. augmenter) and sometimes first a vertical flip augmenter (followed by a
  2548. horizontal flip augmenter). Again, each of them has a ``50%`` probability
  2549. of actually flipping the image.
  2550. """
  2551. def __init__(self, children=None, random_order=False,
  2552. seed=None, name=None,
  2553. random_state="deprecated", deterministic="deprecated"):
  2554. Augmenter.__init__(
  2555. self,
  2556. seed=seed, name=name,
  2557. random_state=random_state, deterministic=deterministic)
  2558. if children is None:
  2559. list.__init__(self, [])
  2560. elif isinstance(children, Augmenter):
  2561. # this must be separate from `list.__init__(self, children)`,
  2562. # otherwise in `Sequential(OneOf(...))` the OneOf(...) is
  2563. # interpreted as a list and OneOf's children become Sequential's
  2564. # children
  2565. list.__init__(self, [children])
  2566. elif ia.is_iterable(children):
  2567. assert all([isinstance(child, Augmenter) for child in children]), (
  2568. "Expected all children to be augmenters, got types %s." % (
  2569. ", ".join([str(type(v)) for v in children])))
  2570. list.__init__(self, children)
  2571. else:
  2572. raise Exception("Expected None or Augmenter or list of Augmenter, "
  2573. "got %s." % (type(children),))
  2574. assert ia.is_single_bool(random_order), (
  2575. "Expected random_order to be boolean, got %s." % (
  2576. type(random_order),))
  2577. self.random_order = random_order
  2578. # Added in 0.4.0.
  2579. def _augment_batch_(self, batch, random_state, parents, hooks):
  2580. with batch.propagation_hooks_ctx(self, hooks, parents):
  2581. if self.random_order:
  2582. order = random_state.permutation(len(self))
  2583. else:
  2584. order = sm.xrange(len(self))
  2585. for index in order:
  2586. batch = self[index].augment_batch_(
  2587. batch,
  2588. parents=parents + [self],
  2589. hooks=hooks
  2590. )
  2591. return batch
  2592. def _to_deterministic(self):
  2593. augs = [aug.to_deterministic() for aug in self]
  2594. seq = self.copy()
  2595. seq[:] = augs
  2596. seq.random_state = self.random_state.derive_rng_()
  2597. seq.deterministic = True
  2598. return seq
  2599. def get_parameters(self):
  2600. """See :func:`~imgaug.augmenters.meta.Augmenter.get_parameters`."""
  2601. return [self.random_order]
  2602. def add(self, augmenter):
  2603. """Add an augmenter to the list of child augmenters.
  2604. Parameters
  2605. ----------
  2606. imgaug.augmenters.meta.Augmenter
  2607. The augmenter to add.
  2608. """
  2609. self.append(augmenter)
  2610. def get_children_lists(self):
  2611. """See :func:`~imgaug.augmenters.meta.Augmenter.get_children_lists`."""
  2612. return [self]
  2613. def __str__(self):
  2614. augs_str = ", ".join([aug.__str__() for aug in self])
  2615. pattern = (
  2616. "%s("
  2617. "name=%s, random_order=%s, children=[%s], deterministic=%s"
  2618. ")")
  2619. return pattern % (
  2620. self.__class__.__name__, self.name, self.random_order, augs_str,
  2621. self.deterministic)
  2622. class SomeOf(Augmenter, list):
  2623. """List augmenter that applies only some of its children to inputs.
  2624. This augmenter is similar to :class:`~imgaug.augmenters.meta.Sequential`,
  2625. but may apply only a fixed or random subset of its child augmenters to
  2626. inputs. E.g. the augmenter could be initialized with a list of 20 child
  2627. augmenters and then apply 5 randomly chosen child augmenters to images.
  2628. The subset of augmenters to apply (and their order) is sampled once
  2629. *per image*. If `random_order` is ``True``, the order will be sampled once
  2630. *per batch* (similar to :class:`~imgaug.augmenters.meta.Sequential`).
  2631. This augmenter currently does not support replacing (i.e. picking the same
  2632. child multiple times) due to implementation difficulties in connection
  2633. with deterministic augmenters.
  2634. **Supported dtypes**:
  2635. * ``uint8``: yes; fully tested
  2636. * ``uint16``: yes; tested
  2637. * ``uint32``: yes; tested
  2638. * ``uint64``: yes; tested
  2639. * ``int8``: yes; tested
  2640. * ``int16``: yes; tested
  2641. * ``int32``: yes; tested
  2642. * ``int64``: yes; tested
  2643. * ``float16``: yes; tested
  2644. * ``float32``: yes; tested
  2645. * ``float64``: yes; tested
  2646. * ``float128``: yes; tested
  2647. * ``bool``: yes; tested
  2648. Parameters
  2649. ----------
  2650. n : int or tuple of int or list of int or imgaug.parameters.StochasticParameter or None, optional
  2651. Count of augmenters to apply.
  2652. * If ``int``, then exactly `n` of the child augmenters are applied
  2653. to every image.
  2654. * If tuple of two ``int`` s ``(a, b)``, then a random value will
  2655. be uniformly sampled per image from the discrete interval
  2656. ``[a..b]`` and denote the number of child augmenters to pick
  2657. and apply. ``b`` may be set to ``None``, which is then equivalent
  2658. to ``(a..C)`` with ``C`` denoting the number of children that
  2659. the augmenter has.
  2660. * If ``StochasticParameter``, then ``N`` numbers will be sampled
  2661. for ``N`` images. The parameter is expected to be discrete.
  2662. * If ``None``, then the total number of available children will be
  2663. used (i.e. all children will be applied).
  2664. children : imgaug.augmenters.meta.Augmenter or list of imgaug.augmenters.meta.Augmenter or None, optional
  2665. The augmenters to apply to images.
  2666. If this is a list of augmenters, it will be converted to a
  2667. :class:`~imgaug.augmenters.meta.Sequential`.
  2668. random_order : boolean, optional
  2669. Whether to apply the child augmenters in random order.
  2670. If ``True``, the order will be randomly sampled once per batch.
  2671. seed : None or int or imgaug.random.RNG or numpy.random.Generator or numpy.random.BitGenerator or numpy.random.SeedSequence or numpy.random.RandomState, optional
  2672. See :func:`~imgaug.augmenters.meta.Augmenter.__init__`.
  2673. name : None or str, optional
  2674. See :func:`~imgaug.augmenters.meta.Augmenter.__init__`.
  2675. random_state : None or int or imgaug.random.RNG or numpy.random.Generator or numpy.random.BitGenerator or numpy.random.SeedSequence or numpy.random.RandomState, optional
  2676. Old name for parameter `seed`.
  2677. Its usage will not yet cause a deprecation warning,
  2678. but it is still recommended to use `seed` now.
  2679. Outdated since 0.4.0.
  2680. deterministic : bool, optional
  2681. Deprecated since 0.4.0.
  2682. See method ``to_deterministic()`` for an alternative and for
  2683. details about what the "deterministic mode" actually does.
  2684. Examples
  2685. --------
  2686. >>> import imgaug.augmenters as iaa
  2687. >>> imgs = [np.random.rand(10, 10)]
  2688. >>> seq = iaa.SomeOf(1, [
  2689. >>> iaa.Fliplr(1.0),
  2690. >>> iaa.Flipud(1.0)
  2691. >>> ])
  2692. >>> imgs_aug = seq.augment_images(imgs)
  2693. Apply either ``Fliplr`` or ``Flipud`` to images.
  2694. >>> seq = iaa.SomeOf((1, 3), [
  2695. >>> iaa.Fliplr(1.0),
  2696. >>> iaa.Flipud(1.0),
  2697. >>> iaa.GaussianBlur(1.0)
  2698. >>> ])
  2699. >>> imgs_aug = seq.augment_images(imgs)
  2700. Apply one to three of the listed augmenters (``Fliplr``, ``Flipud``,
  2701. ``GaussianBlur``) to images. They are always applied in the
  2702. provided order, i.e. first ``Fliplr``, second ``Flipud``, third
  2703. ``GaussianBlur``.
  2704. >>> seq = iaa.SomeOf((1, None), [
  2705. >>> iaa.Fliplr(1.0),
  2706. >>> iaa.Flipud(1.0),
  2707. >>> iaa.GaussianBlur(1.0)
  2708. >>> ], random_order=True)
  2709. >>> imgs_aug = seq.augment_images(imgs)
  2710. Apply one to all of the listed augmenters (``Fliplr``, ``Flipud``,
  2711. ``GaussianBlur``) to images. They are applied in random order, i.e.
  2712. sometimes ``GaussianBlur`` first, followed by ``Fliplr``, sometimes
  2713. ``Fliplr`` followed by ``Flipud`` followed by ``Blur`` etc.
  2714. The order is sampled once per batch.
  2715. """
  2716. def __init__(self, n=None, children=None, random_order=False,
  2717. seed=None, name=None,
  2718. random_state="deprecated", deterministic="deprecated"):
  2719. Augmenter.__init__(
  2720. self,
  2721. seed=seed, name=name,
  2722. random_state=random_state, deterministic=deterministic)
  2723. # TODO use handle_children_list() here?
  2724. if children is None:
  2725. list.__init__(self, [])
  2726. elif isinstance(children, Augmenter):
  2727. # this must be separate from `list.__init__(self, children)`,
  2728. # otherwise in `SomeOf(OneOf(...))` the OneOf(...) is
  2729. # interpreted as a list and OneOf's children become SomeOf's
  2730. # children
  2731. list.__init__(self, [children])
  2732. elif ia.is_iterable(children):
  2733. assert all([isinstance(child, Augmenter) for child in children]), (
  2734. "Expected all children to be augmenters, got types %s." % (
  2735. ", ".join([str(type(v)) for v in children])))
  2736. list.__init__(self, children)
  2737. else:
  2738. raise Exception("Expected None or Augmenter or list of Augmenter, "
  2739. "got %s." % (type(children),))
  2740. self.n, self.n_mode = self._handle_arg_n(n)
  2741. assert ia.is_single_bool(random_order), (
  2742. "Expected random_order to be boolean, got %s." % (
  2743. type(random_order),))
  2744. self.random_order = random_order
  2745. @classmethod
  2746. def _handle_arg_n(cls, n):
  2747. if ia.is_single_number(n):
  2748. n = int(n)
  2749. n_mode = "deterministic"
  2750. elif n is None:
  2751. n = None
  2752. n_mode = "None"
  2753. elif ia.is_iterable(n):
  2754. assert len(n) == 2, (
  2755. "Expected iterable 'n' to contain exactly two values, "
  2756. "got %d." % (len(n),))
  2757. if ia.is_single_number(n[0]) and n[1] is None:
  2758. n = (int(n[0]), None)
  2759. n_mode = "(int,None)"
  2760. elif ia.is_single_number(n[0]) and ia.is_single_number(n[1]):
  2761. n = iap.DiscreteUniform(int(n[0]), int(n[1]))
  2762. n_mode = "stochastic"
  2763. else:
  2764. raise Exception("Expected tuple of (int, None) or (int, int), "
  2765. "got %s" % ([type(el) for el in n],))
  2766. elif isinstance(n, iap.StochasticParameter):
  2767. n_mode = "stochastic"
  2768. else:
  2769. raise Exception("Expected int, (int, None), (int, int) or "
  2770. "StochasticParameter, got %s" % (type(n),))
  2771. return n, n_mode
  2772. def _get_n(self, nb_images, random_state):
  2773. if self.n_mode == "deterministic":
  2774. return [self.n] * nb_images
  2775. if self.n_mode == "None":
  2776. return [len(self)] * nb_images
  2777. if self.n_mode == "(int,None)":
  2778. param = iap.DiscreteUniform(self.n[0], len(self))
  2779. return param.draw_samples((nb_images,), random_state=random_state)
  2780. if self.n_mode == "stochastic":
  2781. return self.n.draw_samples((nb_images,), random_state=random_state)
  2782. raise Exception("Invalid n_mode: %s" % (self.n_mode,))
  2783. def _get_augmenter_order(self, random_state):
  2784. if not self.random_order:
  2785. augmenter_order = np.arange(len(self))
  2786. else:
  2787. augmenter_order = random_state.permutation(len(self))
  2788. return augmenter_order
  2789. def _get_augmenter_active(self, nb_rows, random_state):
  2790. # pylint: disable=invalid-name
  2791. nn = self._get_n(nb_rows, random_state)
  2792. nn = [min(n, len(self)) for n in nn]
  2793. augmenter_active = np.zeros((nb_rows, len(self)), dtype=np.bool)
  2794. for row_idx, n_true in enumerate(nn):
  2795. if n_true > 0:
  2796. augmenter_active[row_idx, 0:n_true] = 1
  2797. for row in augmenter_active:
  2798. random_state.shuffle(row)
  2799. return augmenter_active
  2800. # Added in 0.4.0.
  2801. def _augment_batch_(self, batch, random_state, parents, hooks):
  2802. with batch.propagation_hooks_ctx(self, hooks, parents):
  2803. # This must happen before creating the augmenter_active array,
  2804. # otherwise in case of determinism the number of augmented images
  2805. # would change the random_state's state, resulting in the order
  2806. # being dependent on the number of augmented images (and not be
  2807. # constant). By doing this first, the random state is always the
  2808. # same (when determinism is active), so the order is always the
  2809. # same.
  2810. augmenter_order = self._get_augmenter_order(random_state)
  2811. # create an array of active augmenters per image
  2812. # e.g.
  2813. # [[0, 0, 1],
  2814. # [1, 0, 1],
  2815. # [1, 0, 0]]
  2816. # would signal, that augmenter 3 is active for the first image,
  2817. # augmenter 1 and 3 for the 2nd image and augmenter 1 for the 3rd.
  2818. augmenter_active = self._get_augmenter_active(batch.nb_rows,
  2819. random_state)
  2820. for augmenter_index in augmenter_order:
  2821. active = augmenter_active[:, augmenter_index].nonzero()[0]
  2822. if len(active) > 0:
  2823. batch_sub = batch.subselect_rows_by_indices(active)
  2824. batch_sub = self[augmenter_index].augment_batch_(
  2825. batch_sub,
  2826. parents=parents + [self],
  2827. hooks=hooks
  2828. )
  2829. batch = batch.invert_subselect_rows_by_indices_(active,
  2830. batch_sub)
  2831. return batch
  2832. def _to_deterministic(self):
  2833. augs = [aug.to_deterministic() for aug in self]
  2834. seq = self.copy()
  2835. seq[:] = augs
  2836. seq.random_state = self.random_state.derive_rng_()
  2837. seq.deterministic = True
  2838. return seq
  2839. def get_parameters(self):
  2840. """See :func:`~imgaug.augmenters.meta.Augmenter.get_parameters`."""
  2841. return [self.n]
  2842. def add(self, augmenter):
  2843. """Add an augmenter to the list of child augmenters.
  2844. Parameters
  2845. ----------
  2846. augmenter : imgaug.augmenters.meta.Augmenter
  2847. The augmenter to add.
  2848. """
  2849. self.append(augmenter)
  2850. def get_children_lists(self):
  2851. """See :func:`~imgaug.augmenters.meta.Augmenter.get_children_lists`."""
  2852. return [self]
  2853. def __str__(self):
  2854. augs_str = ", ".join([aug.__str__() for aug in self])
  2855. pattern = (
  2856. "%s("
  2857. "name=%s, n=%s, random_order=%s, augmenters=[%s], deterministic=%s"
  2858. ")")
  2859. return pattern % (
  2860. self.__class__.__name__, self.name, str(self.n),
  2861. str(self.random_order), augs_str, self.deterministic)
  2862. class OneOf(SomeOf):
  2863. """Augmenter that always executes exactly one of its children.
  2864. **Supported dtypes**:
  2865. See :class:`imgaug.augmenters.meta.SomeOf`.
  2866. Parameters
  2867. ----------
  2868. children : imgaug.augmenters.meta.Augmenter or list of imgaug.augmenters.meta.Augmenter
  2869. The choices of augmenters to apply.
  2870. seed : None or int or imgaug.random.RNG or numpy.random.Generator or numpy.random.BitGenerator or numpy.random.SeedSequence or numpy.random.RandomState, optional
  2871. See :func:`~imgaug.augmenters.meta.Augmenter.__init__`.
  2872. name : None or str, optional
  2873. See :func:`~imgaug.augmenters.meta.Augmenter.__init__`.
  2874. random_state : None or int or imgaug.random.RNG or numpy.random.Generator or numpy.random.BitGenerator or numpy.random.SeedSequence or numpy.random.RandomState, optional
  2875. Old name for parameter `seed`.
  2876. Its usage will not yet cause a deprecation warning,
  2877. but it is still recommended to use `seed` now.
  2878. Outdated since 0.4.0.
  2879. deterministic : bool, optional
  2880. Deprecated since 0.4.0.
  2881. See method ``to_deterministic()`` for an alternative and for
  2882. details about what the "deterministic mode" actually does.
  2883. Examples
  2884. --------
  2885. >>> import imgaug.augmenters as iaa
  2886. >>> images = [np.ones((10, 10), dtype=np.uint8)] # dummy example images
  2887. >>> seq = iaa.OneOf([
  2888. >>> iaa.Fliplr(1.0),
  2889. >>> iaa.Flipud(1.0)
  2890. >>> ])
  2891. >>> images_aug = seq.augment_images(images)
  2892. Flip each image either horizontally or vertically.
  2893. >>> images = [np.ones((10, 10), dtype=np.uint8)] # dummy example images
  2894. >>> seq = iaa.OneOf([
  2895. >>> iaa.Fliplr(1.0),
  2896. >>> iaa.Sequential([
  2897. >>> iaa.GaussianBlur(1.0),
  2898. >>> iaa.Dropout(0.05),
  2899. >>> iaa.AdditiveGaussianNoise(0.1*255)
  2900. >>> ]),
  2901. >>> iaa.Noop()
  2902. >>> ])
  2903. >>> images_aug = seq.augment_images(images)
  2904. Either flip each image horizontally, or add blur+dropout+noise or do
  2905. nothing.
  2906. """
  2907. def __init__(self, children,
  2908. seed=None, name=None,
  2909. random_state="deprecated", deterministic="deprecated"):
  2910. super(OneOf, self).__init__(
  2911. n=1,
  2912. children=children,
  2913. random_order=False,
  2914. seed=seed, name=name,
  2915. random_state=random_state, deterministic=deterministic)
  2916. class Sometimes(Augmenter):
  2917. """Apply child augmenter(s) with a probability of `p`.
  2918. Let ``C`` be one or more child augmenters given to
  2919. :class:`~imgaug.augmenters.meta.Sometimes`.
  2920. Let ``p`` be the fraction of images (or other data) to augment.
  2921. Let ``I`` be the input images (or other data).
  2922. Let ``N`` be the number of input images (or other entities).
  2923. Then (on average) ``p*N`` images of ``I`` will be augmented using ``C``.
  2924. **Supported dtypes**:
  2925. * ``uint8``: yes; fully tested
  2926. * ``uint16``: yes; tested
  2927. * ``uint32``: yes; tested
  2928. * ``uint64``: yes; tested
  2929. * ``int8``: yes; tested
  2930. * ``int16``: yes; tested
  2931. * ``int32``: yes; tested
  2932. * ``int64``: yes; tested
  2933. * ``float16``: yes; tested
  2934. * ``float32``: yes; tested
  2935. * ``float64``: yes; tested
  2936. * ``float128``: yes; tested
  2937. * ``bool``: yes; tested
  2938. Parameters
  2939. ----------
  2940. p : float or imgaug.parameters.StochasticParameter, optional
  2941. Sets the probability with which the given augmenters will be applied to
  2942. input images/data. E.g. a value of ``0.5`` will result in ``50%`` of
  2943. all input images (or other augmentables) being augmented.
  2944. then_list : None or imgaug.augmenters.meta.Augmenter or list of imgaug.augmenters.meta.Augmenter, optional
  2945. Augmenter(s) to apply to `p%` percent of all images.
  2946. If this is a list of augmenters, it will be converted to a
  2947. :class:`~imgaug.augmenters.meta.Sequential`.
  2948. else_list : None or imgaug.augmenters.meta.Augmenter or list of imgaug.augmenters.meta.Augmenter, optional
  2949. Augmenter(s) to apply to ``(1-p)`` percent of all images.
  2950. These augmenters will be applied only when the ones in `then_list`
  2951. are *not* applied (either-or-relationship).
  2952. If this is a list of augmenters, it will be converted to a
  2953. :class:`~imgaug.augmenters.meta.Sequential`.
  2954. seed : None or int or imgaug.random.RNG or numpy.random.Generator or numpy.random.BitGenerator or numpy.random.SeedSequence or numpy.random.RandomState, optional
  2955. See :func:`~imgaug.augmenters.meta.Augmenter.__init__`.
  2956. name : None or str, optional
  2957. See :func:`~imgaug.augmenters.meta.Augmenter.__init__`.
  2958. random_state : None or int or imgaug.random.RNG or numpy.random.Generator or numpy.random.BitGenerator or numpy.random.SeedSequence or numpy.random.RandomState, optional
  2959. Old name for parameter `seed`.
  2960. Its usage will not yet cause a deprecation warning,
  2961. but it is still recommended to use `seed` now.
  2962. Outdated since 0.4.0.
  2963. deterministic : bool, optional
  2964. Deprecated since 0.4.0.
  2965. See method ``to_deterministic()`` for an alternative and for
  2966. details about what the "deterministic mode" actually does.
  2967. Examples
  2968. --------
  2969. >>> import imgaug.augmenters as iaa
  2970. >>> aug = iaa.Sometimes(0.5, iaa.GaussianBlur(0.3))
  2971. Apply ``GaussianBlur`` to ``50%`` of all input images.
  2972. >>> aug = iaa.Sometimes(0.5, iaa.GaussianBlur(0.3), iaa.Fliplr(1.0))
  2973. Apply ``GaussianBlur`` to ``50%`` of all input images. Apply ``Fliplr``
  2974. to the other ``50%`` of all input images.
  2975. """
  2976. def __init__(self, p=0.5, then_list=None, else_list=None,
  2977. seed=None, name=None,
  2978. random_state="deprecated", deterministic="deprecated"):
  2979. super(Sometimes, self).__init__(
  2980. seed=seed, name=name,
  2981. random_state=random_state, deterministic=deterministic)
  2982. self.p = iap.handle_probability_param(p, "p")
  2983. self.then_list = handle_children_list(then_list, self.name, "then",
  2984. default=None)
  2985. self.else_list = handle_children_list(else_list, self.name, "else",
  2986. default=None)
  2987. # Added in 0.4.0.
  2988. def _augment_batch_(self, batch, random_state, parents, hooks):
  2989. with batch.propagation_hooks_ctx(self, hooks, parents):
  2990. samples = self.p.draw_samples((batch.nb_rows,),
  2991. random_state=random_state)
  2992. # create lists/arrays of images for if and else lists (one for each)
  2993. # note that np.where returns tuple(array([0, 5, 9, ...])) or
  2994. # tuple(array([]))
  2995. indices_then_list = np.where(samples == 1)[0]
  2996. indices_else_list = np.where(samples == 0)[0]
  2997. indice_lists = [indices_then_list, indices_else_list]
  2998. augmenter_lists = [self.then_list, self.else_list]
  2999. # For then_list: collect augmentables to be processed by then_list
  3000. # augmenters, apply them to the list, then map back to the output
  3001. # list. Analogous for else_list.
  3002. # TODO maybe this would be easier if augment_*() accepted a list
  3003. # that can contain Nones
  3004. for indices, augmenters in zip(indice_lists, augmenter_lists):
  3005. if augmenters is not None and len(augmenters) > 0:
  3006. batch_sub = batch.subselect_rows_by_indices(indices)
  3007. batch_sub = augmenters.augment_batch_(
  3008. batch_sub,
  3009. parents=parents + [self],
  3010. hooks=hooks
  3011. )
  3012. batch = batch.invert_subselect_rows_by_indices_(indices,
  3013. batch_sub)
  3014. return batch
  3015. def _to_deterministic(self):
  3016. aug = self.copy()
  3017. aug.then_list = (aug.then_list.to_deterministic()
  3018. if aug.then_list is not None
  3019. else aug.then_list)
  3020. aug.else_list = (aug.else_list.to_deterministic()
  3021. if aug.else_list is not None
  3022. else aug.else_list)
  3023. aug.deterministic = True
  3024. aug.random_state = self.random_state.derive_rng_()
  3025. return aug
  3026. def get_parameters(self):
  3027. """See :func:`~imgaug.augmenters.meta.Augmenter.get_parameters`."""
  3028. return [self.p]
  3029. def get_children_lists(self):
  3030. """See :func:`~imgaug.augmenters.meta.Augmenter.get_children_lists`."""
  3031. result = []
  3032. if self.then_list is not None:
  3033. result.append(self.then_list)
  3034. if self.else_list is not None:
  3035. result.append(self.else_list)
  3036. return result
  3037. def __str__(self):
  3038. pattern = (
  3039. "%s("
  3040. "p=%s, name=%s, then_list=%s, else_list=%s, deterministic=%s"
  3041. ")")
  3042. return pattern % (
  3043. self.__class__.__name__, self.p, self.name, self.then_list,
  3044. self.else_list, self.deterministic)
  3045. class WithChannels(Augmenter):
  3046. """Apply child augmenters to specific channels.
  3047. Let ``C`` be one or more child augmenters given to this augmenter.
  3048. Let ``H`` be a list of channels.
  3049. Let ``I`` be the input images.
  3050. Then this augmenter will pick the channels ``H`` from each image
  3051. in ``I`` (resulting in new images) and apply ``C`` to them.
  3052. The result of the augmentation will be merged back into the original
  3053. images.
  3054. **Supported dtypes**:
  3055. * ``uint8``: yes; fully tested
  3056. * ``uint16``: yes; tested
  3057. * ``uint32``: yes; tested
  3058. * ``uint64``: yes; tested
  3059. * ``int8``: yes; tested
  3060. * ``int16``: yes; tested
  3061. * ``int32``: yes; tested
  3062. * ``int64``: yes; tested
  3063. * ``float16``: yes; tested
  3064. * ``float32``: yes; tested
  3065. * ``float64``: yes; tested
  3066. * ``float128``: yes; tested
  3067. * ``bool``: yes; tested
  3068. Parameters
  3069. ----------
  3070. channels : None or int or list of int, optional
  3071. Sets the channels to be extracted from each image.
  3072. If ``None``, all channels will be used. Note that this is not
  3073. stochastic - the extracted channels are always the same ones.
  3074. children : imgaug.augmenters.meta.Augmenter or list of imgaug.augmenters.meta.Augmenter or None, optional
  3075. One or more augmenters to apply to images, after the channels
  3076. are extracted.
  3077. seed : None or int or imgaug.random.RNG or numpy.random.Generator or numpy.random.BitGenerator or numpy.random.SeedSequence or numpy.random.RandomState, optional
  3078. See :func:`~imgaug.augmenters.meta.Augmenter.__init__`.
  3079. name : None or str, optional
  3080. See :func:`~imgaug.augmenters.meta.Augmenter.__init__`.
  3081. random_state : None or int or imgaug.random.RNG or numpy.random.Generator or numpy.random.BitGenerator or numpy.random.SeedSequence or numpy.random.RandomState, optional
  3082. Old name for parameter `seed`.
  3083. Its usage will not yet cause a deprecation warning,
  3084. but it is still recommended to use `seed` now.
  3085. Outdated since 0.4.0.
  3086. deterministic : bool, optional
  3087. Deprecated since 0.4.0.
  3088. See method ``to_deterministic()`` for an alternative and for
  3089. details about what the "deterministic mode" actually does.
  3090. Examples
  3091. --------
  3092. >>> import imgaug.augmenters as iaa
  3093. >>> aug = iaa.WithChannels([0], iaa.Add(10))
  3094. Assuming input images are RGB, then this augmenter will add ``10`` only to
  3095. the first channel, i.e. it will make images appear more red.
  3096. """
  3097. def __init__(self, channels=None, children=None,
  3098. seed=None, name=None,
  3099. random_state="deprecated", deterministic="deprecated"):
  3100. super(WithChannels, self).__init__(
  3101. seed=seed, name=name,
  3102. random_state=random_state, deterministic=deterministic)
  3103. # TODO change this to a stochastic parameter
  3104. if channels is None:
  3105. self.channels = None
  3106. elif ia.is_single_integer(channels):
  3107. self.channels = [channels]
  3108. elif ia.is_iterable(channels):
  3109. only_ints = all([
  3110. ia.is_single_integer(channel) for channel in channels])
  3111. assert only_ints, (
  3112. "Expected integers as channels, got %s." % (
  3113. [type(channel) for channel in channels],))
  3114. self.channels = channels
  3115. else:
  3116. raise Exception("Expected None, int or list of ints as channels, "
  3117. "got %s." % (type(channels),))
  3118. self.children = handle_children_list(children, self.name, "then")
  3119. # Added in 0.4.0.
  3120. def _augment_batch_(self, batch, random_state, parents, hooks):
  3121. if self.channels is not None and len(self.channels) == 0:
  3122. return batch
  3123. with batch.propagation_hooks_ctx(self, hooks, parents):
  3124. batch_cp = batch.deepcopy()
  3125. if batch.images is not None:
  3126. batch.images = self._reduce_images_to_channels(batch.images)
  3127. # Note that we augment here all data, including non-image data
  3128. # for which less than 50% of the corresponding image channels
  3129. # were augmented. This is because (a) the system does not yet
  3130. # understand None as cell values and (b) decreasing the length
  3131. # of columns leads to potential RNG misalignments.
  3132. # We replace non-image data that was not supposed to be augmented
  3133. # further below.
  3134. batch = self.children.augment_batch_(
  3135. batch, parents=parents + [self], hooks=hooks)
  3136. # If the shapes changed we cannot insert the augmented channels
  3137. # into the existing ones as the shapes of the non-augmented
  3138. # channels are still the same.
  3139. if batch.images is not None:
  3140. self._assert_lengths_not_changed(batch.images, batch_cp.images)
  3141. self._assert_shapes_not_changed(batch.images, batch_cp.images)
  3142. self._assert_dtypes_not_changed(batch.images, batch_cp.images)
  3143. batch.images = self._recover_images_array(batch.images,
  3144. batch_cp.images)
  3145. for column in batch.columns:
  3146. if column.name != "images":
  3147. value_old = getattr(batch_cp, column.attr_name)
  3148. value = self._replace_unaugmented_cells(column.value,
  3149. value_old)
  3150. setattr(batch, column.attr_name, value)
  3151. if batch.images is not None:
  3152. batch.images = self._invert_reduce_images_to_channels(
  3153. batch.images, batch_cp.images)
  3154. return batch
  3155. # Added in 0.4.0.
  3156. @classmethod
  3157. def _assert_lengths_not_changed(cls, images_aug, images):
  3158. assert len(images_aug) == len(images), (
  3159. "Expected that number of images does not change during "
  3160. "augmentation, but got %d vs. originally %d images." % (
  3161. len(images_aug), len(images)))
  3162. # Added in 0.4.0.
  3163. @classmethod
  3164. def _assert_shapes_not_changed(cls, images_aug, images):
  3165. if ia.is_np_array(images_aug) and ia.is_np_array(images):
  3166. shapes_same = (images_aug.shape[1:3] == images.shape[1:3])
  3167. else:
  3168. shapes_same = all(
  3169. [image_aug.shape[0:2] == image.shape[0:2]
  3170. for image_aug, image
  3171. in zip(images_aug, images)])
  3172. assert shapes_same, (
  3173. "Heights/widths of images changed in WithChannels from "
  3174. "%s to %s, but expected to be the same." % (
  3175. str([image.shape[0:2] for image in images]),
  3176. str([image_aug.shape[0:2] for image_aug in images_aug]),
  3177. ))
  3178. # Added in 0.4.0.
  3179. @classmethod
  3180. def _assert_dtypes_not_changed(cls, images_aug, images):
  3181. if ia.is_np_array(images_aug) and ia.is_np_array(images):
  3182. dtypes_same = (images_aug.dtype.name == images.dtype.name)
  3183. else:
  3184. dtypes_same = all(
  3185. [image_aug.dtype.name == image.dtype.name
  3186. for image_aug, image
  3187. in zip(images_aug, images)])
  3188. assert dtypes_same, (
  3189. "dtypes of images changed in WithChannels from "
  3190. "%s to %s, but expected to be the same." % (
  3191. str([image.dtype.name for image in images]),
  3192. str([image_aug.dtype.name for image_aug in images_aug]),
  3193. ))
  3194. # Added in 0.4.0.
  3195. @classmethod
  3196. def _recover_images_array(cls, images_aug, images):
  3197. if ia.is_np_array(images):
  3198. return np.array(images_aug)
  3199. return images_aug
  3200. # Added in 0.4.0.
  3201. def _reduce_images_to_channels(self, images):
  3202. if self.channels is None:
  3203. return images
  3204. if ia.is_np_array(images):
  3205. return images[..., self.channels]
  3206. return [image[..., self.channels] for image in images]
  3207. # Added in 0.4.0.
  3208. def _invert_reduce_images_to_channels(self, images_aug, images):
  3209. if self.channels is None:
  3210. return images_aug
  3211. for image, image_aug in zip(images, images_aug):
  3212. image[..., self.channels] = image_aug
  3213. return images
  3214. # Added in 0.4.0.
  3215. def _replace_unaugmented_cells(self, augmentables_aug, augmentables):
  3216. if self.channels is None:
  3217. return augmentables_aug
  3218. nb_channels_to_aug = len(self.channels)
  3219. nb_channels_lst = [augm.shape[2] if len(augm.shape) > 2 else 1
  3220. for augm in augmentables]
  3221. # We use the augmented form of a non-image if at least 50% of the
  3222. # corresponding image's channels were augmented. Otherwise we use
  3223. # the unaugmented form.
  3224. fraction_augmented_lst = [nb_channels_to_aug/nb_channels
  3225. for nb_channels in nb_channels_lst]
  3226. result = [
  3227. (augmentable_aug if fraction_augmented >= 0.5 else augmentable)
  3228. for augmentable_aug, augmentable, fraction_augmented
  3229. in zip(augmentables_aug, augmentables, fraction_augmented_lst)]
  3230. return result
  3231. def _to_deterministic(self):
  3232. aug = self.copy()
  3233. aug.children = aug.children.to_deterministic()
  3234. aug.deterministic = True
  3235. aug.random_state = self.random_state.derive_rng_()
  3236. return aug
  3237. def get_parameters(self):
  3238. """See :func:`~imgaug.augmenters.meta.Augmenter.get_parameters`."""
  3239. return [self.channels]
  3240. def get_children_lists(self):
  3241. """See :func:`~imgaug.augmenters.meta.Augmenter.get_children_lists`."""
  3242. return [self.children]
  3243. def __str__(self):
  3244. pattern = (
  3245. "%s("
  3246. "channels=%s, name=%s, children=%s, deterministic=%s"
  3247. ")")
  3248. return pattern % (self.__class__.__name__, self.channels, self.name,
  3249. self.children, self.deterministic)
  3250. class Identity(Augmenter):
  3251. """Augmenter that does not change the input data.
  3252. This augmenter is useful e.g. during validation/testing as it allows
  3253. to re-use the training code without actually performing any augmentation.
  3254. Added in 0.4.0.
  3255. **Supported dtypes**:
  3256. * ``uint8``: yes; fully tested
  3257. * ``uint16``: yes; tested
  3258. * ``uint32``: yes; tested
  3259. * ``uint64``: yes; tested
  3260. * ``int8``: yes; tested
  3261. * ``int16``: yes; tested
  3262. * ``int32``: yes; tested
  3263. * ``int64``: yes; tested
  3264. * ``float16``: yes; tested
  3265. * ``float32``: yes; tested
  3266. * ``float64``: yes; tested
  3267. * ``float128``: yes; tested
  3268. * ``bool``: yes; tested
  3269. Parameters
  3270. ----------
  3271. seed : None or int or imgaug.random.RNG or numpy.random.Generator or numpy.random.BitGenerator or numpy.random.SeedSequence or numpy.random.RandomState, optional
  3272. See :func:`~imgaug.augmenters.meta.Augmenter.__init__`.
  3273. name : None or str, optional
  3274. See :func:`~imgaug.augmenters.meta.Augmenter.__init__`.
  3275. random_state : None or int or imgaug.random.RNG or numpy.random.Generator or numpy.random.BitGenerator or numpy.random.SeedSequence or numpy.random.RandomState, optional
  3276. Old name for parameter `seed`.
  3277. Its usage will not yet cause a deprecation warning,
  3278. but it is still recommended to use `seed` now.
  3279. Outdated since 0.4.0.
  3280. deterministic : bool, optional
  3281. Deprecated since 0.4.0.
  3282. See method ``to_deterministic()`` for an alternative and for
  3283. details about what the "deterministic mode" actually does.
  3284. Examples
  3285. --------
  3286. >>> import imgaug.augmenters as iaa
  3287. >>> aug = iaa.Identity()
  3288. Create an augmenter that does not change inputs.
  3289. """
  3290. # Added in 0.4.0.
  3291. def __init__(self,
  3292. seed=None, name=None,
  3293. random_state="deprecated", deterministic="deprecated"):
  3294. super(Identity, self).__init__(
  3295. seed=seed, name=name,
  3296. random_state=random_state, deterministic=deterministic)
  3297. # Added in 0.4.0.
  3298. def _augment_batch_(self, batch, random_state, parents, hooks):
  3299. return batch
  3300. # Added in 0.4.0.
  3301. def get_parameters(self):
  3302. """See :func:`~imgaug.augmenters.meta.Augmenter.get_parameters`."""
  3303. return []
  3304. class Noop(Identity):
  3305. """Alias for augmenter :class:`Identity`.
  3306. It is recommended to now use :class:`Identity`. :class:`Noop` might be
  3307. deprecated in the future.
  3308. **Supported dtypes**:
  3309. See :class:`~imgaug.augmenters.meta.Identity`.
  3310. Parameters
  3311. ----------
  3312. seed : None or int or imgaug.random.RNG or numpy.random.Generator or numpy.random.BitGenerator or numpy.random.SeedSequence or numpy.random.RandomState, optional
  3313. See :func:`~imgaug.augmenters.meta.Augmenter.__init__`.
  3314. name : None or str, optional
  3315. See :func:`~imgaug.augmenters.meta.Augmenter.__init__`.
  3316. random_state : None or int or imgaug.random.RNG or numpy.random.Generator or numpy.random.BitGenerator or numpy.random.SeedSequence or numpy.random.RandomState, optional
  3317. Old name for parameter `seed`.
  3318. Its usage will not yet cause a deprecation warning,
  3319. but it is still recommended to use `seed` now.
  3320. Outdated since 0.4.0.
  3321. deterministic : bool, optional
  3322. Deprecated since 0.4.0.
  3323. See method ``to_deterministic()`` for an alternative and for
  3324. details about what the "deterministic mode" actually does.
  3325. Examples
  3326. --------
  3327. >>> import imgaug.augmenters as iaa
  3328. >>> aug = iaa.Noop()
  3329. Create an augmenter that does not change inputs.
  3330. """
  3331. def __init__(self,
  3332. seed=None, name=None,
  3333. random_state="deprecated", deterministic="deprecated"):
  3334. super(Noop, self).__init__(
  3335. seed=seed, name=name,
  3336. random_state=random_state, deterministic=deterministic)
  3337. class Lambda(Augmenter):
  3338. """Augmenter that calls a lambda function for each input batch.
  3339. This is useful to add missing functions to a list of augmenters.
  3340. **Supported dtypes**:
  3341. * ``uint8``: yes; fully tested
  3342. * ``uint16``: yes; tested
  3343. * ``uint32``: yes; tested
  3344. * ``uint64``: yes; tested
  3345. * ``int8``: yes; tested
  3346. * ``int16``: yes; tested
  3347. * ``int32``: yes; tested
  3348. * ``int64``: yes; tested
  3349. * ``float16``: yes; tested
  3350. * ``float32``: yes; tested
  3351. * ``float64``: yes; tested
  3352. * ``float128``: yes; tested
  3353. * ``bool``: yes; tested
  3354. Parameters
  3355. ----------
  3356. func_images : None or callable, optional
  3357. The function to call for each batch of images.
  3358. It must follow the form::
  3359. function(images, random_state, parents, hooks)
  3360. and return the changed images (may be transformed in-place).
  3361. This is essentially the interface of
  3362. :func:`~imgaug.augmenters.meta.Augmenter._augment_images`.
  3363. If this is ``None`` instead of a function, the images will not be
  3364. altered.
  3365. func_heatmaps : None or callable, optional
  3366. The function to call for each batch of heatmaps.
  3367. It must follow the form::
  3368. function(heatmaps, random_state, parents, hooks)
  3369. and return the changed heatmaps (may be transformed in-place).
  3370. This is essentially the interface of
  3371. :func:`~imgaug.augmenters.meta.Augmenter._augment_heatmaps`.
  3372. If this is ``None`` instead of a function, the heatmaps will not be
  3373. altered.
  3374. func_segmentation_maps : None or callable, optional
  3375. The function to call for each batch of segmentation maps.
  3376. It must follow the form::
  3377. function(segmaps, random_state, parents, hooks)
  3378. and return the changed segmaps (may be transformed in-place).
  3379. This is essentially the interface of
  3380. :func:`~imgaug.augmenters.meta.Augmenter._augment_segmentation_maps`.
  3381. If this is ``None`` instead of a function, the segmentatio maps will
  3382. not be altered.
  3383. func_keypoints : None or callable, optional
  3384. The function to call for each batch of keypoints.
  3385. It must follow the form::
  3386. function(keypoints_on_images, random_state, parents, hooks)
  3387. and return the changed keypoints (may be transformed in-place).
  3388. This is essentially the interface of
  3389. :func:`~imgaug.augmenters.meta.Augmenter._augment_keypoints`.
  3390. If this is ``None`` instead of a function, the keypoints will not be
  3391. altered.
  3392. func_bounding_boxes : "keypoints" or None or callable, optional
  3393. The function to call for each batch of bounding boxes.
  3394. It must follow the form::
  3395. function(bounding_boxes_on_images, random_state, parents, hooks)
  3396. and return the changed bounding boxes (may be transformed in-place).
  3397. This is essentially the interface of
  3398. :func:`~imgaug.augmenters.meta.Augmenter._augment_bounding_boxes`.
  3399. If this is ``None`` instead of a function, the bounding boxes will not
  3400. be altered.
  3401. If this is the string ``"keypoints"`` instead of a function, the
  3402. bounding boxes will automatically be augmented by transforming their
  3403. corner vertices to keypoints and calling `func_keypoints`.
  3404. Added in 0.4.0.
  3405. func_polygons : "keypoints" or None or callable, optional
  3406. The function to call for each batch of polygons.
  3407. It must follow the form::
  3408. function(polygons_on_images, random_state, parents, hooks)
  3409. and return the changed polygons (may be transformed in-place).
  3410. This is essentially the interface of
  3411. :func:`~imgaug.augmenters.meta.Augmenter._augment_polygons`.
  3412. If this is ``None`` instead of a function, the polygons will not
  3413. be altered.
  3414. If this is the string ``"keypoints"`` instead of a function, the
  3415. polygons will automatically be augmented by transforming their
  3416. corner vertices to keypoints and calling `func_keypoints`.
  3417. func_line_strings : "keypoints" or None or callable, optional
  3418. The function to call for each batch of line strings.
  3419. It must follow the form::
  3420. function(line_strings_on_images, random_state, parents, hooks)
  3421. and return the changed line strings (may be transformed in-place).
  3422. This is essentially the interface of
  3423. :func:`~imgaug.augmenters.meta.Augmenter._augment_line_strings`.
  3424. If this is ``None`` instead of a function, the line strings will not
  3425. be altered.
  3426. If this is the string ``"keypoints"`` instead of a function, the
  3427. line strings will automatically be augmented by transforming their
  3428. corner vertices to keypoints and calling `func_keypoints`.
  3429. Added in 0.4.0.
  3430. seed : None or int or imgaug.random.RNG or numpy.random.Generator or numpy.random.BitGenerator or numpy.random.SeedSequence or numpy.random.RandomState, optional
  3431. See :func:`~imgaug.augmenters.meta.Augmenter.__init__`.
  3432. name : None or str, optional
  3433. See :func:`~imgaug.augmenters.meta.Augmenter.__init__`.
  3434. random_state : None or int or imgaug.random.RNG or numpy.random.Generator or numpy.random.BitGenerator or numpy.random.SeedSequence or numpy.random.RandomState, optional
  3435. Old name for parameter `seed`.
  3436. Its usage will not yet cause a deprecation warning,
  3437. but it is still recommended to use `seed` now.
  3438. Outdated since 0.4.0.
  3439. deterministic : bool, optional
  3440. Deprecated since 0.4.0.
  3441. See method ``to_deterministic()`` for an alternative and for
  3442. details about what the "deterministic mode" actually does.
  3443. Examples
  3444. --------
  3445. >>> import imgaug.augmenters as iaa
  3446. >>>
  3447. >>> def func_images(images, random_state, parents, hooks):
  3448. >>> images[:, ::2, :, :] = 0
  3449. >>> return images
  3450. >>>
  3451. >>> aug = iaa.Lambda(
  3452. >>> func_images=func_images
  3453. >>> )
  3454. Replace every second row in input images with black pixels. Leave
  3455. other data (e.g. heatmaps, keypoints) unchanged.
  3456. >>> def func_images(images, random_state, parents, hooks):
  3457. >>> images[:, ::2, :, :] = 0
  3458. >>> return images
  3459. >>>
  3460. >>> def func_heatmaps(heatmaps, random_state, parents, hooks):
  3461. >>> for heatmaps_i in heatmaps:
  3462. >>> heatmaps.arr_0to1[::2, :, :] = 0
  3463. >>> return heatmaps
  3464. >>>
  3465. >>> def func_keypoints(keypoints_on_images, random_state, parents, hooks):
  3466. >>> return keypoints_on_images
  3467. >>>
  3468. >>> aug = iaa.Lambda(
  3469. >>> func_images=func_images,
  3470. >>> func_heatmaps=func_heatmaps,
  3471. >>> func_keypoints=func_keypoints
  3472. >>> )
  3473. Replace every second row in images with black pixels, set every second
  3474. row in heatmaps to zero and leave other data (e.g. keypoints)
  3475. unchanged.
  3476. """
  3477. def __init__(self, func_images=None, func_heatmaps=None,
  3478. func_segmentation_maps=None, func_keypoints=None,
  3479. func_bounding_boxes="keypoints", func_polygons="keypoints",
  3480. func_line_strings="keypoints",
  3481. seed=None, name=None,
  3482. random_state="deprecated", deterministic="deprecated"):
  3483. super(Lambda, self).__init__(
  3484. seed=seed, name=name,
  3485. random_state=random_state, deterministic=deterministic)
  3486. self.func_images = func_images
  3487. self.func_heatmaps = func_heatmaps
  3488. self.func_segmentation_maps = func_segmentation_maps
  3489. self.func_keypoints = func_keypoints
  3490. self.func_bounding_boxes = func_bounding_boxes
  3491. self.func_polygons = func_polygons
  3492. self.func_line_strings = func_line_strings
  3493. def _augment_images(self, images, random_state, parents, hooks):
  3494. if self.func_images is not None:
  3495. return self.func_images(images, random_state, parents, hooks)
  3496. return images
  3497. def _augment_heatmaps(self, heatmaps, random_state, parents, hooks):
  3498. if self.func_heatmaps is not None:
  3499. result = self.func_heatmaps(heatmaps, random_state, parents, hooks)
  3500. assert ia.is_iterable(result), (
  3501. "Expected callback function for heatmaps to return list of "
  3502. "imgaug.HeatmapsOnImage instances, got %s." % (
  3503. type(result),))
  3504. only_heatmaps = all([
  3505. isinstance(el, ia.HeatmapsOnImage) for el in result])
  3506. assert only_heatmaps, (
  3507. "Expected callback function for heatmaps to return list of "
  3508. "imgaug.HeatmapsOnImage instances, got %s." % (
  3509. [type(el) for el in result],))
  3510. return result
  3511. return heatmaps
  3512. def _augment_segmentation_maps(self, segmaps, random_state, parents, hooks):
  3513. if self.func_segmentation_maps is not None:
  3514. result = self.func_segmentation_maps(segmaps, random_state,
  3515. parents, hooks)
  3516. assert ia.is_iterable(result), (
  3517. "Expected callback function for segmentation maps to return "
  3518. "list of imgaug.SegmentationMapsOnImage() instances, "
  3519. "got %s." % (type(result),))
  3520. only_segmaps = all([
  3521. isinstance(el, ia.SegmentationMapsOnImage) for el in result])
  3522. assert only_segmaps, (
  3523. "Expected callback function for segmentation maps to return "
  3524. "list of imgaug.SegmentationMapsOnImage() instances, "
  3525. "got %s." % ([type(el) for el in result],))
  3526. return result
  3527. return segmaps
  3528. def _augment_keypoints(self, keypoints_on_images, random_state, parents,
  3529. hooks):
  3530. if self.func_keypoints is not None:
  3531. result = self.func_keypoints(keypoints_on_images, random_state,
  3532. parents, hooks)
  3533. assert ia.is_iterable(result), (
  3534. "Expected callback function for keypoints to return list of "
  3535. "imgaug.augmentables.kps.KeypointsOnImage instances, "
  3536. "got %s." % (type(result),))
  3537. only_keypoints = all([
  3538. isinstance(el, ia.KeypointsOnImage) for el in result])
  3539. assert only_keypoints, (
  3540. "Expected callback function for keypoints to return list of "
  3541. "imgaug.augmentables.kps.KeypointsOnImage instances, "
  3542. "got %s." % ([type(el) for el in result],))
  3543. return result
  3544. return keypoints_on_images
  3545. def _augment_polygons(self, polygons_on_images, random_state, parents,
  3546. hooks):
  3547. from imgaug.augmentables.polys import _ConcavePolygonRecoverer
  3548. if self.func_polygons == "keypoints":
  3549. return self._augment_polygons_as_keypoints(
  3550. polygons_on_images, random_state, parents, hooks,
  3551. recoverer=_ConcavePolygonRecoverer())
  3552. if self.func_polygons is not None:
  3553. result = self.func_polygons(polygons_on_images, random_state,
  3554. parents, hooks)
  3555. assert ia.is_iterable(result), (
  3556. "Expected callback function for polygons to return list of "
  3557. "imgaug.augmentables.polys.PolygonsOnImage instances, "
  3558. "got %s." % (type(result),))
  3559. only_polygons = all([
  3560. isinstance(el, ia.PolygonsOnImage) for el in result])
  3561. assert only_polygons, (
  3562. "Expected callback function for polygons to return list of "
  3563. "imgaug.augmentables.polys.PolygonsOnImage instances, "
  3564. "got %s." % ([type(el) for el in result],))
  3565. return result
  3566. return polygons_on_images
  3567. # Added in 0.4.0.
  3568. def _augment_line_strings(self, line_strings_on_images, random_state,
  3569. parents, hooks):
  3570. if self.func_line_strings == "keypoints":
  3571. return self._augment_line_strings_as_keypoints(
  3572. line_strings_on_images, random_state, parents, hooks)
  3573. if self.func_line_strings is not None:
  3574. result = self.func_line_strings(line_strings_on_images,
  3575. random_state, parents, hooks)
  3576. assert ia.is_iterable(result), (
  3577. "Expected callback function for line strings to return list of "
  3578. "imgaug.augmentables.lines.LineStringsOnImage instances, "
  3579. "got %s." % (type(result),))
  3580. only_ls = all([
  3581. isinstance(el, ia.LineStringsOnImage) for el in result])
  3582. assert only_ls, (
  3583. "Expected callback function for line strings to return list of "
  3584. "imgaug.augmentables.lines.LineStringsOnImages instances, "
  3585. "got %s." % ([type(el) for el in result],))
  3586. return result
  3587. return line_strings_on_images
  3588. # Added in 0.4.0.
  3589. def _augment_bounding_boxes(self, bounding_boxes_on_images, random_state,
  3590. parents, hooks):
  3591. if self.func_bounding_boxes == "keypoints":
  3592. return self._augment_bounding_boxes_as_keypoints(
  3593. bounding_boxes_on_images, random_state, parents, hooks)
  3594. if self.func_bounding_boxes is not None:
  3595. result = self.func_bounding_boxes(
  3596. bounding_boxes_on_images, random_state, parents, hooks)
  3597. assert ia.is_iterable(result), (
  3598. "Expected callback function for bounding boxes to return list "
  3599. "of imgaug.augmentables.bbs.BoundingBoxesOnImage instances, "
  3600. "got %s." % (type(result),))
  3601. only_bbs = all([
  3602. isinstance(el, ia.BoundingBoxesOnImage) for el in result])
  3603. assert only_bbs, (
  3604. "Expected callback function for polygons to return list of "
  3605. "imgaug.augmentables.polys.PolygonsOnImage instances, "
  3606. "got %s." % ([type(el) for el in result],))
  3607. for bboi in bounding_boxes_on_images:
  3608. for bb in bboi.bounding_boxes:
  3609. if bb.x1 > bb.x2:
  3610. bb.x1, bb.x2 = bb.x2, bb.x1
  3611. if bb.y1 > bb.y2:
  3612. bb.y1, bb.y2 = bb.y2, bb.y1
  3613. return result
  3614. return bounding_boxes_on_images
  3615. def get_parameters(self):
  3616. """See :func:`~imgaug.augmenters.meta.Augmenter.get_parameters`."""
  3617. return []
  3618. class AssertLambda(Lambda):
  3619. """Assert conditions based on lambda-function to be the case for input data.
  3620. This augmenter applies a lambda function to each image or other input.
  3621. The lambda function must return ``True`` or ``False``. If ``False`` is
  3622. returned, an assertion error is produced.
  3623. This is useful to ensure that generic assumption about the input data
  3624. are actually the case and error out early otherwise.
  3625. **Supported dtypes**:
  3626. * ``uint8``: yes; fully tested
  3627. * ``uint16``: yes; tested
  3628. * ``uint32``: yes; tested
  3629. * ``uint64``: yes; tested
  3630. * ``int8``: yes; tested
  3631. * ``int16``: yes; tested
  3632. * ``int32``: yes; tested
  3633. * ``int64``: yes; tested
  3634. * ``float16``: yes; tested
  3635. * ``float32``: yes; tested
  3636. * ``float64``: yes; tested
  3637. * ``float128``: yes; tested
  3638. * ``bool``: yes; tested
  3639. Parameters
  3640. ----------
  3641. func_images : None or callable, optional
  3642. The function to call for each batch of images.
  3643. It must follow the form::
  3644. function(images, random_state, parents, hooks)
  3645. and return either ``True`` (valid input) or ``False`` (invalid input).
  3646. It essentially re-uses the interface of
  3647. :func:`~imgaug.augmenters.meta.Augmenter._augment_images`.
  3648. func_heatmaps : None or callable, optional
  3649. The function to call for each batch of heatmaps.
  3650. It must follow the form::
  3651. function(heatmaps, random_state, parents, hooks)
  3652. and return either ``True`` (valid input) or ``False`` (invalid input).
  3653. It essentially re-uses the interface of
  3654. :func:`~imgaug.augmenters.meta.Augmenter._augment_heatmaps`.
  3655. func_segmentation_maps : None or callable, optional
  3656. The function to call for each batch of segmentation maps.
  3657. It must follow the form::
  3658. function(segmaps, random_state, parents, hooks)
  3659. and return either ``True`` (valid input) or ``False`` (invalid input).
  3660. It essentially re-uses the interface of
  3661. :func:`~imgaug.augmenters.meta.Augmenter._augment_segmentation_maps`.
  3662. func_keypoints : None or callable, optional
  3663. The function to call for each batch of keypoints.
  3664. It must follow the form::
  3665. function(keypoints_on_images, random_state, parents, hooks)
  3666. and return either ``True`` (valid input) or ``False`` (invalid input).
  3667. It essentially re-uses the interface of
  3668. :func:`~imgaug.augmenters.meta.Augmenter._augment_keypoints`.
  3669. func_bounding_boxes : None or callable, optional
  3670. The function to call for each batch of bounding boxes.
  3671. It must follow the form::
  3672. function(bounding_boxes_on_images, random_state, parents, hooks)
  3673. and return either ``True`` (valid input) or ``False`` (invalid input).
  3674. It essentially re-uses the interface of
  3675. :func:`~imgaug.augmenters.meta.Augmenter._augment_bounding_boxes`.
  3676. Added in 0.4.0.
  3677. func_polygons : None or callable, optional
  3678. The function to call for each batch of polygons.
  3679. It must follow the form::
  3680. function(polygons_on_images, random_state, parents, hooks)
  3681. and return either ``True`` (valid input) or ``False`` (invalid input).
  3682. It essentially re-uses the interface of
  3683. :func:`~imgaug.augmenters.meta.Augmenter._augment_polygons`.
  3684. func_line_strings : None or callable, optional
  3685. The function to call for each batch of line strings.
  3686. It must follow the form::
  3687. function(line_strings_on_images, random_state, parents, hooks)
  3688. and return either ``True`` (valid input) or ``False`` (invalid input).
  3689. It essentially re-uses the interface of
  3690. :func:`~imgaug.augmenters.meta.Augmenter._augment_line_strings`.
  3691. Added in 0.4.0.
  3692. seed : None or int or imgaug.random.RNG or numpy.random.Generator or numpy.random.BitGenerator or numpy.random.SeedSequence or numpy.random.RandomState, optional
  3693. See :func:`~imgaug.augmenters.meta.Augmenter.__init__`.
  3694. name : None or str, optional
  3695. See :func:`~imgaug.augmenters.meta.Augmenter.__init__`.
  3696. random_state : None or int or imgaug.random.RNG or numpy.random.Generator or numpy.random.BitGenerator or numpy.random.SeedSequence or numpy.random.RandomState, optional
  3697. Old name for parameter `seed`.
  3698. Its usage will not yet cause a deprecation warning,
  3699. but it is still recommended to use `seed` now.
  3700. Outdated since 0.4.0.
  3701. deterministic : bool, optional
  3702. Deprecated since 0.4.0.
  3703. See method ``to_deterministic()`` for an alternative and for
  3704. details about what the "deterministic mode" actually does.
  3705. """
  3706. def __init__(self, func_images=None, func_heatmaps=None,
  3707. func_segmentation_maps=None, func_keypoints=None,
  3708. func_bounding_boxes=None, func_polygons=None,
  3709. func_line_strings=None,
  3710. seed=None, name=None,
  3711. random_state="deprecated", deterministic="deprecated"):
  3712. def _default(var, augmentable_name):
  3713. return (
  3714. _AssertLambdaCallback(var, augmentable_name=augmentable_name)
  3715. if var is not None
  3716. else None
  3717. )
  3718. super(AssertLambda, self).__init__(
  3719. func_images=_default(func_images, "images"),
  3720. func_heatmaps=_default(func_heatmaps, "heatmaps"),
  3721. func_segmentation_maps=_default(func_segmentation_maps,
  3722. "segmentation_maps"),
  3723. func_keypoints=_default(func_keypoints, "keypoints"),
  3724. func_bounding_boxes=_default(func_bounding_boxes, "bounding_boxes"),
  3725. func_polygons=_default(func_polygons, "polygons"),
  3726. func_line_strings=_default(func_line_strings, "line_strings"),
  3727. seed=seed, name=name,
  3728. random_state=random_state, deterministic=deterministic)
  3729. # Added in 0.4.0.
  3730. class _AssertLambdaCallback(object):
  3731. # Added in 0.4.0.
  3732. def __init__(self, func, augmentable_name):
  3733. self.func = func
  3734. self.augmentable_name = augmentable_name
  3735. # Added in 0.4.0.
  3736. def __call__(self, augmentables, random_state, parents, hooks):
  3737. assert self.func(augmentables, random_state, parents, hooks), (
  3738. "Input %s did not fulfill user-defined assertion in "
  3739. "AssertLambda." % (self.augmentable_name,))
  3740. return augmentables
  3741. # TODO add tests for segmaps
  3742. # TODO This evaluates .shape for kps/polys, but the array shape for
  3743. # heatmaps/segmaps. Not very consistent.
  3744. class AssertShape(Lambda):
  3745. """Assert that inputs have a specified shape.
  3746. **Supported dtypes**:
  3747. * ``uint8``: yes; fully tested
  3748. * ``uint16``: yes; tested
  3749. * ``uint32``: yes; tested
  3750. * ``uint64``: yes; tested
  3751. * ``int8``: yes; tested
  3752. * ``int16``: yes; tested
  3753. * ``int32``: yes; tested
  3754. * ``int64``: yes; tested
  3755. * ``float16``: yes; tested
  3756. * ``float32``: yes; tested
  3757. * ``float64``: yes; tested
  3758. * ``float128``: yes; tested
  3759. * ``bool``: yes; tested
  3760. Parameters
  3761. ----------
  3762. shape : tuple
  3763. The expected shape, given as a ``tuple``. The number of entries in
  3764. the ``tuple`` must match the number of dimensions, i.e. it must
  3765. contain four entries for ``(N, H, W, C)``. If only a single entity
  3766. is augmented, e.g. via
  3767. :func:`~imgaug.augmenters.meta.Augmenter.augment_image`, then ``N`` is
  3768. ``1`` in the input to this augmenter. Images that don't have
  3769. a channel axis will automatically have one assigned, i.e. ``C`` is
  3770. at least ``1``.
  3771. For each component of the ``tuple`` one of the following datatypes
  3772. may be used:
  3773. * If a component is ``None``, any value for that dimensions is
  3774. accepted.
  3775. * If a component is ``int``, exactly that value (and no other one)
  3776. will be accepted for that dimension.
  3777. * If a component is a ``tuple`` of two ``int`` s with values ``a``
  3778. and ``b``, only a value within the interval ``[a, b)`` will be
  3779. accepted for that dimension.
  3780. * If an entry is a ``list`` of ``int`` s, only a value from that
  3781. ``list`` will be accepted for that dimension.
  3782. check_images : bool, optional
  3783. Whether to validate input images via the given shape.
  3784. check_heatmaps : bool, optional
  3785. Whether to validate input heatmaps via the given shape.
  3786. The number of heatmaps will be verified as ``N``. For each
  3787. :class:`~imgaug.augmentables.heatmaps.HeatmapsOnImage` instance
  3788. its array's height and width will be verified as ``H`` and ``W``,
  3789. but not the channel count.
  3790. check_segmentation_maps : bool, optional
  3791. Whether to validate input segmentation maps via the given shape.
  3792. The number of segmentation maps will be verified as ``N``. For each
  3793. :class:`~imgaug.augmentables.segmaps.SegmentationMapOnImage` instance
  3794. its array's height and width will be verified as ``H`` and ``W``,
  3795. but not the channel count.
  3796. check_keypoints : bool, optional
  3797. Whether to validate input keypoints via the given shape.
  3798. This will check (a) the number of keypoints and (b) for each
  3799. :class:`~imgaug.augmentables.kps.KeypointsOnImage` instance the
  3800. ``.shape`` attribute, i.e. the shape of the corresponding image.
  3801. check_bounding_boxes : bool, optional
  3802. Whether to validate input bounding boxes via the given shape.
  3803. This will check (a) the number of bounding boxes and (b) for each
  3804. :class:`~imgaug.augmentables.bbs.BoundingBoxesOnImage` instance the
  3805. ``.shape`` attribute, i.e. the shape of the corresponding image.
  3806. Added in 0.4.0.
  3807. check_polygons : bool, optional
  3808. Whether to validate input polygons via the given shape.
  3809. This will check (a) the number of polygons and (b) for each
  3810. :class:`~imgaug.augmentables.polys.PolygonsOnImage` instance the
  3811. ``.shape`` attribute, i.e. the shape of the corresponding image.
  3812. check_line_strings : bool, optional
  3813. Whether to validate input line strings via the given shape.
  3814. This will check (a) the number of line strings and (b) for each
  3815. :class:`~imgaug.augmentables.lines.LineStringsOnImage` instance the
  3816. ``.shape`` attribute, i.e. the shape of the corresponding image.
  3817. Added in 0.4.0.
  3818. seed : None or int or imgaug.random.RNG or numpy.random.Generator or numpy.random.BitGenerator or numpy.random.SeedSequence or numpy.random.RandomState, optional
  3819. See :func:`~imgaug.augmenters.meta.Augmenter.__init__`.
  3820. name : None or str, optional
  3821. See :func:`~imgaug.augmenters.meta.Augmenter.__init__`.
  3822. random_state : None or int or imgaug.random.RNG or numpy.random.Generator or numpy.random.BitGenerator or numpy.random.SeedSequence or numpy.random.RandomState, optional
  3823. Old name for parameter `seed`.
  3824. Its usage will not yet cause a deprecation warning,
  3825. but it is still recommended to use `seed` now.
  3826. Outdated since 0.4.0.
  3827. deterministic : bool, optional
  3828. Deprecated since 0.4.0.
  3829. See method ``to_deterministic()`` for an alternative and for
  3830. details about what the "deterministic mode" actually does.
  3831. Examples
  3832. --------
  3833. >>> import imgaug.augmenters as iaa
  3834. >>> seq = iaa.Sequential([
  3835. >>> iaa.AssertShape((None, 32, 32, 3)),
  3836. >>> iaa.Fliplr(0.5)
  3837. >>> ])
  3838. Verify first for each image batch if it contains a variable number of
  3839. ``32x32`` images with ``3`` channels each. Only if that check succeeds, the
  3840. horizontal flip will be executed. Otherwise an assertion error will be
  3841. raised.
  3842. >>> seq = iaa.Sequential([
  3843. >>> iaa.AssertShape((None, (32, 64), 32, [1, 3])),
  3844. >>> iaa.Fliplr(0.5)
  3845. >>> ])
  3846. Similar to the above example, but now the height may be in the interval
  3847. ``[32, 64)`` and the number of channels may be either ``1`` or ``3``.
  3848. """
  3849. def __init__(self, shape, check_images=True, check_heatmaps=True,
  3850. check_segmentation_maps=True, check_keypoints=True,
  3851. check_bounding_boxes=True, check_polygons=True,
  3852. check_line_strings=True,
  3853. seed=None, name=None,
  3854. random_state="deprecated", deterministic="deprecated"):
  3855. assert len(shape) == 4, (
  3856. "Expected shape to have length 4, got %d with shape: %s." % (
  3857. len(shape), str(shape)))
  3858. self.shape = shape
  3859. def _default(func, do_use):
  3860. return func if do_use else None
  3861. super(AssertShape, self).__init__(
  3862. func_images=_default(_AssertShapeImagesCheck(shape),
  3863. check_images),
  3864. func_heatmaps=_default(_AssertShapeHeatmapsCheck(shape),
  3865. check_heatmaps),
  3866. func_segmentation_maps=_default(_AssertShapeSegmapCheck(shape),
  3867. check_segmentation_maps),
  3868. func_keypoints=_default(_AssertShapeKeypointsCheck(shape),
  3869. check_keypoints),
  3870. func_bounding_boxes=_default(_AssertShapeBoundingBoxesCheck(shape),
  3871. check_bounding_boxes),
  3872. func_polygons=_default(_AssertShapePolygonsCheck(shape),
  3873. check_polygons),
  3874. func_line_strings=_default(_AssertShapeLineStringsCheck(shape),
  3875. check_line_strings),
  3876. seed=seed, name=name,
  3877. random_state=random_state, deterministic=deterministic)
  3878. @classmethod
  3879. def _compare(cls, observed, expected, dimension, image_index):
  3880. if expected is not None:
  3881. if ia.is_single_integer(expected):
  3882. assert observed == expected, (
  3883. "Expected dim %d (entry index: %s) to have value %d, "
  3884. "got %d." % (dimension, image_index, expected,
  3885. observed))
  3886. elif isinstance(expected, tuple):
  3887. assert len(expected) == 2, (
  3888. "Expected tuple argument 'expected' to contain "
  3889. "exactly 2 entries, got %d." % (len(expected),))
  3890. assert expected[0] <= observed < expected[1], (
  3891. "Expected dim %d (entry index: %s) to have value in "
  3892. "interval [%d, %d), got %d." % (
  3893. dimension, image_index, expected[0], expected[1],
  3894. observed))
  3895. elif isinstance(expected, list):
  3896. assert any([observed == val for val in expected]), (
  3897. "Expected dim %d (entry index: %s) to have any value "
  3898. "of %s, got %d." % (
  3899. dimension, image_index, str(expected), observed))
  3900. else:
  3901. raise Exception(
  3902. "Invalid datatype for shape entry %d, expected each "
  3903. "entry to be an integer, a tuple (with two entries) "
  3904. "or a list, got %s." % (dimension, type(expected),))
  3905. @classmethod
  3906. def _check_shapes(cls, shapes, shape_target):
  3907. if shape_target[0] is not None:
  3908. cls._compare(len(shapes), shape_target[0], 0, "ALL")
  3909. for augm_idx, shape in enumerate(shapes):
  3910. # note that dim_idx is here per object, dim 0 of shape target
  3911. # denotes "number of all objects" and was checked above
  3912. for dim_idx, expected in enumerate(shape_target[1:]):
  3913. observed = shape[dim_idx]
  3914. cls._compare(observed, expected, dim_idx, augm_idx)
  3915. # turning these checks below into classmethods of AssertShape breaks pickling
  3916. # in python 2.7
  3917. # Added in 0.4.0.
  3918. class _AssertShapeImagesCheck(object):
  3919. def __init__(self, shape):
  3920. self.shape = shape
  3921. def __call__(self, images, _random_state, _parents, _hooks):
  3922. # set shape_target so that we check all target dimensions,
  3923. # including C, which isn't checked for the other methods
  3924. AssertShape._check_shapes([obj.shape for obj in images],
  3925. self.shape)
  3926. return images
  3927. # Added in 0.4.0.
  3928. class _AssertShapeHeatmapsCheck(object):
  3929. def __init__(self, shape):
  3930. self.shape = shape
  3931. def __call__(self, heatmaps, _random_state, _parents, _hooks):
  3932. AssertShape._check_shapes([obj.arr_0to1.shape for obj in heatmaps],
  3933. self.shape[0:3])
  3934. return heatmaps
  3935. # Added in 0.4.0.
  3936. class _AssertShapeSegmapCheck(object):
  3937. def __init__(self, shape):
  3938. self.shape = shape
  3939. def __call__(self, segmaps, _random_state, _parents, _hooks):
  3940. AssertShape._check_shapes([obj.arr.shape for obj in segmaps],
  3941. self.shape[0:3])
  3942. return segmaps
  3943. # Added in 0.4.0.
  3944. class _AssertShapeKeypointsCheck(object):
  3945. def __init__(self, shape):
  3946. self.shape = shape
  3947. def __call__(self, keypoints_on_images, _random_state, _parents, _hooks):
  3948. AssertShape._check_shapes([obj.shape for obj in keypoints_on_images],
  3949. self.shape[0:3])
  3950. return keypoints_on_images
  3951. # Added in 0.4.0.
  3952. class _AssertShapeBoundingBoxesCheck(object):
  3953. def __init__(self, shape):
  3954. self.shape = shape
  3955. def __call__(self, bounding_boxes_on_images, _random_state, _parents,
  3956. _hooks):
  3957. AssertShape._check_shapes([obj.shape for obj
  3958. in bounding_boxes_on_images],
  3959. self.shape[0:3])
  3960. return bounding_boxes_on_images
  3961. # Added in 0.4.0.
  3962. class _AssertShapePolygonsCheck(object):
  3963. def __init__(self, shape):
  3964. self.shape = shape
  3965. def __call__(self, polygons_on_images, _random_state, _parents, _hooks):
  3966. AssertShape._check_shapes([obj.shape for obj in polygons_on_images],
  3967. self.shape[0:3])
  3968. return polygons_on_images
  3969. # Added in 0.4.0.
  3970. class _AssertShapeLineStringsCheck(object):
  3971. def __init__(self, shape):
  3972. self.shape = shape
  3973. def __call__(self, line_strings_on_images, _random_state, _parents,
  3974. _hooks):
  3975. AssertShape._check_shapes([obj.shape for obj
  3976. in line_strings_on_images],
  3977. self.shape[0:3])
  3978. return line_strings_on_images
  3979. class ChannelShuffle(Augmenter):
  3980. """Randomize the order of channels in input images.
  3981. **Supported dtypes**:
  3982. * ``uint8``: yes; fully tested
  3983. * ``uint16``: yes; tested
  3984. * ``uint32``: yes; tested
  3985. * ``uint64``: yes; tested
  3986. * ``int8``: yes; tested
  3987. * ``int16``: yes; tested
  3988. * ``int32``: yes; tested
  3989. * ``int64``: yes; tested
  3990. * ``float16``: yes; tested
  3991. * ``float32``: yes; tested
  3992. * ``float64``: yes; tested
  3993. * ``float128``: yes; tested
  3994. * ``bool``: yes; tested
  3995. Parameters
  3996. ----------
  3997. p : float or imgaug.parameters.StochasticParameter, optional
  3998. Probability of shuffling channels in any given image.
  3999. May be a fixed probability as a ``float``, or a
  4000. :class:`~imgaug.parameters.StochasticParameter` that returns ``0`` s
  4001. and ``1`` s.
  4002. channels : None or imgaug.ALL or list of int, optional
  4003. Which channels are allowed to be shuffled with each other.
  4004. If this is ``None`` or ``imgaug.ALL``, then all channels may be
  4005. shuffled. If it is a ``list`` of ``int`` s,
  4006. then only the channels with indices in that list may be shuffled.
  4007. (Values start at ``0``. All channel indices in the list must exist in
  4008. each image.)
  4009. seed : None or int or imgaug.random.RNG or numpy.random.Generator or numpy.random.BitGenerator or numpy.random.SeedSequence or numpy.random.RandomState, optional
  4010. See :func:`~imgaug.augmenters.meta.Augmenter.__init__`.
  4011. name : None or str, optional
  4012. See :func:`~imgaug.augmenters.meta.Augmenter.__init__`.
  4013. random_state : None or int or imgaug.random.RNG or numpy.random.Generator or numpy.random.BitGenerator or numpy.random.SeedSequence or numpy.random.RandomState, optional
  4014. Old name for parameter `seed`.
  4015. Its usage will not yet cause a deprecation warning,
  4016. but it is still recommended to use `seed` now.
  4017. Outdated since 0.4.0.
  4018. deterministic : bool, optional
  4019. Deprecated since 0.4.0.
  4020. See method ``to_deterministic()`` for an alternative and for
  4021. details about what the "deterministic mode" actually does.
  4022. Examples
  4023. --------
  4024. >>> import imgaug.augmenters as iaa
  4025. >>> aug = iaa.ChannelShuffle(0.35)
  4026. Shuffle all channels of ``35%`` of all images.
  4027. >>> aug = iaa.ChannelShuffle(0.35, channels=[0, 1])
  4028. Shuffle only channels ``0`` and ``1`` of ``35%`` of all images. As the new
  4029. channel orders ``0, 1`` and ``1, 0`` are both valid outcomes of the
  4030. shuffling, it means that for ``0.35 * 0.5 = 0.175`` or ``17.5%`` of all
  4031. images the order of channels ``0`` and ``1`` is inverted.
  4032. """
  4033. def __init__(self, p=1.0, channels=None,
  4034. seed=None, name=None,
  4035. random_state="deprecated", deterministic="deprecated"):
  4036. super(ChannelShuffle, self).__init__(
  4037. seed=seed, name=name,
  4038. random_state=random_state, deterministic=deterministic)
  4039. self.p = iap.handle_probability_param(p, "p")
  4040. valid_channels = (
  4041. channels is None
  4042. or channels == ia.ALL
  4043. or (
  4044. isinstance(channels, list)
  4045. and all([ia.is_single_integer(v) for v in channels])
  4046. ))
  4047. assert valid_channels, (
  4048. "Expected None or imgaug.ALL or list of int, got %s." % (
  4049. type(channels),))
  4050. self.channels = channels
  4051. # Added in 0.4.0.
  4052. def _augment_batch_(self, batch, random_state, parents, hooks):
  4053. if batch.images is None:
  4054. return batch
  4055. images = batch.images
  4056. nb_images = len(images)
  4057. p_samples = self.p.draw_samples((nb_images,),
  4058. random_state=random_state)
  4059. rss = random_state.duplicate(nb_images)
  4060. for i, (image, p_i, rs) in enumerate(zip(images, p_samples, rss)):
  4061. if p_i >= 1-1e-4:
  4062. batch.images[i] = shuffle_channels(image, rs, self.channels)
  4063. return batch
  4064. def get_parameters(self):
  4065. """See :func:`~imgaug.augmenters.meta.Augmenter.get_parameters`."""
  4066. return [self.p, self.channels]
  4067. def shuffle_channels(image, random_state, channels=None):
  4068. """Randomize the order of (color) channels in an image.
  4069. **Supported dtypes**:
  4070. * ``uint8``: yes; fully tested
  4071. * ``uint16``: yes; indirectly tested (1)
  4072. * ``uint32``: yes; indirectly tested (1)
  4073. * ``uint64``: yes; indirectly tested (1)
  4074. * ``int8``: yes; indirectly tested (1)
  4075. * ``int16``: yes; indirectly tested (1)
  4076. * ``int32``: yes; indirectly tested (1)
  4077. * ``int64``: yes; indirectly tested (1)
  4078. * ``float16``: yes; indirectly tested (1)
  4079. * ``float32``: yes; indirectly tested (1)
  4080. * ``float64``: yes; indirectly tested (1)
  4081. * ``float128``: yes; indirectly tested (1)
  4082. * ``bool``: yes; indirectly tested (1)
  4083. - (1) Indirectly tested via :class:`ChannelShuffle`.
  4084. Parameters
  4085. ----------
  4086. image : (H,W,[C]) ndarray
  4087. Image of any dtype for which to shuffle the channels.
  4088. random_state : imgaug.random.RNG
  4089. The random state to use for this shuffling operation.
  4090. channels : None or imgaug.ALL or list of int, optional
  4091. Which channels are allowed to be shuffled with each other.
  4092. If this is ``None`` or ``imgaug.ALL``, then all channels may be
  4093. shuffled. If it is a ``list`` of ``int`` s,
  4094. then only the channels with indices in that list may be shuffled.
  4095. (Values start at ``0``. All channel indices in the list must exist in
  4096. the image.)
  4097. Returns
  4098. -------
  4099. ndarray
  4100. The input image with shuffled channels.
  4101. """
  4102. if image.ndim < 3 or image.shape[2] == 1:
  4103. return image
  4104. nb_channels = image.shape[2]
  4105. all_channels = np.arange(nb_channels)
  4106. is_all_channels = (
  4107. channels is None
  4108. or channels == ia.ALL
  4109. or len(set(all_channels).difference(set(channels))) == 0
  4110. )
  4111. if is_all_channels:
  4112. # note that if this is the case, then 'channels' may be None or
  4113. # imgaug.ALL, so don't simply move the assignment outside of the
  4114. # if/else
  4115. channels_perm = random_state.permutation(all_channels)
  4116. return image[..., channels_perm]
  4117. channels_perm = random_state.permutation(channels)
  4118. channels_perm_full = all_channels
  4119. for channel_source, channel_target in zip(channels, channels_perm):
  4120. channels_perm_full[channel_source] = channel_target
  4121. return image[..., channels_perm_full]
  4122. class RemoveCBAsByOutOfImageFraction(Augmenter):
  4123. """Remove coordinate-based augmentables exceeding an out of image fraction.
  4124. This augmenter inspects all coordinate-based augmentables (e.g.
  4125. bounding boxes, line strings) within a given batch and removes any such
  4126. augmentable which's out of image fraction is exactly a given value or
  4127. greater than that. The out of image fraction denotes the fraction of the
  4128. augmentable's area that is outside of the image, e.g. for a bounding box
  4129. that has half of its area outside of the image it would be ``0.5``.
  4130. Added in 0.4.0.
  4131. **Supported dtypes**:
  4132. * ``uint8``: yes; fully tested
  4133. * ``uint16``: yes; fully tested
  4134. * ``uint32``: yes; fully tested
  4135. * ``uint64``: yes; fully tested
  4136. * ``int8``: yes; fully tested
  4137. * ``int16``: yes; fully tested
  4138. * ``int32``: yes; fully tested
  4139. * ``int64``: yes; fully tested
  4140. * ``float16``: yes; fully tested
  4141. * ``float32``: yes; fully tested
  4142. * ``float64``: yes; fully tested
  4143. * ``float128``: yes; fully tested
  4144. * ``bool``: yes; fully tested
  4145. Parameters
  4146. ----------
  4147. fraction : number
  4148. Remove any augmentable for which ``fraction_{actual} >= fraction``,
  4149. where ``fraction_{actual}`` denotes the estimated out of image
  4150. fraction.
  4151. seed : None or int or imgaug.random.RNG or numpy.random.Generator or numpy.random.BitGenerator or numpy.random.SeedSequence or numpy.random.RandomState, optional
  4152. See :func:`~imgaug.augmenters.meta.Augmenter.__init__`.
  4153. name : None or str, optional
  4154. See :func:`~imgaug.augmenters.meta.Augmenter.__init__`.
  4155. random_state : None or int or imgaug.random.RNG or numpy.random.Generator or numpy.random.BitGenerator or numpy.random.SeedSequence or numpy.random.RandomState, optional
  4156. Old name for parameter `seed`.
  4157. Its usage will not yet cause a deprecation warning,
  4158. but it is still recommended to use `seed` now.
  4159. Outdated since 0.4.0.
  4160. deterministic : bool, optional
  4161. Deprecated since 0.4.0.
  4162. See method ``to_deterministic()`` for an alternative and for
  4163. details about what the "deterministic mode" actually does.
  4164. Examples
  4165. --------
  4166. >>> import imgaug.augmenters as iaa
  4167. >>> aug = iaa.Sequential([
  4168. >>> iaa.Affine(translate_px={"x": (-100, 100)}),
  4169. >>> iaa.RemoveCBAsByOutOfImageFraction(0.5)
  4170. >>> ])
  4171. Translate all inputs by ``-100`` to ``100`` pixels on the x-axis, then
  4172. remove any coordinate-based augmentable (e.g. bounding boxes) which has
  4173. at least ``50%`` of its area outside of the image plane.
  4174. >>> import imgaug as ia
  4175. >>> import imgaug.augmenters as iaa
  4176. >>> image = ia.quokka_square((100, 100))
  4177. >>> bb = ia.BoundingBox(x1=50-25, y1=0, x2=50+25, y2=100)
  4178. >>> bbsoi = ia.BoundingBoxesOnImage([bb], shape=image.shape)
  4179. >>> aug_without = iaa.Affine(translate_px={"x": 51})
  4180. >>> aug_with = iaa.Sequential([
  4181. >>> iaa.Affine(translate_px={"x": 51}),
  4182. >>> iaa.RemoveCBAsByOutOfImageFraction(0.5)
  4183. >>> ])
  4184. >>>
  4185. >>> image_without, bbsoi_without = aug_without(
  4186. >>> image=image, bounding_boxes=bbsoi)
  4187. >>> image_with, bbsoi_with = aug_with(
  4188. >>> image=image, bounding_boxes=bbsoi)
  4189. >>>
  4190. >>> assert len(bbsoi_without.bounding_boxes) == 1
  4191. >>> assert len(bbsoi_with.bounding_boxes) == 0
  4192. Create a bounding box on an example image, then translate the image so that
  4193. ``50%`` of the bounding box's area is outside of the image and compare
  4194. the effects and using ``RemoveCBAsByOutOfImageFraction`` with not using it.
  4195. """
  4196. # Added in 0.4.0.
  4197. def __init__(self, fraction,
  4198. seed=None, name=None,
  4199. random_state="deprecated", deterministic="deprecated"):
  4200. super(RemoveCBAsByOutOfImageFraction, self).__init__(
  4201. seed=seed, name=name,
  4202. random_state=random_state, deterministic=deterministic)
  4203. self.fraction = fraction
  4204. # Added in 0.4.0.
  4205. def _augment_batch_(self, batch, random_state, parents, hooks):
  4206. for column in batch.columns:
  4207. if column.name in ["keypoints", "bounding_boxes", "polygons",
  4208. "line_strings"]:
  4209. for i, cbaoi in enumerate(column.value):
  4210. column.value[i] = cbaoi.remove_out_of_image_fraction_(
  4211. self.fraction)
  4212. return batch
  4213. # Added in 0.4.0.
  4214. def get_parameters(self):
  4215. """See :func:`~imgaug.augmenters.meta.Augmenter.get_parameters`."""
  4216. return [self.fraction]
  4217. class ClipCBAsToImagePlanes(Augmenter):
  4218. """Clip coordinate-based augmentables to areas within the image plane.
  4219. This augmenter inspects all coordinate-based augmentables (e.g.
  4220. bounding boxes, line strings) within a given batch and from each of them
  4221. parts that are outside of the image plane. Parts within the image plane
  4222. will be retained. This may e.g. shrink down bounding boxes. For keypoints,
  4223. it removes any single points outside of the image plane. Any augmentable
  4224. that is completely outside of the image plane will be removed.
  4225. Added in 0.4.0.
  4226. **Supported dtypes**:
  4227. * ``uint8``: yes; fully tested
  4228. * ``uint16``: yes; fully tested
  4229. * ``uint32``: yes; fully tested
  4230. * ``uint64``: yes; fully tested
  4231. * ``int8``: yes; fully tested
  4232. * ``int16``: yes; fully tested
  4233. * ``int32``: yes; fully tested
  4234. * ``int64``: yes; fully tested
  4235. * ``float16``: yes; fully tested
  4236. * ``float32``: yes; fully tested
  4237. * ``float64``: yes; fully tested
  4238. * ``float128``: yes; fully tested
  4239. * ``bool``: yes; fully tested
  4240. Parameters
  4241. ----------
  4242. seed : None or int or imgaug.random.RNG or numpy.random.Generator or numpy.random.BitGenerator or numpy.random.SeedSequence or numpy.random.RandomState, optional
  4243. See :func:`~imgaug.augmenters.meta.Augmenter.__init__`.
  4244. name : None or str, optional
  4245. See :func:`~imgaug.augmenters.meta.Augmenter.__init__`.
  4246. random_state : None or int or imgaug.random.RNG or numpy.random.Generator or numpy.random.BitGenerator or numpy.random.SeedSequence or numpy.random.RandomState, optional
  4247. Old name for parameter `seed`.
  4248. Its usage will not yet cause a deprecation warning,
  4249. but it is still recommended to use `seed` now.
  4250. Outdated since 0.4.0.
  4251. deterministic : bool, optional
  4252. Deprecated since 0.4.0.
  4253. See method ``to_deterministic()`` for an alternative and for
  4254. details about what the "deterministic mode" actually does.
  4255. Examples
  4256. --------
  4257. >>> import imgaug.augmenters as iaa
  4258. >>> aug = iaa.Sequential([
  4259. >>> iaa.Affine(translate_px={"x": (-100, 100)}),
  4260. >>> iaa.ClipCBAsToImagePlanes()
  4261. >>> ])
  4262. Translate input data on the x-axis by ``-100`` to ``100`` pixels,
  4263. then cut all coordinate-based augmentables (e.g. bounding boxes) down
  4264. to areas that are within the image planes of their corresponding images.
  4265. """
  4266. # Added in 0.4.0.
  4267. def __init__(self,
  4268. seed=None, name=None,
  4269. random_state="deprecated", deterministic="deprecated"):
  4270. super(ClipCBAsToImagePlanes, self).__init__(
  4271. seed=seed, name=name,
  4272. random_state=random_state, deterministic=deterministic)
  4273. # Added in 0.4.0.
  4274. def _augment_batch_(self, batch, random_state, parents, hooks):
  4275. for column in batch.columns:
  4276. if column.name in ["keypoints", "bounding_boxes", "polygons",
  4277. "line_strings"]:
  4278. for i, cbaoi in enumerate(column.value):
  4279. column.value[i] = cbaoi.clip_out_of_image_()
  4280. return batch
  4281. # Added in 0.4.0.
  4282. def get_parameters(self):
  4283. """See :func:`~imgaug.augmenters.meta.Augmenter.get_parameters`."""
  4284. return []