arithmetic.py 192 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908390939103911391239133914391539163917391839193920392139223923392439253926392739283929393039313932393339343935393639373938393939403941394239433944394539463947394839493950395139523953395439553956395739583959396039613962396339643965396639673968396939703971397239733974397539763977397839793980398139823983398439853986398739883989399039913992399339943995399639973998399940004001400240034004400540064007400840094010401140124013401440154016401740184019402040214022402340244025402640274028402940304031403240334034403540364037403840394040404140424043404440454046404740484049405040514052405340544055405640574058405940604061406240634064406540664067406840694070407140724073407440754076407740784079408040814082408340844085408640874088408940904091409240934094409540964097409840994100410141024103410441054106410741084109411041114112411341144115411641174118411941204121412241234124412541264127412841294130413141324133413441354136413741384139414041414142414341444145414641474148414941504151415241534154415541564157415841594160416141624163416441654166416741684169417041714172417341744175417641774178417941804181418241834184418541864187418841894190419141924193419441954196419741984199420042014202420342044205420642074208420942104211421242134214421542164217421842194220422142224223422442254226422742284229423042314232423342344235423642374238423942404241424242434244424542464247424842494250425142524253425442554256425742584259426042614262426342644265426642674268426942704271427242734274427542764277427842794280428142824283428442854286428742884289429042914292429342944295429642974298429943004301430243034304430543064307430843094310431143124313431443154316431743184319432043214322432343244325432643274328432943304331433243334334433543364337433843394340434143424343434443454346434743484349435043514352435343544355435643574358435943604361436243634364436543664367436843694370437143724373437443754376437743784379438043814382438343844385438643874388438943904391439243934394439543964397439843994400440144024403440444054406440744084409441044114412441344144415441644174418441944204421442244234424442544264427442844294430443144324433443444354436443744384439444044414442444344444445444644474448444944504451445244534454445544564457445844594460446144624463446444654466446744684469447044714472447344744475447644774478447944804481448244834484448544864487448844894490449144924493449444954496449744984499450045014502450345044505450645074508450945104511451245134514451545164517451845194520452145224523452445254526452745284529453045314532453345344535453645374538453945404541454245434544454545464547454845494550455145524553455445554556455745584559456045614562456345644565456645674568456945704571457245734574457545764577457845794580458145824583458445854586458745884589459045914592459345944595459645974598459946004601460246034604460546064607460846094610461146124613461446154616461746184619462046214622462346244625462646274628462946304631463246334634463546364637463846394640464146424643464446454646464746484649465046514652465346544655465646574658465946604661466246634664466546664667466846694670467146724673467446754676467746784679468046814682468346844685468646874688468946904691469246934694469546964697469846994700470147024703470447054706470747084709471047114712471347144715471647174718471947204721472247234724472547264727472847294730473147324733473447354736473747384739474047414742474347444745474647474748474947504751475247534754475547564757475847594760476147624763476447654766476747684769
  1. """
  2. Augmenters that perform simple arithmetic changes.
  3. List of augmenters:
  4. * :class:`Add`
  5. * :class:`AddElementwise`
  6. * :class:`AdditiveGaussianNoise`
  7. * :class:`AdditiveLaplaceNoise`
  8. * :class:`AdditivePoissonNoise`
  9. * :class:`Multiply`
  10. * :class:`MultiplyElementwise`
  11. * :class:`Cutout`
  12. * :class:`Dropout`
  13. * :class:`CoarseDropout`
  14. * :class:`Dropout2d`
  15. * :class:`TotalDropout`
  16. * :class:`ReplaceElementwise`
  17. * :class:`ImpulseNoise`
  18. * :class:`SaltAndPepper`
  19. * :class:`CoarseSaltAndPepper`
  20. * :class:`Salt`
  21. * :class:`CoarseSalt`
  22. * :class:`Pepper`
  23. * :class:`CoarsePepper`
  24. * :class:`Invert`
  25. * :class:`Solarize`
  26. * :class:`ContrastNormalization`
  27. * :class:`JpegCompression`
  28. """
  29. from __future__ import print_function, division, absolute_import
  30. import tempfile
  31. import imageio
  32. import numpy as np
  33. import imgaug as ia
  34. from . import meta
  35. from .. import parameters as iap
  36. from .. import dtypes as iadt
  37. from .. import random as iarandom
  38. # fill modes for apply_cutout_() and Cutout augmenter
  39. # contains roughly:
  40. # 'str fill_mode_name => (str module_name, str function_name)'
  41. # We could also assign the function to each fill mode name instead of its
  42. # name, but that has the disadvantage that these aren't defined yet (they
  43. # are defined further below) and that during unittesting they would be harder
  44. # to mock. (mock.patch() seems to not automatically replace functions
  45. # assigned in that way.)
  46. _CUTOUT_FILL_MODES = {
  47. "constant": ("imgaug.augmenters.arithmetic", "_fill_rectangle_constant_"),
  48. "gaussian": ("imgaug.augmenters.arithmetic", "_fill_rectangle_gaussian_")
  49. }
  50. def add_scalar(image, value):
  51. """Add a single scalar value or one scalar value per channel to an image.
  52. This method ensures that ``uint8`` does not overflow during the addition.
  53. **Supported dtypes**:
  54. * ``uint8``: yes; fully tested
  55. * ``uint16``: limited; tested (1)
  56. * ``uint32``: no
  57. * ``uint64``: no
  58. * ``int8``: limited; tested (1)
  59. * ``int16``: limited; tested (1)
  60. * ``int32``: no
  61. * ``int64``: no
  62. * ``float16``: limited; tested (1)
  63. * ``float32``: limited; tested (1)
  64. * ``float64``: no
  65. * ``float128``: no
  66. * ``bool``: limited; tested (1)
  67. - (1) Non-uint8 dtypes can overflow. For floats, this can result
  68. in +/-inf.
  69. Parameters
  70. ----------
  71. image : ndarray
  72. Image array of shape ``(H,W,[C])``.
  73. If `value` contains more than one value, the shape of the image is
  74. expected to be ``(H,W,C)``.
  75. value : number or ndarray
  76. The value to add to the image. Either a single value or an array
  77. containing exactly one component per channel, i.e. ``C`` components.
  78. Returns
  79. -------
  80. ndarray
  81. Image with value added to it.
  82. """
  83. if image.size == 0:
  84. return np.copy(image)
  85. iadt.gate_dtypes(
  86. image,
  87. allowed=["bool",
  88. "uint8", "uint16",
  89. "int8", "int16",
  90. "float16", "float32"],
  91. disallowed=["uint32", "uint64", "uint128", "uint256",
  92. "int32", "int64", "int128", "int256",
  93. "float64", "float96", "float128",
  94. "float256"],
  95. augmenter=None)
  96. if image.dtype.name == "uint8":
  97. return _add_scalar_to_uint8(image, value)
  98. return _add_scalar_to_non_uint8(image, value)
  99. def _add_scalar_to_uint8(image, value):
  100. # Using this LUT approach is significantly faster than using
  101. # numpy-based adding with dtype checks (around 3-4x speedup) and is
  102. # still faster than the simple numpy image+sample approach without LUT
  103. # (about 10% at 64x64 and about 2x at 224x224 -- maybe dependent on
  104. # installed BLAS libraries?)
  105. # pylint: disable=no-else-return
  106. is_single_value = (
  107. ia.is_single_number(value)
  108. or ia.is_np_scalar(value)
  109. or (ia.is_np_array(value) and value.size == 1))
  110. is_channelwise = not is_single_value
  111. nb_channels = 1 if image.ndim == 2 else image.shape[-1]
  112. value = np.clip(np.round(value), -255, 255).astype(np.int16)
  113. value_range = np.arange(0, 256, dtype=np.int16)
  114. if is_channelwise:
  115. assert value.ndim == 1, (
  116. "Expected `value` to be 1-dimensional, got %d-dimensional "
  117. "data with shape %s." % (value.ndim, value.shape))
  118. assert image.ndim == 3, (
  119. "Expected `image` to be 3-dimensional when adding one value per "
  120. "channel, got %d-dimensional data with shape %s." % (
  121. image.ndim, image.shape))
  122. assert image.shape[-1] == value.size, (
  123. "Expected number of channels in `image` and number of components "
  124. "in `value` to be identical. Got %d vs. %d." % (
  125. image.shape[-1], value.size))
  126. # TODO check if tile() is here actually needed
  127. tables = np.tile(
  128. value_range[:, np.newaxis],
  129. (1, nb_channels)
  130. ) + value[np.newaxis, :]
  131. else:
  132. tables = value_range + value
  133. tables = np.clip(tables, 0, 255).astype(image.dtype)
  134. return ia.apply_lut(image, tables)
  135. def _add_scalar_to_non_uint8(image, value):
  136. input_dtype = image.dtype
  137. is_single_value = (
  138. ia.is_single_number(value)
  139. or ia.is_np_scalar(value)
  140. or (ia.is_np_array(value) and value.size == 1))
  141. is_channelwise = not is_single_value
  142. nb_channels = 1 if image.ndim == 2 else image.shape[-1]
  143. shape = (1, 1, nb_channels if is_channelwise else 1)
  144. value = np.array(value).reshape(shape)
  145. # We limit here the value range of the value parameter to the
  146. # bytes in the image's dtype. This prevents overflow problems
  147. # and makes it less likely that the image has to be up-casted,
  148. # which again improves performance and saves memory. Note that
  149. # this also enables more dtypes for image inputs.
  150. # The downside is that the mul parameter is limited in its
  151. # value range.
  152. #
  153. # We need 2* the itemsize of the image here to allow to shift
  154. # the image's max value to the lowest possible value, e.g. for
  155. # uint8 it must allow for -255 to 255.
  156. itemsize = image.dtype.itemsize * 2
  157. dtype_target = np.dtype("%s%d" % (value.dtype.kind, itemsize))
  158. value = iadt.clip_to_dtype_value_range_(
  159. value, dtype_target, validate=True)
  160. # Itemsize is currently reduced from 2 to 1 due to clip no
  161. # longer supporting int64, which can cause issues with int32
  162. # samples (32*2 = 64bit).
  163. # TODO limit value ranges of samples to int16/uint16 for
  164. # security
  165. image, value = iadt.promote_array_dtypes_(
  166. [image, value],
  167. dtypes=[image.dtype, dtype_target],
  168. increase_itemsize_factor=1)
  169. image = np.add(image, value, out=image, casting="no")
  170. return iadt.restore_dtypes_(image, input_dtype)
  171. def add_elementwise(image, values):
  172. """Add an array of values to an image.
  173. This method ensures that ``uint8`` does not overflow during the addition.
  174. **Supported dtypes**:
  175. * ``uint8``: yes; fully tested
  176. * ``uint16``: limited; tested (1)
  177. * ``uint32``: no
  178. * ``uint64``: no
  179. * ``int8``: limited; tested (1)
  180. * ``int16``: limited; tested (1)
  181. * ``int32``: no
  182. * ``int64``: no
  183. * ``float16``: limited; tested (1)
  184. * ``float32``: limited; tested (1)
  185. * ``float64``: no
  186. * ``float128``: no
  187. * ``bool``: limited; tested (1)
  188. - (1) Non-uint8 dtypes can overflow. For floats, this can result
  189. in +/-inf.
  190. Parameters
  191. ----------
  192. image : ndarray
  193. Image array of shape ``(H,W,[C])``.
  194. values : ndarray
  195. The values to add to the image. Expected to have the same height
  196. and width as `image` and either no channels or one channel or
  197. the same number of channels as `image`.
  198. Returns
  199. -------
  200. ndarray
  201. Image with values added to it.
  202. """
  203. iadt.gate_dtypes(
  204. image,
  205. allowed=["bool",
  206. "uint8", "uint16",
  207. "int8", "int16",
  208. "float16", "float32"],
  209. disallowed=["uint32", "uint64", "uint128", "uint256",
  210. "int32", "int64", "int128", "int256",
  211. "float64", "float96", "float128",
  212. "float256"],
  213. augmenter=None)
  214. if image.dtype.name == "uint8":
  215. return _add_elementwise_to_uint8(image, values)
  216. return _add_elementwise_to_non_uint8(image, values)
  217. def _add_elementwise_to_uint8(image, values):
  218. # This special uint8 block is around 60-100% faster than the
  219. # corresponding non-uint8 function further below (more speedup
  220. # for smaller images).
  221. #
  222. # Also tested to instead compute min/max of image and value
  223. # and then only convert image/value dtype if actually
  224. # necessary, but that was like 20-30% slower, even for 224x224
  225. # images.
  226. #
  227. if values.dtype.kind == "f":
  228. values = np.round(values)
  229. image = image.astype(np.int16)
  230. values = np.clip(values, -255, 255).astype(np.int16)
  231. image_aug = image + values
  232. image_aug = np.clip(image_aug, 0, 255).astype(np.uint8)
  233. return image_aug
  234. def _add_elementwise_to_non_uint8(image, values):
  235. # We limit here the value range of the value parameter to the
  236. # bytes in the image's dtype. This prevents overflow problems
  237. # and makes it less likely that the image has to be up-casted,
  238. # which again improves performance and saves memory. Note that
  239. # this also enables more dtypes for image inputs.
  240. # The downside is that the mul parameter is limited in its
  241. # value range.
  242. #
  243. # We need 2* the itemsize of the image here to allow to shift
  244. # the image's max value to the lowest possible value, e.g. for
  245. # uint8 it must allow for -255 to 255.
  246. input_shape = image.shape
  247. input_dtype = image.dtype
  248. if image.ndim == 2:
  249. image = image[..., np.newaxis]
  250. if values.ndim == 2:
  251. values = values[..., np.newaxis]
  252. nb_channels = image.shape[-1]
  253. itemsize = image.dtype.itemsize * 2
  254. dtype_target = np.dtype("%s%d" % (values.dtype.kind, itemsize))
  255. values = iadt.clip_to_dtype_value_range_(values, dtype_target,
  256. validate=100)
  257. if values.shape[2] == 1:
  258. values = np.tile(values, (1, 1, nb_channels))
  259. # Decreased itemsize from 2 to 1 here, see explanation in Add.
  260. image, values = iadt.promote_array_dtypes_(
  261. [image, values],
  262. dtypes=[image.dtype, dtype_target],
  263. increase_itemsize_factor=1)
  264. image = np.add(image, values, out=image, casting="no")
  265. image = iadt.restore_dtypes_(image, input_dtype)
  266. if len(input_shape) == 2:
  267. return image[..., 0]
  268. return image
  269. def multiply_scalar(image, multiplier):
  270. """Multiply an image by a single scalar or one scalar per channel.
  271. This method ensures that ``uint8`` does not overflow during the
  272. multiplication.
  273. **Supported dtypes**:
  274. * ``uint8``: yes; fully tested
  275. * ``uint16``: limited; tested (1)
  276. * ``uint32``: no
  277. * ``uint64``: no
  278. * ``int8``: limited; tested (1)
  279. * ``int16``: limited; tested (1)
  280. * ``int32``: no
  281. * ``int64``: no
  282. * ``float16``: limited; tested (1)
  283. * ``float32``: limited; tested (1)
  284. * ``float64``: no
  285. * ``float128``: no
  286. * ``bool``: limited; tested (1)
  287. - (1) Non-uint8 dtypes can overflow. For floats, this can result in
  288. +/-inf.
  289. note::
  290. Tests were only conducted for rather small multipliers, around
  291. ``-10.0`` to ``+10.0``.
  292. In general, the multipliers sampled from `multiplier` must be in a
  293. value range that corresponds to the input image's dtype. E.g. if the
  294. input image has dtype ``uint16`` and the samples generated from
  295. `multiplier` are ``float64``, this function will still force all
  296. samples to be within the value range of ``float16``, as it has the
  297. same number of bytes (two) as ``uint16``. This is done to make
  298. overflows less likely to occur.
  299. Parameters
  300. ----------
  301. image : ndarray
  302. Image array of shape ``(H,W,[C])``.
  303. If `value` contains more than one value, the shape of the image is
  304. expected to be ``(H,W,C)``.
  305. multiplier : number or ndarray
  306. The multiplier to use. Either a single value or an array
  307. containing exactly one component per channel, i.e. ``C`` components.
  308. Returns
  309. -------
  310. ndarray
  311. Image, multiplied by `multiplier`.
  312. """
  313. if image.size == 0:
  314. return np.copy(image)
  315. iadt.gate_dtypes(
  316. image,
  317. allowed=["bool",
  318. "uint8", "uint16",
  319. "int8", "int16",
  320. "float16", "float32"],
  321. disallowed=["uint32", "uint64", "uint128", "uint256",
  322. "int32", "int64", "int128", "int256",
  323. "float64", "float96", "float128",
  324. "float256"],
  325. augmenter=None)
  326. if image.dtype.name == "uint8":
  327. return _multiply_scalar_to_uint8(image, multiplier)
  328. return _multiply_scalar_to_non_uint8(image, multiplier)
  329. def _multiply_scalar_to_uint8(image, multiplier):
  330. # Using this LUT approach is significantly faster than
  331. # else-block code (more than 10x speedup) and is still faster
  332. # than the simpler image*sample approach without LUT (1.5-3x
  333. # speedup, maybe dependent on installed BLAS libraries?)
  334. # pylint: disable=no-else-return
  335. is_single_value = (
  336. ia.is_single_number(multiplier)
  337. or ia.is_np_scalar(multiplier)
  338. or (ia.is_np_array(multiplier) and multiplier.size == 1))
  339. is_channelwise = not is_single_value
  340. nb_channels = 1 if image.ndim == 2 else image.shape[-1]
  341. multiplier = np.float32(multiplier)
  342. value_range = np.arange(0, 256, dtype=np.float32)
  343. if is_channelwise:
  344. assert multiplier.ndim == 1, (
  345. "Expected `multiplier` to be 1-dimensional, got %d-dimensional "
  346. "data with shape %s." % (multiplier.ndim, multiplier.shape))
  347. assert image.ndim == 3, (
  348. "Expected `image` to be 3-dimensional when multiplying by one "
  349. "value per channel, got %d-dimensional data with shape %s." % (
  350. image.ndim, image.shape))
  351. assert image.shape[-1] == multiplier.size, (
  352. "Expected number of channels in `image` and number of components "
  353. "in `multiplier` to be identical. Got %d vs. %d." % (
  354. image.shape[-1], multiplier.size))
  355. # TODO check if tile() is here actually needed
  356. tables = np.tile(
  357. value_range[:, np.newaxis],
  358. (1, nb_channels)
  359. ) * multiplier[np.newaxis, :]
  360. else:
  361. tables = value_range * multiplier
  362. tables = np.clip(tables, 0, 255).astype(image.dtype)
  363. return ia.apply_lut(image, tables)
  364. def _multiply_scalar_to_non_uint8(image, multiplier):
  365. # TODO estimate via image min/max values whether a resolution
  366. # increase is necessary
  367. input_dtype = image.dtype
  368. is_single_value = (
  369. ia.is_single_number(multiplier)
  370. or ia.is_np_scalar(multiplier)
  371. or (ia.is_np_array(multiplier) and multiplier.size == 1))
  372. is_channelwise = not is_single_value
  373. nb_channels = 1 if image.ndim == 2 else image.shape[-1]
  374. shape = (1, 1, nb_channels if is_channelwise else 1)
  375. multiplier = np.array(multiplier).reshape(shape)
  376. # deactivated itemsize increase due to clip causing problems
  377. # with int64, see Add
  378. # mul_min = np.min(mul)
  379. # mul_max = np.max(mul)
  380. # is_not_increasing_value_range = (
  381. # (-1 <= mul_min <= 1)
  382. # and (-1 <= mul_max <= 1))
  383. # We limit here the value range of the mul parameter to the
  384. # bytes in the image's dtype. This prevents overflow problems
  385. # and makes it less likely that the image has to be up-casted,
  386. # which again improves performance and saves memory. Note that
  387. # this also enables more dtypes for image inputs.
  388. # The downside is that the mul parameter is limited in its
  389. # value range.
  390. itemsize = max(
  391. image.dtype.itemsize,
  392. 2 if multiplier.dtype.kind == "f" else 1
  393. ) # float min itemsize is 2 not 1
  394. dtype_target = np.dtype("%s%d" % (multiplier.dtype.kind, itemsize))
  395. multiplier = iadt.clip_to_dtype_value_range_(
  396. multiplier, dtype_target, validate=True)
  397. image, multiplier = iadt.promote_array_dtypes_(
  398. [image, multiplier],
  399. dtypes=[image.dtype, dtype_target],
  400. # increase_itemsize_factor=(
  401. # 1 if is_not_increasing_value_range else 2)
  402. increase_itemsize_factor=1
  403. )
  404. image = np.multiply(image, multiplier, out=image, casting="no")
  405. return iadt.restore_dtypes_(image, input_dtype)
  406. def multiply_elementwise(image, multipliers):
  407. """Multiply an image with an array of values.
  408. This method ensures that ``uint8`` does not overflow during the addition.
  409. **Supported dtypes**:
  410. * ``uint8``: yes; fully tested
  411. * ``uint16``: limited; tested (1)
  412. * ``uint32``: no
  413. * ``uint64``: no
  414. * ``int8``: limited; tested (1)
  415. * ``int16``: limited; tested (1)
  416. * ``int32``: no
  417. * ``int64``: no
  418. * ``float16``: limited; tested (1)
  419. * ``float32``: limited; tested (1)
  420. * ``float64``: no
  421. * ``float128``: no
  422. * ``bool``: limited; tested (1)
  423. - (1) Non-uint8 dtypes can overflow. For floats, this can result
  424. in +/-inf.
  425. note::
  426. Tests were only conducted for rather small multipliers, around
  427. ``-10.0`` to ``+10.0``.
  428. In general, the multipliers sampled from `multipliers` must be in a
  429. value range that corresponds to the input image's dtype. E.g. if the
  430. input image has dtype ``uint16`` and the samples generated from
  431. `multipliers` are ``float64``, this function will still force all
  432. samples to be within the value range of ``float16``, as it has the
  433. same number of bytes (two) as ``uint16``. This is done to make
  434. overflows less likely to occur.
  435. Parameters
  436. ----------
  437. image : ndarray
  438. Image array of shape ``(H,W,[C])``.
  439. multipliers : ndarray
  440. The multipliers with which to multiply the image. Expected to have
  441. the same height and width as `image` and either no channels or one
  442. channel or the same number of channels as `image`.
  443. Returns
  444. -------
  445. ndarray
  446. Image, multiplied by `multipliers`.
  447. """
  448. iadt.gate_dtypes(
  449. image,
  450. allowed=["bool",
  451. "uint8", "uint16",
  452. "int8", "int16",
  453. "float16", "float32"],
  454. disallowed=["uint32", "uint64", "uint128", "uint256",
  455. "int32", "int64", "int128", "int256",
  456. "float64", "float96", "float128", "float256"],
  457. augmenter=None)
  458. if multipliers.dtype.kind == "b":
  459. # TODO extend this with some shape checks
  460. image *= multipliers
  461. return image
  462. if image.dtype.name == "uint8":
  463. return _multiply_elementwise_to_uint8(image, multipliers)
  464. return _multiply_elementwise_to_non_uint8(image, multipliers)
  465. def _multiply_elementwise_to_uint8(image, multipliers):
  466. # This special uint8 block is around 60-100% faster than the
  467. # non-uint8 block further below (more speedup for larger images).
  468. if multipliers.dtype.kind == "f":
  469. # interestingly, float32 is here significantly faster than
  470. # float16
  471. # TODO is that system dependent?
  472. # TODO does that affect int8-int32 too?
  473. multipliers = multipliers.astype(np.float32, copy=False)
  474. image_aug = image.astype(np.float32)
  475. else:
  476. multipliers = multipliers.astype(np.int16, copy=False)
  477. image_aug = image.astype(np.int16)
  478. image_aug = np.multiply(image_aug, multipliers, casting="no", out=image_aug)
  479. return iadt.restore_dtypes_(image_aug, np.uint8, round=False)
  480. def _multiply_elementwise_to_non_uint8(image, multipliers):
  481. input_dtype = image.dtype
  482. # TODO maybe introduce to stochastic parameters some way to
  483. # get the possible min/max values, could make things
  484. # faster for dropout to get 0/1 min/max from the binomial
  485. # itemsize decrease is currently deactivated due to issues
  486. # with clip and int64, see Add
  487. mul_min = np.min(multipliers)
  488. mul_max = np.max(multipliers)
  489. # is_not_increasing_value_range = (
  490. # (-1 <= mul_min <= 1) and (-1 <= mul_max <= 1))
  491. # We limit here the value range of the mul parameter to the
  492. # bytes in the image's dtype. This prevents overflow problems
  493. # and makes it less likely that the image has to be up-casted,
  494. # which again improves performance and saves memory. Note that
  495. # this also enables more dtypes for image inputs.
  496. # The downside is that the mul parameter is limited in its
  497. # value range.
  498. itemsize = max(
  499. image.dtype.itemsize,
  500. 2 if multipliers.dtype.kind == "f" else 1
  501. ) # float min itemsize is 2
  502. dtype_target = np.dtype("%s%d" % (multipliers.dtype.kind, itemsize))
  503. multipliers = iadt.clip_to_dtype_value_range_(
  504. multipliers, dtype_target,
  505. validate=True, validate_values=(mul_min, mul_max))
  506. if multipliers.shape[2] == 1:
  507. # TODO check if tile() is here actually needed
  508. nb_channels = image.shape[-1]
  509. multipliers = np.tile(multipliers, (1, 1, nb_channels))
  510. image, multipliers = iadt.promote_array_dtypes_(
  511. [image, multipliers],
  512. dtypes=[image, dtype_target],
  513. increase_itemsize_factor=1
  514. # increase_itemsize_factor=(
  515. # 1 if is_not_increasing_value_range else 2)
  516. )
  517. image = np.multiply(image, multipliers, out=image, casting="no")
  518. return iadt.restore_dtypes_(image, input_dtype)
  519. def cutout(image, x1, y1, x2, y2,
  520. fill_mode="constant", cval=0, fill_per_channel=False,
  521. seed=None):
  522. """Fill a single area within an image using a fill mode.
  523. This cutout method uses the top-left and bottom-right corner coordinates
  524. of the cutout region given as absolute pixel values.
  525. .. note::
  526. Gaussian fill mode will assume that float input images contain values
  527. in the interval ``[0.0, 1.0]`` and hence sample values from a
  528. gaussian within that interval, i.e. from ``N(0.5, std=0.5/3)``.
  529. **Supported dtypes**:
  530. See :func:`~imgaug.augmenters.arithmetic.cutout_`.
  531. Added in 0.4.0.
  532. Parameters
  533. ----------
  534. image : ndarray
  535. Image to modify.
  536. x1 : number
  537. See :func:`~imgaug.augmenters.arithmetic.cutout_`.
  538. y1 : number
  539. See :func:`~imgaug.augmenters.arithmetic.cutout_`.
  540. x2 : number
  541. See :func:`~imgaug.augmenters.arithmetic.cutout_`.
  542. y2 : number
  543. See :func:`~imgaug.augmenters.arithmetic.cutout_`.
  544. fill_mode : {'constant', 'gaussian'}, optional
  545. See :func:`~imgaug.augmenters.arithmetic.cutout_`.
  546. cval : number or tuple of number, optional
  547. See :func:`~imgaug.augmenters.arithmetic.cutout_`.
  548. fill_per_channel : number or bool, optional
  549. See :func:`~imgaug.augmenters.arithmetic.cutout_`.
  550. 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
  551. See :func:`~imgaug.augmenters.arithmetic.cutout_`.
  552. Returns
  553. -------
  554. ndarray
  555. Image with area filled in.
  556. """
  557. return cutout_(np.copy(image),
  558. x1, y1, x2, y2,
  559. fill_mode, cval, fill_per_channel, seed)
  560. def cutout_(image, x1, y1, x2, y2,
  561. fill_mode="constant", cval=0, fill_per_channel=False,
  562. seed=None):
  563. """Fill a single area within an image using a fill mode (in-place).
  564. This cutout method uses the top-left and bottom-right corner coordinates
  565. of the cutout region given as absolute pixel values.
  566. .. note::
  567. Gaussian fill mode will assume that float input images contain values
  568. in the interval ``[0.0, 1.0]`` and hence sample values from a
  569. gaussian within that interval, i.e. from ``N(0.5, std=0.5/3)``.
  570. Added in 0.4.0.
  571. **Supported dtypes**:
  572. minimum of (
  573. :func:`~imgaug.augmenters.arithmetic._fill_rectangle_gaussian_`,
  574. :func:`~imgaug.augmenters.arithmetic._fill_rectangle_constant_`
  575. )
  576. Parameters
  577. ----------
  578. image : ndarray
  579. Image to modify. Might be modified in-place.
  580. x1 : number
  581. X-coordinate of the top-left corner of the cutout region.
  582. y1 : number
  583. Y-coordinate of the top-left corner of the cutout region.
  584. x2 : number
  585. X-coordinate of the bottom-right corner of the cutout region.
  586. y2 : number
  587. Y-coordinate of the bottom-right corner of the cutout region.
  588. fill_mode : {'constant', 'gaussian'}, optional
  589. Fill mode to use.
  590. cval : number or tuple of number, optional
  591. The constant value to use when filling with mode ``constant``.
  592. May be an intensity value or color tuple.
  593. fill_per_channel : number or bool, optional
  594. Whether to fill in a channelwise fashion.
  595. If number then a value ``>=0.5`` will be interpreted as ``True``.
  596. 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
  597. A random number generator to sample random values from.
  598. Usually an integer seed value or an ``RNG`` instance.
  599. See :class:`imgaug.random.RNG` for details.
  600. Returns
  601. -------
  602. ndarray
  603. Image with area filled in.
  604. The input image might have been modified in-place.
  605. """
  606. import importlib
  607. height, width = image.shape[0:2]
  608. x1 = min(max(int(x1), 0), width)
  609. y1 = min(max(int(y1), 0), height)
  610. x2 = min(max(int(x2), 0), width)
  611. y2 = min(max(int(y2), 0), height)
  612. if x2 > x1 and y2 > y1:
  613. assert fill_mode in _CUTOUT_FILL_MODES, (
  614. "Expected one of the following fill modes: %s. "
  615. "Got: %s." % (
  616. str(list(_CUTOUT_FILL_MODES.keys())), fill_mode))
  617. module_name, fname = _CUTOUT_FILL_MODES[fill_mode]
  618. module = importlib.import_module(module_name)
  619. func = getattr(module, fname)
  620. image = func(
  621. image,
  622. x1=x1, y1=y1, x2=x2, y2=y2,
  623. cval=cval,
  624. per_channel=(fill_per_channel >= 0.5),
  625. random_state=(
  626. iarandom.RNG(seed)
  627. if not isinstance(seed, iarandom.RNG)
  628. else seed) # only RNG(.) without "if" is ~8x slower
  629. )
  630. return image
  631. def _fill_rectangle_gaussian_(image, x1, y1, x2, y2, cval, per_channel,
  632. random_state):
  633. """Fill a rectangular image area with samples from a gaussian.
  634. Added in 0.4.0.
  635. **Supported dtypes**:
  636. * ``uint8``: yes; fully tested
  637. * ``uint16``: yes; tested
  638. * ``uint32``: yes; tested
  639. * ``uint64``: limited; tested (1)
  640. * ``int8``: yes; tested
  641. * ``int16``: yes; tested
  642. * ``int32``: yes; tested
  643. * ``int64``: limited; tested (1)
  644. * ``float16``: yes; tested (2)
  645. * ``float32``: yes; tested (2)
  646. * ``float64``: yes; tested (2)
  647. * ``float128``: limited; tested (1) (2)
  648. * ``bool``: yes; tested
  649. - (1) Possible loss of resolution due to gaussian values being sampled
  650. as ``float64`` s.
  651. - (2) Float input arrays are assumed to be in interval ``[0.0, 1.0]``
  652. and all gaussian samples are within that interval too.
  653. """
  654. # for float we assume value range [0.0, 1.0]
  655. # that matches the common use case and also makes the tests way easier
  656. # we also set bool here manually as the center value returned by
  657. # get_value_range_for_dtype() is None
  658. kind = image.dtype.kind
  659. if kind in ["f", "b"]:
  660. min_value = 0.0
  661. center_value = 0.5
  662. max_value = 1.0
  663. else:
  664. min_value, center_value, max_value = iadt.get_value_range_of_dtype(
  665. image.dtype)
  666. # set standard deviation to 1/3 of value range to get 99.7% of values
  667. # within [min v.r., max v.r.]
  668. # we also divide by 2 because we want to spread towards the
  669. # "left"/"right" of the center value by half of the value range
  670. stddev = (float(max_value) - float(min_value)) / 2.0 / 3.0
  671. height = y2 - y1
  672. width = x2 - x1
  673. shape = (height, width)
  674. if per_channel and image.ndim == 3:
  675. shape = shape + (image.shape[2],)
  676. rect = random_state.normal(center_value, stddev, size=shape)
  677. if image.dtype.kind == "b":
  678. rect_vr = (rect > 0.5)
  679. else:
  680. rect_vr = np.clip(rect, min_value, max_value).astype(image.dtype)
  681. if image.ndim == 3:
  682. image[y1:y2, x1:x2, :] = np.atleast_3d(rect_vr)
  683. else:
  684. image[y1:y2, x1:x2] = rect_vr
  685. return image
  686. def _fill_rectangle_constant_(image, x1, y1, x2, y2, cval, per_channel,
  687. random_state):
  688. """Fill a rectangular area within an image with constant value(s).
  689. `cval` may be a single value or one per channel. If the number of items
  690. in `cval` does not match the number of channels in `image`, it may
  691. be tiled up to the number of channels.
  692. Added in 0.4.0.
  693. **Supported dtypes**:
  694. * ``uint8``: yes; fully tested
  695. * ``uint16``: yes; tested
  696. * ``uint32``: yes; tested
  697. * ``uint64``: yes; tested
  698. * ``int8``: yes; tested
  699. * ``int16``: yes; tested
  700. * ``int32``: yes; tested
  701. * ``int64``: yes; tested
  702. * ``float16``: yes; tested
  703. * ``float32``: yes; tested
  704. * ``float64``: yes; tested
  705. * ``float128``: yes; tested
  706. * ``bool``: yes; tested
  707. """
  708. if ia.is_iterable(cval):
  709. if per_channel:
  710. nb_channels = None if image.ndim == 2 else image.shape[-1]
  711. if nb_channels is None:
  712. cval = cval[0]
  713. elif len(cval) < nb_channels:
  714. mul = int(np.ceil(nb_channels / len(cval)))
  715. cval = np.tile(cval, (mul,))[0:nb_channels]
  716. elif len(cval) > nb_channels:
  717. cval = cval[0:nb_channels]
  718. else:
  719. cval = cval[0]
  720. # without the array(), uint64 max value is assigned as 0
  721. image[y1:y2, x1:x2, ...] = np.array(cval, dtype=image.dtype)
  722. return image
  723. def replace_elementwise_(image, mask, replacements):
  724. """Replace components in an image array with new values.
  725. **Supported dtypes**:
  726. * ``uint8``: yes; fully tested
  727. * ``uint16``: yes; tested
  728. * ``uint32``: yes; tested
  729. * ``uint64``: no (1)
  730. * ``int8``: yes; tested
  731. * ``int16``: yes; tested
  732. * ``int32``: yes; tested
  733. * ``int64``: no (2)
  734. * ``float16``: yes; tested
  735. * ``float32``: yes; tested
  736. * ``float64``: yes; tested
  737. * ``float128``: no
  738. * ``bool``: yes; tested
  739. - (1) ``uint64`` is currently not supported, because
  740. :func:`~imgaug.dtypes.clip_to_dtype_value_range_()` does not
  741. support it, which again is because numpy.clip() seems to not
  742. support it.
  743. - (2) `int64` is disallowed due to being converted to `float64`
  744. by :func:`numpy.clip` since 1.17 (possibly also before?).
  745. Parameters
  746. ----------
  747. image : ndarray
  748. Image array of shape ``(H,W,[C])``.
  749. mask : ndarray
  750. Mask of shape ``(H,W,[C])`` denoting which components to replace.
  751. If ``C`` is provided, it must be ``1`` or match the ``C`` of `image`.
  752. May contain floats in the interval ``[0.0, 1.0]``.
  753. replacements : iterable
  754. Replacements to place in `image` at the locations defined by `mask`.
  755. This 1-dimensional iterable must contain exactly as many values
  756. as there are replaced components in `image`.
  757. Returns
  758. -------
  759. ndarray
  760. Image with replaced components.
  761. """
  762. iadt.gate_dtypes(
  763. image,
  764. allowed=["bool",
  765. "uint8", "uint16", "uint32",
  766. "int8", "int16", "int32",
  767. "float16", "float32", "float64"],
  768. disallowed=["uint64", "uint128", "uint256",
  769. "int64", "int128", "int256",
  770. "float96", "float128", "float256"],
  771. augmenter=None)
  772. # This is slightly faster (~20%) for masks that are True at many
  773. # locations, but slower (~50%) for masks with few Trues, which is
  774. # probably the more common use-case:
  775. #
  776. # replacement_samples = self.replacement.draw_samples(
  777. # sampling_shape, random_state=rs_replacement)
  778. #
  779. # # round, this makes 0.2 e.g. become 0 in case of boolean
  780. # # image (otherwise replacing values with 0.2 would
  781. # # lead to True instead of False).
  782. # if (image.dtype.kind in ["i", "u", "b"]
  783. # and replacement_samples.dtype.kind == "f"):
  784. # replacement_samples = np.round(replacement_samples)
  785. #
  786. # replacement_samples = iadt.clip_to_dtype_value_range_(
  787. # replacement_samples, image.dtype, validate=False)
  788. # replacement_samples = replacement_samples.astype(
  789. # image.dtype, copy=False)
  790. #
  791. # if sampling_shape[2] == 1:
  792. # mask_samples = np.tile(mask_samples, (1, 1, nb_channels))
  793. # replacement_samples = np.tile(
  794. # replacement_samples, (1, 1, nb_channels))
  795. # mask_thresh = mask_samples > 0.5
  796. # image[mask_thresh] = replacement_samples[mask_thresh]
  797. input_shape = image.shape
  798. if image.ndim == 2:
  799. image = image[..., np.newaxis]
  800. if mask.ndim == 2:
  801. mask = mask[..., np.newaxis]
  802. mask_thresh = mask > 0.5
  803. if mask.shape[2] == 1:
  804. nb_channels = image.shape[-1]
  805. # TODO verify if tile() is here really necessary
  806. mask_thresh = np.tile(mask_thresh, (1, 1, nb_channels))
  807. # round, this makes 0.2 e.g. become 0 in case of boolean
  808. # image (otherwise replacing values with 0.2 would lead to True
  809. # instead of False).
  810. if image.dtype.kind in ["i", "u", "b"] and replacements.dtype.kind == "f":
  811. replacements = np.round(replacements)
  812. replacement_samples = iadt.clip_to_dtype_value_range_(
  813. replacements, image.dtype, validate=False)
  814. replacement_samples = replacement_samples.astype(image.dtype, copy=False)
  815. image[mask_thresh] = replacement_samples
  816. if len(input_shape) == 2:
  817. return image[..., 0]
  818. return image
  819. def invert(image, min_value=None, max_value=None, threshold=None,
  820. invert_above_threshold=True):
  821. """Invert an array.
  822. **Supported dtypes**:
  823. See :func:`~imgaug.augmenters.arithmetic.invert_`.
  824. Parameters
  825. ----------
  826. image : ndarray
  827. See :func:`invert_`.
  828. min_value : None or number, optional
  829. See :func:`invert_`.
  830. max_value : None or number, optional
  831. See :func:`invert_`.
  832. threshold : None or number, optional
  833. See :func:`invert_`.
  834. invert_above_threshold : bool, optional
  835. See :func:`invert_`.
  836. Returns
  837. -------
  838. ndarray
  839. Inverted image.
  840. """
  841. return invert_(np.copy(image), min_value=min_value, max_value=max_value,
  842. threshold=threshold,
  843. invert_above_threshold=invert_above_threshold)
  844. def invert_(image, min_value=None, max_value=None, threshold=None,
  845. invert_above_threshold=True):
  846. """Invert an array in-place.
  847. Added in 0.4.0.
  848. **Supported dtypes**:
  849. if (min_value=None and max_value=None):
  850. * ``uint8``: yes; fully tested
  851. * ``uint16``: yes; tested
  852. * ``uint32``: yes; tested
  853. * ``uint64``: yes; tested
  854. * ``int8``: yes; tested
  855. * ``int16``: yes; tested
  856. * ``int32``: yes; tested
  857. * ``int64``: yes; tested
  858. * ``float16``: yes; tested
  859. * ``float32``: yes; tested
  860. * ``float64``: yes; tested
  861. * ``float128``: yes; tested
  862. * ``bool``: yes; tested
  863. if (min_value!=None or max_value!=None):
  864. * ``uint8``: yes; fully tested
  865. * ``uint16``: yes; tested
  866. * ``uint32``: yes; tested
  867. * ``uint64``: no (1)
  868. * ``int8``: yes; tested
  869. * ``int16``: yes; tested
  870. * ``int32``: yes; tested
  871. * ``int64``: no (2)
  872. * ``float16``: yes; tested
  873. * ``float32``: yes; tested
  874. * ``float64``: no (2)
  875. * ``float128``: no (3)
  876. * ``bool``: no (4)
  877. - (1) Not allowed due to numpy's clip converting from ``uint64`` to
  878. ``float64``.
  879. - (2) Not allowed as int/float have to be increased in resolution
  880. when using min/max values.
  881. - (3) Not tested.
  882. - (4) Makes no sense when using min/max values.
  883. Parameters
  884. ----------
  885. image : ndarray
  886. Image array of shape ``(H,W,[C])``.
  887. The array *might* be modified in-place.
  888. min_value : None or number, optional
  889. Minimum of the value range of input images, e.g. ``0`` for ``uint8``
  890. images. If set to ``None``, the value will be automatically derived
  891. from the image's dtype.
  892. max_value : None or number, optional
  893. Maximum of the value range of input images, e.g. ``255`` for ``uint8``
  894. images. If set to ``None``, the value will be automatically derived
  895. from the image's dtype.
  896. threshold : None or number, optional
  897. A threshold to use in order to invert only numbers above or below
  898. the threshold. If ``None`` no thresholding will be used.
  899. invert_above_threshold : bool, optional
  900. If ``True``, only values ``>=threshold`` will be inverted.
  901. Otherwise, only values ``<threshold`` will be inverted.
  902. If `threshold` is ``None`` this parameter has no effect.
  903. Returns
  904. -------
  905. ndarray
  906. Inverted image. This *can* be the same array as input in `image`,
  907. modified in-place.
  908. """
  909. # when no custom min/max are chosen, all bool, uint, int and float dtypes
  910. # should be invertable (float tested only up to 64bit)
  911. # when chosing custom min/max:
  912. # - bool makes no sense, not allowed
  913. # - int and float must be increased in resolution if custom min/max values
  914. # are chosen, hence they are limited to 32 bit and below
  915. # - uint64 is converted by numpy's clip to float64, hence loss of accuracy
  916. # - float16 seems to not be perfectly accurate, but still ok-ish -- was
  917. # off by 10 for center value of range (float 16 min, 16), where float
  918. # 16 min is around -65500
  919. allow_dtypes_custom_minmax = {"uint8", "uint16", "uint32",
  920. "int8", "int16", "int32",
  921. "float16", "float32"}
  922. min_value_dt, _, max_value_dt = \
  923. iadt.get_value_range_of_dtype(image.dtype)
  924. min_value = (min_value_dt
  925. if min_value is None else min_value)
  926. max_value = (max_value_dt
  927. if max_value is None else max_value)
  928. assert min_value >= min_value_dt, (
  929. "Expected min_value to be above or equal to dtype's min "
  930. "value, got %s (vs. min possible %s for %s)" % (
  931. str(min_value), str(min_value_dt), image.dtype.name)
  932. )
  933. assert max_value <= max_value_dt, (
  934. "Expected max_value to be below or equal to dtype's max "
  935. "value, got %s (vs. max possible %s for %s)" % (
  936. str(max_value), str(max_value_dt), image.dtype.name)
  937. )
  938. assert min_value < max_value, (
  939. "Expected min_value to be below max_value, got %s "
  940. "and %s" % (
  941. str(min_value), str(max_value))
  942. )
  943. if min_value != min_value_dt or max_value != max_value_dt:
  944. assert image.dtype.name in allow_dtypes_custom_minmax, (
  945. "Can use custom min/max values only with the following "
  946. "dtypes: %s. Got: %s." % (
  947. ", ".join(allow_dtypes_custom_minmax), image.dtype.name))
  948. if image.dtype.name == "uint8":
  949. return _invert_uint8_(image, min_value, max_value, threshold,
  950. invert_above_threshold)
  951. dtype_kind_to_invert_func = {
  952. "b": _invert_bool,
  953. "u": _invert_uint16_or_larger_, # uint8 handled above
  954. "i": _invert_int_,
  955. "f": _invert_float
  956. }
  957. func = dtype_kind_to_invert_func[image.dtype.kind]
  958. if threshold is None:
  959. return func(image, min_value, max_value)
  960. arr_inv = func(np.copy(image), min_value, max_value)
  961. if invert_above_threshold:
  962. mask = (image >= threshold)
  963. else:
  964. mask = (image < threshold)
  965. image[mask] = arr_inv[mask]
  966. return image
  967. def _invert_bool(arr, min_value, max_value):
  968. assert min_value == 0 and max_value == 1, (
  969. "min_value and max_value must be 0 and 1 for bool arrays. "
  970. "Got %.4f and %.4f." % (min_value, max_value))
  971. return ~arr
  972. # Added in 0.4.0.
  973. def _invert_uint8_(arr, min_value, max_value, threshold,
  974. invert_above_threshold):
  975. table = _generate_table_for_invert_uint8(
  976. min_value, max_value, threshold, invert_above_threshold)
  977. arr = ia.apply_lut_(arr, table)
  978. return arr
  979. # Added in 0.4.0.
  980. def _invert_uint16_or_larger_(arr, min_value, max_value):
  981. min_max_is_vr = (min_value == 0
  982. and max_value == np.iinfo(arr.dtype).max)
  983. if min_max_is_vr:
  984. return max_value - arr
  985. return _invert_by_distance(
  986. np.clip(arr, min_value, max_value),
  987. min_value, max_value
  988. )
  989. # Added in 0.4.0.
  990. def _invert_int_(arr, min_value, max_value):
  991. # note that for int dtypes the max value is
  992. # (-1) * min_value - 1
  993. # e.g. -128 and 127 (min/max) for int8
  994. # mapping example:
  995. # [-4, -3, -2, -1, 0, 1, 2, 3]
  996. # will be mapped to
  997. # [ 3, 2, 1, 0, -1, -2, -3, -4]
  998. # hence we can not simply compute the inverse as:
  999. # after = (-1) * before
  1000. # but instead need
  1001. # after = (-1) * before - 1
  1002. # however, this exceeds the value range for the minimum value, e.g.
  1003. # for int8: -128 -> 128 -> 127, where 128 exceeds it. Hence, we must
  1004. # compute the inverse via a mask (extra step for the minimum)
  1005. # or we have to increase the resolution of the array. Here, a
  1006. # two-step approach is used.
  1007. if min_value == (-1) * max_value - 1:
  1008. arr_inv = np.copy(arr)
  1009. mask = (arr_inv == min_value)
  1010. # there is probably a one-liner here to do this, but
  1011. # ((-1) * (arr_inv * ~mask) - 1) + mask * max_value
  1012. # has the disadvantage of inverting min_value to max_value - 1
  1013. # while
  1014. # ((-1) * (arr_inv * ~mask) - 1) + mask * (max_value+1)
  1015. # ((-1) * (arr_inv * ~mask) - 1) + mask * max_value + mask
  1016. # both sometimes increase the dtype resolution (e.g. int32 to int64)
  1017. arr_inv[mask] = max_value
  1018. arr_inv[~mask] = (-1) * arr_inv[~mask] - 1
  1019. return arr_inv
  1020. return _invert_by_distance(
  1021. np.clip(arr, min_value, max_value),
  1022. min_value, max_value
  1023. )
  1024. def _invert_float(arr, min_value, max_value):
  1025. if np.isclose(max_value, (-1)*min_value, rtol=0):
  1026. return (-1) * arr
  1027. return _invert_by_distance(
  1028. np.clip(arr, min_value, max_value),
  1029. min_value, max_value
  1030. )
  1031. def _invert_by_distance(arr, min_value, max_value):
  1032. arr_inv = arr
  1033. if arr.dtype.kind in ["i", "f"]:
  1034. arr_inv = iadt.increase_array_resolutions_([np.copy(arr)], 2)[0]
  1035. distance_from_min = np.abs(arr_inv - min_value) # d=abs(v-min)
  1036. arr_inv = max_value - distance_from_min # v'=MAX-d
  1037. # due to floating point inaccuracies, we might exceed the min/max
  1038. # values for floats here, hence clip this happens especially for
  1039. # values close to the float dtype's maxima
  1040. if arr.dtype.kind == "f":
  1041. arr_inv = np.clip(arr_inv, min_value, max_value)
  1042. if arr.dtype.kind in ["i", "f"]:
  1043. arr_inv = iadt.restore_dtypes_(
  1044. arr_inv, arr.dtype, clip=False)
  1045. return arr_inv
  1046. # Added in 0.4.0.
  1047. def _generate_table_for_invert_uint8(min_value, max_value, threshold,
  1048. invert_above_threshold):
  1049. table = np.arange(256).astype(np.int32)
  1050. full_value_range = (min_value == 0 and max_value == 255)
  1051. if full_value_range:
  1052. table_inv = table[::-1]
  1053. else:
  1054. distance_from_min = np.abs(table - min_value)
  1055. table_inv = max_value - distance_from_min
  1056. table_inv = np.clip(table_inv, min_value, max_value).astype(np.uint8)
  1057. if threshold is not None:
  1058. table = table.astype(np.uint8)
  1059. if invert_above_threshold:
  1060. table_inv = np.concatenate([
  1061. table[0:int(threshold)],
  1062. table_inv[int(threshold):]
  1063. ], axis=0)
  1064. else:
  1065. table_inv = np.concatenate([
  1066. table_inv[0:int(threshold)],
  1067. table[int(threshold):]
  1068. ], axis=0)
  1069. return table_inv
  1070. def solarize(image, threshold=128):
  1071. """Invert pixel values above a threshold.
  1072. Added in 0.4.0.
  1073. **Supported dtypes**:
  1074. See :func:`~imgaug.augmenters.arithmetic.solarize_`.
  1075. Parameters
  1076. ----------
  1077. image : ndarray
  1078. See :func:`solarize_`.
  1079. threshold : None or number, optional
  1080. See :func:`solarize_`.
  1081. Returns
  1082. -------
  1083. ndarray
  1084. Inverted image.
  1085. """
  1086. return solarize_(np.copy(image), threshold=threshold)
  1087. def solarize_(image, threshold=128):
  1088. """Invert pixel values above a threshold in-place.
  1089. This function is a wrapper around :func:`invert`.
  1090. This function performs the same transformation as
  1091. :func:`PIL.ImageOps.solarize`.
  1092. Added in 0.4.0.
  1093. **Supported dtypes**:
  1094. See ``~imgaug.augmenters.arithmetic.invert_(min_value=None and max_value=None)``.
  1095. Parameters
  1096. ----------
  1097. image : ndarray
  1098. See :func:`invert_`.
  1099. threshold : None or number, optional
  1100. See :func:`invert_`.
  1101. Note: The default threshold is optimized for ``uint8`` images.
  1102. Returns
  1103. -------
  1104. ndarray
  1105. Inverted image. This *can* be the same array as input in `image`,
  1106. modified in-place.
  1107. """
  1108. return invert_(image, threshold=threshold)
  1109. def compress_jpeg(image, compression):
  1110. """Compress an image using jpeg compression.
  1111. **Supported dtypes**:
  1112. * ``uint8``: yes; fully tested
  1113. * ``uint16``: ?
  1114. * ``uint32``: ?
  1115. * ``uint64``: ?
  1116. * ``int8``: ?
  1117. * ``int16``: ?
  1118. * ``int32``: ?
  1119. * ``int64``: ?
  1120. * ``float16``: ?
  1121. * ``float32``: ?
  1122. * ``float64``: ?
  1123. * ``float128``: ?
  1124. * ``bool``: ?
  1125. Parameters
  1126. ----------
  1127. image : ndarray
  1128. Image of dtype ``uint8`` and shape ``(H,W,[C])``. If ``C`` is provided,
  1129. it must be ``1`` or ``3``.
  1130. compression : int
  1131. Strength of the compression in the interval ``[0, 100]``.
  1132. Returns
  1133. -------
  1134. ndarray
  1135. Input image after applying jpeg compression to it and reloading
  1136. the result into a new array. Same shape and dtype as the input.
  1137. """
  1138. import PIL.Image
  1139. if image.size == 0:
  1140. return np.copy(image)
  1141. # The value range 1 to 95 is suggested by PIL's save() documentation
  1142. # Values above 95 seem to not make sense (no improvement in visual
  1143. # quality, but large file size).
  1144. # A value of 100 would mostly deactivate jpeg compression.
  1145. # A value of 0 would lead to no compression (instead of maximum
  1146. # compression).
  1147. # We use range 1 to 100 here, because this augmenter is about
  1148. # generating images for training and not for saving, hence we do not
  1149. # care about large file sizes.
  1150. maximum_quality = 100
  1151. minimum_quality = 1
  1152. assert image.dtype.name == "uint8", (
  1153. "Jpeg compression can only be applied to uint8 images. "
  1154. "Got dtype %s." % (image.dtype.name,))
  1155. assert 0 <= compression <= 100, (
  1156. "Expected compression to be in the interval [0, 100], "
  1157. "got %.4f." % (compression,))
  1158. has_no_channels = (image.ndim == 2)
  1159. is_single_channel = (image.ndim == 3 and image.shape[-1] == 1)
  1160. if is_single_channel:
  1161. image = image[..., 0]
  1162. assert has_no_channels or is_single_channel or image.shape[-1] == 3, (
  1163. "Expected either a grayscale image of shape (H,W) or (H,W,1) or an "
  1164. "RGB image of shape (H,W,3). Got shape %s." % (image.shape,))
  1165. # Map from compression to quality used by PIL
  1166. # We have valid compressions from 0 to 100, i.e. 101 possible
  1167. # values
  1168. quality = int(
  1169. np.clip(
  1170. np.round(
  1171. minimum_quality
  1172. + (maximum_quality - minimum_quality)
  1173. * (1.0 - (compression / 101))
  1174. ),
  1175. minimum_quality,
  1176. maximum_quality
  1177. )
  1178. )
  1179. image_pil = PIL.Image.fromarray(image)
  1180. with tempfile.NamedTemporaryFile(mode="wb+", suffix=".jpg") as f:
  1181. image_pil.save(f, quality=quality)
  1182. # Read back from file.
  1183. # We dont read from f.name, because that leads to PermissionDenied
  1184. # errors on Windows. We add f.seek(0) here, because otherwise we get
  1185. # `SyntaxError: index out of range` in PIL.
  1186. f.seek(0)
  1187. pilmode = "RGB"
  1188. if has_no_channels or is_single_channel:
  1189. pilmode = "L"
  1190. image = imageio.imread(f, pilmode=pilmode, format="jpeg")
  1191. if is_single_channel:
  1192. image = image[..., np.newaxis]
  1193. return image
  1194. class Add(meta.Augmenter):
  1195. """
  1196. Add a value to all pixels in an image.
  1197. **Supported dtypes**:
  1198. See :func:`~imgaug.augmenters.arithmetic.add_scalar`.
  1199. Parameters
  1200. ----------
  1201. value : number or tuple of number or list of number or imgaug.parameters.StochasticParameter, optional
  1202. Value to add to all pixels.
  1203. * If a number, exactly that value will always be used.
  1204. * If a tuple ``(a, b)``, then a value from the discrete
  1205. interval ``[a..b]`` will be sampled per image.
  1206. * If a list, then a random value will be sampled from that list
  1207. per image.
  1208. * If a ``StochasticParameter``, then a value will be sampled per
  1209. image from that parameter.
  1210. per_channel : bool or float or imgaug.parameters.StochasticParameter, optional
  1211. Whether to use (imagewise) the same sample(s) for all
  1212. channels (``False``) or to sample value(s) for each channel (``True``).
  1213. Setting this to ``True`` will therefore lead to different
  1214. transformations per image *and* channel, otherwise only per image.
  1215. If this value is a float ``p``, then for ``p`` percent of all images
  1216. `per_channel` will be treated as ``True``.
  1217. If it is a ``StochasticParameter`` it is expected to produce samples
  1218. with values between ``0.0`` and ``1.0``, where values ``>0.5`` will
  1219. lead to per-channel behaviour (i.e. same as ``True``).
  1220. 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
  1221. See :func:`~imgaug.augmenters.meta.Augmenter.__init__`.
  1222. name : None or str, optional
  1223. See :func:`~imgaug.augmenters.meta.Augmenter.__init__`.
  1224. 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
  1225. Old name for parameter `seed`.
  1226. Its usage will not yet cause a deprecation warning,
  1227. but it is still recommended to use `seed` now.
  1228. Outdated since 0.4.0.
  1229. deterministic : bool, optional
  1230. Deprecated since 0.4.0.
  1231. See method ``to_deterministic()`` for an alternative and for
  1232. details about what the "deterministic mode" actually does.
  1233. Examples
  1234. --------
  1235. >>> import imgaug.augmenters as iaa
  1236. >>> aug = iaa.Add(10)
  1237. Always adds a value of 10 to all channels of all pixels of all input
  1238. images.
  1239. >>> aug = iaa.Add((-10, 10))
  1240. Adds a value from the discrete interval ``[-10..10]`` to all pixels of
  1241. input images. The exact value is sampled per image.
  1242. >>> aug = iaa.Add((-10, 10), per_channel=True)
  1243. Adds a value from the discrete interval ``[-10..10]`` to all pixels of
  1244. input images. The exact value is sampled per image *and* channel,
  1245. i.e. to a red-channel it might add 5 while subtracting 7 from the
  1246. blue channel of the same image.
  1247. >>> aug = iaa.Add((-10, 10), per_channel=0.5)
  1248. Identical to the previous example, but the `per_channel` feature is only
  1249. active for 50 percent of all images.
  1250. """
  1251. def __init__(self, value=(-20, 20), per_channel=False,
  1252. seed=None, name=None,
  1253. random_state="deprecated", deterministic="deprecated"):
  1254. super(Add, self).__init__(
  1255. seed=seed, name=name,
  1256. random_state=random_state, deterministic=deterministic)
  1257. self.value = iap.handle_continuous_param(
  1258. value, "value", value_range=None, tuple_to_uniform=True,
  1259. list_to_choice=True)
  1260. self.per_channel = iap.handle_probability_param(
  1261. per_channel, "per_channel")
  1262. # Added in 0.4.0.
  1263. def _augment_batch_(self, batch, random_state, parents, hooks):
  1264. if batch.images is None:
  1265. return batch
  1266. images = batch.images
  1267. nb_images = len(images)
  1268. nb_channels_max = meta.estimate_max_number_of_channels(images)
  1269. rss = random_state.duplicate(2)
  1270. per_channel_samples = self.per_channel.draw_samples(
  1271. (nb_images,), random_state=rss[0])
  1272. value_samples = self.value.draw_samples(
  1273. (nb_images, nb_channels_max), random_state=rss[1])
  1274. gen = enumerate(zip(images, value_samples, per_channel_samples))
  1275. for i, (image, value_samples_i, per_channel_samples_i) in gen:
  1276. nb_channels = image.shape[2]
  1277. # Example code to directly add images via image+sample (uint8 only)
  1278. # if per_channel_samples_i > 0.5:
  1279. # result = []
  1280. # image = image.astype(np.int16)
  1281. # value_samples_i = value_samples_i.astype(np.int16)
  1282. # for c, value in enumerate(value_samples_i[0:nb_channels]):
  1283. # result.append(
  1284. # np.clip(
  1285. # image[..., c:c+1] + value, 0, 255
  1286. # ).astype(np.uint8))
  1287. # images[i] = np.concatenate(result, axis=2)
  1288. # else:
  1289. # images[i] = np.clip(
  1290. # image.astype(np.int16)
  1291. # + value_samples_i[0].astype(np.int16),
  1292. # 0, 255
  1293. # ).astype(np.uint8)
  1294. if per_channel_samples_i > 0.5:
  1295. value = value_samples_i[0:nb_channels]
  1296. else:
  1297. # the if/else here catches the case of the channel axis being 0
  1298. value = value_samples_i[0] if value_samples_i.size > 0 else []
  1299. batch.images[i] = add_scalar(image, value)
  1300. return batch
  1301. def get_parameters(self):
  1302. """See :func:`~imgaug.augmenters.meta.Augmenter.get_parameters`."""
  1303. return [self.value, self.per_channel]
  1304. # TODO merge this with Add
  1305. class AddElementwise(meta.Augmenter):
  1306. """
  1307. Add to the pixels of images values that are pixelwise randomly sampled.
  1308. While the ``Add`` Augmenter samples one value to add *per image* (and
  1309. optionally per channel), this augmenter samples different values per image
  1310. and *per pixel* (and optionally per channel), i.e. intensities of
  1311. neighbouring pixels may be increased/decreased by different amounts.
  1312. **Supported dtypes**:
  1313. See :func:`~imgaug.augmenters.arithmetic.add_elementwise`.
  1314. Parameters
  1315. ----------
  1316. value : int or tuple of int or list of int or imgaug.parameters.StochasticParameter, optional
  1317. Value to add to the pixels.
  1318. * If an int, exactly that value will always be used.
  1319. * If a tuple ``(a, b)``, then values from the discrete interval
  1320. ``[a..b]`` will be sampled per image and pixel.
  1321. * If a list of integers, a random value will be sampled from the
  1322. list per image and pixel.
  1323. * If a ``StochasticParameter``, then values will be sampled per
  1324. image and pixel from that parameter.
  1325. per_channel : bool or float or imgaug.parameters.StochasticParameter, optional
  1326. Whether to use (imagewise) the same sample(s) for all
  1327. channels (``False``) or to sample value(s) for each channel (``True``).
  1328. Setting this to ``True`` will therefore lead to different
  1329. transformations per image *and* channel, otherwise only per image.
  1330. If this value is a float ``p``, then for ``p`` percent of all images
  1331. `per_channel` will be treated as ``True``.
  1332. If it is a ``StochasticParameter`` it is expected to produce samples
  1333. with values between ``0.0`` and ``1.0``, where values ``>0.5`` will
  1334. lead to per-channel behaviour (i.e. same as ``True``).
  1335. 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
  1336. See :func:`~imgaug.augmenters.meta.Augmenter.__init__`.
  1337. name : None or str, optional
  1338. See :func:`~imgaug.augmenters.meta.Augmenter.__init__`.
  1339. 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
  1340. Old name for parameter `seed`.
  1341. Its usage will not yet cause a deprecation warning,
  1342. but it is still recommended to use `seed` now.
  1343. Outdated since 0.4.0.
  1344. deterministic : bool, optional
  1345. Deprecated since 0.4.0.
  1346. See method ``to_deterministic()`` for an alternative and for
  1347. details about what the "deterministic mode" actually does.
  1348. Examples
  1349. --------
  1350. >>> import imgaug.augmenters as iaa
  1351. >>> aug = iaa.AddElementwise(10)
  1352. Always adds a value of 10 to all channels of all pixels of all input
  1353. images.
  1354. >>> aug = iaa.AddElementwise((-10, 10))
  1355. Samples per image and pixel a value from the discrete interval
  1356. ``[-10..10]`` and adds that value to the respective pixel.
  1357. >>> aug = iaa.AddElementwise((-10, 10), per_channel=True)
  1358. Samples per image, pixel *and also channel* a value from the discrete
  1359. interval ``[-10..10]`` and adds it to the respective pixel's channel value.
  1360. Therefore, added values may differ between channels of the same pixel.
  1361. >>> aug = iaa.AddElementwise((-10, 10), per_channel=0.5)
  1362. Identical to the previous example, but the `per_channel` feature is only
  1363. active for 50 percent of all images.
  1364. """
  1365. def __init__(self, value=(-20, 20), per_channel=False,
  1366. seed=None, name=None,
  1367. random_state="deprecated", deterministic="deprecated"):
  1368. super(AddElementwise, self).__init__(
  1369. seed=seed, name=name,
  1370. random_state=random_state, deterministic=deterministic)
  1371. self.value = iap.handle_continuous_param(
  1372. value, "value", value_range=None, tuple_to_uniform=True,
  1373. list_to_choice=True)
  1374. self.per_channel = iap.handle_probability_param(
  1375. per_channel, "per_channel")
  1376. # Added in 0.4.0.
  1377. def _augment_batch_(self, batch, random_state, parents, hooks):
  1378. if batch.images is None:
  1379. return batch
  1380. images = batch.images
  1381. nb_images = len(images)
  1382. rss = random_state.duplicate(1+nb_images)
  1383. per_channel_samples = self.per_channel.draw_samples(
  1384. (nb_images,), random_state=rss[0])
  1385. gen = enumerate(zip(images, per_channel_samples, rss[1:]))
  1386. for i, (image, per_channel_samples_i, rs) in gen:
  1387. height, width, nb_channels = image.shape
  1388. sample_shape = (height,
  1389. width,
  1390. nb_channels if per_channel_samples_i > 0.5 else 1)
  1391. values = self.value.draw_samples(sample_shape, random_state=rs)
  1392. batch.images[i] = add_elementwise(image, values)
  1393. return batch
  1394. def get_parameters(self):
  1395. """See :func:`~imgaug.augmenters.meta.Augmenter.get_parameters`."""
  1396. return [self.value, self.per_channel]
  1397. # TODO rename to AddGaussianNoise?
  1398. # TODO examples say that iaa.AdditiveGaussianNoise(scale=(0, 0.1*255)) samples
  1399. # the scale from the uniform dist. per image, but is that still the case?
  1400. # AddElementwise seems to now sample once for all images, which should
  1401. # lead to a single scale value.
  1402. class AdditiveGaussianNoise(AddElementwise):
  1403. """
  1404. Add noise sampled from gaussian distributions elementwise to images.
  1405. This augmenter samples and adds noise elementwise, i.e. it can add
  1406. different noise values to neighbouring pixels and is comparable
  1407. to ``AddElementwise``.
  1408. **Supported dtypes**:
  1409. See :class:`~imgaug.augmenters.arithmetic.AddElementwise`.
  1410. Parameters
  1411. ----------
  1412. loc : number or tuple of number or list of number or imgaug.parameters.StochasticParameter, optional
  1413. Mean of the normal distribution from which the noise is sampled.
  1414. * If a number, exactly that value will always be used.
  1415. * If a tuple ``(a, b)``, a random value from the interval
  1416. ``[a, b]`` will be sampled per image.
  1417. * If a list, then a random value will be sampled from that list per
  1418. image.
  1419. * If a ``StochasticParameter``, a value will be sampled from the
  1420. parameter per image.
  1421. scale : number or tuple of number or list of number or imgaug.parameters.StochasticParameter, optional
  1422. Standard deviation of the normal distribution that generates the noise.
  1423. Must be ``>=0``. If ``0`` then `loc` will simply be added to all
  1424. pixels.
  1425. * If a number, exactly that value will always be used.
  1426. * If a tuple ``(a, b)``, a random value from the interval
  1427. ``[a, b]`` will be sampled per image.
  1428. * If a list, then a random value will be sampled from that list per
  1429. image.
  1430. * If a ``StochasticParameter``, a value will be sampled from the
  1431. parameter per image.
  1432. per_channel : bool or float or imgaug.parameters.StochasticParameter, optional
  1433. Whether to use (imagewise) the same sample(s) for all
  1434. channels (``False``) or to sample value(s) for each channel (``True``).
  1435. Setting this to ``True`` will therefore lead to different
  1436. transformations per image *and* channel, otherwise only per image.
  1437. If this value is a float ``p``, then for ``p`` percent of all images
  1438. `per_channel` will be treated as ``True``.
  1439. If it is a ``StochasticParameter`` it is expected to produce samples
  1440. with values between ``0.0`` and ``1.0``, where values ``>0.5`` will
  1441. lead to per-channel behaviour (i.e. same as ``True``).
  1442. 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
  1443. See :func:`~imgaug.augmenters.meta.Augmenter.__init__`.
  1444. name : None or str, optional
  1445. See :func:`~imgaug.augmenters.meta.Augmenter.__init__`.
  1446. 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
  1447. Old name for parameter `seed`.
  1448. Its usage will not yet cause a deprecation warning,
  1449. but it is still recommended to use `seed` now.
  1450. Outdated since 0.4.0.
  1451. deterministic : bool, optional
  1452. Deprecated since 0.4.0.
  1453. See method ``to_deterministic()`` for an alternative and for
  1454. details about what the "deterministic mode" actually does.
  1455. Examples
  1456. --------
  1457. >>> import imgaug.augmenters as iaa
  1458. >>> aug = iaa.AdditiveGaussianNoise(scale=0.1*255)
  1459. Adds gaussian noise from the distribution ``N(0, 0.1*255)`` to images.
  1460. The samples are drawn per image and pixel.
  1461. >>> aug = iaa.AdditiveGaussianNoise(scale=(0, 0.1*255))
  1462. Adds gaussian noise from the distribution ``N(0, s)`` to images,
  1463. where ``s`` is sampled per image from the interval ``[0, 0.1*255]``.
  1464. >>> aug = iaa.AdditiveGaussianNoise(scale=0.1*255, per_channel=True)
  1465. Adds gaussian noise from the distribution ``N(0, 0.1*255)`` to images,
  1466. where the noise value is different per image and pixel *and* channel (e.g.
  1467. a different one for red, green and blue channels of the same pixel).
  1468. This leads to "colorful" noise.
  1469. >>> aug = iaa.AdditiveGaussianNoise(scale=0.1*255, per_channel=0.5)
  1470. Identical to the previous example, but the `per_channel` feature is only
  1471. active for 50 percent of all images.
  1472. """
  1473. def __init__(self, loc=0, scale=(0, 15), per_channel=False,
  1474. seed=None, name=None,
  1475. random_state="deprecated", deterministic="deprecated"):
  1476. loc2 = iap.handle_continuous_param(
  1477. loc, "loc", value_range=None, tuple_to_uniform=True,
  1478. list_to_choice=True)
  1479. scale2 = iap.handle_continuous_param(
  1480. scale, "scale", value_range=(0, None), tuple_to_uniform=True,
  1481. list_to_choice=True)
  1482. value = iap.Normal(loc=loc2, scale=scale2)
  1483. super(AdditiveGaussianNoise, self).__init__(
  1484. value, per_channel=per_channel,
  1485. seed=seed, name=name,
  1486. random_state=random_state, deterministic=deterministic)
  1487. # TODO add tests
  1488. # TODO rename to AddLaplaceNoise?
  1489. class AdditiveLaplaceNoise(AddElementwise):
  1490. """
  1491. Add noise sampled from laplace distributions elementwise to images.
  1492. The laplace distribution is similar to the gaussian distribution, but
  1493. puts more weight on the long tail. Hence, this noise will add more
  1494. outliers (very high/low values). It is somewhere between gaussian noise and
  1495. salt and pepper noise.
  1496. Values of around ``255 * 0.05`` for `scale` lead to visible noise (for
  1497. ``uint8``).
  1498. Values of around ``255 * 0.10`` for `scale` lead to very visible
  1499. noise (for ``uint8``).
  1500. It is recommended to usually set `per_channel` to ``True``.
  1501. This augmenter samples and adds noise elementwise, i.e. it can add
  1502. different noise values to neighbouring pixels and is comparable
  1503. to ``AddElementwise``.
  1504. **Supported dtypes**:
  1505. See :class:`~imgaug.augmenters.arithmetic.AddElementwise`.
  1506. Parameters
  1507. ----------
  1508. loc : number or tuple of number or list of number or imgaug.parameters.StochasticParameter, optional
  1509. Mean of the laplace distribution that generates the noise.
  1510. * If a number, exactly that value will always be used.
  1511. * If a tuple ``(a, b)``, a random value from the interval
  1512. ``[a, b]`` will be sampled per image.
  1513. * If a list, then a random value will be sampled from that list per
  1514. image.
  1515. * If a ``StochasticParameter``, a value will be sampled from the
  1516. parameter per image.
  1517. scale : number or tuple of number or list of number or imgaug.parameters.StochasticParameter, optional
  1518. Standard deviation of the laplace distribution that generates the noise.
  1519. Must be ``>=0``. If ``0`` then only `loc` will be used.
  1520. Recommended to be around ``255*0.05``.
  1521. * If a number, exactly that value will always be used.
  1522. * If a tuple ``(a, b)``, a random value from the interval
  1523. ``[a, b]`` will be sampled per image.
  1524. * If a list, then a random value will be sampled from that list per
  1525. image.
  1526. * If a ``StochasticParameter``, a value will be sampled from the
  1527. parameter per image.
  1528. per_channel : bool or float or imgaug.parameters.StochasticParameter, optional
  1529. Whether to use (imagewise) the same sample(s) for all
  1530. channels (``False``) or to sample value(s) for each channel (``True``).
  1531. Setting this to ``True`` will therefore lead to different
  1532. transformations per image *and* channel, otherwise only per image.
  1533. If this value is a float ``p``, then for ``p`` percent of all images
  1534. `per_channel` will be treated as ``True``.
  1535. If it is a ``StochasticParameter`` it is expected to produce samples
  1536. with values between ``0.0`` and ``1.0``, where values ``>0.5`` will
  1537. lead to per-channel behaviour (i.e. same as ``True``).
  1538. 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
  1539. See :func:`~imgaug.augmenters.meta.Augmenter.__init__`.
  1540. name : None or str, optional
  1541. See :func:`~imgaug.augmenters.meta.Augmenter.__init__`.
  1542. 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
  1543. Old name for parameter `seed`.
  1544. Its usage will not yet cause a deprecation warning,
  1545. but it is still recommended to use `seed` now.
  1546. Outdated since 0.4.0.
  1547. deterministic : bool, optional
  1548. Deprecated since 0.4.0.
  1549. See method ``to_deterministic()`` for an alternative and for
  1550. details about what the "deterministic mode" actually does.
  1551. Examples
  1552. --------
  1553. >>> import imgaug.augmenters as iaa
  1554. >>> aug = iaa.AdditiveLaplaceNoise(scale=0.1*255)
  1555. Adds laplace noise from the distribution ``Laplace(0, 0.1*255)`` to images.
  1556. The samples are drawn per image and pixel.
  1557. >>> aug = iaa.AdditiveLaplaceNoise(scale=(0, 0.1*255))
  1558. Adds laplace noise from the distribution ``Laplace(0, s)`` to images,
  1559. where ``s`` is sampled per image from the interval ``[0, 0.1*255]``.
  1560. >>> aug = iaa.AdditiveLaplaceNoise(scale=0.1*255, per_channel=True)
  1561. Adds laplace noise from the distribution ``Laplace(0, 0.1*255)`` to images,
  1562. where the noise value is different per image and pixel *and* channel (e.g.
  1563. a different one for the red, green and blue channels of the same pixel).
  1564. This leads to "colorful" noise.
  1565. >>> aug = iaa.AdditiveLaplaceNoise(scale=0.1*255, per_channel=0.5)
  1566. Identical to the previous example, but the `per_channel` feature is only
  1567. active for 50 percent of all images.
  1568. """
  1569. def __init__(self, loc=0, scale=(0, 15), per_channel=False,
  1570. seed=None, name=None,
  1571. random_state="deprecated", deterministic="deprecated"):
  1572. loc2 = iap.handle_continuous_param(
  1573. loc, "loc", value_range=None, tuple_to_uniform=True,
  1574. list_to_choice=True)
  1575. scale2 = iap.handle_continuous_param(
  1576. scale, "scale", value_range=(0, None), tuple_to_uniform=True,
  1577. list_to_choice=True)
  1578. value = iap.Laplace(loc=loc2, scale=scale2)
  1579. super(AdditiveLaplaceNoise, self).__init__(
  1580. value,
  1581. per_channel=per_channel,
  1582. seed=seed, name=name,
  1583. random_state=random_state, deterministic=deterministic)
  1584. # TODO add tests
  1585. # TODO rename to AddPoissonNoise?
  1586. class AdditivePoissonNoise(AddElementwise):
  1587. """
  1588. Add noise sampled from poisson distributions elementwise to images.
  1589. Poisson noise is comparable to gaussian noise, as e.g. generated via
  1590. ``AdditiveGaussianNoise``. As poisson distributions produce only positive
  1591. numbers, the sign of the sampled values are here randomly flipped.
  1592. Values of around ``10.0`` for `lam` lead to visible noise (for ``uint8``).
  1593. Values of around ``20.0`` for `lam` lead to very visible noise (for
  1594. ``uint8``).
  1595. It is recommended to usually set `per_channel` to ``True``.
  1596. This augmenter samples and adds noise elementwise, i.e. it can add
  1597. different noise values to neighbouring pixels and is comparable
  1598. to ``AddElementwise``.
  1599. **Supported dtypes**:
  1600. See :class:`~imgaug.augmenters.arithmetic.AddElementwise`.
  1601. Parameters
  1602. ----------
  1603. lam : number or tuple of number or list of number or imgaug.parameters.StochasticParameter, optional
  1604. Lambda parameter of the poisson distribution. Must be ``>=0``.
  1605. Recommended values are around ``0.0`` to ``10.0``.
  1606. * If a number, exactly that value will always be used.
  1607. * If a tuple ``(a, b)``, a random value from the interval
  1608. ``[a, b]`` will be sampled per image.
  1609. * If a list, then a random value will be sampled from that list
  1610. per image.
  1611. * If a ``StochasticParameter``, a value will be sampled from the
  1612. parameter per image.
  1613. per_channel : bool or float or imgaug.parameters.StochasticParameter, optional
  1614. Whether to use (imagewise) the same sample(s) for all
  1615. channels (``False``) or to sample value(s) for each channel (``True``).
  1616. Setting this to ``True`` will therefore lead to different
  1617. transformations per image *and* channel, otherwise only per image.
  1618. If this value is a float ``p``, then for ``p`` percent of all images
  1619. `per_channel` will be treated as ``True``.
  1620. If it is a ``StochasticParameter`` it is expected to produce samples
  1621. with values between ``0.0`` and ``1.0``, where values ``>0.5`` will
  1622. lead to per-channel behaviour (i.e. same as ``True``).
  1623. 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
  1624. See :func:`~imgaug.augmenters.meta.Augmenter.__init__`.
  1625. name : None or str, optional
  1626. See :func:`~imgaug.augmenters.meta.Augmenter.__init__`.
  1627. 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
  1628. Old name for parameter `seed`.
  1629. Its usage will not yet cause a deprecation warning,
  1630. but it is still recommended to use `seed` now.
  1631. Outdated since 0.4.0.
  1632. deterministic : bool, optional
  1633. Deprecated since 0.4.0.
  1634. See method ``to_deterministic()`` for an alternative and for
  1635. details about what the "deterministic mode" actually does.
  1636. Examples
  1637. --------
  1638. >>> import imgaug.augmenters as iaa
  1639. >>> aug = iaa.AdditivePoissonNoise(lam=5.0)
  1640. Adds poisson noise sampled from a poisson distribution with a ``lambda``
  1641. parameter of ``5.0`` to images.
  1642. The samples are drawn per image and pixel.
  1643. >>> aug = iaa.AdditivePoissonNoise(lam=(0.0, 15.0))
  1644. Adds poisson noise sampled from ``Poisson(x)`` to images, where ``x`` is
  1645. randomly sampled per image from the interval ``[0.0, 15.0]``.
  1646. >>> aug = iaa.AdditivePoissonNoise(lam=5.0, per_channel=True)
  1647. Adds poisson noise sampled from ``Poisson(5.0)`` to images,
  1648. where the values are different per image and pixel *and* channel (e.g. a
  1649. different one for red, green and blue channels for the same pixel).
  1650. >>> aug = iaa.AdditivePoissonNoise(lam=(0.0, 15.0), per_channel=True)
  1651. Adds poisson noise sampled from ``Poisson(x)`` to images,
  1652. with ``x`` being sampled from ``uniform(0.0, 15.0)`` per image and
  1653. channel. This is the *recommended* configuration.
  1654. >>> aug = iaa.AdditivePoissonNoise(lam=(0.0, 15.0), per_channel=0.5)
  1655. Identical to the previous example, but the `per_channel` feature is only
  1656. active for 50 percent of all images.
  1657. """
  1658. def __init__(self, lam=(0.0, 15.0), per_channel=False,
  1659. seed=None, name=None,
  1660. random_state="deprecated", deterministic="deprecated"):
  1661. lam2 = iap.handle_continuous_param(
  1662. lam, "lam",
  1663. value_range=(0, None), tuple_to_uniform=True, list_to_choice=True)
  1664. value = iap.RandomSign(iap.Poisson(lam=lam2))
  1665. super(AdditivePoissonNoise, self).__init__(
  1666. value,
  1667. per_channel=per_channel,
  1668. seed=seed, name=name,
  1669. random_state=random_state, deterministic=deterministic)
  1670. class Multiply(meta.Augmenter):
  1671. """
  1672. Multiply all pixels in an image with a random value sampled once per image.
  1673. This augmenter can be used to make images lighter or darker.
  1674. **Supported dtypes**:
  1675. See :func:`~imgaug.augmenters.arithmetic.multiply_scalar`.
  1676. Parameters
  1677. ----------
  1678. mul : number or tuple of number or list of number or imgaug.parameters.StochasticParameter, optional
  1679. The value with which to multiply the pixel values in each image.
  1680. * If a number, then that value will always be used.
  1681. * If a tuple ``(a, b)``, then a value from the interval ``[a, b]``
  1682. will be sampled per image and used for all pixels.
  1683. * If a list, then a random value will be sampled from that list per
  1684. image.
  1685. * If a ``StochasticParameter``, then that parameter will be used to
  1686. sample a new value per image.
  1687. per_channel : bool or float or imgaug.parameters.StochasticParameter, optional
  1688. Whether to use (imagewise) the same sample(s) for all
  1689. channels (``False``) or to sample value(s) for each channel (``True``).
  1690. Setting this to ``True`` will therefore lead to different
  1691. transformations per image *and* channel, otherwise only per image.
  1692. If this value is a float ``p``, then for ``p`` percent of all images
  1693. `per_channel` will be treated as ``True``.
  1694. If it is a ``StochasticParameter`` it is expected to produce samples
  1695. with values between ``0.0`` and ``1.0``, where values ``>0.5`` will
  1696. lead to per-channel behaviour (i.e. same as ``True``).
  1697. 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
  1698. See :func:`~imgaug.augmenters.meta.Augmenter.__init__`.
  1699. name : None or str, optional
  1700. See :func:`~imgaug.augmenters.meta.Augmenter.__init__`.
  1701. 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
  1702. Old name for parameter `seed`.
  1703. Its usage will not yet cause a deprecation warning,
  1704. but it is still recommended to use `seed` now.
  1705. Outdated since 0.4.0.
  1706. deterministic : bool, optional
  1707. Deprecated since 0.4.0.
  1708. See method ``to_deterministic()`` for an alternative and for
  1709. details about what the "deterministic mode" actually does.
  1710. Examples
  1711. --------
  1712. >>> import imgaug.augmenters as iaa
  1713. >>> aug = iaa.Multiply(2.0)
  1714. Multiplies all images by a factor of ``2``, making the images significantly
  1715. brighter.
  1716. >>> aug = iaa.Multiply((0.5, 1.5))
  1717. Multiplies images by a random value sampled uniformly from the interval
  1718. ``[0.5, 1.5]``, making some images darker and others brighter.
  1719. >>> aug = iaa.Multiply((0.5, 1.5), per_channel=True)
  1720. Identical to the previous example, but the sampled multipliers differ by
  1721. image *and* channel, instead of only by image.
  1722. >>> aug = iaa.Multiply((0.5, 1.5), per_channel=0.5)
  1723. Identical to the previous example, but the `per_channel` feature is only
  1724. active for 50 percent of all images.
  1725. """
  1726. def __init__(self, mul=(0.8, 1.2), per_channel=False,
  1727. seed=None, name=None,
  1728. random_state="deprecated", deterministic="deprecated"):
  1729. super(Multiply, self).__init__(
  1730. seed=seed, name=name,
  1731. random_state=random_state, deterministic=deterministic)
  1732. self.mul = iap.handle_continuous_param(
  1733. mul, "mul", value_range=None, tuple_to_uniform=True,
  1734. list_to_choice=True)
  1735. self.per_channel = iap.handle_probability_param(
  1736. per_channel, "per_channel")
  1737. # Added in 0.4.0.
  1738. def _augment_batch_(self, batch, random_state, parents, hooks):
  1739. if batch.images is None:
  1740. return batch
  1741. images = batch.images
  1742. nb_images = len(images)
  1743. nb_channels_max = meta.estimate_max_number_of_channels(images)
  1744. rss = random_state.duplicate(2)
  1745. per_channel_samples = self.per_channel.draw_samples(
  1746. (nb_images,), random_state=rss[0])
  1747. mul_samples = self.mul.draw_samples(
  1748. (nb_images, nb_channels_max), random_state=rss[1])
  1749. gen = enumerate(zip(images, mul_samples, per_channel_samples))
  1750. for i, (image, mul_samples_i, per_channel_samples_i) in gen:
  1751. nb_channels = image.shape[2]
  1752. # Example code to directly multiply images via image*sample
  1753. # (uint8 only) -- apparently slower than LUT
  1754. # if per_channel_samples_i > 0.5:
  1755. # result = []
  1756. # image = image.astype(np.float32)
  1757. # mul_samples_i = mul_samples_i.astype(np.float32)
  1758. # for c, mul in enumerate(mul_samples_i[0:nb_channels]):
  1759. # result.append(
  1760. # np.clip(
  1761. # image[..., c:c+1] * mul, 0, 255
  1762. # ).astype(np.uint8))
  1763. # images[i] = np.concatenate(result, axis=2)
  1764. # else:
  1765. # images[i] = np.clip(
  1766. # image.astype(np.float32)
  1767. # * mul_samples_i[0].astype(np.float32),
  1768. # 0, 255
  1769. # ).astype(np.uint8)
  1770. if per_channel_samples_i > 0.5:
  1771. mul = mul_samples_i[0:nb_channels]
  1772. else:
  1773. # the if/else here catches the case of the channel axis being 0
  1774. mul = mul_samples_i[0] if mul_samples_i.size > 0 else []
  1775. batch.images[i] = multiply_scalar(image, mul)
  1776. return batch
  1777. def get_parameters(self):
  1778. """See :func:`~imgaug.augmenters.meta.Augmenter.get_parameters`."""
  1779. return [self.mul, self.per_channel]
  1780. # TODO merge with Multiply
  1781. class MultiplyElementwise(meta.Augmenter):
  1782. """
  1783. Multiply image pixels with values that are pixelwise randomly sampled.
  1784. While the ``Multiply`` Augmenter uses a constant multiplier *per
  1785. image* (and optionally channel), this augmenter samples the multipliers
  1786. to use per image and *per pixel* (and optionally per channel).
  1787. **Supported dtypes**:
  1788. See :func:`~imgaug.augmenters.arithmetic.multiply_elementwise`.
  1789. Parameters
  1790. ----------
  1791. mul : number or tuple of number or list of number or imgaug.parameters.StochasticParameter, optional
  1792. The value with which to multiply pixel values in the image.
  1793. * If a number, then that value will always be used.
  1794. * If a tuple ``(a, b)``, then a value from the interval ``[a, b]``
  1795. will be sampled per image and pixel.
  1796. * If a list, then a random value will be sampled from that list
  1797. per image and pixel.
  1798. * If a ``StochasticParameter``, then that parameter will be used to
  1799. sample a new value per image and pixel.
  1800. per_channel : bool or float or imgaug.parameters.StochasticParameter, optional
  1801. Whether to use (imagewise) the same sample(s) for all
  1802. channels (``False``) or to sample value(s) for each channel (``True``).
  1803. Setting this to ``True`` will therefore lead to different
  1804. transformations per image *and* channel, otherwise only per image.
  1805. If this value is a float ``p``, then for ``p`` percent of all images
  1806. `per_channel` will be treated as ``True``.
  1807. If it is a ``StochasticParameter`` it is expected to produce samples
  1808. with values between ``0.0`` and ``1.0``, where values ``>0.5`` will
  1809. lead to per-channel behaviour (i.e. same as ``True``).
  1810. 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
  1811. See :func:`~imgaug.augmenters.meta.Augmenter.__init__`.
  1812. name : None or str, optional
  1813. See :func:`~imgaug.augmenters.meta.Augmenter.__init__`.
  1814. 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
  1815. Old name for parameter `seed`.
  1816. Its usage will not yet cause a deprecation warning,
  1817. but it is still recommended to use `seed` now.
  1818. Outdated since 0.4.0.
  1819. deterministic : bool, optional
  1820. Deprecated since 0.4.0.
  1821. See method ``to_deterministic()`` for an alternative and for
  1822. details about what the "deterministic mode" actually does.
  1823. Examples
  1824. --------
  1825. >>> import imgaug.augmenters as iaa
  1826. >>> aug = iaa.MultiplyElementwise(2.0)
  1827. Multiply all images by a factor of ``2.0``, making them significantly
  1828. bighter.
  1829. >>> aug = iaa.MultiplyElementwise((0.5, 1.5))
  1830. Samples per image and pixel uniformly a value from the interval
  1831. ``[0.5, 1.5]`` and multiplies the pixel with that value.
  1832. >>> aug = iaa.MultiplyElementwise((0.5, 1.5), per_channel=True)
  1833. Samples per image and pixel *and channel* uniformly a value from the
  1834. interval ``[0.5, 1.5]`` and multiplies the pixel with that value. Therefore,
  1835. used multipliers may differ between channels of the same pixel.
  1836. >>> aug = iaa.MultiplyElementwise((0.5, 1.5), per_channel=0.5)
  1837. Identical to the previous example, but the `per_channel` feature is only
  1838. active for 50 percent of all images.
  1839. """
  1840. def __init__(self, mul=(0.8, 1.2), per_channel=False,
  1841. seed=None, name=None,
  1842. random_state="deprecated", deterministic="deprecated"):
  1843. super(MultiplyElementwise, self).__init__(
  1844. seed=seed, name=name,
  1845. random_state=random_state, deterministic=deterministic)
  1846. self.mul = iap.handle_continuous_param(
  1847. mul, "mul",
  1848. value_range=None, tuple_to_uniform=True, list_to_choice=True)
  1849. self.per_channel = iap.handle_probability_param(per_channel,
  1850. "per_channel")
  1851. # Added in 0.4.0.
  1852. def _augment_batch_(self, batch, random_state, parents, hooks):
  1853. if batch.images is None:
  1854. return batch
  1855. images = batch.images
  1856. nb_images = len(images)
  1857. rss = random_state.duplicate(1+nb_images)
  1858. per_channel_samples = self.per_channel.draw_samples(
  1859. (nb_images,), random_state=rss[0])
  1860. is_mul_binomial = isinstance(self.mul, iap.Binomial) or (
  1861. isinstance(self.mul, iap.FromLowerResolution)
  1862. and isinstance(self.mul.other_param, iap.Binomial)
  1863. )
  1864. gen = enumerate(zip(images, per_channel_samples, rss[1:]))
  1865. for i, (image, per_channel_samples_i, rs) in gen:
  1866. height, width, nb_channels = image.shape
  1867. sample_shape = (height,
  1868. width,
  1869. nb_channels if per_channel_samples_i > 0.5 else 1)
  1870. mul = self.mul.draw_samples(sample_shape, random_state=rs)
  1871. # TODO let Binomial return boolean mask directly instead of [0, 1]
  1872. # integers?
  1873. # hack to improve performance for Dropout and CoarseDropout
  1874. # converts mul samples to mask if mul is binomial
  1875. if mul.dtype.kind != "b" and is_mul_binomial:
  1876. mul = mul.astype(bool, copy=False)
  1877. batch.images[i] = multiply_elementwise(image, mul)
  1878. return batch
  1879. def get_parameters(self):
  1880. """See :func:`~imgaug.augmenters.meta.Augmenter.get_parameters`."""
  1881. return [self.mul, self.per_channel]
  1882. # Added in 0.4.0.
  1883. class _CutoutSamples(object):
  1884. # Added in 0.4.0.
  1885. def __init__(self, nb_iterations, pos_x, pos_y, size_h, size_w, squared,
  1886. fill_mode, cval, fill_per_channel):
  1887. self.nb_iterations = nb_iterations
  1888. self.pos_x = pos_x
  1889. self.pos_y = pos_y
  1890. self.size_h = size_h
  1891. self.size_w = size_w
  1892. self.squared = squared
  1893. self.fill_mode = fill_mode
  1894. self.cval = cval
  1895. self.fill_per_channel = fill_per_channel
  1896. class Cutout(meta.Augmenter):
  1897. """Fill one or more rectangular areas in an image using a fill mode.
  1898. See paper "Improved Regularization of Convolutional Neural Networks with
  1899. Cutout" by DeVries and Taylor.
  1900. In contrast to the paper, this implementation also supports replacing
  1901. image sub-areas with gaussian noise, random intensities or random RGB
  1902. colors. It also supports non-squared areas. While the paper uses
  1903. absolute pixel values for the size and position, this implementation
  1904. uses relative values, which seems more appropriate for mixed-size
  1905. datasets. The position parameter furthermore allows more flexibility, e.g.
  1906. gaussian distributions around the center.
  1907. .. note::
  1908. This augmenter affects only image data. Other datatypes (e.g.
  1909. segmentation map pixels or keypoints within the filled areas)
  1910. are not affected.
  1911. .. note::
  1912. Gaussian fill mode will assume that float input images contain values
  1913. in the interval ``[0.0, 1.0]`` and hence sample values from a
  1914. gaussian within that interval, i.e. from ``N(0.5, std=0.5/3)``.
  1915. Added in 0.4.0.
  1916. **Supported dtypes**:
  1917. See :func:`~imgaug.augmenters.arithmetic.cutout_`.
  1918. Parameters
  1919. ----------
  1920. nb_iterations : int or tuple of int or list of int or imgaug.parameters.StochasticParameter, optional
  1921. How many rectangular areas to fill.
  1922. * If ``int``: Exactly that many areas will be filled on all images.
  1923. * If ``tuple`` ``(a, b)``: A value from the interval ``[a, b]``
  1924. will be sampled per image.
  1925. * If ``list``: A random value will be sampled from that ``list``
  1926. per image.
  1927. * If ``StochasticParameter``: That parameter will be used to
  1928. sample ``(B,)`` values per batch of ``B`` images.
  1929. position : {'uniform', 'normal', 'center', 'left-top', 'left-center', 'left-bottom', 'center-top', 'center-center', 'center-bottom', 'right-top', 'right-center', 'right-bottom'} or tuple of float or StochasticParameter or tuple of StochasticParameter, optional
  1930. Defines the position of each area to fill.
  1931. Analogous to the definition in e.g.
  1932. :class:`~imgaug.augmenters.size.CropToFixedSize`.
  1933. Usually, ``uniform`` (anywhere in the image) or ``normal`` (anywhere
  1934. in the image with preference around the center) are sane values.
  1935. size : number or tuple of number or list of number or imgaug.parameters.StochasticParameter, optional
  1936. The size of the rectangle to fill as a fraction of the corresponding
  1937. image size, i.e. with value range ``[0.0, 1.0]``. The size is sampled
  1938. independently per image axis.
  1939. * If ``number``: Exactly that size is always used.
  1940. * If ``tuple`` ``(a, b)``: A value from the interval ``[a, b]``
  1941. will be sampled per area and axis.
  1942. * If ``list``: A random value will be sampled from that ``list``
  1943. per area and axis.
  1944. * If ``StochasticParameter``: That parameter will be used to
  1945. sample ``(N, 2)`` values per batch, where ``N`` is the total
  1946. number of areas to fill within the whole batch.
  1947. squared : bool or float or imgaug.parameters.StochasticParameter, optional
  1948. Whether to generate only squared areas cutout areas or allow
  1949. rectangular ones. If this evaluates to a true-like value, the
  1950. first value from `size` will be converted to absolute pixels and used
  1951. for both axes.
  1952. If this value is a float ``p``, then for ``p`` percent of all areas
  1953. to be filled `per_channel` will be treated as ``True``.
  1954. If it is a ``StochasticParameter`` it is expected to produce samples
  1955. with values between ``0.0`` and ``1.0``, where values ``>0.5`` will
  1956. lead to per-channel behaviour (i.e. same as ``True``).
  1957. fill_mode : str or list of str or imgaug.parameters.StochasticParameter, optional
  1958. Mode to use in order to fill areas. Corresponds to ``mode`` parameter
  1959. in some other augmenters. Valid strings for the mode are:
  1960. * ``contant``: Fill each area with a single value.
  1961. * ``gaussian``: Fill each area with gaussian noise.
  1962. Valid datatypes are:
  1963. * If ``str``: Exactly that mode will alaways be used.
  1964. * If ``list``: A random value will be sampled from that ``list``
  1965. per area.
  1966. * If ``StochasticParameter``: That parameter will be used to
  1967. sample ``(N,)`` values per batch, where ``N`` is the total number
  1968. of areas to fill within the whole batch.
  1969. cval : number or tuple of number or list of number or imgaug.parameters.StochasticParameter, optional
  1970. The value to use (i.e. the color) to fill areas if `fill_mode` is
  1971. ```constant``.
  1972. * If ``number``: Exactly that value is used for all areas
  1973. and channels.
  1974. * If ``tuple`` ``(a, b)``: A value from the interval ``[a, b]``
  1975. will be sampled per area (and channel if ``per_channel=True``).
  1976. * If ``list``: A random value will be sampled from that ``list``
  1977. per area (and channel if ``per_channel=True``).
  1978. * If ``StochasticParameter``: That parameter will be used to
  1979. sample ``(N, Cmax)`` values per batch, where ``N`` is the total
  1980. number of areas to fill within the whole batch and ``Cmax``
  1981. is the maximum number of channels in any image (usually ``3``).
  1982. If ``per_channel=False``, only the first value of the second
  1983. axis is used.
  1984. fill_per_channel : bool or float or imgaug.parameters.StochasticParameter, optional
  1985. Whether to fill each area in a channelwise fashion (``True``) or
  1986. not (``False``).
  1987. The behaviour per fill mode is:
  1988. * ``constant``: Whether to fill all channels with the same value
  1989. (i.e, grayscale) or different values (i.e. usually RGB color).
  1990. * ``gaussian``: Whether to sample once from a gaussian and use the
  1991. values for all channels (i.e. grayscale) or to sample
  1992. channelwise (i.e. RGB colors)
  1993. If this value is a float ``p``, then for ``p`` percent of all areas
  1994. to be filled `per_channel` will be treated as ``True``.
  1995. If it is a ``StochasticParameter`` it is expected to produce samples
  1996. with values between ``0.0`` and ``1.0``, where values ``>0.5`` will
  1997. lead to per-channel behaviour (i.e. same as ``True``).
  1998. name : None or str, optional
  1999. See :func:`~imgaug.augmenters.meta.Augmenter.__init__`.
  2000. deterministic : bool, optional
  2001. See :func:`~imgaug.augmenters.meta.Augmenter.__init__`.
  2002. random_state : None or int or imgaug.random.RNG or numpy.random.Generator or numpy.random.bit_generator.BitGenerator or numpy.random.SeedSequence or numpy.random.RandomState, optional
  2003. See :func:`~imgaug.augmenters.meta.Augmenter.__init__`.
  2004. Examples
  2005. --------
  2006. >>> import imgaug.augmenters as iaa
  2007. >>> aug = iaa.Cutout(nb_iterations=2)
  2008. Fill per image two random areas, by default with grayish pixels.
  2009. >>> aug = iaa.Cutout(nb_iterations=(1, 5), size=0.2, squared=False)
  2010. Fill per image between one and five areas, each having ``20%``
  2011. of the corresponding size of the height and width (for non-square
  2012. images this results in non-square areas to be filled).
  2013. >>> aug = iaa.Cutout(fill_mode="constant", cval=255)
  2014. Fill all areas with white pixels.
  2015. >>> aug = iaa.Cutout(fill_mode="constant", cval=(0, 255),
  2016. >>> fill_per_channel=0.5)
  2017. Fill ``50%`` of all areas with a random intensity value between
  2018. ``0`` and ``256``. Fill the other ``50%`` of all areas with
  2019. random colors.
  2020. >>> aug = iaa.Cutout(fill_mode="gaussian", fill_per_channel=True)
  2021. Fill areas with gaussian channelwise noise (i.e. usually RGB).
  2022. """
  2023. # Added in 0.4.0.
  2024. def __init__(self,
  2025. nb_iterations=1,
  2026. position="uniform",
  2027. size=0.2,
  2028. squared=True,
  2029. fill_mode="constant",
  2030. cval=128,
  2031. fill_per_channel=False,
  2032. seed=None, name=None,
  2033. random_state="deprecated", deterministic="deprecated"):
  2034. from .size import _handle_position_parameter # TODO move to iap
  2035. from .geometric import _handle_cval_arg # TODO move to iap
  2036. super(Cutout, self).__init__(
  2037. seed=seed, name=name,
  2038. random_state=random_state, deterministic=deterministic)
  2039. self.nb_iterations = iap.handle_discrete_param(
  2040. nb_iterations, "nb_iterations", value_range=(0, None),
  2041. tuple_to_uniform=True, list_to_choice=True, allow_floats=False)
  2042. self.position = _handle_position_parameter(position)
  2043. self.size = iap.handle_continuous_param(
  2044. size, "size", value_range=(0.0, 1.0+1e-4),
  2045. tuple_to_uniform=True, list_to_choice=True)
  2046. self.squared = iap.handle_probability_param(squared, "squared")
  2047. self.fill_mode = self._handle_fill_mode_param(fill_mode)
  2048. self.cval = _handle_cval_arg(cval)
  2049. self.fill_per_channel = iap.handle_probability_param(
  2050. fill_per_channel, "fill_per_channel")
  2051. # Added in 0.4.0.
  2052. @classmethod
  2053. def _handle_fill_mode_param(cls, fill_mode):
  2054. if ia.is_string(fill_mode):
  2055. assert fill_mode in _CUTOUT_FILL_MODES, (
  2056. "Expected 'fill_mode' to be one of: %s. Got %s." % (
  2057. str(list(_CUTOUT_FILL_MODES.keys())), fill_mode))
  2058. return iap.Deterministic(fill_mode)
  2059. if isinstance(fill_mode, iap.StochasticParameter):
  2060. return fill_mode
  2061. assert ia.is_iterable(fill_mode), (
  2062. "Expected 'fill_mode' to be a string, "
  2063. "StochasticParameter or list of strings. Got type %s." % (
  2064. type(fill_mode).__name__))
  2065. return iap.Choice(fill_mode)
  2066. # Added in 0.4.0.
  2067. def _augment_batch_(self, batch, random_state, parents, hooks):
  2068. if batch.images is None:
  2069. return batch
  2070. samples = self._draw_samples(batch.images, random_state)
  2071. # map from xyhw to xyxy (both relative coords)
  2072. cutout_height_half = samples.size_h / 2
  2073. cutout_width_half = samples.size_w / 2
  2074. x1_rel = samples.pos_x - cutout_width_half
  2075. y1_rel = samples.pos_y - cutout_height_half
  2076. x2_rel = samples.pos_x + cutout_width_half
  2077. y2_rel = samples.pos_y + cutout_height_half
  2078. nb_iterations_sum = 0
  2079. gen = enumerate(zip(batch.images, samples.nb_iterations))
  2080. for i, (image, nb_iterations) in gen:
  2081. start = nb_iterations_sum
  2082. end = start + nb_iterations
  2083. height, width = image.shape[0:2]
  2084. # map from relative xyxy to absolute xyxy coords
  2085. batch.images[i] = self._augment_image_by_samples(
  2086. image,
  2087. x1_rel[start:end] * width,
  2088. y1_rel[start:end] * height,
  2089. x2_rel[start:end] * width,
  2090. y2_rel[start:end] * height,
  2091. samples.squared[start:end],
  2092. samples.fill_mode[start:end],
  2093. samples.cval[start:end],
  2094. samples.fill_per_channel[start:end],
  2095. random_state)
  2096. nb_iterations_sum += nb_iterations
  2097. return batch
  2098. # Added in 0.4.0.
  2099. def _draw_samples(self, images, random_state):
  2100. rngs = random_state.duplicate(8)
  2101. nb_rows = len(images)
  2102. nb_channels_max = meta.estimate_max_number_of_channels(images)
  2103. nb_iterations = self.nb_iterations.draw_samples(
  2104. (nb_rows,), random_state=rngs[0])
  2105. nb_dropped_areas = int(np.sum(nb_iterations))
  2106. if isinstance(self.position, tuple):
  2107. pos_x = self.position[0].draw_samples((nb_dropped_areas,),
  2108. random_state=rngs[1])
  2109. pos_y = self.position[1].draw_samples((nb_dropped_areas,),
  2110. random_state=rngs[2])
  2111. else:
  2112. pos = self.position.draw_samples((nb_dropped_areas, 2),
  2113. random_state=rngs[1])
  2114. pos_x = pos[:, 0]
  2115. pos_y = pos[:, 1]
  2116. size = self.size.draw_samples((nb_dropped_areas, 2),
  2117. random_state=rngs[3])
  2118. squared = self.squared.draw_samples((nb_dropped_areas,),
  2119. random_state=rngs[4])
  2120. fill_mode = self.fill_mode.draw_samples(
  2121. (nb_dropped_areas,), random_state=rngs[5])
  2122. cval = self.cval.draw_samples((nb_dropped_areas, nb_channels_max),
  2123. random_state=rngs[6])
  2124. fill_per_channel = self.fill_per_channel.draw_samples(
  2125. (nb_dropped_areas,), random_state=rngs[7])
  2126. return _CutoutSamples(
  2127. nb_iterations=nb_iterations,
  2128. pos_x=pos_x,
  2129. pos_y=pos_y,
  2130. size_h=size[:, 0],
  2131. size_w=size[:, 1],
  2132. squared=squared,
  2133. fill_mode=fill_mode,
  2134. cval=cval,
  2135. fill_per_channel=fill_per_channel
  2136. )
  2137. # Added in 0.4.0.
  2138. @classmethod
  2139. def _augment_image_by_samples(cls, image, x1, y1, x2, y2, squared,
  2140. fill_mode, cval, fill_per_channel,
  2141. random_state):
  2142. for i, x1_i in enumerate(x1):
  2143. x2_i = x2[i]
  2144. if squared[i] >= 0.5:
  2145. height_h = (y2[i] - y1[i]) / 2
  2146. x_center = x1_i + (x2_i - x1_i) / 2
  2147. x1_i = x_center - height_h
  2148. x2_i = x_center + height_h
  2149. image = cutout_(
  2150. image,
  2151. x1=x1_i,
  2152. y1=y1[i],
  2153. x2=x2_i,
  2154. y2=y2[i],
  2155. fill_mode=fill_mode[i],
  2156. cval=cval[i],
  2157. fill_per_channel=fill_per_channel[i],
  2158. seed=random_state)
  2159. return image
  2160. # Added in 0.4.0.
  2161. def get_parameters(self):
  2162. """See :func:`~imgaug.augmenters.meta.Augmenter.get_parameters`."""
  2163. return [self.nb_iterations, self.position, self.size, self.squared,
  2164. self.fill_mode, self.cval, self.fill_per_channel]
  2165. # TODO verify that (a, b) still leads to a p being sampled per image and not
  2166. # per batch
  2167. class Dropout(MultiplyElementwise):
  2168. """
  2169. Set a fraction of pixels in images to zero.
  2170. **Supported dtypes**:
  2171. See :class:`~imgaug.augmenters.arithmetic.MultiplyElementwise`.
  2172. Parameters
  2173. ----------
  2174. p : float or tuple of float or imgaug.parameters.StochasticParameter, optional
  2175. The probability of any pixel being dropped (i.e. to set it to zero).
  2176. * If a float, then that value will be used for all images. A value
  2177. of ``1.0`` would mean that all pixels will be dropped
  2178. and ``0.0`` that no pixels will be dropped. A value of ``0.05``
  2179. corresponds to ``5`` percent of all pixels being dropped.
  2180. * If a tuple ``(a, b)``, then a value ``p`` will be sampled from
  2181. the interval ``[a, b]`` per image and be used as the pixel's
  2182. dropout probability.
  2183. * If a list, then a value will be sampled from that list per
  2184. batch and used as the probability.
  2185. * If a ``StochasticParameter``, then this parameter will be used to
  2186. determine per pixel whether it should be *kept* (sampled value
  2187. of ``>0.5``) or shouldn't be kept (sampled value of ``<=0.5``).
  2188. If you instead want to provide the probability as a stochastic
  2189. parameter, you can usually do ``imgaug.parameters.Binomial(1-p)``
  2190. to convert parameter `p` to a 0/1 representation.
  2191. per_channel : bool or float or imgaug.parameters.StochasticParameter, optional
  2192. Whether to use (imagewise) the same sample(s) for all
  2193. channels (``False``) or to sample value(s) for each channel (``True``).
  2194. Setting this to ``True`` will therefore lead to different
  2195. transformations per image *and* channel, otherwise only per image.
  2196. If this value is a float ``p``, then for ``p`` percent of all images
  2197. `per_channel` will be treated as ``True``.
  2198. If it is a ``StochasticParameter`` it is expected to produce samples
  2199. with values between ``0.0`` and ``1.0``, where values ``>0.5`` will
  2200. lead to per-channel behaviour (i.e. same as ``True``).
  2201. 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
  2202. See :func:`~imgaug.augmenters.meta.Augmenter.__init__`.
  2203. name : None or str, optional
  2204. See :func:`~imgaug.augmenters.meta.Augmenter.__init__`.
  2205. 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
  2206. Old name for parameter `seed`.
  2207. Its usage will not yet cause a deprecation warning,
  2208. but it is still recommended to use `seed` now.
  2209. Outdated since 0.4.0.
  2210. deterministic : bool, optional
  2211. Deprecated since 0.4.0.
  2212. See method ``to_deterministic()`` for an alternative and for
  2213. details about what the "deterministic mode" actually does.
  2214. Examples
  2215. --------
  2216. >>> import imgaug.augmenters as iaa
  2217. >>> aug = iaa.Dropout(0.02)
  2218. Drops ``2`` percent of all pixels.
  2219. >>> aug = iaa.Dropout((0.0, 0.05))
  2220. Drops in each image a random fraction of all pixels, where the fraction
  2221. is uniformly sampled from the interval ``[0.0, 0.05]``.
  2222. >>> aug = iaa.Dropout(0.02, per_channel=True)
  2223. Drops ``2`` percent of all pixels in a channelwise fashion, i.e. it is
  2224. unlikely for any pixel to have all channels set to zero (black pixels).
  2225. >>> aug = iaa.Dropout(0.02, per_channel=0.5)
  2226. Identical to the previous example, but the `per_channel` feature is only
  2227. active for ``50`` percent of all images.
  2228. """
  2229. def __init__(self, p=(0.0, 0.05), per_channel=False,
  2230. seed=None, name=None,
  2231. random_state="deprecated", deterministic="deprecated"):
  2232. p_param = _handle_dropout_probability_param(p, "p")
  2233. super(Dropout, self).__init__(
  2234. p_param,
  2235. per_channel=per_channel,
  2236. seed=seed, name=name,
  2237. random_state=random_state, deterministic=deterministic)
  2238. # Added in 0.4.0.
  2239. def _handle_dropout_probability_param(p, name):
  2240. if ia.is_single_number(p):
  2241. p_param = iap.Binomial(1 - p)
  2242. elif isinstance(p, tuple):
  2243. assert len(p) == 2, (
  2244. "Expected `%s` to be given as a tuple containing exactly 2 values, "
  2245. "got %d values." % (name, len(p),))
  2246. assert p[0] < p[1], (
  2247. "Expected `%s` to be given as a tuple containing exactly 2 values "
  2248. "(a, b) with a < b. Got %.4f and %.4f." % (name, p[0], p[1]))
  2249. assert 0 <= p[0] <= 1.0 and 0 <= p[1] <= 1.0, (
  2250. "Expected `%s` given as tuple to only contain values in the "
  2251. "interval [0.0, 1.0], got %.4f and %.4f." % (name, p[0], p[1]))
  2252. p_param = iap.Binomial(iap.Uniform(1 - p[1], 1 - p[0]))
  2253. elif ia.is_iterable(p):
  2254. assert all([ia.is_single_number(v) for v in p]), (
  2255. "Expected iterable parameter '%s' to only contain numbers, "
  2256. "got %s." % (name, [type(v) for v in p],))
  2257. assert all([0 <= p_i <= 1.0 for p_i in p]), (
  2258. "Expected iterable parameter '%s' to only contain probabilities "
  2259. "in the interval [0.0, 1.0], got values %s." % (
  2260. name, ", ".join(["%.4f" % (p_i,) for p_i in p])))
  2261. p_param = iap.Binomial(1 - iap.Choice(p))
  2262. elif isinstance(p, iap.StochasticParameter):
  2263. p_param = p
  2264. else:
  2265. raise Exception(
  2266. "Expected `%s` to be float or int or tuple (<number>, <number>) "
  2267. "or StochasticParameter, got type '%s'." % (
  2268. name, type(p).__name__,))
  2269. return p_param
  2270. # TODO invert size_px and size_percent so that larger values denote larger
  2271. # areas being dropped instead of the opposite way around
  2272. class CoarseDropout(MultiplyElementwise):
  2273. """
  2274. Set rectangular areas within images to zero.
  2275. In contrast to ``Dropout``, these areas can have larger sizes.
  2276. (E.g. you might end up with three large black rectangles in an image.)
  2277. Note that the current implementation leads to correlated sizes,
  2278. so if e.g. there is any thin and high rectangle that is dropped, there is
  2279. a high likelihood that all other dropped areas are also thin and high.
  2280. This method is implemented by generating the dropout mask at a
  2281. lower resolution (than the image has) and then upsampling the mask
  2282. before dropping the pixels.
  2283. This augmenter is similar to Cutout. Usually, cutout is defined as an
  2284. operation that drops exactly one rectangle from an image, while here
  2285. ``CoarseDropout`` can drop multiple rectangles (with some correlation
  2286. between the sizes of these rectangles).
  2287. **Supported dtypes**:
  2288. See :class:`~imgaug.augmenters.arithmetic.MultiplyElementwise`.
  2289. Parameters
  2290. ----------
  2291. p : float or tuple of float or imgaug.parameters.StochasticParameter, optional
  2292. The probability of any pixel being dropped (i.e. set to zero) in
  2293. the lower-resolution dropout mask.
  2294. * If a float, then that value will be used for all pixels. A value
  2295. of ``1.0`` would mean, that all pixels will be dropped. A value
  2296. of ``0.0`` would lead to no pixels being dropped.
  2297. * If a tuple ``(a, b)``, then a value ``p`` will be sampled from
  2298. the interval ``[a, b]`` per image and be used as the dropout
  2299. probability.
  2300. * If a list, then a value will be sampled from that list per
  2301. batch and used as the probability.
  2302. * If a ``StochasticParameter``, then this parameter will be used to
  2303. determine per pixel whether it should be *kept* (sampled value
  2304. of ``>0.5``) or shouldn't be kept (sampled value of ``<=0.5``).
  2305. If you instead want to provide the probability as a stochastic
  2306. parameter, you can usually do ``imgaug.parameters.Binomial(1-p)``
  2307. to convert parameter `p` to a 0/1 representation.
  2308. size_px : None or int or tuple of int or imgaug.parameters.StochasticParameter, optional
  2309. The size of the lower resolution image from which to sample the dropout
  2310. mask in absolute pixel dimensions.
  2311. Note that this means that *lower* values of this parameter lead to
  2312. *larger* areas being dropped (as any pixel in the lower resolution
  2313. image will correspond to a larger area at the original resolution).
  2314. * If ``None`` then `size_percent` must be set.
  2315. * If an integer, then that size will always be used for both height
  2316. and width. E.g. a value of ``3`` would lead to a ``3x3`` mask,
  2317. which is then upsampled to ``HxW``, where ``H`` is the image size
  2318. and ``W`` the image width.
  2319. * If a tuple ``(a, b)``, then two values ``M``, ``N`` will be
  2320. sampled from the discrete interval ``[a..b]``. The dropout mask
  2321. will then be generated at size ``MxN`` and upsampled to ``HxW``.
  2322. * If a ``StochasticParameter``, then this parameter will be used to
  2323. determine the sizes. It is expected to be discrete.
  2324. size_percent : None or float or tuple of float or imgaug.parameters.StochasticParameter, optional
  2325. The size of the lower resolution image from which to sample the dropout
  2326. mask *in percent* of the input image.
  2327. Note that this means that *lower* values of this parameter lead to
  2328. *larger* areas being dropped (as any pixel in the lower resolution
  2329. image will correspond to a larger area at the original resolution).
  2330. * If ``None`` then `size_px` must be set.
  2331. * If a float, then that value will always be used as the percentage
  2332. of the height and width (relative to the original size). E.g. for
  2333. value ``p``, the mask will be sampled from ``(p*H)x(p*W)`` and
  2334. later upsampled to ``HxW``.
  2335. * If a tuple ``(a, b)``, then two values ``m``, ``n`` will be
  2336. sampled from the interval ``(a, b)`` and used as the size
  2337. fractions, i.e the mask size will be ``(m*H)x(n*W)``.
  2338. * If a ``StochasticParameter``, then this parameter will be used to
  2339. sample the percentage values. It is expected to be continuous.
  2340. per_channel : bool or float or imgaug.parameters.StochasticParameter, optional
  2341. Whether to use (imagewise) the same sample(s) for all
  2342. channels (``False``) or to sample value(s) for each channel (``True``).
  2343. Setting this to ``True`` will therefore lead to different
  2344. transformations per image *and* channel, otherwise only per image.
  2345. If this value is a float ``p``, then for ``p`` percent of all images
  2346. `per_channel` will be treated as ``True``.
  2347. If it is a ``StochasticParameter`` it is expected to produce samples
  2348. with values between ``0.0`` and ``1.0``, where values ``>0.5`` will
  2349. lead to per-channel behaviour (i.e. same as ``True``).
  2350. min_size : int, optional
  2351. Minimum height and width of the low resolution mask. If
  2352. `size_percent` or `size_px` leads to a lower value than this,
  2353. `min_size` will be used instead. This should never have a value of
  2354. less than ``2``, otherwise one may end up with a ``1x1`` low resolution
  2355. mask, leading easily to the whole image being dropped.
  2356. 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
  2357. See :func:`~imgaug.augmenters.meta.Augmenter.__init__`.
  2358. name : None or str, optional
  2359. See :func:`~imgaug.augmenters.meta.Augmenter.__init__`.
  2360. 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
  2361. Old name for parameter `seed`.
  2362. Its usage will not yet cause a deprecation warning,
  2363. but it is still recommended to use `seed` now.
  2364. Outdated since 0.4.0.
  2365. deterministic : bool, optional
  2366. Deprecated since 0.4.0.
  2367. See method ``to_deterministic()`` for an alternative and for
  2368. details about what the "deterministic mode" actually does.
  2369. Examples
  2370. --------
  2371. >>> import imgaug.augmenters as iaa
  2372. >>> aug = iaa.CoarseDropout(0.02, size_percent=0.5)
  2373. Drops ``2`` percent of all pixels on a lower-resolution image that has
  2374. ``50`` percent of the original image's size, leading to dropped areas that
  2375. have roughly ``2x2`` pixels size.
  2376. >>> aug = iaa.CoarseDropout((0.0, 0.05), size_percent=(0.05, 0.5))
  2377. Generates a dropout mask at ``5`` to ``50`` percent of each input image's
  2378. size. In that mask, ``0`` to ``5`` percent of all pixels are marked as
  2379. being dropped. The mask is afterwards projected to the input image's
  2380. size to apply the actual dropout operation.
  2381. >>> aug = iaa.CoarseDropout((0.0, 0.05), size_px=(2, 16))
  2382. Same as the previous example, but the lower resolution image has ``2`` to
  2383. ``16`` pixels size. On images of e.g. ``224x224` pixels in size this would
  2384. lead to fairly large areas being dropped (height/width of ``224/2`` to
  2385. ``224/16``).
  2386. >>> aug = iaa.CoarseDropout(0.02, size_percent=0.5, per_channel=True)
  2387. Drops ``2`` percent of all pixels at ``50`` percent resolution (``2x2``
  2388. sizes) in a channel-wise fashion, i.e. it is unlikely for any pixel to
  2389. have all channels set to zero (black pixels).
  2390. >>> aug = iaa.CoarseDropout(0.02, size_percent=0.5, per_channel=0.5)
  2391. Same as the previous example, but the `per_channel` feature is only active
  2392. for ``50`` percent of all images.
  2393. """
  2394. def __init__(self, p=(0.02, 0.1), size_px=None, size_percent=None,
  2395. per_channel=False, min_size=3,
  2396. seed=None, name=None,
  2397. random_state="deprecated", deterministic="deprecated"):
  2398. p_param = _handle_dropout_probability_param(p, "p")
  2399. if size_px is not None:
  2400. p_param = iap.FromLowerResolution(other_param=p_param,
  2401. size_px=size_px,
  2402. min_size=min_size)
  2403. elif size_percent is not None:
  2404. p_param = iap.FromLowerResolution(other_param=p_param,
  2405. size_percent=size_percent,
  2406. min_size=min_size)
  2407. else:
  2408. # default if neither size_px nor size_percent is provided
  2409. # is size_px=(3, 8)
  2410. p_param = iap.FromLowerResolution(other_param=p_param,
  2411. size_px=(3, 8),
  2412. min_size=min_size)
  2413. super(CoarseDropout, self).__init__(
  2414. p_param,
  2415. per_channel=per_channel,
  2416. seed=seed, name=name,
  2417. random_state=random_state, deterministic=deterministic)
  2418. class Dropout2d(meta.Augmenter):
  2419. """Drop random channels from images.
  2420. For image data, dropped channels will be filled with zeros.
  2421. .. note::
  2422. This augmenter may also set the arrays of heatmaps and segmentation
  2423. maps to zero and remove all coordinate-based data (e.g. it removes
  2424. all bounding boxes on images that were filled with zeros).
  2425. It does so if and only if *all* channels of an image are dropped.
  2426. If ``nb_keep_channels >= 1`` then that never happens.
  2427. Added in 0.4.0.
  2428. **Supported dtypes**:
  2429. * ``uint8``: yes; fully tested
  2430. * ``uint16``: yes; tested
  2431. * ``uint32``: yes; tested
  2432. * ``uint64``: yes; tested
  2433. * ``int8``: yes; tested
  2434. * ``int16``: yes; tested
  2435. * ``int32``: yes; tested
  2436. * ``int64``: yes; tested
  2437. * ``float16``: yes; tested
  2438. * ``float32``: yes; tested
  2439. * ``float64``: yes; tested
  2440. * ``float128``: yes; tested
  2441. * ``bool``: yes; tested
  2442. Parameters
  2443. ----------
  2444. p : float or tuple of float or imgaug.parameters.StochasticParameter, optional
  2445. The probability of any channel to be dropped (i.e. set to zero).
  2446. * If a ``float``, then that value will be used for all channels.
  2447. A value of ``1.0`` would mean, that all channels will be dropped.
  2448. A value of ``0.0`` would lead to no channels being dropped.
  2449. * If a tuple ``(a, b)``, then a value ``p`` will be sampled from
  2450. the interval ``[a, b)`` per batch and be used as the dropout
  2451. probability.
  2452. * If a list, then a value will be sampled from that list per
  2453. batch and used as the probability.
  2454. * If a ``StochasticParameter``, then this parameter will be used to
  2455. determine per channel whether it should be *kept* (sampled value
  2456. of ``>=0.5``) or shouldn't be kept (sampled value of ``<0.5``).
  2457. If you instead want to provide the probability as a stochastic
  2458. parameter, you can usually do ``imgaug.parameters.Binomial(1-p)``
  2459. to convert parameter `p` to a 0/1 representation.
  2460. nb_keep_channels : int
  2461. Minimum number of channels to keep unaltered in all images.
  2462. E.g. a value of ``1`` means that at least one channel in every image
  2463. will not be dropped, even if ``p=1.0``. Set to ``0`` to allow dropping
  2464. all channels.
  2465. 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
  2466. See :func:`~imgaug.augmenters.meta.Augmenter.__init__`.
  2467. name : None or str, optional
  2468. See :func:`~imgaug.augmenters.meta.Augmenter.__init__`.
  2469. 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
  2470. Old name for parameter `seed`.
  2471. Its usage will not yet cause a deprecation warning,
  2472. but it is still recommended to use `seed` now.
  2473. Outdated since 0.4.0.
  2474. deterministic : bool, optional
  2475. Deprecated since 0.4.0.
  2476. See method ``to_deterministic()`` for an alternative and for
  2477. details about what the "deterministic mode" actually does.
  2478. Examples
  2479. --------
  2480. >>> import imgaug.augmenters as iaa
  2481. >>> aug = iaa.Dropout2d(p=0.5)
  2482. Create a dropout augmenter that drops on average half of all image
  2483. channels. Dropped channels will be filled with zeros. At least one
  2484. channel is kept unaltered in each image (default setting).
  2485. >>> import imgaug.augmenters as iaa
  2486. >>> aug = iaa.Dropout2d(p=0.5, nb_keep_channels=0)
  2487. Create a dropout augmenter that drops on average half of all image
  2488. channels *and* may drop *all* channels in an image (i.e. images may
  2489. contain nothing but zeros).
  2490. """
  2491. # Added in 0.4.0.
  2492. def __init__(self, p=0.1, nb_keep_channels=1,
  2493. seed=None, name=None,
  2494. random_state="deprecated", deterministic="deprecated"):
  2495. super(Dropout2d, self).__init__(
  2496. seed=seed, name=name,
  2497. random_state=random_state, deterministic=deterministic)
  2498. self.p = _handle_dropout_probability_param(p, "p")
  2499. self.nb_keep_channels = max(nb_keep_channels, 0)
  2500. self._drop_images = True
  2501. self._drop_heatmaps = True
  2502. self._drop_segmentation_maps = True
  2503. self._drop_keypoints = True
  2504. self._drop_bounding_boxes = True
  2505. self._drop_polygons = True
  2506. self._drop_line_strings = True
  2507. self._heatmaps_cval = 0.0
  2508. self._segmentation_maps_cval = 0
  2509. # Added in 0.4.0.
  2510. def _augment_batch_(self, batch, random_state, parents, hooks):
  2511. imagewise_drop_channel_ids, all_dropped_ids = self._draw_samples(
  2512. batch, random_state)
  2513. if batch.images is not None:
  2514. for image, drop_ids in zip(batch.images,
  2515. imagewise_drop_channel_ids):
  2516. image[:, :, drop_ids] = 0
  2517. # Skip the non-image data steps below if we won't modify non-image
  2518. # anyways. Minor performance improvement.
  2519. if len(all_dropped_ids) == 0:
  2520. return batch
  2521. if batch.heatmaps is not None and self._drop_heatmaps:
  2522. cval = self._heatmaps_cval
  2523. for drop_idx in all_dropped_ids:
  2524. batch.heatmaps[drop_idx].arr_0to1[...] = cval
  2525. if batch.segmentation_maps is not None and self._drop_segmentation_maps:
  2526. cval = self._segmentation_maps_cval
  2527. for drop_idx in all_dropped_ids:
  2528. batch.segmentation_maps[drop_idx].arr[...] = cval
  2529. for attr_name in ["keypoints", "bounding_boxes", "polygons",
  2530. "line_strings"]:
  2531. do_drop = getattr(self, "_drop_%s" % (attr_name,))
  2532. attr_value = getattr(batch, attr_name)
  2533. if attr_value is not None and do_drop:
  2534. for drop_idx in all_dropped_ids:
  2535. # same as e.g.:
  2536. # batch.bounding_boxes[drop_idx].bounding_boxes = []
  2537. setattr(attr_value[drop_idx], attr_name, [])
  2538. return batch
  2539. # Added in 0.4.0.
  2540. def _draw_samples(self, batch, random_state):
  2541. # maybe noteworthy here that the channel axis can have size 0,
  2542. # e.g. (5, 5, 0)
  2543. shapes = batch.get_rowwise_shapes()
  2544. shapes = [shape
  2545. if len(shape) >= 2
  2546. else tuple(list(shape) + [1])
  2547. for shape in shapes]
  2548. imagewise_channels = np.array([
  2549. shape[2] for shape in shapes
  2550. ], dtype=np.int32)
  2551. # channelwise drop value over all images (float <0.5 = drop channel)
  2552. p_samples = self.p.draw_samples((int(np.sum(imagewise_channels)),),
  2553. random_state=random_state)
  2554. # We map the flat p_samples array to an imagewise one,
  2555. # convert the mask to channel-ids to drop and remove channel ids if
  2556. # there are more to be dropped than are allowed to be dropped (see
  2557. # nb_keep_channels).
  2558. # We also track all_dropped_ids, which contains the ids of examples
  2559. # (not channel ids!) where all channels were dropped.
  2560. imagewise_channels_to_drop = []
  2561. all_dropped_ids = []
  2562. channel_idx = 0
  2563. for i, nb_channels in enumerate(imagewise_channels):
  2564. p_samples_i = p_samples[channel_idx:channel_idx+nb_channels]
  2565. drop_ids = np.nonzero(p_samples_i < 0.5)[0]
  2566. nb_dropable = max(nb_channels - self.nb_keep_channels, 0)
  2567. if len(drop_ids) > nb_dropable:
  2568. random_state.shuffle(drop_ids)
  2569. drop_ids = drop_ids[:nb_dropable]
  2570. imagewise_channels_to_drop.append(drop_ids)
  2571. all_dropped = (len(drop_ids) == nb_channels)
  2572. if all_dropped:
  2573. all_dropped_ids.append(i)
  2574. channel_idx += nb_channels
  2575. return imagewise_channels_to_drop, all_dropped_ids
  2576. # Added in 0.4.0.
  2577. def get_parameters(self):
  2578. """See :func:`~imgaug.augmenters.meta.Augmenter.get_parameters`."""
  2579. return [self.p, self.nb_keep_channels]
  2580. class TotalDropout(meta.Augmenter):
  2581. """Drop all channels of a defined fraction of all images.
  2582. For image data, all components of dropped images will be filled with zeros.
  2583. .. note::
  2584. This augmenter also sets the arrays of heatmaps and segmentation
  2585. maps to zero and removes all coordinate-based data (e.g. it removes
  2586. all bounding boxes on images that were filled with zeros).
  2587. Added in 0.4.0.
  2588. **Supported dtypes**:
  2589. * ``uint8``: yes; fully tested
  2590. * ``uint16``: yes; tested
  2591. * ``uint32``: yes; tested
  2592. * ``uint64``: yes; tested
  2593. * ``int8``: yes; tested
  2594. * ``int16``: yes; tested
  2595. * ``int32``: yes; tested
  2596. * ``int64``: yes; tested
  2597. * ``float16``: yes; tested
  2598. * ``float32``: yes; tested
  2599. * ``float64``: yes; tested
  2600. * ``float128``: yes; tested
  2601. * ``bool``: yes; tested
  2602. Parameters
  2603. ----------
  2604. p : float or tuple of float or imgaug.parameters.StochasticParameter, optional
  2605. The probability of an image to be filled with zeros.
  2606. * If ``float``: The value will be used for all images.
  2607. A value of ``1.0`` would mean that all images will be set to zero.
  2608. A value of ``0.0`` would lead to no images being set to zero.
  2609. * If ``tuple`` ``(a, b)``: A value ``p`` will be sampled from
  2610. the interval ``[a, b)`` per batch and be used as the dropout
  2611. probability.
  2612. * If a list, then a value will be sampled from that list per
  2613. batch and used as the probability.
  2614. * If ``StochasticParameter``: The parameter will be used to
  2615. determine per image whether it should be *kept* (sampled value
  2616. of ``>=0.5``) or shouldn't be kept (sampled value of ``<0.5``).
  2617. If you instead want to provide the probability as a stochastic
  2618. parameter, you can usually do ``imgaug.parameters.Binomial(1-p)``
  2619. to convert parameter `p` to a 0/1 representation.
  2620. 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
  2621. See :func:`~imgaug.augmenters.meta.Augmenter.__init__`.
  2622. name : None or str, optional
  2623. See :func:`~imgaug.augmenters.meta.Augmenter.__init__`.
  2624. 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
  2625. Old name for parameter `seed`.
  2626. Its usage will not yet cause a deprecation warning,
  2627. but it is still recommended to use `seed` now.
  2628. Outdated since 0.4.0.
  2629. deterministic : bool, optional
  2630. Deprecated since 0.4.0.
  2631. See method ``to_deterministic()`` for an alternative and for
  2632. details about what the "deterministic mode" actually does.
  2633. Examples
  2634. --------
  2635. >>> import imgaug.augmenters as iaa
  2636. >>> aug = iaa.TotalDropout(1.0)
  2637. Create an augmenter that sets *all* components of all images to zero.
  2638. >>> aug = iaa.TotalDropout(0.5)
  2639. Create an augmenter that sets *all* components of ``50%`` of all images to
  2640. zero.
  2641. """
  2642. # Added in 0.4.0.
  2643. def __init__(self, p=1,
  2644. seed=None, name=None,
  2645. random_state="deprecated", deterministic="deprecated"):
  2646. super(TotalDropout, self).__init__(
  2647. seed=seed, name=name,
  2648. random_state=random_state, deterministic=deterministic)
  2649. self.p = _handle_dropout_probability_param(p, "p")
  2650. self._drop_images = True
  2651. self._drop_heatmaps = True
  2652. self._drop_segmentation_maps = True
  2653. self._drop_keypoints = True
  2654. self._drop_bounding_boxes = True
  2655. self._drop_polygons = True
  2656. self._drop_line_strings = True
  2657. self._heatmaps_cval = 0.0
  2658. self._segmentation_maps_cval = 0
  2659. # Added in 0.4.0.
  2660. def _augment_batch_(self, batch, random_state, parents, hooks):
  2661. drop_mask = self._draw_samples(batch, random_state)
  2662. drop_ids = None
  2663. if batch.images is not None and self._drop_images:
  2664. if ia.is_np_array(batch.images):
  2665. batch.images[drop_mask, ...] = 0
  2666. else:
  2667. drop_ids = self._generate_drop_ids_once(drop_mask, drop_ids)
  2668. for drop_idx in drop_ids:
  2669. batch.images[drop_idx][...] = 0
  2670. if batch.heatmaps is not None and self._drop_heatmaps:
  2671. drop_ids = self._generate_drop_ids_once(drop_mask, drop_ids)
  2672. cval = self._heatmaps_cval
  2673. for drop_idx in drop_ids:
  2674. batch.heatmaps[drop_idx].arr_0to1[...] = cval
  2675. if batch.segmentation_maps is not None and self._drop_segmentation_maps:
  2676. drop_ids = self._generate_drop_ids_once(drop_mask, drop_ids)
  2677. cval = self._segmentation_maps_cval
  2678. for drop_idx in drop_ids:
  2679. batch.segmentation_maps[drop_idx].arr[...] = cval
  2680. for attr_name in ["keypoints", "bounding_boxes", "polygons",
  2681. "line_strings"]:
  2682. do_drop = getattr(self, "_drop_%s" % (attr_name,))
  2683. attr_value = getattr(batch, attr_name)
  2684. if attr_value is not None and do_drop:
  2685. drop_ids = self._generate_drop_ids_once(drop_mask, drop_ids)
  2686. for drop_idx in drop_ids:
  2687. # same as e.g.:
  2688. # batch.bounding_boxes[drop_idx].bounding_boxes = []
  2689. setattr(attr_value[drop_idx], attr_name, [])
  2690. return batch
  2691. # Added in 0.4.0.
  2692. def _draw_samples(self, batch, random_state):
  2693. p = self.p.draw_samples((batch.nb_rows,), random_state=random_state)
  2694. drop_mask = (p < 0.5)
  2695. return drop_mask
  2696. # Added in 0.4.0.
  2697. @classmethod
  2698. def _generate_drop_ids_once(cls, drop_mask, drop_ids):
  2699. if drop_ids is None:
  2700. drop_ids = np.nonzero(drop_mask)[0]
  2701. return drop_ids
  2702. # Added in 0.4.0.
  2703. def get_parameters(self):
  2704. """See :func:`~imgaug.augmenters.meta.Augmenter.get_parameters`."""
  2705. return [self.p]
  2706. class ReplaceElementwise(meta.Augmenter):
  2707. """
  2708. Replace pixels in an image with new values.
  2709. **Supported dtypes**:
  2710. See :func:`~imgaug.augmenters.arithmetic.replace_elementwise_`.
  2711. Parameters
  2712. ----------
  2713. mask : float or tuple of float or list of float or imgaug.parameters.StochasticParameter
  2714. Mask that indicates the pixels that are supposed to be replaced.
  2715. The mask will be binarized using a threshold of ``0.5``. A value
  2716. of ``1`` then indicates a pixel that is supposed to be replaced.
  2717. * If this is a float, then that value will be used as the
  2718. probability of being a ``1`` in the mask (sampled per image and
  2719. pixel) and hence being replaced.
  2720. * If a tuple ``(a, b)``, then the probability will be uniformly
  2721. sampled per image from the interval ``[a, b]``.
  2722. * If a list, then a random value will be sampled from that list
  2723. per image and pixel.
  2724. * If a ``StochasticParameter``, then this parameter will be used to
  2725. sample a mask per image.
  2726. replacement : number or tuple of number or list of number or imgaug.parameters.StochasticParameter
  2727. The replacement to use at all locations that are marked as ``1`` in
  2728. the mask.
  2729. * If this is a number, then that value will always be used as the
  2730. replacement.
  2731. * If a tuple ``(a, b)``, then the replacement will be sampled
  2732. uniformly per image and pixel from the interval ``[a, b]``.
  2733. * If a list, then a random value will be sampled from that list
  2734. per image and pixel.
  2735. * If a ``StochasticParameter``, then this parameter will be used
  2736. sample replacement values per image and pixel.
  2737. per_channel : bool or float or imgaug.parameters.StochasticParameter, optional
  2738. Whether to use (imagewise) the same sample(s) for all
  2739. channels (``False``) or to sample value(s) for each channel (``True``).
  2740. Setting this to ``True`` will therefore lead to different
  2741. transformations per image *and* channel, otherwise only per image.
  2742. If this value is a float ``p``, then for ``p`` percent of all images
  2743. `per_channel` will be treated as ``True``.
  2744. If it is a ``StochasticParameter`` it is expected to produce samples
  2745. with values between ``0.0`` and ``1.0``, where values ``>0.5`` will
  2746. lead to per-channel behaviour (i.e. same as ``True``).
  2747. 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
  2748. See :func:`~imgaug.augmenters.meta.Augmenter.__init__`.
  2749. name : None or str, optional
  2750. See :func:`~imgaug.augmenters.meta.Augmenter.__init__`.
  2751. 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
  2752. Old name for parameter `seed`.
  2753. Its usage will not yet cause a deprecation warning,
  2754. but it is still recommended to use `seed` now.
  2755. Outdated since 0.4.0.
  2756. deterministic : bool, optional
  2757. Deprecated since 0.4.0.
  2758. See method ``to_deterministic()`` for an alternative and for
  2759. details about what the "deterministic mode" actually does.
  2760. Examples
  2761. --------
  2762. >>> import imgaug.augmenters as iaa
  2763. >>> aug = ReplaceElementwise(0.05, [0, 255])
  2764. Replaces ``5`` percent of all pixels in each image by either ``0``
  2765. or ``255``.
  2766. >>> import imgaug.augmenters as iaa
  2767. >>> aug = ReplaceElementwise(0.1, [0, 255], per_channel=0.5)
  2768. For ``50%`` of all images, replace ``10%`` of all pixels with either the
  2769. value ``0`` or the value ``255`` (same as in the previous example). For
  2770. the other ``50%`` of all images, replace *channelwise* ``10%`` of all
  2771. pixels with either the value ``0`` or the value ``255``. So, it will be
  2772. very rare for each pixel to have all channels replaced by ``255`` or
  2773. ``0``.
  2774. >>> import imgaug.augmenters as iaa
  2775. >>> import imgaug.parameters as iap
  2776. >>> aug = ReplaceElementwise(0.1, iap.Normal(128, 0.4*128), per_channel=0.5)
  2777. Replace ``10%`` of all pixels by gaussian noise centered around ``128``.
  2778. Both the replacement mask and the gaussian noise are sampled channelwise
  2779. for ``50%`` of all images.
  2780. >>> import imgaug.augmenters as iaa
  2781. >>> import imgaug.parameters as iap
  2782. >>> aug = ReplaceElementwise(
  2783. >>> iap.FromLowerResolution(iap.Binomial(0.1), size_px=8),
  2784. >>> iap.Normal(128, 0.4*128),
  2785. >>> per_channel=0.5)
  2786. Replace ``10%`` of all pixels by gaussian noise centered around ``128``.
  2787. Sample the replacement mask at a lower resolution (``8x8`` pixels) and
  2788. upscale it to the image size, resulting in coarse areas being replaced by
  2789. gaussian noise.
  2790. """
  2791. def __init__(self, mask, replacement, per_channel=False,
  2792. seed=None, name=None,
  2793. random_state="deprecated", deterministic="deprecated"):
  2794. super(ReplaceElementwise, self).__init__(
  2795. seed=seed, name=name,
  2796. random_state=random_state, deterministic=deterministic)
  2797. self.mask = iap.handle_probability_param(
  2798. mask, "mask", tuple_to_uniform=True, list_to_choice=True)
  2799. self.replacement = iap.handle_continuous_param(replacement,
  2800. "replacement")
  2801. self.per_channel = iap.handle_probability_param(per_channel,
  2802. "per_channel")
  2803. # Added in 0.4.0.
  2804. def _augment_batch_(self, batch, random_state, parents, hooks):
  2805. if batch.images is None:
  2806. return batch
  2807. images = batch.images
  2808. nb_images = len(images)
  2809. rss = random_state.duplicate(1+2*nb_images)
  2810. per_channel_samples = self.per_channel.draw_samples(
  2811. (nb_images,), random_state=rss[0])
  2812. gen = enumerate(zip(images, per_channel_samples, rss[1::2], rss[2::2]))
  2813. for i, (image, per_channel_i, rs_mask, rs_replacement) in gen:
  2814. height, width, nb_channels = image.shape
  2815. sampling_shape = (height,
  2816. width,
  2817. nb_channels if per_channel_i > 0.5 else 1)
  2818. mask_samples = self.mask.draw_samples(sampling_shape,
  2819. random_state=rs_mask)
  2820. # TODO add separate per_channels for mask and replacement
  2821. # TODO add test that replacement with per_channel=False is not
  2822. # sampled per channel
  2823. if per_channel_i <= 0.5:
  2824. nb_channels = image.shape[-1]
  2825. replacement_samples = self.replacement.draw_samples(
  2826. (int(np.sum(mask_samples[:, :, 0])),),
  2827. random_state=rs_replacement)
  2828. # important here to use repeat instead of tile. repeat
  2829. # converts e.g. [0, 1, 2] to [0, 0, 1, 1, 2, 2], while tile
  2830. # leads to [0, 1, 2, 0, 1, 2]. The assignment below iterates
  2831. # over each channel and pixel simultaneously, *not* first
  2832. # over all pixels of channel 0, then all pixels in
  2833. # channel 1, ...
  2834. replacement_samples = np.repeat(replacement_samples,
  2835. nb_channels)
  2836. else:
  2837. replacement_samples = self.replacement.draw_samples(
  2838. (int(np.sum(mask_samples)),), random_state=rs_replacement)
  2839. batch.images[i] = replace_elementwise_(image, mask_samples,
  2840. replacement_samples)
  2841. return batch
  2842. def get_parameters(self):
  2843. """See :func:`~imgaug.augmenters.meta.Augmenter.get_parameters`."""
  2844. return [self.mask, self.replacement, self.per_channel]
  2845. class SaltAndPepper(ReplaceElementwise):
  2846. """
  2847. Replace pixels in images with salt/pepper noise (white/black-ish colors).
  2848. **Supported dtypes**:
  2849. See :class:`~imgaug.augmenters.arithmetic.ReplaceElementwise`.
  2850. Parameters
  2851. ----------
  2852. p : float or tuple of float or list of float or imgaug.parameters.StochasticParameter, optional
  2853. Probability of replacing a pixel to salt/pepper noise.
  2854. * If a float, then that value will always be used as the
  2855. probability.
  2856. * If a tuple ``(a, b)``, then a probability will be sampled
  2857. uniformly per image from the interval ``[a, b]``.
  2858. * If a list, then a random value will be sampled from that list
  2859. per image.
  2860. * If a ``StochasticParameter``, then a image-sized mask will be
  2861. sampled from that parameter per image. Any value ``>0.5`` in
  2862. that mask will be replaced with salt and pepper noise.
  2863. per_channel : bool or float or imgaug.parameters.StochasticParameter, optional
  2864. Whether to use (imagewise) the same sample(s) for all
  2865. channels (``False``) or to sample value(s) for each channel (``True``).
  2866. Setting this to ``True`` will therefore lead to different
  2867. transformations per image *and* channel, otherwise only per image.
  2868. If this value is a float ``p``, then for ``p`` percent of all images
  2869. `per_channel` will be treated as ``True``.
  2870. If it is a ``StochasticParameter`` it is expected to produce samples
  2871. with values between ``0.0`` and ``1.0``, where values ``>0.5`` will
  2872. lead to per-channel behaviour (i.e. same as ``True``).
  2873. 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
  2874. See :func:`~imgaug.augmenters.meta.Augmenter.__init__`.
  2875. name : None or str, optional
  2876. See :func:`~imgaug.augmenters.meta.Augmenter.__init__`.
  2877. 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
  2878. Old name for parameter `seed`.
  2879. Its usage will not yet cause a deprecation warning,
  2880. but it is still recommended to use `seed` now.
  2881. Outdated since 0.4.0.
  2882. deterministic : bool, optional
  2883. Deprecated since 0.4.0.
  2884. See method ``to_deterministic()`` for an alternative and for
  2885. details about what the "deterministic mode" actually does.
  2886. Examples
  2887. --------
  2888. >>> import imgaug.augmenters as iaa
  2889. >>> aug = iaa.SaltAndPepper(0.05)
  2890. Replace ``5%`` of all pixels with salt and pepper noise.
  2891. >>> import imgaug.augmenters as iaa
  2892. >>> aug = iaa.SaltAndPepper(0.05, per_channel=True)
  2893. Replace *channelwise* ``5%`` of all pixels with salt and pepper
  2894. noise.
  2895. """
  2896. def __init__(self, p=(0.0, 0.03), per_channel=False,
  2897. seed=None, name=None,
  2898. random_state="deprecated", deterministic="deprecated"):
  2899. super(SaltAndPepper, self).__init__(
  2900. mask=p,
  2901. replacement=iap.Beta(0.5, 0.5) * 255,
  2902. per_channel=per_channel,
  2903. seed=seed, name=name,
  2904. random_state=random_state, deterministic=deterministic)
  2905. class ImpulseNoise(SaltAndPepper):
  2906. """
  2907. Add impulse noise to images.
  2908. This is identical to ``SaltAndPepper``, except that `per_channel` is
  2909. always set to ``True``.
  2910. **Supported dtypes**:
  2911. See :class:`~imgaug.augmenters.arithmetic.SaltAndPepper`.
  2912. Parameters
  2913. ----------
  2914. p : float or tuple of float or list of float or imgaug.parameters.StochasticParameter, optional
  2915. Probability of replacing a pixel to impulse noise.
  2916. * If a float, then that value will always be used as the
  2917. probability.
  2918. * If a tuple ``(a, b)``, then a probability will be sampled
  2919. uniformly per image from the interval ``[a, b]``.
  2920. * If a list, then a random value will be sampled from that list
  2921. per image.
  2922. * If a ``StochasticParameter``, then a image-sized mask will be
  2923. sampled from that parameter per image. Any value ``>0.5`` in
  2924. that mask will be replaced with impulse noise noise.
  2925. 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
  2926. See :func:`~imgaug.augmenters.meta.Augmenter.__init__`.
  2927. name : None or str, optional
  2928. See :func:`~imgaug.augmenters.meta.Augmenter.__init__`.
  2929. 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
  2930. Old name for parameter `seed`.
  2931. Its usage will not yet cause a deprecation warning,
  2932. but it is still recommended to use `seed` now.
  2933. Outdated since 0.4.0.
  2934. deterministic : bool, optional
  2935. Deprecated since 0.4.0.
  2936. See method ``to_deterministic()`` for an alternative and for
  2937. details about what the "deterministic mode" actually does.
  2938. Examples
  2939. --------
  2940. >>> import imgaug.augmenters as iaa
  2941. >>> aug = iaa.ImpulseNoise(0.1)
  2942. Replace ``10%`` of all pixels with impulse noise.
  2943. """
  2944. def __init__(self, p=(0.0, 0.03),
  2945. seed=None, name=None,
  2946. random_state="deprecated", deterministic="deprecated"):
  2947. super(ImpulseNoise, self).__init__(
  2948. p=p,
  2949. per_channel=True,
  2950. seed=seed, name=name,
  2951. random_state=random_state, deterministic=deterministic)
  2952. class CoarseSaltAndPepper(ReplaceElementwise):
  2953. """
  2954. Replace rectangular areas in images with white/black-ish pixel noise.
  2955. This adds salt and pepper noise (noisy white-ish and black-ish pixels) to
  2956. rectangular areas within the image. Note that this means that within these
  2957. rectangular areas the color varies instead of each rectangle having only
  2958. one color.
  2959. See also the similar ``CoarseDropout``.
  2960. TODO replace dtype support with uint8 only, because replacement is
  2961. geared towards that value range
  2962. **Supported dtypes**:
  2963. See :class:`~imgaug.augmenters.arithmetic.ReplaceElementwise`.
  2964. Parameters
  2965. ----------
  2966. p : float or tuple of float or list of float or imgaug.parameters.StochasticParameter, optional
  2967. Probability of changing a pixel to salt/pepper noise.
  2968. * If a float, then that value will always be used as the
  2969. probability.
  2970. * If a tuple ``(a, b)``, then a probability will be sampled
  2971. uniformly per image from the interval ``[a, b]``.
  2972. * If a list, then a random value will be sampled from that list
  2973. per image.
  2974. * If a ``StochasticParameter``, then a lower-resolution mask will
  2975. be sampled from that parameter per image. Any value ``>0.5`` in
  2976. that mask will denote a spatial location that is to be replaced
  2977. by salt and pepper noise.
  2978. size_px : int or tuple of int or imgaug.parameters.StochasticParameter, optional
  2979. The size of the lower resolution image from which to sample the
  2980. replacement mask in absolute pixel dimensions.
  2981. Note that this means that *lower* values of this parameter lead to
  2982. *larger* areas being replaced (as any pixel in the lower resolution
  2983. image will correspond to a larger area at the original resolution).
  2984. * If ``None`` then `size_percent` must be set.
  2985. * If an integer, then that size will always be used for both height
  2986. and width. E.g. a value of ``3`` would lead to a ``3x3`` mask,
  2987. which is then upsampled to ``HxW``, where ``H`` is the image size
  2988. and ``W`` the image width.
  2989. * If a tuple ``(a, b)``, then two values ``M``, ``N`` will be
  2990. sampled from the discrete interval ``[a..b]``. The mask
  2991. will then be generated at size ``MxN`` and upsampled to ``HxW``.
  2992. * If a ``StochasticParameter``, then this parameter will be used to
  2993. determine the sizes. It is expected to be discrete.
  2994. size_percent : float or tuple of float or imgaug.parameters.StochasticParameter, optional
  2995. The size of the lower resolution image from which to sample the
  2996. replacement mask *in percent* of the input image.
  2997. Note that this means that *lower* values of this parameter lead to
  2998. *larger* areas being replaced (as any pixel in the lower resolution
  2999. image will correspond to a larger area at the original resolution).
  3000. * If ``None`` then `size_px` must be set.
  3001. * If a float, then that value will always be used as the percentage
  3002. of the height and width (relative to the original size). E.g. for
  3003. value ``p``, the mask will be sampled from ``(p*H)x(p*W)`` and
  3004. later upsampled to ``HxW``.
  3005. * If a tuple ``(a, b)``, then two values ``m``, ``n`` will be
  3006. sampled from the interval ``(a, b)`` and used as the size
  3007. fractions, i.e the mask size will be ``(m*H)x(n*W)``.
  3008. * If a ``StochasticParameter``, then this parameter will be used to
  3009. sample the percentage values. It is expected to be continuous.
  3010. per_channel : bool or float or imgaug.parameters.StochasticParameter, optional
  3011. Whether to use (imagewise) the same sample(s) for all
  3012. channels (``False``) or to sample value(s) for each channel (``True``).
  3013. Setting this to ``True`` will therefore lead to different
  3014. transformations per image *and* channel, otherwise only per image.
  3015. If this value is a float ``p``, then for ``p`` percent of all images
  3016. `per_channel` will be treated as ``True``.
  3017. If it is a ``StochasticParameter`` it is expected to produce samples
  3018. with values between ``0.0`` and ``1.0``, where values ``>0.5`` will
  3019. lead to per-channel behaviour (i.e. same as ``True``).
  3020. min_size : int, optional
  3021. Minimum height and width of the low resolution mask. If
  3022. `size_percent` or `size_px` leads to a lower value than this,
  3023. `min_size` will be used instead. This should never have a value of
  3024. less than ``2``, otherwise one may end up with a ``1x1`` low resolution
  3025. mask, leading easily to the whole image being replaced.
  3026. 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
  3027. See :func:`~imgaug.augmenters.meta.Augmenter.__init__`.
  3028. name : None or str, optional
  3029. See :func:`~imgaug.augmenters.meta.Augmenter.__init__`.
  3030. 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
  3031. Old name for parameter `seed`.
  3032. Its usage will not yet cause a deprecation warning,
  3033. but it is still recommended to use `seed` now.
  3034. Outdated since 0.4.0.
  3035. deterministic : bool, optional
  3036. Deprecated since 0.4.0.
  3037. See method ``to_deterministic()`` for an alternative and for
  3038. details about what the "deterministic mode" actually does.
  3039. Examples
  3040. --------
  3041. >>> import imgaug.augmenters as iaa
  3042. >>> aug = iaa.CoarseSaltAndPepper(0.05, size_percent=(0.01, 0.1))
  3043. Marks ``5%`` of all pixels in a mask to be replaced by salt/pepper
  3044. noise. The mask has ``1%`` to ``10%`` the size of the input image.
  3045. The mask is then upscaled to the input image size, leading to large
  3046. rectangular areas being marked as to be replaced. These areas are then
  3047. replaced in the input image by salt/pepper noise.
  3048. >>> aug = iaa.CoarseSaltAndPepper(0.05, size_px=(4, 16))
  3049. Same as in the previous example, but the replacement mask before upscaling
  3050. has a size between ``4x4`` and ``16x16`` pixels (the axis sizes are sampled
  3051. independently, i.e. the mask may be rectangular).
  3052. >>> aug = iaa.CoarseSaltAndPepper(
  3053. >>> 0.05, size_percent=(0.01, 0.1), per_channel=True)
  3054. Same as in the first example, but mask and replacement are each sampled
  3055. independently per image channel.
  3056. """
  3057. def __init__(self, p=(0.02, 0.1), size_px=None, size_percent=None,
  3058. per_channel=False, min_size=3,
  3059. seed=None, name=None,
  3060. random_state="deprecated", deterministic="deprecated"):
  3061. mask = iap.handle_probability_param(
  3062. p, "p", tuple_to_uniform=True, list_to_choice=True)
  3063. if size_px is not None:
  3064. mask_low = iap.FromLowerResolution(
  3065. other_param=mask, size_px=size_px, min_size=min_size)
  3066. elif size_percent is not None:
  3067. mask_low = iap.FromLowerResolution(
  3068. other_param=mask, size_percent=size_percent, min_size=min_size)
  3069. else:
  3070. mask_low = iap.FromLowerResolution(
  3071. other_param=mask, size_px=(3, 8), min_size=min_size)
  3072. replacement = iap.Beta(0.5, 0.5) * 255
  3073. super(CoarseSaltAndPepper, self).__init__(
  3074. mask=mask_low,
  3075. replacement=replacement,
  3076. per_channel=per_channel,
  3077. seed=seed, name=name,
  3078. random_state=random_state, deterministic=deterministic)
  3079. class Salt(ReplaceElementwise):
  3080. """
  3081. Replace pixels in images with salt noise, i.e. white-ish pixels.
  3082. This augmenter is similar to ``SaltAndPepper``, but adds no pepper noise to
  3083. images.
  3084. **Supported dtypes**:
  3085. See :class:`~imgaug.augmenters.arithmetic.ReplaceElementwise`.
  3086. Parameters
  3087. ----------
  3088. p : float or tuple of float or list of float or imgaug.parameters.StochasticParameter, optional
  3089. Probability of replacing a pixel with salt noise.
  3090. * If a float, then that value will always be used as the
  3091. probability.
  3092. * If a tuple ``(a, b)``, then a probability will be sampled
  3093. uniformly per image from the interval ``[a, b]``.
  3094. * If a list, then a random value will be sampled from that list
  3095. per image.
  3096. * If a ``StochasticParameter``, then a image-sized mask will be
  3097. sampled from that parameter per image. Any value ``>0.5`` in
  3098. that mask will be replaced with salt noise.
  3099. per_channel : bool or float or imgaug.parameters.StochasticParameter, optional
  3100. Whether to use (imagewise) the same sample(s) for all
  3101. channels (``False``) or to sample value(s) for each channel (``True``).
  3102. Setting this to ``True`` will therefore lead to different
  3103. transformations per image *and* channel, otherwise only per image.
  3104. If this value is a float ``p``, then for ``p`` percent of all images
  3105. `per_channel` will be treated as ``True``.
  3106. If it is a ``StochasticParameter`` it is expected to produce samples
  3107. with values between ``0.0`` and ``1.0``, where values ``>0.5`` will
  3108. lead to per-channel behaviour (i.e. same as ``True``).
  3109. 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
  3110. See :func:`~imgaug.augmenters.meta.Augmenter.__init__`.
  3111. name : None or str, optional
  3112. See :func:`~imgaug.augmenters.meta.Augmenter.__init__`.
  3113. 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
  3114. Old name for parameter `seed`.
  3115. Its usage will not yet cause a deprecation warning,
  3116. but it is still recommended to use `seed` now.
  3117. Outdated since 0.4.0.
  3118. deterministic : bool, optional
  3119. Deprecated since 0.4.0.
  3120. See method ``to_deterministic()`` for an alternative and for
  3121. details about what the "deterministic mode" actually does.
  3122. Examples
  3123. --------
  3124. >>> import imgaug.augmenters as iaa
  3125. >>> aug = iaa.Salt(0.05)
  3126. Replace ``5%`` of all pixels with salt noise (white-ish colors).
  3127. """
  3128. def __init__(self, p=(0.0, 0.03), per_channel=False,
  3129. seed=None, name=None,
  3130. random_state="deprecated", deterministic="deprecated"):
  3131. replacement01 = iap.ForceSign(
  3132. iap.Beta(0.5, 0.5) - 0.5,
  3133. positive=True,
  3134. mode="invert"
  3135. ) + 0.5
  3136. # FIXME max replacement seems to essentially never exceed 254
  3137. replacement = replacement01 * 255
  3138. super(Salt, self).__init__(
  3139. mask=p,
  3140. replacement=replacement,
  3141. per_channel=per_channel,
  3142. seed=seed, name=name,
  3143. random_state=random_state, deterministic=deterministic)
  3144. class CoarseSalt(ReplaceElementwise):
  3145. """
  3146. Replace rectangular areas in images with white-ish pixel noise.
  3147. See also the similar ``CoarseSaltAndPepper``.
  3148. **Supported dtypes**:
  3149. See :class:`~imgaug.augmenters.arithmetic.ReplaceElementwise`.
  3150. Parameters
  3151. ----------
  3152. p : float or tuple of float or list of float or imgaug.parameters.StochasticParameter, optional
  3153. Probability of changing a pixel to salt noise.
  3154. * If a float, then that value will always be used as the
  3155. probability.
  3156. * If a tuple ``(a, b)``, then a probability will be sampled
  3157. uniformly per image from the interval ``[a, b]``.
  3158. * If a list, then a random value will be sampled from that list
  3159. per image.
  3160. * If a ``StochasticParameter``, then a lower-resolution mask will
  3161. be sampled from that parameter per image. Any value ``>0.5`` in
  3162. that mask will denote a spatial location that is to be replaced
  3163. by salt noise.
  3164. size_px : int or tuple of int or imgaug.parameters.StochasticParameter, optional
  3165. The size of the lower resolution image from which to sample the
  3166. replacement mask in absolute pixel dimensions.
  3167. Note that this means that *lower* values of this parameter lead to
  3168. *larger* areas being replaced (as any pixel in the lower resolution
  3169. image will correspond to a larger area at the original resolution).
  3170. * If ``None`` then `size_percent` must be set.
  3171. * If an integer, then that size will always be used for both height
  3172. and width. E.g. a value of ``3`` would lead to a ``3x3`` mask,
  3173. which is then upsampled to ``HxW``, where ``H`` is the image size
  3174. and ``W`` the image width.
  3175. * If a tuple ``(a, b)``, then two values ``M``, ``N`` will be
  3176. sampled from the discrete interval ``[a..b]``. The mask
  3177. will then be generated at size ``MxN`` and upsampled to ``HxW``.
  3178. * If a ``StochasticParameter``, then this parameter will be used to
  3179. determine the sizes. It is expected to be discrete.
  3180. size_percent : float or tuple of float or imgaug.parameters.StochasticParameter, optional
  3181. The size of the lower resolution image from which to sample the
  3182. replacement mask *in percent* of the input image.
  3183. Note that this means that *lower* values of this parameter lead to
  3184. *larger* areas being replaced (as any pixel in the lower resolution
  3185. image will correspond to a larger area at the original resolution).
  3186. * If ``None`` then `size_px` must be set.
  3187. * If a float, then that value will always be used as the percentage
  3188. of the height and width (relative to the original size). E.g. for
  3189. value ``p``, the mask will be sampled from ``(p*H)x(p*W)`` and
  3190. later upsampled to ``HxW``.
  3191. * If a tuple ``(a, b)``, then two values ``m``, ``n`` will be
  3192. sampled from the interval ``(a, b)`` and used as the size
  3193. fractions, i.e the mask size will be ``(m*H)x(n*W)``.
  3194. * If a ``StochasticParameter``, then this parameter will be used to
  3195. sample the percentage values. It is expected to be continuous.
  3196. per_channel : bool or float or imgaug.parameters.StochasticParameter, optional
  3197. Whether to use (imagewise) the same sample(s) for all
  3198. channels (``False``) or to sample value(s) for each channel (``True``).
  3199. Setting this to ``True`` will therefore lead to different
  3200. transformations per image *and* channel, otherwise only per image.
  3201. If this value is a float ``p``, then for ``p`` percent of all images
  3202. `per_channel` will be treated as ``True``.
  3203. If it is a ``StochasticParameter`` it is expected to produce samples
  3204. with values between ``0.0`` and ``1.0``, where values ``>0.5`` will
  3205. lead to per-channel behaviour (i.e. same as ``True``).
  3206. min_size : int, optional
  3207. Minimum height and width of the low resolution mask. If
  3208. `size_percent` or `size_px` leads to a lower value than this,
  3209. `min_size` will be used instead. This should never have a value of
  3210. less than ``2``, otherwise one may end up with a ``1x1`` low resolution
  3211. mask, leading easily to the whole image being replaced.
  3212. 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
  3213. See :func:`~imgaug.augmenters.meta.Augmenter.__init__`.
  3214. name : None or str, optional
  3215. See :func:`~imgaug.augmenters.meta.Augmenter.__init__`.
  3216. 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
  3217. Old name for parameter `seed`.
  3218. Its usage will not yet cause a deprecation warning,
  3219. but it is still recommended to use `seed` now.
  3220. Outdated since 0.4.0.
  3221. deterministic : bool, optional
  3222. Deprecated since 0.4.0.
  3223. See method ``to_deterministic()`` for an alternative and for
  3224. details about what the "deterministic mode" actually does.
  3225. Examples
  3226. --------
  3227. >>> import imgaug.augmenters as iaa
  3228. >>> aug = iaa.CoarseSalt(0.05, size_percent=(0.01, 0.1))
  3229. Mark ``5%`` of all pixels in a mask to be replaced by salt
  3230. noise. The mask has ``1%`` to ``10%`` the size of the input image.
  3231. The mask is then upscaled to the input image size, leading to large
  3232. rectangular areas being marked as to be replaced. These areas are then
  3233. replaced in the input image by salt noise.
  3234. """
  3235. def __init__(self, p=(0.02, 0.1), size_px=None, size_percent=None,
  3236. per_channel=False, min_size=3,
  3237. seed=None, name=None,
  3238. random_state="deprecated", deterministic="deprecated"):
  3239. mask = iap.handle_probability_param(
  3240. p, "p", tuple_to_uniform=True, list_to_choice=True)
  3241. if size_px is not None:
  3242. mask_low = iap.FromLowerResolution(
  3243. other_param=mask, size_px=size_px, min_size=min_size)
  3244. elif size_percent is not None:
  3245. mask_low = iap.FromLowerResolution(
  3246. other_param=mask, size_percent=size_percent, min_size=min_size)
  3247. else:
  3248. mask_low = iap.FromLowerResolution(
  3249. other_param=mask, size_px=(3, 8), min_size=min_size)
  3250. replacement01 = iap.ForceSign(
  3251. iap.Beta(0.5, 0.5) - 0.5,
  3252. positive=True,
  3253. mode="invert"
  3254. ) + 0.5
  3255. replacement = replacement01 * 255
  3256. super(CoarseSalt, self).__init__(
  3257. mask=mask_low,
  3258. replacement=replacement,
  3259. per_channel=per_channel,
  3260. seed=seed, name=name,
  3261. random_state=random_state, deterministic=deterministic)
  3262. class Pepper(ReplaceElementwise):
  3263. """
  3264. Replace pixels in images with pepper noise, i.e. black-ish pixels.
  3265. This augmenter is similar to ``SaltAndPepper``, but adds no salt noise to
  3266. images.
  3267. This augmenter is similar to ``Dropout``, but slower and the black pixels
  3268. are not uniformly black.
  3269. **Supported dtypes**:
  3270. See :class:`~imgaug.augmenters.arithmetic.ReplaceElementwise`.
  3271. Parameters
  3272. ----------
  3273. p : float or tuple of float or list of float or imgaug.parameters.StochasticParameter, optional
  3274. Probability of replacing a pixel with pepper noise.
  3275. * If a float, then that value will always be used as the
  3276. probability.
  3277. * If a tuple ``(a, b)``, then a probability will be sampled
  3278. uniformly per image from the interval ``[a, b]``.
  3279. * If a list, then a random value will be sampled from that list
  3280. per image.
  3281. * If a ``StochasticParameter``, then a image-sized mask will be
  3282. sampled from that parameter per image. Any value ``>0.5`` in
  3283. that mask will be replaced with pepper noise.
  3284. per_channel : bool or float or imgaug.parameters.StochasticParameter, optional
  3285. Whether to use (imagewise) the same sample(s) for all
  3286. channels (``False``) or to sample value(s) for each channel (``True``).
  3287. Setting this to ``True`` will therefore lead to different
  3288. transformations per image *and* channel, otherwise only per image.
  3289. If this value is a float ``p``, then for ``p`` percent of all images
  3290. `per_channel` will be treated as ``True``.
  3291. If it is a ``StochasticParameter`` it is expected to produce samples
  3292. with values between ``0.0`` and ``1.0``, where values ``>0.5`` will
  3293. lead to per-channel behaviour (i.e. same as ``True``).
  3294. 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
  3295. See :func:`~imgaug.augmenters.meta.Augmenter.__init__`.
  3296. name : None or str, optional
  3297. See :func:`~imgaug.augmenters.meta.Augmenter.__init__`.
  3298. 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
  3299. Old name for parameter `seed`.
  3300. Its usage will not yet cause a deprecation warning,
  3301. but it is still recommended to use `seed` now.
  3302. Outdated since 0.4.0.
  3303. deterministic : bool, optional
  3304. Deprecated since 0.4.0.
  3305. See method ``to_deterministic()`` for an alternative and for
  3306. details about what the "deterministic mode" actually does.
  3307. Examples
  3308. --------
  3309. >>> import imgaug.augmenters as iaa
  3310. >>> aug = iaa.Pepper(0.05)
  3311. Replace ``5%`` of all pixels with pepper noise (black-ish colors).
  3312. """
  3313. def __init__(self, p=(0.0, 0.05), per_channel=False,
  3314. seed=None, name=None,
  3315. random_state="deprecated", deterministic="deprecated"):
  3316. replacement01 = iap.ForceSign(
  3317. iap.Beta(0.5, 0.5) - 0.5,
  3318. positive=False,
  3319. mode="invert"
  3320. ) + 0.5
  3321. replacement = replacement01 * 255
  3322. super(Pepper, self).__init__(
  3323. mask=p,
  3324. replacement=replacement,
  3325. per_channel=per_channel,
  3326. seed=seed, name=name,
  3327. random_state=random_state, deterministic=deterministic)
  3328. class CoarsePepper(ReplaceElementwise):
  3329. """
  3330. Replace rectangular areas in images with black-ish pixel noise.
  3331. **Supported dtypes**:
  3332. See :class:`~imgaug.augmenters.arithmetic.ReplaceElementwise`.
  3333. Parameters
  3334. ----------
  3335. p : float or tuple of float or list of float or imgaug.parameters.StochasticParameter, optional
  3336. Probability of changing a pixel to pepper noise.
  3337. * If a float, then that value will always be used as the
  3338. probability.
  3339. * If a tuple ``(a, b)``, then a probability will be sampled
  3340. uniformly per image from the interval ``[a, b]``.
  3341. * If a list, then a random value will be sampled from that list
  3342. per image.
  3343. * If a ``StochasticParameter``, then a lower-resolution mask will
  3344. be sampled from that parameter per image. Any value ``>0.5`` in
  3345. that mask will denote a spatial location that is to be replaced
  3346. by pepper noise.
  3347. size_px : int or tuple of int or imgaug.parameters.StochasticParameter, optional
  3348. The size of the lower resolution image from which to sample the
  3349. replacement mask in absolute pixel dimensions.
  3350. Note that this means that *lower* values of this parameter lead to
  3351. *larger* areas being replaced (as any pixel in the lower resolution
  3352. image will correspond to a larger area at the original resolution).
  3353. * If ``None`` then `size_percent` must be set.
  3354. * If an integer, then that size will always be used for both height
  3355. and width. E.g. a value of ``3`` would lead to a ``3x3`` mask,
  3356. which is then upsampled to ``HxW``, where ``H`` is the image size
  3357. and ``W`` the image width.
  3358. * If a tuple ``(a, b)``, then two values ``M``, ``N`` will be
  3359. sampled from the discrete interval ``[a..b]``. The mask
  3360. will then be generated at size ``MxN`` and upsampled to ``HxW``.
  3361. * If a ``StochasticParameter``, then this parameter will be used to
  3362. determine the sizes. It is expected to be discrete.
  3363. size_percent : float or tuple of float or imgaug.parameters.StochasticParameter, optional
  3364. The size of the lower resolution image from which to sample the
  3365. replacement mask *in percent* of the input image.
  3366. Note that this means that *lower* values of this parameter lead to
  3367. *larger* areas being replaced (as any pixel in the lower resolution
  3368. image will correspond to a larger area at the original resolution).
  3369. * If ``None`` then `size_px` must be set.
  3370. * If a float, then that value will always be used as the percentage
  3371. of the height and width (relative to the original size). E.g. for
  3372. value ``p``, the mask will be sampled from ``(p*H)x(p*W)`` and
  3373. later upsampled to ``HxW``.
  3374. * If a tuple ``(a, b)``, then two values ``m``, ``n`` will be
  3375. sampled from the interval ``(a, b)`` and used as the size
  3376. fractions, i.e the mask size will be ``(m*H)x(n*W)``.
  3377. * If a ``StochasticParameter``, then this parameter will be used to
  3378. sample the percentage values. It is expected to be continuous.
  3379. per_channel : bool or float or imgaug.parameters.StochasticParameter, optional
  3380. Whether to use (imagewise) the same sample(s) for all
  3381. channels (``False``) or to sample value(s) for each channel (``True``).
  3382. Setting this to ``True`` will therefore lead to different
  3383. transformations per image *and* channel, otherwise only per image.
  3384. If this value is a float ``p``, then for ``p`` percent of all images
  3385. `per_channel` will be treated as ``True``.
  3386. If it is a ``StochasticParameter`` it is expected to produce samples
  3387. with values between ``0.0`` and ``1.0``, where values ``>0.5`` will
  3388. lead to per-channel behaviour (i.e. same as ``True``).
  3389. min_size : int, optional
  3390. Minimum size of the low resolution mask, both width and height. If
  3391. `size_percent` or `size_px` leads to a lower value than this, `min_size`
  3392. will be used instead. This should never have a value of less than 2,
  3393. otherwise one may end up with a ``1x1`` low resolution mask, leading
  3394. easily to the whole image being replaced.
  3395. 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
  3396. See :func:`~imgaug.augmenters.meta.Augmenter.__init__`.
  3397. name : None or str, optional
  3398. See :func:`~imgaug.augmenters.meta.Augmenter.__init__`.
  3399. 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
  3400. Old name for parameter `seed`.
  3401. Its usage will not yet cause a deprecation warning,
  3402. but it is still recommended to use `seed` now.
  3403. Outdated since 0.4.0.
  3404. deterministic : bool, optional
  3405. Deprecated since 0.4.0.
  3406. See method ``to_deterministic()`` for an alternative and for
  3407. details about what the "deterministic mode" actually does.
  3408. Examples
  3409. --------
  3410. >>> import imgaug.augmenters as iaa
  3411. >>> aug = iaa.CoarsePepper(0.05, size_percent=(0.01, 0.1))
  3412. Mark ``5%`` of all pixels in a mask to be replaced by pepper
  3413. noise. The mask has ``1%`` to ``10%`` the size of the input image.
  3414. The mask is then upscaled to the input image size, leading to large
  3415. rectangular areas being marked as to be replaced. These areas are then
  3416. replaced in the input image by pepper noise.
  3417. """
  3418. def __init__(self, p=(0.02, 0.1), size_px=None, size_percent=None,
  3419. per_channel=False, min_size=3,
  3420. seed=None, name=None,
  3421. random_state="deprecated", deterministic="deprecated"):
  3422. mask = iap.handle_probability_param(
  3423. p, "p", tuple_to_uniform=True, list_to_choice=True)
  3424. if size_px is not None:
  3425. mask_low = iap.FromLowerResolution(
  3426. other_param=mask, size_px=size_px, min_size=min_size)
  3427. elif size_percent is not None:
  3428. mask_low = iap.FromLowerResolution(
  3429. other_param=mask, size_percent=size_percent, min_size=min_size)
  3430. else:
  3431. mask_low = iap.FromLowerResolution(
  3432. other_param=mask, size_px=(3, 8), min_size=min_size)
  3433. replacement01 = iap.ForceSign(
  3434. iap.Beta(0.5, 0.5) - 0.5,
  3435. positive=False,
  3436. mode="invert"
  3437. ) + 0.5
  3438. replacement = replacement01 * 255
  3439. super(CoarsePepper, self).__init__(
  3440. mask=mask_low,
  3441. replacement=replacement,
  3442. per_channel=per_channel,
  3443. seed=seed, name=name,
  3444. random_state=random_state, deterministic=deterministic)
  3445. class Invert(meta.Augmenter):
  3446. """
  3447. Invert all values in images, e.g. turn ``5`` into ``255-5=250``.
  3448. For the standard value range of 0-255 it converts ``0`` to ``255``,
  3449. ``255`` to ``0`` and ``10`` to ``(255-10)=245``.
  3450. Let ``M`` be the maximum value possible, ``m`` the minimum value possible,
  3451. ``v`` a value. Then the distance of ``v`` to ``m`` is ``d=abs(v-m)`` and
  3452. the new value is given by ``v'=M-d``.
  3453. **Supported dtypes**:
  3454. See :func:`~imgaug.augmenters.arithmetic.invert_`.
  3455. Parameters
  3456. ----------
  3457. p : float or imgaug.parameters.StochasticParameter, optional
  3458. The probability of an image to be inverted.
  3459. * If a float, then that probability will be used for all images,
  3460. i.e. `p` percent of all images will be inverted.
  3461. * If a ``StochasticParameter``, then that parameter will be queried
  3462. per image and is expected to return values in the interval
  3463. ``[0.0, 1.0]``, where values ``>0.5`` mean that the image
  3464. is supposed to be inverted. Recommended to be some form of
  3465. ``imgaug.parameters.Binomial``.
  3466. per_channel : bool or float or imgaug.parameters.StochasticParameter, optional
  3467. Whether to use (imagewise) the same sample(s) for all
  3468. channels (``False``) or to sample value(s) for each channel (``True``).
  3469. Setting this to ``True`` will therefore lead to different
  3470. transformations per image *and* channel, otherwise only per image.
  3471. If this value is a float ``p``, then for ``p`` percent of all images
  3472. `per_channel` will be treated as ``True``.
  3473. If it is a ``StochasticParameter`` it is expected to produce samples
  3474. with values between ``0.0`` and ``1.0``, where values ``>0.5`` will
  3475. lead to per-channel behaviour (i.e. same as ``True``).
  3476. min_value : None or number, optional
  3477. Minimum of the value range of input images, e.g. ``0`` for ``uint8``
  3478. images. If set to ``None``, the value will be automatically derived
  3479. from the image's dtype.
  3480. max_value : None or number, optional
  3481. Maximum of the value range of input images, e.g. ``255`` for ``uint8``
  3482. images. If set to ``None``, the value will be automatically derived
  3483. from the image's dtype.
  3484. threshold : None or number or tuple of number or list of number or imgaug.parameters.StochasticParameter, optional
  3485. A threshold to use in order to invert only numbers above or below
  3486. the threshold. If ``None`` no thresholding will be used.
  3487. * If ``None``: No thresholding will be used.
  3488. * If ``number``: The value will be used for all images.
  3489. * If ``tuple`` ``(a, b)``: A value will be uniformly sampled per
  3490. image from the interval ``[a, b)``.
  3491. * If ``list``: A random value will be picked from the list per
  3492. image.
  3493. * If ``StochasticParameter``: Per batch of size ``N``, the
  3494. parameter will be queried once to return ``(N,)`` samples.
  3495. invert_above_threshold : bool or float or imgaug.parameters.StochasticParameter, optional
  3496. If ``True``, only values ``>=threshold`` will be inverted.
  3497. Otherwise, only values ``<threshold`` will be inverted.
  3498. If a ``number``, then expected to be in the interval ``[0.0, 1.0]`` and
  3499. denoting an imagewise probability. If a ``StochasticParameter`` then
  3500. ``(N,)`` values will be sampled from the parameter per batch of size
  3501. ``N`` and interpreted as ``True`` if ``>0.5``.
  3502. If `threshold` is ``None`` this parameter has no effect.
  3503. 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
  3504. See :func:`~imgaug.augmenters.meta.Augmenter.__init__`.
  3505. name : None or str, optional
  3506. See :func:`~imgaug.augmenters.meta.Augmenter.__init__`.
  3507. 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
  3508. Old name for parameter `seed`.
  3509. Its usage will not yet cause a deprecation warning,
  3510. but it is still recommended to use `seed` now.
  3511. Outdated since 0.4.0.
  3512. deterministic : bool, optional
  3513. Deprecated since 0.4.0.
  3514. See method ``to_deterministic()`` for an alternative and for
  3515. details about what the "deterministic mode" actually does.
  3516. Examples
  3517. --------
  3518. >>> import imgaug.augmenters as iaa
  3519. >>> aug = iaa.Invert(0.1)
  3520. Inverts the colors in ``10`` percent of all images.
  3521. >>> aug = iaa.Invert(0.1, per_channel=True)
  3522. Inverts the colors in ``10`` percent of all image channels. This may or
  3523. may not lead to multiple channels in an image being inverted.
  3524. >>> aug = iaa.Invert(0.1, per_channel=0.5)
  3525. Identical to the previous example, but the `per_channel` feature is only
  3526. active for 50 percent of all images.
  3527. """
  3528. # when no custom min/max are chosen, all bool, uint, int and float dtypes
  3529. # should be invertable (float tested only up to 64bit)
  3530. # when chosing custom min/max:
  3531. # - bool makes no sense, not allowed
  3532. # - int and float must be increased in resolution if custom min/max values
  3533. # are chosen, hence they are limited to 32 bit and below
  3534. # - uint64 is converted by numpy's clip to float64, hence loss of accuracy
  3535. # - float16 seems to not be perfectly accurate, but still ok-ish -- was
  3536. # off by 10 for center value of range (float 16 min, 16), where float
  3537. # 16 min is around -65500
  3538. ALLOW_DTYPES_CUSTOM_MINMAX = [
  3539. np.dtype(dt) for dt in [
  3540. np.uint8, np.uint16, np.uint32,
  3541. np.int8, np.int16, np.int32,
  3542. np.float16, np.float32
  3543. ]
  3544. ]
  3545. def __init__(self, p=1, per_channel=False, min_value=None, max_value=None,
  3546. threshold=None, invert_above_threshold=0.5,
  3547. seed=None, name=None,
  3548. random_state="deprecated", deterministic="deprecated"):
  3549. super(Invert, self).__init__(
  3550. seed=seed, name=name,
  3551. random_state=random_state, deterministic=deterministic)
  3552. # TODO allow list and tuple for p
  3553. self.p = iap.handle_probability_param(p, "p")
  3554. self.per_channel = iap.handle_probability_param(per_channel,
  3555. "per_channel")
  3556. self.min_value = min_value
  3557. self.max_value = max_value
  3558. if threshold is None:
  3559. self.threshold = None
  3560. else:
  3561. self.threshold = iap.handle_continuous_param(
  3562. threshold, "threshold", value_range=None, tuple_to_uniform=True,
  3563. list_to_choice=True)
  3564. self.invert_above_threshold = iap.handle_probability_param(
  3565. invert_above_threshold, "invert_above_threshold")
  3566. # Added in 0.4.0.
  3567. def _augment_batch_(self, batch, random_state, parents, hooks):
  3568. if batch.images is None:
  3569. return batch
  3570. samples = self._draw_samples(batch, random_state)
  3571. for i, image in enumerate(batch.images):
  3572. if 0 in image.shape:
  3573. continue
  3574. kwargs = {
  3575. "min_value": samples.min_value[i],
  3576. "max_value": samples.max_value[i],
  3577. "threshold": samples.threshold[i],
  3578. "invert_above_threshold": samples.invert_above_threshold[i]
  3579. }
  3580. if samples.per_channel[i]:
  3581. nb_channels = image.shape[2]
  3582. mask = samples.p[i, :nb_channels]
  3583. image[..., mask] = invert_(image[..., mask], **kwargs)
  3584. else:
  3585. if samples.p[i, 0]:
  3586. image[:, :, :] = invert_(image, **kwargs)
  3587. return batch
  3588. # Added in 0.4.0.
  3589. def _draw_samples(self, batch, random_state):
  3590. nb_images = batch.nb_rows
  3591. nb_channels = meta.estimate_max_number_of_channels(batch.images)
  3592. p = self.p.draw_samples((nb_images, nb_channels),
  3593. random_state=random_state)
  3594. p = (p > 0.5)
  3595. per_channel = self.per_channel.draw_samples((nb_images,),
  3596. random_state=random_state)
  3597. per_channel = (per_channel > 0.5)
  3598. min_value = [self.min_value] * nb_images
  3599. max_value = [self.max_value] * nb_images
  3600. if self.threshold is None:
  3601. threshold = [None] * nb_images
  3602. else:
  3603. threshold = self.threshold.draw_samples(
  3604. (nb_images,), random_state=random_state)
  3605. invert_above_threshold = self.invert_above_threshold.draw_samples(
  3606. (nb_images,), random_state=random_state)
  3607. invert_above_threshold = (invert_above_threshold > 0.5)
  3608. return _InvertSamples(
  3609. p=p,
  3610. per_channel=per_channel,
  3611. min_value=min_value,
  3612. max_value=max_value,
  3613. threshold=threshold,
  3614. invert_above_threshold=invert_above_threshold
  3615. )
  3616. def get_parameters(self):
  3617. """See :func:`~imgaug.augmenters.meta.Augmenter.get_parameters`."""
  3618. return [self.p, self.per_channel, self.min_value, self.max_value,
  3619. self.threshold, self.invert_above_threshold]
  3620. # Added in 0.4.0.
  3621. class _InvertSamples(object):
  3622. # Added in 0.4.0.
  3623. def __init__(self, p, per_channel, min_value, max_value,
  3624. threshold, invert_above_threshold):
  3625. self.p = p
  3626. self.per_channel = per_channel
  3627. self.min_value = min_value
  3628. self.max_value = max_value
  3629. self.threshold = threshold
  3630. self.invert_above_threshold = invert_above_threshold
  3631. class Solarize(Invert):
  3632. """Invert all pixel values above a threshold.
  3633. This is the same as :class:`Invert`, but sets a default threshold around
  3634. ``128`` (+/- 64, decided per image) and default `invert_above_threshold`
  3635. to ``True`` (i.e. only values above the threshold will be inverted).
  3636. See :class:`Invert` for more details.
  3637. Added in 0.4.0.
  3638. **Supported dtypes**:
  3639. See :class:`~imgaug.augmenters.arithmetic.Invert`.
  3640. Parameters
  3641. ----------
  3642. p : float or imgaug.parameters.StochasticParameter
  3643. See :class:`Invert`.
  3644. per_channel : bool or float or imgaug.parameters.StochasticParameter, optional
  3645. See :class:`Invert`.
  3646. min_value : None or number, optional
  3647. See :class:`Invert`.
  3648. max_value : None or number, optional
  3649. See :class:`Invert`.
  3650. threshold : None or number or tuple of number or list of number or imgaug.parameters.StochasticParameter, optional
  3651. See :class:`Invert`.
  3652. invert_above_threshold : bool or float or imgaug.parameters.StochasticParameter, optional
  3653. See :class:`Invert`.
  3654. 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
  3655. See :func:`~imgaug.augmenters.meta.Augmenter.__init__`.
  3656. name : None or str, optional
  3657. See :func:`~imgaug.augmenters.meta.Augmenter.__init__`.
  3658. 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
  3659. Old name for parameter `seed`.
  3660. Its usage will not yet cause a deprecation warning,
  3661. but it is still recommended to use `seed` now.
  3662. Outdated since 0.4.0.
  3663. deterministic : bool, optional
  3664. Deprecated since 0.4.0.
  3665. See method ``to_deterministic()`` for an alternative and for
  3666. details about what the "deterministic mode" actually does.
  3667. Examples
  3668. --------
  3669. >>> import imgaug.augmenters as iaa
  3670. >>> aug = iaa.Solarize(0.5, threshold=(32, 128))
  3671. Invert the colors in ``50`` percent of all images for pixels with a
  3672. value between ``32`` and ``128`` or more. The threshold is sampled once
  3673. per image. The thresholding operation happens per channel.
  3674. """
  3675. def __init__(self, p=1, per_channel=False, min_value=None, max_value=None,
  3676. threshold=(128-64, 128+64), invert_above_threshold=True,
  3677. seed=None, name=None,
  3678. random_state="deprecated", deterministic="deprecated"):
  3679. super(Solarize, self).__init__(
  3680. p=p, per_channel=per_channel,
  3681. min_value=min_value, max_value=max_value,
  3682. threshold=threshold, invert_above_threshold=invert_above_threshold,
  3683. seed=seed, name=name,
  3684. random_state=random_state, deterministic=deterministic)
  3685. # TODO remove from examples
  3686. @ia.deprecated("imgaug.contrast.LinearContrast")
  3687. def ContrastNormalization(alpha=1.0, per_channel=False,
  3688. seed=None, name=None,
  3689. random_state="deprecated",
  3690. deterministic="deprecated"):
  3691. """
  3692. Change the contrast of images.
  3693. dtype support:
  3694. See ``imgaug.augmenters.contrast.LinearContrast``.
  3695. Deprecated since 0.3.0.
  3696. Parameters
  3697. ----------
  3698. alpha : number or tuple of number or list of number or imgaug.parameters.StochasticParameter, optional
  3699. Strength of the contrast normalization. Higher values than 1.0
  3700. lead to higher contrast, lower values decrease the contrast.
  3701. * If a number, then that value will be used for all images.
  3702. * If a tuple ``(a, b)``, then a value will be sampled per image
  3703. uniformly from the interval ``[a, b]`` and be used as the alpha
  3704. value.
  3705. * If a list, then a random value will be picked per image from
  3706. that list.
  3707. * If a ``StochasticParameter``, then this parameter will be used to
  3708. sample the alpha value per image.
  3709. per_channel : bool or float or imgaug.parameters.StochasticParameter, optional
  3710. Whether to use (imagewise) the same sample(s) for all
  3711. channels (``False``) or to sample value(s) for each channel (``True``).
  3712. Setting this to ``True`` will therefore lead to different
  3713. transformations per image *and* channel, otherwise only per image.
  3714. If this value is a float ``p``, then for ``p`` percent of all images
  3715. `per_channel` will be treated as ``True``.
  3716. If it is a ``StochasticParameter`` it is expected to produce samples
  3717. with values between ``0.0`` and ``1.0``, where values ``>0.5`` will
  3718. lead to per-channel behaviour (i.e. same as ``True``).
  3719. 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
  3720. See :func:`~imgaug.augmenters.meta.Augmenter.__init__`.
  3721. name : None or str, optional
  3722. See :func:`~imgaug.augmenters.meta.Augmenter.__init__`.
  3723. 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
  3724. Old name for parameter `seed`.
  3725. Its usage will not yet cause a deprecation warning,
  3726. but it is still recommended to use `seed` now.
  3727. Outdated since 0.4.0.
  3728. deterministic : bool, optional
  3729. Deprecated since 0.4.0.
  3730. See method ``to_deterministic()`` for an alternative and for
  3731. details about what the "deterministic mode" actually does.
  3732. Examples
  3733. --------
  3734. >>> import imgaug.augmenters as iaa
  3735. >>> iaa.ContrastNormalization((0.5, 1.5))
  3736. Decreases oder improves contrast per image by a random factor between
  3737. ``0.5`` and ``1.5``. The factor ``0.5`` means that any difference from
  3738. the center value (i.e. 128) will be halved, leading to less contrast.
  3739. >>> iaa.ContrastNormalization((0.5, 1.5), per_channel=0.5)
  3740. Same as before, but for 50 percent of all images the normalization is done
  3741. independently per channel (i.e. factors can vary per channel for the same
  3742. image). In the other 50 percent of all images, the factor is the same for
  3743. all channels.
  3744. """
  3745. # pylint: disable=invalid-name
  3746. # placed here to avoid cyclic dependency
  3747. from . import contrast as contrast_lib
  3748. return contrast_lib.LinearContrast(
  3749. alpha=alpha, per_channel=per_channel,
  3750. seed=seed, name=name, random_state=random_state, deterministic=deterministic)
  3751. # TODO try adding per channel somehow
  3752. class JpegCompression(meta.Augmenter):
  3753. """
  3754. Degrade the quality of images by JPEG-compressing them.
  3755. During JPEG compression, high frequency components (e.g. edges) are removed.
  3756. With low compression (strength) only the highest frequency components are
  3757. removed, while very high compression (strength) will lead to only the
  3758. lowest frequency components "surviving". This lowers the image quality.
  3759. For more details, see https://en.wikipedia.org/wiki/Compression_artifact.
  3760. Note that this augmenter still returns images as numpy arrays (i.e. saves
  3761. the images with JPEG compression and then reloads them into arrays). It
  3762. does not return the raw JPEG file content.
  3763. **Supported dtypes**:
  3764. See :func:`~imgaug.augmenters.arithmetic.compress_jpeg`.
  3765. Parameters
  3766. ----------
  3767. compression : number or tuple of number or list of number or imgaug.parameters.StochasticParameter, optional
  3768. Degree of compression used during JPEG compression within value range
  3769. ``[0, 100]``. Higher values denote stronger compression and will cause
  3770. low-frequency components to disappear. Note that JPEG's compression
  3771. strength is also often set as a *quality*, which is the inverse of this
  3772. parameter. Common choices for the *quality* setting are around 80 to 95,
  3773. depending on the image. This translates here to a *compression*
  3774. parameter of around 20 to 5.
  3775. * If a single number, then that value always will be used as the
  3776. compression.
  3777. * If a tuple ``(a, b)``, then the compression will be
  3778. a value sampled uniformly from the interval ``[a, b]``.
  3779. * If a list, then a random value will be sampled from that list
  3780. per image and used as the compression.
  3781. * If a ``StochasticParameter``, then ``N`` samples will be drawn
  3782. from that parameter per ``N`` input images, each representing the
  3783. compression for the ``n``-th image.
  3784. 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
  3785. See :func:`~imgaug.augmenters.meta.Augmenter.__init__`.
  3786. name : None or str, optional
  3787. See :func:`~imgaug.augmenters.meta.Augmenter.__init__`.
  3788. 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
  3789. Old name for parameter `seed`.
  3790. Its usage will not yet cause a deprecation warning,
  3791. but it is still recommended to use `seed` now.
  3792. Outdated since 0.4.0.
  3793. deterministic : bool, optional
  3794. Deprecated since 0.4.0.
  3795. See method ``to_deterministic()`` for an alternative and for
  3796. details about what the "deterministic mode" actually does.
  3797. Examples
  3798. --------
  3799. >>> import imgaug.augmenters as iaa
  3800. >>> aug = iaa.JpegCompression(compression=(70, 99))
  3801. Remove high frequency components in images via JPEG compression with
  3802. a *compression strength* between ``70`` and ``99`` (randomly and
  3803. uniformly sampled per image). This corresponds to a (very low) *quality*
  3804. setting of ``1`` to ``30``.
  3805. """
  3806. def __init__(self, compression=(0, 100),
  3807. seed=None, name=None,
  3808. random_state="deprecated", deterministic="deprecated"):
  3809. super(JpegCompression, self).__init__(
  3810. seed=seed, name=name,
  3811. random_state=random_state, deterministic=deterministic)
  3812. # will be converted to int during augmentation, which is why we allow
  3813. # floats here
  3814. self.compression = iap.handle_continuous_param(
  3815. compression, "compression",
  3816. value_range=(0, 100), tuple_to_uniform=True, list_to_choice=True)
  3817. # Added in 0.4.0.
  3818. def _augment_batch_(self, batch, random_state, parents, hooks):
  3819. if batch.images is None:
  3820. return batch
  3821. images = batch.images
  3822. nb_images = len(images)
  3823. samples = self.compression.draw_samples((nb_images,),
  3824. random_state=random_state)
  3825. for i, (image, sample) in enumerate(zip(images, samples)):
  3826. batch.images[i] = compress_jpeg(image, int(sample))
  3827. return batch
  3828. def get_parameters(self):
  3829. """See :func:`~imgaug.augmenters.meta.Augmenter.get_parameters`."""
  3830. return [self.compression]