aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--README.md15
-rw-r--r--artists.csv3041
-rw-r--r--extensions-builtin/LDSR/ldsr_model_arch.py3
-rw-r--r--extensions-builtin/Lora/extra_networks_lora.py20
-rw-r--r--extensions-builtin/Lora/lora.py199
-rw-r--r--extensions-builtin/Lora/preload.py6
-rw-r--r--extensions-builtin/Lora/scripts/lora_script.py30
-rw-r--r--extensions-builtin/Lora/ui_extra_networks_lora.py36
-rw-r--r--extensions-builtin/prompt-bracket-checker/javascript/prompt-bracket-checker.js45
-rw-r--r--extensions-builtin/roll-artist/scripts/roll-artist.py50
-rw-r--r--html/card-no-preview.pngbin0 -> 84440 bytes
-rw-r--r--html/extra-networks-card.html11
-rw-r--r--html/extra-networks-no-cards.html8
-rw-r--r--javascript/edit-attention.js127
-rw-r--r--javascript/extensions.js2
-rw-r--r--javascript/extraNetworks.js69
-rw-r--r--javascript/hints.js9
-rw-r--r--javascript/hires_fix.js3
-rw-r--r--javascript/imageviewer.js10
-rw-r--r--javascript/localization.js6
-rw-r--r--javascript/progressbar.js50
-rw-r--r--javascript/ui.js63
-rw-r--r--launch.py2
-rw-r--r--modules/api/api.py28
-rw-r--r--modules/artists.py25
-rw-r--r--modules/devices.py14
-rw-r--r--modules/errors.py14
-rw-r--r--modules/extra_networks.py147
-rw-r--r--modules/extra_networks_hypernet.py21
-rw-r--r--modules/extras.py376
-rw-r--r--modules/generation_parameters_copypaste.py12
-rw-r--r--modules/hypernetworks/hypernetwork.py116
-rw-r--r--modules/hypernetworks/ui.py5
-rw-r--r--modules/images.py5
-rw-r--r--modules/img2img.py4
-rw-r--r--modules/interrogate.py55
-rw-r--r--modules/postprocessing.py103
-rw-r--r--modules/processing.py41
-rw-r--r--modules/progress.py11
-rw-r--r--modules/realesrgan_model.py12
-rw-r--r--modules/script_callbacks.py15
-rw-r--r--modules/scripts.py28
-rw-r--r--modules/scripts_postprocessing.py147
-rw-r--r--modules/sd_disable_initialization.py4
-rw-r--r--modules/sd_hijack.py9
-rw-r--r--modules/sd_hijack_checkpoint.py38
-rw-r--r--modules/sd_hijack_optimizations.py32
-rw-r--r--modules/sd_models.py15
-rw-r--r--modules/sd_vae.py16
-rw-r--r--modules/shared.py56
-rw-r--r--modules/styles.py12
-rw-r--r--modules/textual_inversion/preprocess.py38
-rw-r--r--modules/textual_inversion/textual_inversion.py8
-rw-r--r--modules/txt2img.py4
-rw-r--r--modules/ui.py603
-rw-r--r--modules/ui_common.py202
-rw-r--r--modules/ui_components.py11
-rw-r--r--modules/ui_extra_networks.py171
-rw-r--r--modules/ui_extra_networks_hypernets.py35
-rw-r--r--modules/ui_extra_networks_textual_inversion.py33
-rw-r--r--modules/ui_postprocessing.py57
-rw-r--r--modules/upscaler.py1
-rw-r--r--requirements.txt2
-rw-r--r--requirements_versions.txt2
-rw-r--r--script.js13
-rw-r--r--scripts/postprocessing_codeformer.py36
-rw-r--r--scripts/postprocessing_gfpgan.py33
-rw-r--r--scripts/postprocessing_upscale.py106
-rw-r--r--scripts/prompts_from_file.py2
-rw-r--r--scripts/xy_grid.py79
-rw-r--r--style.css364
-rw-r--r--test/basic_features/utils_test.py10
-rw-r--r--webui.py35
-rwxr-xr-xwebui.sh31
74 files changed, 2781 insertions, 4261 deletions
diff --git a/README.md b/README.md
index d783fdf0..9c0cd1ef 100644
--- a/README.md
+++ b/README.md
@@ -49,9 +49,9 @@ A browser interface based on Gradio library for Stable Diffusion.
- Running arbitrary python code from UI (must run with --allow-code to enable)
- Mouseover hints for most UI elements
- Possible to change defaults/mix/max/step values for UI elements via text config
-- Random artist button
- Tiling support, a checkbox to create images that can be tiled like textures
- Progress bar and live image generation preview
+ - Can use a separate neural network to produce previews with almost none VRAM or compute requirement
- Negative prompt, an extra text field that allows you to list what you don't want to see in generated image
- Styles, a way to save part of prompt and easily apply them via dropdown later
- Variations, a way to generate same image but with tiny differences
@@ -76,13 +76,22 @@ A browser interface based on Gradio library for Stable Diffusion.
- hypernetworks and embeddings options
- Preprocessing images: cropping, mirroring, autotagging using BLIP or deepdanbooru (for anime)
- Clip skip
-- Use Hypernetworks
-- Use VAEs
+- Hypernetworks
+- Loras (same as Hypernetworks but more pretty)
+- A sparate UI where you can choose, with preview, which embeddings, hypernetworks or Loras to add to your prompt.
+- Can select to load a different VAE from settings screen
- Estimated completion time in progress bar
- API
- Support for dedicated [inpainting model](https://github.com/runwayml/stable-diffusion#inpainting-with-stable-diffusion) by RunwayML.
- via extension: [Aesthetic Gradients](https://github.com/AUTOMATIC1111/stable-diffusion-webui-aesthetic-gradients), a way to generate images with a specific aesthetic by using clip images embeds (implementation of [https://github.com/vicgalle/stable-diffusion-aesthetic-gradients](https://github.com/vicgalle/stable-diffusion-aesthetic-gradients))
- [Stable Diffusion 2.0](https://github.com/Stability-AI/stablediffusion) support - see [wiki](https://github.com/AUTOMATIC1111/stable-diffusion-webui/wiki/Features#stable-diffusion-20) for instructions
+- [Alt-Diffusion](https://arxiv.org/abs/2211.06679) support - see [wiki](https://github.com/AUTOMATIC1111/stable-diffusion-webui/wiki/Features#alt-diffusion) for instructions
+- Now without any bad letters!
+- Load checkpoints in safetensors format
+- Eased resolution restriction: generated image's domension must be a multiple of 8 rather than 64
+- Now with a license!
+- Reorder elements in the UI from settings screen
+-
## Installation and Running
Make sure the required [dependencies](https://github.com/AUTOMATIC1111/stable-diffusion-webui/wiki/Dependencies) are met and follow the instructions available for both [NVidia](https://github.com/AUTOMATIC1111/stable-diffusion-webui/wiki/Install-and-Run-on-NVidia-GPUs) (recommended) and [AMD](https://github.com/AUTOMATIC1111/stable-diffusion-webui/wiki/Install-and-Run-on-AMD-GPUs) GPUs.
diff --git a/artists.csv b/artists.csv
deleted file mode 100644
index 1a61ed88..00000000
--- a/artists.csv
+++ /dev/null
@@ -1,3041 +0,0 @@
-artist,score,category
-Peter Max,0.99715996,weird
-Roy Lichtenstein,0.98272276,cartoon
-Romero Britto,0.9498342,scribbles
-Keith Haring,0.9431302,weird
-Hiroshige,0.93995106,ukioe
-Joan Miró,0.9169429,scribbles
-Jean-Michel Basquiat,0.90080947,scribbles
-Katsushika Hokusai,0.8887236,ukioe
-Paul Klee,0.8868682,scribbles
-Marc Chagall,0.8868168,scribbles
-Karl Schmidt-Rottluff,0.88444495,scribbles
-Howard Hodgkin,0.8808578,scribbles
-Jean Metzinger,0.88056004,scribbles
-Alma Thomas,0.87658304,weird
-Rufino Tamayo,0.8749848,scribbles
-Utagawa Hiroshige,0.8728796,ukioe
-Chagall,0.8718535,scribbles
-Harumi Hironaka,0.86914605,scribbles
-Hans Hofmann,0.8686159,scribbles
-Kawanabe Kyōsai,0.86612236,ukioe
-Andy Warhol,0.8654825,scribbles
-Barbara Takenaga,0.86223894,scribbles
-Tatsuro Kiuchi,0.8597267,cartoon
-Vincent Van Gogh,0.85538065,scribbles
-Wassily Kandinsky,0.85490596,scribbles
-Georges Seurat,0.8534801,scribbles
-Karel Appel,0.8529153,scribbles
-Sonia Delaunay,0.8506156,scribbles
-Hokusai,0.85046995,ukioe
-Eduardo Kobra,0.85036755,weird
-Fra Angelico,0.84984255,fineart
-Milton Avery,0.849746,scribbles
-David Hockney,0.8496144,scribbles
-Hiroshi Nagai,0.847129,cartoon
-Aristarkh Lentulov,0.846537,scribbles
-Lyonel Feininger,0.84573764,scribbles
-Mary Blair,0.845709,scribbles
-Ellsworth Kelly,0.8455428,scribbles
-Jun Kaneko,0.8448367,scribbles
-Roz Chast,0.8432013,weird
-Ida Rentoul Outhwaite,0.84275174,scribbles
-Robert Motherwell,0.8409468,scribbles
-Garry Winogrand,0.83994275,black-white
-Andrei Rublev,0.83950496,fineart
-Alexander Calder,0.83832693,scribbles
-Tomokazu Matsuyama,0.8376121,scribbles
-August Macke,0.8362022,scribbles
-Kazimir Malevich,0.8356527,scribbles
-Richard Scarry,0.83554685,scribbles
-Victor Vasarely,0.8335438,scribbles
-Kitagawa Utamaro,0.83333457,ukioe
-Matt Bors,0.83252287,scribbles
-Emil Nolde,0.8323225,scribbles
-Patrick Caulfield,0.8322225,scribbles
-Charles Blackman,0.83200824,scribbles
-Peter Doig,0.83111644,scribbles
-Alexej von Jawlensky,0.8308932,scribbles
-Rumiko Takahashi,0.8301817,anime
-Eileen Agar,0.82945526,scribbles
-Ernst Ludwig Kirchner,0.82756275,scribbles
-Nicolas Delort,0.8261329,scribbles
-Marsden Hartley,0.8250993,scribbles
-Keith Negley,0.8212553,scribbles
-Jamini Roy,0.8212199,scribbles
-Quentin Blake,0.82115215,scribbles
-Andy Kehoe,0.82063186,cartoon
-George barbier,0.82046914,fineart
-Frans Masereel,0.81997275,scribbles
-Umberto Boccioni,0.81921184,scribbles
-Conrad Roset,0.8190752,cartoon
-Paul Ranson,0.81903255,scribbles
-Yayoi Kusama,0.81886625,weird
-Tomi Ungerer,0.81848705,scribbles
-Saul Steinberg,0.81778854,scribbles
-Jon Klassen,0.81773067,scribbles
-W.W. Denslow,0.81708044,fineart
-Helen Frankenthaler,0.81704986,scribbles
-Jean Jullien,0.816437,scribbles
-Brett Whiteley,0.81601924,scribbles
-Giotto Di Bondone,0.81427747,fineart
-Takashi Murakami,0.81338763,weird
-Howard Finster,0.81333554,scribbles
-Eduardo Paolozzi,0.81312317,scribbles
-Charles Rennie Mackintosh,0.81297064,scribbles
-Brandon Mably,0.8128239,weird
-Rebecca Louise Law,0.81214285,weird
-Victo Ngai,0.81195843,cartoon
-Hanabusa Itchō II,0.81187993,ukioe
-Edmund Dulac,0.81104875,scribbles
-Ben Shahn,0.8104582,scribbles
-Howard Arkley,0.8103746,scribbles
-Wilfredo Lam,0.8096211,scribbles
-Michael Deforge,0.8095954,scribbles
-John Hoyland,0.8094592,fineart
-Francesco Clemente,0.8090387,scribbles
-Leonetto Cappiello,0.8087691,scribbles
-Norman Ackroyd,0.80788493,scribbles
-Bhupen Khakhar,0.8077607,scribbles
-Jeremiah Ketner,0.8075384,cartoon
-Chris Ofili,0.8073793,scribbles
-Banksy,0.80695426,scribbles
-Tom Whalen,0.805867,scribbles
-Ernst Wilhelm Nay,0.805295,scribbles
-Henri Rousseau,0.8049866,scribbles
-Kunisada,0.80493814,ukioe
-Naoko Takeuchi,0.80482674,anime
-Kaethe Butcher,0.80406916,scribbles
-Hasui Kawase,0.8040483,ukioe
-Alvin Langdon Coburn,0.8035004,black-white
-Stanley Donwood,0.8033054,scribbles
-Agnes Martin,0.8028028,scribbles
-Osamu Tezuka,0.8005524,cartoon
-Frank Stella,0.80049455,scribbles
-Dale Chihuly,0.79982775,digipa-high-impact
-Evgeni Gordiets,0.79967916,scribbles
-Janek Sedlar,0.7993992,fineart
-Alasdair Gray,0.7992301,scribbles
-Yasuo Kuniyoshi,0.79870003,ukioe
-Edward Gorey,0.7984938,scribbles
-Johannes Itten,0.798481,scribbles
-Cuno Amiet,0.7979497,scribbles
-M.C. Escher,0.7976657,scribbles
-Albert Irvin,0.79688835,scribbles
-Jack Gaughan,0.79443675,scribbles
-Ravi Zupa,0.7939542,scribbles
-Kay Nielsen,0.79385525,scribbles
-Agnolo Gaddi,0.79369193,fineart
-Alessandro Gottardo,0.79321593,scribbles
-Paul Laffoley,0.79196846,scribbles
-Giovanni Battista Piranesi,0.79111177,fineart
-Adrian Tomine,0.79109013,scribbles
-Adolph Gottlieb,0.79061794,scribbles
-Milton Caniff,0.7905358,cartoon
-Philip Guston,0.78994095,scribbles
-Debbie Criswell,0.7895031,cartoon
-Alice Pasquini,0.78949904,cartoon
-Johannes Vermeer,0.78931487,fineart
-Lisa Frank,0.7892591,cartoon
-Patrick Heron,0.78889126,scribbles
-Mikhail Nesterov,0.78814346,fineart
-Cézanne,0.7879481,scribbles
-Tristan Eaton,0.787513,scribbles
-Jillian Tamaki,0.7868066,scribbles
-Takato Yamamoto,0.78460765,ukioe
-Martiros Saryan,0.7844924,scribbles
-Emil Orlik,0.7842625,scribbles
-Armand Guillaumin,0.7840431,scribbles
-Jane Newland,0.7837676,scribbles
-Paul Cézanne,0.78368753,scribbles
-Tove Jansson,0.78356475,scribbles
-Guido Crepax,0.7835321,cartoon
-OSGEMEOS,0.7829088,weird
-Albert Watson,0.48901254,digipa-med-impact
-Emory Douglas,0.78179604,scribbles
-Chris Van Allsburg,0.66413003,fineart
-Ohara Koson,0.78132576,ukioe
-Nicolas de Stael,0.7802779,scribbles
-Aubrey Beardsley,0.77970016,scribbles
-Hishikawa Moronobu,0.7794119,ukioe
-Alfred Wallis,0.77926695,scribbles
-Friedensreich Hundertwasser,0.7791805,scribbles
-Eyvind Earle,0.7788089,scribbles
-Giotto,0.7785216,fineart
-Simone Martini,0.77843,fineart
-Ivan Bilibin,0.77720606,fineart
-Karl Blossfeldt,0.77652574,black-white
-Duy Huynh,0.77634746,scribbles
-Giovanni da Udina,0.7763063,fineart
-Henri-Edmond Cross,0.7762994,fineart
-Barry McGee,0.77618384,scribbles
-William Kentridge,0.77615225,scribbles
-Alexander Archipenko,0.7759824,scribbles
-Jaume Plensa,0.7756799,weird
-Bill Jacklin,0.77504414,fineart
-Alberto Vargas,0.7747376,cartoon
-Jean Dubuffet,0.7744374,scribbles
-Eugène Grasset,0.7741958,fineart
-Arthur Rackham,0.77418125,fineart
-Yves Tanguy,0.77380997,scribbles
-Elsa Beskow,0.7736908,fineart
-Georgia O’Keeffe,0.77368987,scribbles
-Georgia O'Keeffe,0.77368987,scribbles
-Henri Cartier-Bresson,0.7735415,black-white
-Andrea del Verrocchio,0.77307427,fineart
-Mark Rothko,0.77294236,scribbles
-Bruce Gilden,0.7256681,black-white
-Gino Severini,0.77247965,scribbles
-Delphin Enjolras,0.5594248,fineart
-Alena Aenami,0.77210015,cartoon
-Ed Freeman,0.42526615,digipa-low-impact
-Apollonia Saintclair,0.7718383,anime
-László Moholy-Nagy,0.771497,scribbles
-Louis Glackens,0.7713224,fineart
-Fang Lijun,0.77097225,fineart
-Alfred Kubin,0.74409986,fineart
-David Wojnarowicz,0.7705802,scribbles
-Tara McPherson,0.77023256,scribbles
-Gustav Doré,0.7367536,fineart
-Patricia Polacco,0.7696109,scribbles
-Norman Bluhm,0.7692634,fineart
-Elizabeth Gadd,0.7691194,digipa-high-impact
-Gabriele Münter,0.7690926,scribbles
-David Inshaw,0.76905304,scribbles
-Maurice Sendak,0.7690118,cartoon
-Harry Clarke,0.7688428,cartoon
-Howardena Pindell,0.7686921,n
-Jamie Hewlett,0.7680373,scribbles
-Steve Ditko,0.76725733,scribbles
-Annie Soudain,0.7671485,scribbles
-Albert Gleizes,0.76658314,scribbles
-Henry Fuseli,0.69147265,fineart
-Alain Laboile,0.67634284,c
-Albrecht Altdorfer,0.7663378,fineart
-Jack Butler Yeats,0.7661406,fineart
-Yue Minjun,0.76583517,scribbles
-Art Spiegelman,0.7656343,scribbles
-Grete Stern,0.7656276,fineart
-Mordecai Ardon,0.7648692,scribbles
-Joel Sternfeld,0.76456416,digipa-high-impact
-Milton Glaser,0.7641823,scribbles
-Eishōsai Chōki,0.7639659,scribbles
-Domenico Ghirlandaio,0.76372653,fineart
-Alex Timmermans,0.64443207,digipa-high-impact
-Andreas Vesalius,0.763446,fineart
-Bruce McLean,0.76335883,scribbles
-Jacob Lawrence,0.76330304,scribbles
-Alex Katz,0.76317835,scribbles
-Henri de Toulouse-Lautrec,0.76268333,scribbles
-Franz Sedlacek,0.762062,scribbles
-Paul Lehr,0.70854837,cartoon
-Nicholas Roerich,0.76117516,scribbles
-Henri Matisse,0.76110923,scribbles
-Colin McCahon,0.76086944,scribbles
-Max Dupain,0.6661642,black-white
-Stephen Gammell,0.74001735,weird
-Alberto Giacometti,0.7596302,scribbles
-Goyō Hashiguchi,0.7595048,ukioe
-Gustave Doré,0.7018832,fineart
-Butcher Billy,0.7593378,cartoon
-Pieter de Hooch,0.75916564,fineart
-Gaetano Pesce,0.75906265,scribbles
-Winsor McCay,0.7589382,scribbles
-Claude Cahun,0.7588153,weird
-Roger Ballen,0.64683115,black-white
-Ellen Gallagher,0.758621,scribbles
-Anton Corbijn,0.5550669,digipa-high-impact
-Margaret Macdonald Mackintosh,0.75781375,fineart
-Franz Kline,0.7576461,scribbles
-Cimabue,0.75720495,fineart
-André Kertész,0.7319392,black-white
-Hans Hartung,0.75718236,scribbles
-J. J. Grandville,0.7321584,fineart
-David Octavius Hill,0.6333561,digipa-high-impact
-teamLab,0.7566472,digipa-high-impact
-Paul Gauguin,0.75635266,scribbles
-Etel Adnan,0.75631833,scribbles
-Barbara Kruger,0.7562784,scribbles
-Franz Marc,0.75538874,scribbles
-Saul Bass,0.75496316,scribbles
-El Lissitzky,0.7549487,scribbles
-Thomas Moran,0.6507399,fineart
-Claude Monet,0.7541377,fineart
-David Young Cameron,0.7541016,scribbles
-W. Heath Robinson,0.75374347,cartoon
-Yves Klein,0.7536262,fineart
-Albert Pinkham Ryder,0.7338848,fineart
-Elizabeth Shippen Green,0.7533686,fineart
-Robert Stivers,0.5516287,fineart
-Emily Kame Kngwarreye,0.7532016,weird
-Charline von Heyl,0.753142,scribbles
-Frida Kahlo,0.75303876,scribbles
-Amy Sillman,0.752921,scribbles
-Emperor Huizong of Song,0.7525214,ukioe
-Edward Burne-Jones,0.75220466,fineart
-Brett Weston,0.6891357,black-white
-Charles E. Burchfield,0.75174403,scribbles
-Hishida Shunsō,0.751617,fareast
-Elaine de Kooning,0.7514996,scribbles
-Gary Panter,0.7514598,scribbles
-Frederick Hammersley,0.7514268,scribbles
-Gustave Dore,0.6735896,fineart
-Ephraim Moses Lilien,0.7510494,fineart
-Hannah Hoch,0.7509496,scribbles
-Shepard Fairey,0.7508583,scribbles
-Richard Burlet,0.7506659,scribbles
-Bill Brandt,0.6833408,black-white
-Herbert List,0.68455493,black-white
-Joseph Cornell,0.75023884,nudity
-Nathan Wirth,0.6436741,black-white
-John Kenn Mortensen,0.74758303,anime
-Andre De Dienes,0.5683014,digipa-high-impact
-Albert Robida,0.7485741,cartoon
-Shintaro Kago,0.7484431,anime
-Sidney Nolan,0.74809414,scribbles
-Patrice Murciano,0.61973965,fineart
-Brian Stelfreeze,0.7478351,scribbles
-Francisco De Goya,0.6954584,fineart
-William Morris,0.7478111,fineart
-Honoré Daumier,0.74767774,scribbles
-Hubert Robert,0.6863421,fineart
-Marianne von Werefkin,0.7475825,fineart
-Edvard Munch,0.74719715,scribbles
-Victor Brauner,0.74719006,scribbles
-George Inness,0.7470588,fineart
-Naoki Urasawa,0.7469665,anime
-Kilian Eng,0.7468486,scribbles
-Bordalo II,0.7467364,digipa-high-impact
-Katsuhiro Otomo,0.746364,anime
-Maximilien Luce,0.74609685,fineart
-Amy Earles,0.74603415,fineart
-Jeanloup Sieff,0.7196009,black-white
-William Zorach,0.74574494,scribbles
-Pascale Campion,0.74516207,fineart
-Dorothy Lathrop,0.74418795,fineart
-Sofonisba Anguissola,0.74418664,fineart
-Natalia Goncharova,0.74414873,scribbles
-August Sander,0.6644566,black-white
-Jasper Johns,0.74395454,scribbles
-Arthur Dove,0.74383533,scribbles
-Darwyn Cooke,0.7435789,scribbles
-Leonardo Da Vinci,0.6825216,fineart
-Fra Filippo Lippi,0.7433891,fineart
-Pierre-Auguste Renoir,0.742464,fineart
-Jeff Lemire,0.7422893,scribbles
-Al Williamson,0.742113,cartoon
-Childe Hassam,0.7418015,fineart
-Francisco Goya,0.69522625,fineart
-Alphonse Mucha,0.74171394,special
-Cleon Peterson,0.74163914,scribbles
-J.M.W. Turner,0.65582645,fineart
-Walter Crane,0.74146044,fineart
-Brassaï,0.6361966,digipa-high-impact
-Virgil Finlay,0.74133486,fineart
-Fernando Botero,0.7412504,nudity
-Ben Nicholson,0.7411573,scribbles
-Robert Rauschenberg,0.7410054,fineart
-David Wiesner,0.7406237,scribbles
-Bartolome Esteban Murillo,0.6933951,fineart
-Jean Arp,0.7403873,scribbles
-Andre Kertesz,0.7228358,black-white
-Simeon Solomon,0.66441345,fineart
-Hugh Ferriss,0.72443527,black-white
-Agnes Lawrence Pelton,0.73960555,scribbles
-Charles Camoin,0.7395686,scribbles
-Paul Strand,0.7080332,black-white
-Charles Gwathmey,0.7394747,scribbles
-Bartolomé Esteban Murillo,0.7011274,fineart
-Oskar Kokoschka,0.7392038,scribbles
-Bruno Munari,0.73918355,weird
-Willem de Kooning,0.73916197,scribbles
-Hans Memling,0.7387886,fineart
-Chris Mars,0.5861489,digipa-high-impact
-Hiroshi Yoshida,0.73787534,ukioe
-Hundertwasser,0.7377672,fineart
-David Bowie,0.73773724,weird
-Ettore Sottsass,0.7376095,digipa-high-impact
-Antanas Sutkus,0.7369492,black-white
-Leonora Carrington,0.73726475,scribbles
-Hieronymus Bosch,0.7369955,scribbles
-A. J. Casson,0.73666203,scribbles
-Chaim Soutine,0.73662066,scribbles
-Artur Bordalo,0.7364549,weird
-Thomas Allom,0.68792284,fineart
-Louis Comfort Tiffany,0.7363504,fineart
-Philippe Druillet,0.7363382,cartoon
-Jan Van Eyck,0.7360621,fineart
-Sandro Botticelli,0.7359395,fineart
-Hieronim Bosch,0.7359308,scribbles
-Everett Shinn,0.7355817,fineart
-Camille Corot,0.7355603,fineart
-Nick Sharratt,0.73470485,scribbles
-Fernand Léger,0.7079839,scribbles
-Robert S. Duncanson,0.7346282,fineart
-Hieronymous Bosch,0.73453265,scribbles
-Charles Addams,0.7344034,scribbles
-Studio Ghibli,0.73439026,anime
-Archibald Motley,0.7343683,scribbles
-Anton Fadeev,0.73433846,cartoon
-Uemura Shoen,0.7342118,ukioe
-Ando Fuchs,0.73406494,black-white
-Jessie Willcox Smith,0.73398125,fineart
-Alex Garant,0.7333658,scribbles
-Lawren Harris,0.73331416,scribbles
-Anne Truitt,0.73297834,scribbles
-Richard Lindner,0.7328564,scribbles
-Sailor Moon,0.73281246,anime
-Bridget Bate Tichenor,0.73274165,scribbles
-Ralph Steadman,0.7325864,scribbles
-Annibale Carracci,0.73251307,fineart
-Dürer,0.7324789,fineart
-Abigail Larson,0.7319012,cartoon
-Bill Traylor,0.73189163,scribbles
-Louis Rhead,0.7318623,fineart
-David Burliuk,0.731803,scribbles
-Camille Pissarro,0.73172396,fineart
-Catrin Welz-Stein,0.73117495,scribbles
-William Etty,0.6497544,nudity
-Pierre Bonnard,0.7310132,scribbles
-Benoit B. Mandelbrot,0.5033001,digipa-med-impact
-Théodore Géricault,0.692039,fineart
-Andy Goldsworthy,0.7307565,digipa-high-impact
-Alfred Sisley,0.7306032,fineart
-Charles-Francois Daubigny,0.73057353,fineart
-Karel Thole,0.7305395,cartoon
-Andre Derain,0.73050404,scribbles
-Larry Poons,0.73023695,fineart
-Beauford Delaney,0.72999024,scribbles
-Ruth Bernhard,0.72990334,black-white
-David Alfaro Siqueiros,0.7297947,scribbles
-Gaugin,0.729636,fineart
-Carl Larsson,0.7296195,cartoon
-Albrecht Dürer,0.72946966,fineart
-Henri De Toulouse Lautrec,0.7294263,cartoon
-Shotaro Ishinomori,0.7292093,anime
-Hope Gangloff,0.729082,scribbles
-Vivian Maier,0.72897506,digipa-high-impact
-Alex Andreev,0.6442978,digipa-high-impact
-Julie Blackmon,0.72862685,c
-Arthur Melville,0.7286146,fineart
-Henri Michaux,0.599607,fineart
-William Steig,0.7283096,scribbles
-Octavio Ocampo,0.72814554,scribbles
-Cy Twombly,0.72814107,scribbles
-Guy Denning,0.67375445,fineart
-Maxfield Parrish,0.7280283,fineart
-Randolph Caldecott,0.7279564,fineart
-Duccio,0.72795,fineart
-Ray Donley,0.5837457,fineart
-Hiroshi Sugimoto,0.6497892,digipa-high-impact
-Daniela Uhlig,0.4691466,special
-Go Nagai,0.72770613,anime
-Carlo Crivelli,0.72764605,fineart
-Helmut Newton,0.44433144,digipa-low-impact
-Josef Albers,0.7061394,scribbles
-Henry Moret,0.7274567,fineart
-André Masson,0.727404,scribbles
-Henri Fantin Latour,0.72732764,fineart
-Theo van Rysselberghe,0.7272843,fineart
-John Wayne Gacy,0.72686327,scribbles
-Carlos Schwabe,0.7267612,fineart
-Herbert Bayer,0.7094297,scribbles
-Domenichino,0.72667265,fineart
-Liam Wong,0.7262276,special
-George Caleb Bingham,0.7262154,digipa-high-impact
-Gigadō Ashiyuki,0.7261864,fineart
-Chaïm Soutine,0.72603923,scribbles
-Ary Scheffer,0.64913243,fineart
-Rockwell Kent,0.7257272,scribbles
-Jean-Paul Riopelle,0.72570604,fineart
-Ed Mell,0.6637067,cartoon
-Ismail Inceoglu,0.72561014,special
-Edgar Degas,0.72538006,fineart
-Giorgione,0.7252798,fineart
-Charles-François Daubigny,0.7252482,fineart
-Arthur Lismer,0.7251765,scribbles
-Aaron Siskind,0.4852289,digipa-med-impact
-Arkhip Kuindzhi,0.7249981,fineart
-Joseph Mallord William Turner,0.6834406,fineart
-Dante Gabriel Rossetti,0.7244541,fineart
-Ernst Haeckel,0.6660129,fineart
-Rebecca Guay,0.72439146,cartoon
-Anthony Gerace,0.636678,digipa-high-impact
-Martin Kippenberger,0.72418386,scribbles
-Diego Giacometti,0.72415763,scribbles
-Dmitry Kustanovich,0.7241322,cartoon
-Dora Carrington,0.7239633,scribbles
-Shusei Nagaoko,0.7238965,anime
-Odilon Redon,0.72381747,scribbles
-Shohei Otomo,0.7132803,nudity
-Barnett Newman,0.7236389,scribbles
-Jean Fouquet,0.7235963,fineart
-Gustav Klimt,0.72356784,nudity
-Francisco Josè de Goya,0.6589663,fineart
-Bonnard Pierre,0.72309464,nudity
-Brooke Shaden,0.61281693,digipa-high-impact
-Mao Hamaguchi,0.7228292,scribbles
-Frederick Edwin Church,0.64416,fineart
-Asher Brown Durand,0.72264796,fineart
-George Baselitz,0.7223453,scribbles
-Sam Bosma,0.7223237,fineart
-Asaf Hanuka,0.72222745,scribbles
-David Teniers the Younger,0.7221168,fineart
-Nicola Samori,0.68747556,nudity
-Claude Lorrain,0.7217102,fineart
-Hermenegildo Anglada Camarasa,0.7214374,nudity
-Pablo Picasso,0.72142905,scribbles
-Howard Chaykin,0.7213998,cartoon
-Ferdinand Hodler,0.7213758,nudity
-Farel Dalrymple,0.7213298,fineart
-Lyubov Popova,0.7213024,scribbles
-Albin Egger-Lienz,0.72120845,fineart
-Geertgen tot Sint Jans,0.72107565,fineart
-Kate Greenaway,0.72069687,fineart
-Louise Bourgeois,0.7206516,fineart
-Miriam Schapiro,0.72026414,fineart
-Pieter Claesz,0.7200939,fineart
-George B. Bridgman,0.5592567,fineart
-Piet Mondrian,0.71990657,scribbles
-Michelangelo Merisi Da Caravaggio,0.7094674,fineart
-Marie Spartali Stillman,0.71986604,fineart
-Gertrude Abercrombie,0.7196962,scribbles
-Louis Icart,0.7195913,fineart
-David Driskell,0.719564,scribbles
-Paula Modersohn-Becker,0.7193769,scribbles
-George Hurrell,0.57496595,digipa-high-impact
-Andrea Mantegna,0.7190254,fineart
-Silvestro Lega,0.71891177,fineart
-Junji Ito,0.7188978,anime
-Jacob Hashimoto,0.7186867,digipa-high-impact
-Benjamin West,0.6642946,fineart
-David Teniers the Elder,0.7181293,fineart
-Roberto Matta,0.71808386,fineart
-Chiho Aoshima,0.71801454,anime
-Amedeo Modigliani,0.71788836,scribbles
-Raja Ravi Varma,0.71788085,fineart
-Roberto Ferri,0.538221,nudity
-Winslow Homer,0.7176876,fineart
-Horace Vernet,0.65729,fineart
-Lucas Cranach the Elder,0.71738195,fineart
-Godfried Schalcken,0.625893,fineart
-Affandi,0.7170285,nudity
-Diane Arbus,0.655138,digipa-high-impact
-Joseph Ducreux,0.65247905,digipa-high-impact
-Berthe Morisot,0.7165984,fineart
-Hilma af Klint,0.71643853,scribbles
-Filippino Lippi,0.7163017,fineart
-Leonid Afremov,0.7163005,fineart
-Chris Ware,0.71628594,scribbles
-Marius Borgeaud,0.7162446,scribbles
-M.W. Kaluta,0.71612585,cartoon
-Govert Flinck,0.68975246,fineart
-Charles Demuth,0.71605396,scribbles
-Coles Phillips,0.7158309,scribbles
-Oskar Fischinger,0.6721027,digipa-high-impact
-David Teniers III,0.71569765,fineart
-Jean Delville,0.7156771,fineart
-Antonio Saura,0.7155949,scribbles
-Bridget Riley,0.7155669,fineart
-Gordon Parks,0.5759978,digipa-high-impact
-Anselm Kiefer,0.71514887,scribbles
-Remedios Varo,0.7150927,weird
-Franz Hegi,0.71495223,scribbles
-Kati Horna,0.71486115,black-white
-Arshile Gorky,0.71459055,scribbles
-David LaChapelle,0.7144903,scribbles
-Fritz von Dardel,0.71446383,scribbles
-Edward Ruscha,0.71438885,fineart
-Blanche Hoschedé Monet,0.7143073,fineart
-Alexandre Calame,0.5735474,fineart
-Sean Scully,0.714154,fineart
-Alexandre Benois,0.7141515,fineart
-Sally Mann,0.6534312,black-white
-Thomas Eakins,0.7141104,fineart
-Arnold Böcklin,0.71407956,fineart
-Alfonse Mucha,0.7139052,special
-Damien Hirst,0.7136273,scribbles
-Lee Krasner,0.71362555,scribbles
-Dorothea Lange,0.71361613,black-white
-Juan Gris,0.7132987,scribbles
-Bernardo Bellotto,0.70720065,fineart
-John Martin,0.5376847,fineart
-Harriet Backer,0.7131594,fineart
-Arnold Newman,0.5736342,digipa-high-impact
-Gjon Mili,0.46520913,digipa-low-impact
-Asger Jorn,0.7129575,scribbles
-Chesley Bonestell,0.6063316,fineart
-Agostino Carracci,0.7128167,fineart
-Peter Wileman,0.71271706,cartoon
-Chen Hongshou,0.71268153,ukioe
-Catherine Hyde,0.71266896,scribbles
-Andrea Pozzo,0.626546,fineart
-Kitty Lange Kielland,0.7125735,fineart
-Cornelis Saftleven,0.6684047,fineart
-Félix Vallotton,0.71237606,fineart
-Albrecht Durer,0.7122327,fineart
-Jackson Pollock,0.71222305,scribbles
-John Bratby,0.7122171,scribbles
-Beksinski,0.71218586,fineart
-James Thomas Watts,0.5959548,fineart
-Konstantin Korovin,0.71188873,fineart
-Gustave Caillebotte,0.71181154,fineart
-Dean Ellis,0.50233585,fineart
-Friedrich von Amerling,0.6420181,fineart
-Christopher Balaskas,0.67935324,special
-Alexander Rodchenko,0.67415404,scribbles
-Alfred Cheney Johnston,0.6647291,fineart
-Mikalojus Konstantinas Ciurlionis,0.710677,scribbles
-Jean-Antoine Watteau,0.71061164,fineart
-Paul Delvaux,0.7105914,scribbles
-Francesco del Cossa,0.7104901,nudity
-Isaac Cordal,0.71046066,weird
-Hikari Shimoda,0.7104546,weird
-François Boucher,0.67153126,fineart
-Akos Major,0.7103802,digipa-high-impact
-Bernard Buffet,0.7103491,cartoon
-Brandon Woelfel,0.6727086,digipa-high-impact
-Edouard Manet,0.7101296,fineart
-Auguste Herbin,0.6866145,scribbles
-Eugene Delacroix,0.70995826,fineart
-L. Birge Harrison,0.70989627,fineart
-Howard Pyle,0.70979863,fineart
-Diane Dillon,0.70968723,scribbles
-Hans Erni,0.7096618,scribbles
-Richard Diebenkorn,0.7096184,scribbles
-Thomas Gainsborough,0.6759419,fineart
-Maria Sibylla Merian,0.7093275,fineart
-François Joseph Heim,0.6175854,fineart
-E. H. Shepard,0.7091189,cartoon
-Hsiao-Ron Cheng,0.7090618,scribbles
-Canaletto,0.7090392,fineart
-John Atkinson Grimshaw,0.7087531,fineart
-Giovanni Battista Tiepolo,0.6754107,fineart
-Cornelis van Poelenburgh,0.69821274,fineart
-Raina Telgemeier,0.70846486,scribbles
-Francesco Hayez,0.6960006,fineart
-Gilbert Stuart,0.659772,fineart
-Konstantin Yuon,0.7081486,fineart
-Antonello da Messina,0.70806944,fineart
-Austin Osman Spare,0.7079903,fineart
-James Ensor,0.70781446,scribbles
-Claude Bonin-Pissarro,0.70739406,fineart
-Mikhail Vrubel,0.70738363,fineart
-Angelica Kauffman,0.6748828,fineart
-Viktor Vasnetsov,0.7072422,fineart
-Alphonse Osbert,0.70724136,fineart
-Tsutomu Nihei,0.7070495,anime
-Harvey Quaytman,0.63613266,fineart
-Jamie Hawkesworth,0.706914,digipa-high-impact
-Francesco Guardi,0.70682615,fineart
-Jean-Honoré Fragonard,0.6518248,fineart
-Brice Marden,0.70673287,digipa-high-impact
-Charles-Amédée-Philippe van Loo,0.6725916,fineart
-Mati Klarwein,0.7066092,n
-Gerard ter Borch,0.706589,fineart
-Dan Hillier,0.48966256,digipa-med-impact
-Federico Barocci,0.682664,fineart
-Henri Le Sidaner,0.70637953,fineart
-Olivier Bonhomme,0.7063748,scribbles
-Edward Weston,0.7061382,black-white
-Giovanni Paolo Cavagna,0.6840265,fineart
-Germaine Krull,0.6621777,black-white
-Hans Holbein the Younger,0.70590156,fineart
-François Bocion,0.6272365,fineart
-Georg Baselitz,0.7053314,scribbles
-Caravaggio,0.7050303,fineart
-Anne Rothenstein,0.70502245,scribbles
-Wadim Kashin,0.43714935,digipa-low-impact
-Heinrich Lefler,0.7048054,fineart
-Jacob van Ruisdael,0.7047918,fineart
-Bartholomeus van Bassen,0.6676872,fineart
-Jeffrey Smith art,0.56750107,fineart
-Anne Packard,0.7046703,weird
-Jean-François Millet,0.7045456,fineart
-Andrey Remnev,0.7041204,digipa-high-impact
-Fujiwara Takanobu,0.70410216,ukioe
-Elliott Erwitt,0.69950557,black-white
-Fern Coppedge,0.7036215,fineart
-Bartholomeus van der Helst,0.66411966,fineart
-Rembrandt Van Rijn,0.6979987,fineart
-Rene Magritte,0.703457,scribbles
-Aelbert Cuyp,0.7033657,fineart
-Gerda Wegener,0.70319015,scribbles
-Graham Sutherland,0.7031714,scribbles
-Gerrit Dou,0.7029986,fineart
-August Friedrich Schenck,0.6801586,fineart
-George Herriman,0.7028568,scribbles
-Stanisław Szukalski,0.6903354,fineart
-Slim Aarons,0.70222545,digipa-high-impact
-Ernst Thoms,0.70221686,fineart
-Louis Wain,0.702186,fineart
-Artemisia Gentileschi,0.70198226,fineart
-Eugène Delacroix,0.70155394,fineart
-Peter Bagge,0.70127463,scribbles
-Jeffrey Catherine Jones,0.7012148,cartoon
-Eugène Carrière,0.65272695,fineart
-Alexander Millar,0.7011144,scribbles
-Nobuyoshi Araki,0.70108867,fareast
-Tintoretto,0.6702795,fineart
-André Derain,0.7009005,scribbles
-Charles Maurice Detmold,0.70079994,fineart
-Francisco de Zurbarán,0.7007234,fineart
-Laurie Greasley,0.70072114,cartoon
-Lynda Benglis,0.7006948,digipa-high-impact
-Cecil Beaton,0.66362655,black-white
-Gustaf Tenggren,0.7006041,cartoon
-Abdur Rahman Chughtai,0.7004994,ukioe
-Constantin Brancusi,0.7004367,scribbles
-Mikhail Larionov,0.7004066,fineart
-Jan van Kessel the Elder,0.70040506,fineart
-Chantal Joffe,0.70036674,scribbles
-Charles-André van Loo,0.6830367,fineart
-Reginald Marsh,0.6301042,fineart
-Elsa Bleda,0.70005083,digipa-high-impact
-Peter Paul Rubens,0.65745676,fineart
-Eugène Boudin,0.70001304,fineart
-Charles Willson Peale,0.66907954,fineart
-Brian Mashburn,0.63395154,digipa-high-impact
-Barkley L. Hendricks,0.69986427,n
-Yoshiyuki Tomino,0.6998095,anime
-Guido Reni,0.6416875,fineart
-Lynd Ward,0.69958556,fineart
-John Constable,0.6907788,fineart
-František Kupka,0.6993329,fineart
-Pieter Bruegel The Elder,0.6992879,scribbles
-Benjamin Gerritsz Cuyp,0.6992173,fineart
-Nicolas Mignard,0.6988214,fineart
-Augustus Edwin Mulready,0.6482165,fineart
-Andrea del Sarto,0.698532,fineart
-Edward Steichen,0.69837445,black-white
-James Abbott McNeill Whistler,0.69836813,fineart
-Alphonse Legros,0.6983243,fineart
-Ivan Aivazovsky,0.64588225,fineart
-Giovanni Francesco Barbieri,0.6981316,fineart
-Grace Cossington Smith,0.69811064,fineart
-Bert Stern,0.53411555,scribbles
-Mary Cassatt,0.6980135,fineart
-Jules Bastien-Lepage,0.69796044,fineart
-Max Ernst,0.69777006,fineart
-Kentaro Miura,0.697743,anime
-Georges Rouault,0.69758564,scribbles
-Josephine Wall,0.6973667,fineart
-Anne-Louis Girodet,0.58104825,nudity
-Bert Hardy,0.6972966,black-white
-Adriaen van de Velde,0.69716156,fineart
-Andreas Achenbach,0.61108655,fineart
-Hayv Kahraman,0.69705284,fineart
-Beatrix Potter,0.6969851,fineart
-Elmer Bischoff,0.6968948,fineart
-Cornelis de Heem,0.6968436,fineart
-Inio Asano,0.6965007,anime
-Alfred Henry Maurer,0.6964837,fineart
-Gottfried Helnwein,0.6962953,digipa-high-impact
-Paul Barson,0.54196984,digipa-high-impact
-Roger de La Fresnaye,0.69620967,fineart
-Abraham Mignon,0.60605425,fineart
-Albert Bloch,0.69573116,nudity
-Charles Dana Gibson,0.67155975,fineart
-Alexandre-Évariste Fragonard,0.6507174,fineart
-Ernst Fuchs,0.6953538,nudity
-Alfredo Jaar,0.6952965,digipa-high-impact
-Judy Chicago,0.6952246,weird
-Frans van Mieris the Younger,0.6951849,fineart
-Aertgen van Leyden,0.6951305,fineart
-Emily Carr,0.69512105,fineart
-Frances MacDonald,0.6950408,scribbles
-Hannah Höch,0.69495845,scribbles
-Gillis Rombouts,0.58770025,fineart
-Käthe Kollwitz,0.6947756,fineart
-Barbara Stauffacher Solomon,0.6920825,fineart
-Georges Lacombe,0.6944455,fineart
-Gwen John,0.6944161,fineart
-Terada Katsuya,0.6944026,cartoon
-James Gillray,0.6871335,fineart
-Robert Crumb,0.69420326,fineart
-Bruce Pennington,0.6545669,fineart
-David Firth,0.69400465,scribbles
-Arthur Boyd,0.69399726,fineart
-Antonin Artaud,0.67321455,fineart
-Giuseppe Arcimboldo,0.6937329,fineart
-Jim Mahfood,0.6936606,cartoon
-Ossip Zadkine,0.6494374,scribbles
-Atelier Olschinsky,0.69349927,fineart
-Carl Frederik von Breda,0.57274634,fineart
-Ken Sugimori,0.6932626,anime
-Chris Friel,0.5399168,fineart
-Andrew Macara,0.69307995,fineart
-Alexander Jansson,0.69298327,scribbles
-Anne Brigman,0.6865817,black-white
-George Ault,0.66756654,fineart
-Arkhyp Kuindzhi,0.6928072,digipa-high-impact
-Emiliano Ponzi,0.69278395,scribbles
-William Holman Hunt,0.6927663,fineart
-Tamara Lempicka,0.6386007,scribbles
-Mark Ryden,0.69259655,fineart
-Giovanni Paolo Pannini,0.6802902,fineart
-Carl Barks,0.6923666,cartoon
-Fritz Bultman,0.6318746,fineart
-Salomon van Ruysdael,0.690313,fineart
-Carrie Mae Weems,0.6645416,n
-Agostino Arrivabene,0.61166185,fineart
-Gustave Boulanger,0.655797,fineart
-Henry Justice Ford,0.51214355,fareast
-Bernardo Strozzi,0.63510317,fineart
-André Lhote,0.68718815,scribbles
-Paul Corfield,0.6915611,scribbles
-Gifford Beal,0.6914777,fineart
-Hirohiko Araki,0.6914078,anime
-Emil Carlsen,0.691326,fineart
-Frans van Mieris the Elder,0.6912799,fineart
-Simon Stalenhag,0.6912775,special
-Henry van de Velde,0.64838886,fineart
-Eleanor Fortescue-Brickdale,0.6909729,fineart
-Thomas W Schaller,0.69093937,special
-NHK Animation,0.6907677,cartoon
-Euan Uglow,0.69060403,scribbles
-Hendrick Goltzius,0.69058937,fineart
-William Blake,0.69038224,fineart
-Vito Acconci,0.58409876,digipa-high-impact
-Billy Childish,0.6902057,scribbles
-Ben Quilty,0.6875855,fineart
-Mark Briscoe,0.69010437,fineart
-Adriaen van de Venne,0.6899867,fineart
-Alasdair McLellan,0.6898454,digipa-high-impact
-Ed Paschke,0.68974686,scribbles
-Guy Rose,0.68960273,fineart
-Barbara Hepworth,0.68958247,fineart
-Edward Henry Potthast,0.6895703,fineart
-Francis Bacon,0.6895397,scribbles
-Pawel Kuczynski,0.6894536,fineart
-Bjarke Ingels,0.68933153,digipa-high-impact
-Henry Ossawa Tanner,0.68932164,fineart
-Alessandro Allori,0.6892961,fineart
-Abraham van Calraet,0.63841593,fineart
-Egon Schiele,0.6891415,scribbles
-Tim Doyle,0.5474768,digipa-high-impact
-Grandma Moses,0.6890782,fineart
-John Frederick Kensett,0.61981744,fineart
-Giacomo Balla,0.68893707,fineart
-Jamie Baldridge,0.6546651,digipa-high-impact
-Max Beckmann,0.6884731,scribbles
-Cornelis van Haarlem,0.6677613,fineart
-Edward Hopper,0.6884258,special
-Barkley Hendricks,0.6883637,n
-Patrick Dougherty,0.688321,digipa-high-impact
-Karol Bak,0.6367705,fineart
-Pierre Puvis de Chavannes,0.6880703,fineart
-Antoni Tàpies,0.685689,fineart
-Alexander Nasmyth,0.57695735,fineart
-Laurent Grasso,0.5793272,fineart
-Camille Walala,0.6076875,digipa-high-impact
-Fairfield Porter,0.68790644,fineart
-Alex Colville,0.68787855,fineart
-Herb Ritts,0.51471305,scribbles
-Gerhard Munthe,0.687658,fineart
-Susan Seddon Boulet,0.68762136,scribbles
-Liu Ye,0.68760437,fineart
-Robert Antoine Pinchon,0.68744636,fineart
-Fujiwara Nobuzane,0.6873439,fineart
-Frederick Carl Frieseke,0.6873361,fineart
-Aert van der Neer,0.6159286,fineart
-Allen Jones,0.6869935,scribbles
-Anja Millen,0.6064488,digipa-high-impact
-Esaias van de Velde,0.68673944,fineart
-Gyoshū Hayami,0.68665624,anime
-William Hogarth,0.6720842,fineart
-Frederic Church,0.6865637,fineart
-Cyril Rolando,0.68644965,cartoon
-Frederic Edwin Church,0.6863009,fineart
-Thomas Rowlandson,0.66726154,fineart
-Joachim Brohm,0.68601763,digipa-high-impact
-Cristofano Allori,0.6858083,fineart
-Adrianus Eversen,0.58259964,fineart
-Richard Dadd,0.68546164,fineart
-Ambrosius Bosschaert II,0.6854217,fineart
-Paolo Veronese,0.68422073,fineart
-Abraham van den Tempel,0.66463804,fineart
-Duncan Grant,0.6852565,scribbles
-Hendrick Cornelisz. van Vliet,0.6851691,fineart
-Geof Darrow,0.6851174,scribbles
-Émile Bernard,0.6850957,fineart
-Brian Bolland,0.68496394,scribbles
-James Gilleard,0.6849431,cartoon
-Anton Raphael Mengs,0.6689196,fineart
-Augustus Jansson,0.6845705,digipa-high-impact
-Hendrik Goltzius,0.6843367,fineart
-Domenico Quaglio the Younger,0.65769434,fineart
-Cicely Mary Barker,0.6841806,fineart
-William Eggleston,0.6840795,digipa-high-impact
-David Choe,0.6840449,scribbles
-Adam Elsheimer,0.6716068,fineart
-Heinrich Danioth,0.5390186,fineart
-Franz Stuck,0.6836468,fineart
-Bernie Wrightson,0.64101505,fineart
-Dorina Costras,0.6835419,fineart
-El Greco,0.68343943,fineart
-Gatōken Shunshi,0.6833314,anime
-Giovanni Bellini,0.67622876,fineart
-Aron Wiesenfeld,0.68331146,nudity
-Boris Kustodiev,0.68329334,fineart
-Alec Soth,0.5597321,digipa-high-impact
-Artus Scheiner,0.6313348,fineart
-Kelly Vivanco,0.6830933,scribbles
-Shaun Tan,0.6830649,fineart
-Anthony van Dyck,0.6577681,fineart
-Neil Welliver,0.68297863,nudity
-Robert McCall,0.68294585,fineart
-Sandra Chevrier,0.68284667,scribbles
-Yinka Shonibare,0.68256056,n
-Arthur Tress,0.6301861,digipa-high-impact
-Richard McGuire,0.6820089,scribbles
-Anni Albers,0.65708244,digipa-high-impact
-Aleksey Savrasov,0.65207493,fineart
-Wayne Barlowe,0.6537874,fineart
-Giorgio de Chirico,0.6815907,fineart
-Ernest Procter,0.6815795,fineart
-Adriaen Brouwer,0.6815058,fineart
-Ilya Glazunov,0.6813533,fineart
-Alison Bechdel,0.68096143,scribbles
-Carl Holsoe,0.68082225,fineart
-Alfred Edward Chalon,0.6464571,fineart
-Gerard David,0.68058,fineart
-Basil Blackshaw,0.6805679,fineart
-Gerrit Adriaenszoon Berckheyde,0.67340267,fineart
-George Hendrik Breitner,0.6804209,fineart
-Abraham Bloemaert,0.68036544,fineart
-Ferdinand Van Kessel,0.67742276,fineart
-Hugo Simberg,0.68031186,fineart
-Gaston Bussière,0.665221,fineart
-Shawn Coss,0.42407864,digipa-low-impact
-Hanabusa Itchō,0.68023074,ukioe
-Magnus Enckell,0.6801553,fineart
-Gary Larson,0.6801336,scribbles
-George Manson,0.68013126,digipa-high-impact
-Hayao Miyazaki,0.6800754,anime
-Carl Spitzweg,0.66581815,fineart
-Ambrosius Holbein,0.6798341,fineart
-Domenico Pozzi,0.6434162,fineart
-Dorothea Tanning,0.6797955,fineart
-Jeannette Guichard-Bunel,0.5251578,digipa-high-impact
-Victor Moscoso,0.62962687,fineart
-Francis Picabia,0.6795391,scribbles
-Charles W. Bartlett,0.67947805,fineart
-David A Hardy,0.5554935,fineart
-C. R. W. Nevinson,0.67946506,fineart
-Man Ray,0.6507145,scribbles
-Albert Bierstadt,0.67935765,fineart
-Charles Le Brun,0.6758479,fineart
-Lovis Corinth,0.67913896,fineart
-Herbert Abrams,0.5507507,digipa-high-impact
-Giorgio Morandi,0.6789025,fineart
-Agnolo Bronzino,0.6787985,fineart
-Abraham Pether,0.66922426,fineart
-John Bauer,0.6786695,fineart
-Arthur Stanley Wilkinson,0.67860866,fineart
-Arthur Wardle,0.5510789,fineart
-George Romney,0.62868094,fineart
-Laurie Lipton,0.5201844,fineart
-Mickalene Thomas,0.45433685,digipa-low-impact
-Alice Rahon,0.6777824,scribbles
-Gustave Van de Woestijne,0.6777346,scribbles
-Laurel Burch,0.67766285,fineart
-Hendrik Gerritsz Pot,0.67750573,fineart
-John William Waterhouse,0.677472,fineart
-Conor Harrington,0.5967809,fineart
-Gabriel Ba,0.6773366,cartoon
-Franz Xaver Winterhalter,0.62229514,fineart
-George Cruikshank,0.6473593,fineart
-Hyacinthe Rigaud,0.67717785,fineart
-Cornelis Claesz van Wieringen,0.6770269,fineart
-Adriaen van Outrecht,0.67682564,fineart
-Yaacov Agam,0.6767926,fineart
-Franz von Lenbach,0.61948,fineart
-Clyfford Still,0.67667866,fineart
-Alexander Roslin,0.66719526,fineart
-Barry Windsor Smith,0.6765375,cartoon
-Takeshi Obata,0.67643225,anime
-John Harris,0.47712502,fineart
-Bruce Davidson,0.6763525,digipa-high-impact
-Hendrik Willem Mesdag,0.6762745,fineart
-Makoto Shinkai,0.67610705,anime
-Andreas Gursky,0.67610145,digipa-high-impact
-Mike Winkelmann (Beeple),0.6510196,digipa-high-impact
-Gustave Moreau,0.67607844,fineart
-Frank Weston Benson,0.6760142,fineart
-Eduardo Kingman,0.6759026,fineart
-Benjamin Williams Leader,0.5611925,fineart
-Hervé Guibert,0.55973417,black-white
-Cornelis Dusart,0.6753622,fineart
-Amédée Guillemin,0.6752696,fineart
-Alessio Albi,0.6752633,digipa-high-impact
-Matthias Grünewald,0.6751779,fineart
-Fujishima Takeji,0.6751577,anime
-Georges Braque,0.67514753,scribbles
-John Salminen,0.67498183,fineart
-Atey Ghailan,0.674873,scribbles
-Giovanni Antonio Galli,0.657484,fineart
-Julie Mehretu,0.6748382,fineart
-Jean Auguste Dominique Ingres,0.6746286,fineart
-Francesco Albani,0.6621554,fineart
-Anato Finnstark,0.6744919,digipa-high-impact
-Giovanni Bernardino Mazzolini,0.64416045,fineart
-Antoine Le Nain,0.6233709,fineart
-Ford Madox Brown,0.6743224,fineart
-Gerhard Richter,0.67426133,fineart
-theCHAMBA,0.6742506,cartoon
-Edward Julius Detmold,0.67421955,fineart
-George Stubbs,0.6209227,fineart
-George Tooker,0.6740602,scribbles
-Faith Ringgold,0.6739976,scribbles
-Giambattista Pittoni,0.5792371,fineart
-George Bellows,0.6737008,fineart
-Aldus Manutius,0.67366326,fineart
-Ambrosius Bosschaert,0.67364097,digipa-high-impact
-Michael Parkes,0.6133628,fineart
-Hans Bellmer,0.6735973,nudity
-Sir James Guthrie,0.67359626,fineart
-Charles Spencelayh,0.67356884,fineart
-Ivan Shishkin,0.6734136,fineart
-Hans Holbein the Elder,0.6733856,fineart
-Filip Hodas,0.60053295,digipa-high-impact
-Herman Saftleven,0.6732188,digipa-high-impact
-Dirck de Quade van Ravesteyn,0.67309594,fineart
-Joe Fenton,0.6730916,scribbles
-Arnold Bocklin,0.6730706,fineart
-Baiōken Eishun,0.6730663,anime
-Giovanni Giacometti,0.6730505,fineart
-Giovanni Battista Gaulli,0.65036476,fineart
-William Stout,0.672887,fineart
-Gavin Hamilton,0.5982757,fineart
-John Stezaker,0.6726847,black-white
-Frederick McCubbin,0.67263377,fineart
-Christoph Ludwig Agricola,0.62750757,fineart
-Alice Neel,0.67255914,scribbles
-Giovanni Battista Venanzi,0.61996603,fineart
-Miho Hirano,0.6724092,anime
-Tom Thomson,0.6723876,fineart
-Alfred Munnings,0.6723851,fineart
-David Wilkie,0.6722781,fineart
-Adriaen van Ostade,0.67220736,fineart
-Alfred Eisenstaedt,0.67213774,black-white
-Leon Kossoff,0.67208946,fineart
-Georges de La Tour,0.6421979,fineart
-Chuck Close,0.6719756,digipa-high-impact
-Herbert MacNair,0.6719506,scribbles
-Edward Atkinson Hornel,0.6719265,fineart
-Becky Cloonan,0.67192084,cartoon
-Gian Lorenzo Bernini,0.58210254,fineart
-Hein Gorny,0.4982776,digipa-med-impact
-Joe Webb,0.6714884,fineart
-Cornelis Pietersz Bega,0.64423996,fineart
-Christian Krohg,0.6713641,fineart
-Cornelia Parker,0.6712246,fineart
-Anna Mary Robertson Moses,0.6709144,fineart
-Quentin Tarantino,0.6708354,digipa-high-impact
-Frederic Remington,0.67074275,fineart
-Barent Fabritius,0.6707407,fineart
-Oleg Oprisco,0.6707388,digipa-high-impact
-Hendrick van Streeck,0.670666,fineart
-Bakemono Zukushi,0.67051035,anime
-Lucy Madox Brown,0.67032814,fineart
-Paul Wonner,0.6700563,scribbles
-Guido Borelli Da Caluso,0.66966087,digipa-high-impact
-Emil Alzamora,0.5844039,nudity
-Heinrich Brocksieper,0.64469147,fineart
-Dan Smith,0.669563,digipa-high-impact
-Lois van Baarle,0.6695091,scribbles
-Arthur Garfield Dove,0.6694996,scribbles
-Matthias Jung,0.66936135,digipa-high-impact
-José Clemente Orozco,0.6693544,scribbles
-Don Bluth,0.6693046,cartoon
-Akseli Gallen-Kallela,0.66927314,fineart
-Alex Howitt,0.52858865,digipa-high-impact
-Giovanni Bernardino Asoleni,0.6635405,fineart
-Frederick Goodall,0.6690712,fineart
-Francesco Bartolozzi,0.63431,fineart
-Edmund Leighton,0.6689639,fineart
-Abraham Willaerts,0.5966594,fineart
-François Louis Thomas Francia,0.6207474,fineart
-Carel Fabritius,0.6688478,fineart
-Flora Macdonald Reid,0.6687404,fineart
-Bartholomeus Breenbergh,0.6163084,fineart
-Bernardino Mei,0.6486895,fineart
-Carel Weight,0.6684968,fineart
-Aristide Maillol,0.66843045,scribbles
-Chris Leib,0.60567486,fineart
-Giovanni Battista Piazzetta,0.65012705,fineart
-Daniel Maclise,0.6678073,fineart
-Giovanni Bernardino Azzolini,0.65774256,fineart
-Aaron Horkey,0.6676864,fineart
-Otto Dix,0.667294,scribbles
-Ferdinand Bol,0.6414797,fineart
-Adriaen Coorte,0.6670663,fineart
-William Gropper,0.6669881,scribbles
-Gerard de Lairesse,0.6639489,fineart
-Mab Graves,0.6668356,scribbles
-Fernando Amorsolo,0.66683346,fineart
-Pixar Concept Artists,0.6667752,cartoon
-Alfred Augustus Glendening,0.64009607,fineart
-Diego Velázquez,0.6666799,fineart
-Jerry Pinkney,0.6665478,fineart
-Antoine Wiertz,0.6143825,fineart
-Alberto Burri,0.6618252,scribbles
-Max Weber,0.6664029,fineart
-Hans Baluschek,0.66636246,fineart
-Annie Swynnerton,0.6663346,fineart
-Albert Dubois-Pillet,0.57526016,fineart
-Dora Maar,0.62862253,digipa-high-impact
-Kay Sage,0.5614823,fineart
-David A. Hardy,0.51376164,fineart
-Alberto Biasi,0.42917693,digipa-low-impact
-Fra Bartolomeo,0.6661105,fineart
-Hendrick van Balen,0.65754294,fineart
-Edwin Austin Abbey,0.66596496,fineart
-George Frederic Watts,0.66595024,fineart
-Alexei Kondratyevich Savrasov,0.6470352,fineart
-Anna Ancher,0.66581213,fineart
-Irma Stern,0.66580737,fineart
-Frédéric Bazille,0.6657115,fineart
-Awataguchi Takamitsu,0.6656272,anime
-Edward Sorel,0.6655388,fineart
-Edward Lear,0.6655078,fineart
-Gabriel Metsu,0.6654555,fineart
-Giovanni Battista Innocenzo Colombo,0.6653655,fineart
-Scott Naismith,0.6650656,fineart
-John Perceval,0.6650283,fineart
-Girolamo Muziano,0.64234406,fineart
-Cornelis de Man,0.66494393,fineart
-Cornelis Bisschop,0.64119905,digipa-high-impact
-Hans Leu the Elder,0.64770013,fineart
-Michael Hutter,0.62479556,fineart
-Cornelia MacIntyre Foley,0.6510235,fineart
-Todd McFarlane,0.6647763,cartoon
-John James Audubon,0.6279882,digipa-high-impact
-William Henry Hunt,0.57340264,fineart
-John Anster Fitzgerald,0.6644317,fineart
-Tomer Hanuka,0.6643152,cartoon
-Alex Prager,0.6641814,fineart
-Heinrich Kley,0.6641148,fineart
-Anne Redpath,0.66407835,scribbles
-Marianne North,0.6640104,fineart
-Daniel Merriam,0.6639365,fineart
-Bill Carman,0.66390574,fineart
-Méret Oppenheim,0.66387725,digipa-high-impact
-Erich Heckel,0.66384083,fineart
-Iryna Yermolova,0.663623,fineart
-Antoine Ignace Melling,0.61502695,fineart
-Akira Toriyama,0.6635002,anime
-Gregory Crewdson,0.59810174,digipa-high-impact
-Helene Schjerfbeck,0.66333634,fineart
-Antonio Mancini,0.6631618,fineart
-Zanele Muholi,0.58554715,n
-Balthasar van der Ast,0.66294503,fineart
-Toei Animations,0.6629127,anime
-Arthur Quartley,0.6628106,fineart
-Diego Rivera,0.6625808,fineart
-Hendrik van Steenwijk II,0.6623777,fineart
-James Tissot,0.6623415,fineart
-Kehinde Wiley,0.66218376,n
-Chiharu Shiota,0.6621249,digipa-high-impact
-George Grosz,0.6620224,fineart
-Peter De Seve,0.6616659,cartoon
-Ryan Hewett,0.6615638,fineart
-Hasegawa Tōhaku,0.66146004,anime
-Apollinary Vasnetsov,0.6613177,fineart
-Francis Cadell,0.66119456,fineart
-Henri Harpignies,0.6611012,fineart
-Henry Macbeth-Raeburn,0.6213787,fineart
-Christoffel van den Berghe,0.6609149,fineart
-Leiji Matsumoto,0.66089404,anime
-Adriaen van der Werff,0.638286,fineart
-Ramon Casas,0.6606529,fineart
-Arthur Hacker,0.66062653,fineart
-Edward Willis Redfield,0.66058433,fineart
-Carl Gustav Carus,0.65355223,fineart
-Francesca Woodman,0.60435605,digipa-high-impact
-Hans Makart,0.5881955,fineart
-Carne Griffiths,0.660091,weird
-Will Barnet,0.65995145,scribbles
-Fitz Henry Lane,0.659841,fineart
-Masaaki Sasamoto,0.6597158,anime
-Salvador Dali,0.6290813,scribbles
-Walt Kelly,0.6596993,digipa-high-impact
-Charlotte Nasmyth,0.56481636,fineart
-Ferdinand Knab,0.6596528,fineart
-Steve Lieber,0.6596117,scribbles
-Zhang Kechun,0.6595939,fareast
-Olivier Valsecchi,0.5324838,digipa-high-impact
-Joel Meyerowitz,0.65937585,digipa-high-impact
-Arthur Streeton,0.6592294,fineart
-Henriett Seth F.,0.6592273,fineart
-Genndy Tartakovsky,0.6591695,scribbles
-Otto Marseus van Schrieck,0.65890455,fineart
-Hanna-Barbera,0.6588123,cartoon
-Mary Anning,0.6588001,fineart
-Pamela Colman Smith,0.6587648,fineart
-Anton Mauve,0.6586873,fineart
-Hendrick Avercamp,0.65866685,fineart
-Max Pechstein,0.65860206,scribbles
-Franciszek Żmurko,0.56855476,fineart
-Felice Casorati,0.6584761,fineart
-Louis Janmot,0.65298057,fineart
-Thomas Cole,0.5408042,fineart
-Peter Mohrbacher,0.58273685,fineart
-Arnold Franz Brasz,0.65834284,nudity
-Christian Rohlfs,0.6582814,fineart
-Basil Gogos,0.658105,fineart
-Fitz Hugh Lane,0.657923,fineart
-Liubov Sergeevna Popova,0.62325525,fineart
-Elizabeth MacNicol,0.65773135,fineart
-Zinaida Serebriakova,0.6577016,fineart
-Ernest Lawson,0.6575238,fineart
-Bruno Catalano,0.6574354,fineart
-Albert Namatjira,0.6573372,fineart
-Fritz von Uhde,0.6572697,fineart
-Edwin Henry Landseer,0.62363374,fineart
-Naoto Hattori,0.621745,fareast
-Reylia Slaby,0.65709853,fineart
-Arthur Burdett Frost,0.6147318,fineart
-Frank Miller,0.65707314,digipa-high-impact
-Algernon Talmage,0.65702903,fineart
-Itō Jakuchū,0.6570199,digipa-high-impact
-Billie Waters,0.65684533,digipa-high-impact
-Ingrid Baars,0.58558,digipa-high-impact
-Pieter Jansz Saenredam,0.6566058,fineart
-Egbert van Heemskerck,0.6125889,fineart
-John French Sloan,0.6362145,fineart
-Craola,0.65639997,scribbles
-Benjamin Marra,0.61809736,nudity
-Anthony Thieme,0.65609205,fineart
-Satoshi Kon,0.65606606,anime
-Masamune Shirow,0.65592873,anime
-Alfred Stevens,0.6557321,fineart
-Hariton Pushwagner,0.6556745,anime
-Carlo Carrà,0.6556279,fineart
-Stuart Davis,0.6050534,digipa-high-impact
-David Shrigley,0.6553904,digipa-high-impact
-Albrecht Anker,0.65531695,fineart
-Anton Semenov,0.6552501,digipa-high-impact
-Fabio Hurtado,0.5955889,fineart
-Donald Judd,0.6552257,fineart
-Francisco de Burgos Mantilla,0.65516514,fineart
-Barthel Bruyn the Younger,0.6551433,fineart
-Abram Arkhipov,0.6550962,fineart
-Paulus Potter,0.65498203,fineart
-Edward Lamson Henry,0.6549521,fineart
-Audrey Kawasaki,0.654843,fineart
-George Catlin,0.6547183,fineart
-Adélaïde Labille-Guiard,0.6066263,fineart
-Sandy Skoglund,0.6546999,digipa-high-impact
-Hans Baldung,0.654431,fineart
-Ethan Van Sciver,0.65442884,cartoon
-Frans Hals,0.6542338,fineart
-Caspar David Friedrich,0.6542175,fineart
-Charles Conder,0.65420866,fineart
-Betty Churcher,0.65387225,fineart
-Claes Corneliszoon Moeyaert,0.65386075,fineart
-David Bomberg,0.6537477,fineart
-Abraham Bosschaert,0.6535562,fineart
-Giuseppe de Nittis,0.65354455,fineart
-John La Farge,0.65342575,fineart
-Frits Thaulow,0.65341854,fineart
-John Duncan,0.6532379,fineart
-Floris van Dyck,0.64900756,fineart
-Anton Pieck,0.65310377,fineart
-Roger Dean,0.6529647,nudity
-Maximilian Pirner,0.65280807,fineart
-Dorothy Johnstone,0.65267503,fineart
-Govert Dircksz Camphuysen,0.65258145,fineart
-Ryohei Hase,0.6168618,fineart
-Hans von Aachen,0.62437224,fineart
-Gustaf Munch-Petersen,0.6522485,fineart
-Earnst Haeckel,0.6344333,fineart
-Giovanni Battista Bracelli,0.62635326,fineart
-Hendrick Goudt,0.6521433,fineart
-Aneurin Jones,0.65191466,fineart
-Bryan Hitch,0.6518333,cartoon
-Coby Whitmore,0.6515695,fineart
-Barthélemy d'Eyck,0.65156406,fineart
-Quint Buchholz,0.65151155,fineart
-Adriaen Hanneman,0.6514815,fineart
-Tom Roberts,0.5855832,fineart
-Fernand Khnopff,0.6512954,nudity
-Charles Vess,0.6512271,cartoon
-Carlo Galli Bibiena,0.6511681,nudity
-Alexander Milne Calder,0.6081027,fineart
-Josan Gonzalez,0.6193469,cartoon
-Barthel Bruyn the Elder,0.6509954,fineart
-Jon Whitcomb,0.6046063,fineart
-Arcimboldo,0.6509897,fineart
-Hendrik van Steenwijk I,0.65086293,fineart
-Albert Joseph Pénot,0.65085316,fineart
-Edward Wadsworth,0.6308917,scribbles
-Andrew Wyeth,0.6507103,fineart
-Correggio,0.650689,fineart
-Frances Currey,0.65068,fineart
-Henryk Siemiradzki,0.56721973,fineart
-Worthington Whittredge,0.6504713,fineart
-Federico Zandomeneghi,0.65033823,fineart
-Isaac Levitan,0.6503356,fineart
-Russ Mills,0.65012795,fineart
-Edith Lawrence,0.65010095,fineart
-Gil Elvgren,0.5614284,digipa-high-impact
-Chris Foss,0.56495357,fineart
-Francesco Zuccarelli,0.612805,fineart
-Hendrick Bloemaert,0.64962655,fineart
-Egon von Vietinghoff,0.57180583,fineart
-Pixar,0.6495793,cartoon
-Daniel Clowes,0.6495775,fineart
-Friedrich Ritter von Friedländer-Malheim,0.6493772,fineart
-Rebecca Sugar,0.6492679,scribbles
-Chen Daofu,0.6492026,fineart
-Dustin Nguyen,0.64909416,cartoon
-Raymond Duchamp-Villon,0.6489605,nudity
-Daniel Garber,0.6489332,fineart
-Antonio Canova,0.58764786,fineart
-Algernon Blackwood,0.59256804,fineart
-Betye Saar,0.64877665,fineart
-William S. Burroughs,0.5505619,fineart
-Rodney Matthews,0.64844495,fineart
-Michelangelo Buonarroti,0.6484401,fineart
-Posuka Demizu,0.64843124,anime
-Joao Ruas,0.6484134,fineart
-Andy Fairhurst,0.6480388,special
-"Andries Stock, Dutch Baroque painter",0.6479797,fineart
-Antonio de la Gandara,0.6479292,fineart
-Bruce Timm,0.6477877,scribbles
-Harvey Kurtzman,0.64772683,cartoon
-Eiichiro Oda,0.64772165,anime
-Edwin Landseer,0.6166703,fineart
-Carl Heinrich Bloch,0.64755356,fineart
-Adriaen Isenbrant,0.6475428,fineart
-Santiago Caruso,0.6473954,fineart
-Alfred Guillou,0.6472603,fineart
-Clara Peeters,0.64725095,fineart
-Kim Jung Gi,0.6472225,cartoon
-Milo Manara,0.6471776,cartoon
-Phil Noto,0.6470769,anime
-Kaws,0.6470336,cartoon
-Desmond Morris,0.5951916,fineart
-Gediminas Pranckevicius,0.6467787,fineart
-Jack Kirby,0.6467424,cartoon
-Claes Jansz. Visscher,0.6466888,fineart
-Augustin Meinrad Bächtiger,0.6465789,fineart
-John Lavery,0.64643383,fineart
-Anne Bachelier,0.6464065,fineart
-Giuseppe Bernardino Bison,0.64633006,fineart
-E. T. A. Hoffmann,0.5887251,fineart
-Ambrosius Benson,0.6457839,fineart
-Cornelis Verbeeck,0.645782,fineart
-H. R. Giger,0.6456823,weird
-Adolph Menzel,0.6455246,fineart
-Aliza Razell,0.5863178,digipa-high-impact
-Gerard Seghers,0.6205679,fineart
-David Aja,0.62812066,scribbles
-Gustave Courbet,0.64476407,fineart
-Alexandre Cabanel,0.63849115,fineart
-Albert Marquet,0.64471006,fineart
-Harold Harvey,0.64464307,fineart
-William Wegman,0.6446265,scribbles
-Harold Gilman,0.6445966,fineart
-Jeremy Geddes,0.57839495,digipa-high-impact
-Abraham van Beijeren,0.6356113,fineart
-Eugène Isabey,0.6160607,fineart
-Jorge Jacinto,0.58618563,fineart
-Frederic Leighton,0.64383554,fineart
-Dave McKean,0.6438012,cartoon
-Hiromu Arakawa,0.64371413,anime
-Aaron Douglas,0.6437089,fineart
-Adolf Dietrich,0.590169,fineart
-Frederik de Moucheron,0.6435952,fineart
-Siya Oum,0.6435919,cartoon
-Alberto Morrocco,0.64352196,fineart
-Robert Vonnoh,0.6433115,fineart
-Tom Bagshaw,0.5322264,fineart
-Guerrilla Girls,0.64309967,digipa-high-impact
-Johann Wolfgang von Goethe,0.6429888,fineart
-Charles Le Roux,0.6426594,fineart
-Auguste Toulmouche,0.64261353,fineart
-Cindy Sherman,0.58666563,digipa-high-impact
-Federico Zuccari,0.6425021,fineart
-Mike Mignola,0.642346,cartoon
-Cecily Brown,0.6421981,fineart
-Brian K. Vaughan,0.64147836,cartoon
-RETNA (Marquis Lewis),0.47963,n
-Klaus Janson,0.64129144,cartoon
-Alessandro Galli Bibiena,0.6412889,fineart
-Jeremy Lipking,0.64123213,fineart
-Stephen Shore,0.64108944,digipa-high-impact
-Heinz Edelmann,0.51325977,digipa-med-impact
-Joaquín Sorolla,0.6409732,fineart
-Bella Kotak,0.6409608,digipa-high-impact
-Cornelis Engebrechtsz,0.64091057,fineart
-Bruce Munro,0.64084166,digipa-high-impact
-Marjane Satrapi,0.64076495,fineart
-Jeremy Mann,0.557744,digipa-high-impact
-Heinrich Maria Davringhausen,0.6403986,fineart
-Kengo Kuma,0.6402023,digipa-high-impact
-Alfred Manessier,0.640153,fineart
-Antonio Galli Bibiena,0.6399247,digipa-high-impact
-Eduard von Grützner,0.6397164,fineart
-Bunny Yeager,0.5455078,digipa-high-impact
-Adolphe Willette,0.6396935,fineart
-Wangechi Mutu,0.6394607,n
-Peter Milligan,0.6391612,digipa-high-impact
-Dalí,0.45400402,digipa-low-impact
-Élisabeth Vigée Le Brun,0.6388982,fineart
-Beth Conklin,0.6388204,digipa-high-impact
-Charles Alphonse du Fresnoy,0.63881266,fineart
-Thomas Benjamin Kennington,0.56668127,fineart
-Jim Woodring,0.5625168,fineart
-Francisco Oller,0.63846034,fineart
-Csaba Markus,0.6384506,fineart
-Botero,0.63843524,scribbles
-Bill Henson,0.5394536,digipa-high-impact
-Anna Bocek,0.6382304,scribbles
-Hugo van der Goes,0.63822484,fineart
-Robert William Hume,0.5433574,fineart
-Chip Zdarsky,0.6381826,cartoon
-Daniel Seghers,0.53494316,fineart
-Richard Doyle,0.6377541,fineart
-Hendrick Terbrugghen,0.63773805,fineart
-Joe Madureira,0.6377177,special
-Floris van Schooten,0.6376191,fineart
-Jeff Simpson,0.3959046,fineart
-Albert Joseph Moore,0.6374316,fineart
-Arthur Merric Boyd,0.6373228,fineart
-Amadeo de Souza Cardoso,0.5927926,fineart
-Os Gemeos,0.6368859,digipa-high-impact
-Giovanni Boldini,0.6368698,fineart
-Albert Goodwin,0.6368695,fineart
-Hans Eduard von Berlepsch-Valendas,0.61562145,fineart
-Edmond Xavier Kapp,0.5758474,fineart
-François Quesnel,0.6365935,fineart
-Nathan Coley,0.6365817,digipa-high-impact
-Jasmine Becket-Griffith,0.6365083,digipa-high-impact
-Raphaelle Peale,0.6364422,fineart
-Candido Portinari,0.63634276,fineart
-Edward Dugmore,0.63179636,fineart
-Anders Zorn,0.6361722,fineart
-Ed Emshwiller,0.63615763,fineart
-Francis Coates Jones,0.6361159,fineart
-Ernst Haas,0.6361123,digipa-high-impact
-Dirck van Baburen,0.6213001,fineart
-René Lalique,0.63594735,fineart
-Sydney Prior Hall,0.6359345,fineart
-Brad Kunkle,0.5659712,fineart
-Corneille,0.6356381,fineart
-Henry Lamb,0.63560975,fineart
-Dirck Hals,0.63559663,fineart
-Alex Grey,0.62908936,nudity
-Michael Heizer,0.63555753,fineart
-Yiannis Moralis,0.61731136,fineart
-Emily Murray Paterson,0.4392335,fineart
-Georg Friedrich Kersting,0.6256248,fineart
-Frances Hodgkins,0.6352128,fineart
-Charles Cundall,0.6349486,fineart
-Henry Wallis,0.63478243,fineart
-Goro Fujita,0.6346491,cartoon
-Jean-Léon Gérôme,0.5954844,fineart
-August von Pettenkofen,0.60910493,fineart
-Abbott Handerson Thayer,0.63428533,fineart
-Martin John Heade,0.5926603,fineart
-Ellen Jewett,0.63420236,digipa-high-impact
-Hidari Jingorō,0.63388014,fareast
-Taiyō Matsumoto,0.63372946,special
-Emanuel Leutze,0.6007246,fineart
-Adam Martinakis,0.48973057,digipa-med-impact
-Will Eisner,0.63349223,cartoon
-Alexander Stirling Calder,0.6331682,fineart
-Saturno Butto,0.6331184,nudity
-Cecilia Beaux,0.6330725,fineart
-Amandine Van Ray,0.6174208,digipa-high-impact
-Bob Eggleton,0.63277495,digipa-high-impact
-Sherree Valentine Daines,0.63274443,fineart
-Frederick Lord Leighton,0.6299176,fineart
-Daniel Ridgway Knight,0.63251615,fineart
-Gaetano Previati,0.61743724,fineart
-John Berkey,0.63226986,fineart
-Richard Misrach,0.63201725,digipa-high-impact
-Aaron Jasinski,0.57948315,fineart
-"Edward Otho Cresap Ord, II",0.6317712,fineart
-Evelyn De Morgan,0.6317376,fineart
-Noelle Stevenson,0.63159716,digipa-high-impact
-Edward Robert Hughes,0.6315573,fineart
-Allan Ramsay,0.63150716,fineart
-Balthus,0.6314323,scribbles
-Hendrick Cornelisz Vroom,0.63143134,digipa-high-impact
-Ilya Repin,0.6313043,fineart
-George Lambourn,0.6312267,fineart
-Arthur Hughes,0.6310194,fineart
-Antonio J. Manzanedo,0.53841716,fineart
-John Singleton Copley,0.6264835,fineart
-Dennis Miller Bunker,0.63078755,fineart
-Ernie Barnes,0.6307126,cartoon
-Alison Kinnaird,0.6306353,digipa-high-impact
-Alex Toth,0.6305541,digipa-high-impact
-Henry Raeburn,0.6155551,fineart
-Alice Bailly,0.6305177,fineart
-Brian Kesinger,0.63037646,scribbles
-Antoine Blanchard,0.63036835,fineart
-Ron Walotsky,0.63035095,fineart
-Kent Monkman,0.63027304,fineart
-Naomi Okubo,0.5782754,fareast
-Hercules Seghers,0.62957174,fineart
-August Querfurt,0.6295643,fineart
-Samuel Melton Fisher,0.6283333,fineart
-David Burdeny,0.62950236,digipa-high-impact
-George Bain,0.58519644,fineart
-Peter Holme III,0.62938106,fineart
-Grayson Perry,0.62928164,digipa-high-impact
-Chris Claremont,0.6292076,digipa-high-impact
-Dod Procter,0.6291759,fineart
-Huang Tingjian,0.6290358,fareast
-Dorothea Warren O'Hara,0.6290113,fineart
-Ivan Albright,0.6289551,fineart
-Hubert von Herkomer,0.6288955,fineart
-Barbara Nessim,0.60589516,digipa-high-impact
-Henry Scott Tuke,0.6286309,fineart
-Ditlev Blunck,0.6282925,fineart
-Sven Nordqvist,0.62828535,fineart
-Lee Madgwick,0.6281731,fineart
-Hubert van Eyck,0.6281529,fineart
-Edmond Bille,0.62339354,fineart
-Ejnar Nielsen,0.6280824,fineart
-Arturo Souto,0.6280583,fineart
-Jean Giraud,0.6279888,fineart
-Storm Thorgerson,0.6277394,digipa-high-impact
-Ed Benedict,0.62764007,digipa-high-impact
-Christoffer Wilhelm Eckersberg,0.6014842,fineart
-Clarence Holbrook Carter,0.5514105,fineart
-Dorothy Lockwood,0.6273235,fineart
-John Singer Sargent,0.6272487,fineart
-Brigid Derham,0.6270125,digipa-high-impact
-Henricus Hondius II,0.6268505,fineart
-Gertrude Harvey,0.5903887,fineart
-Grant Wood,0.6266253,fineart
-Fyodor Vasilyev,0.5234919,digipa-med-impact
-Cagnaccio di San Pietro,0.6261671,fineart
-Doris Boulton-Maude,0.62593174,fineart
-Adolf Hirémy-Hirschl,0.5946784,fineart
-Harold von Schmidt,0.6256755,fineart
-Martine Johanna,0.6256161,digipa-high-impact
-Gerald Kelly,0.5579602,digipa-high-impact
-Ub Iwerks,0.625396,cartoon
-Dirck van der Lisse,0.6253871,fineart
-Edouard Riou,0.6250113,fineart
-Ilya Yefimovich Repin,0.62491584,fineart
-Martin Johnson Heade,0.59421235,fineart
-Afarin Sajedi,0.62475824,scribbles
-Alfred Thompson Bricher,0.6247515,fineart
-Edwin G. Lucas,0.5553578,fineart
-Georges Emile Lebacq,0.56175387,fineart
-Francis Davis Millet,0.5988504,fineart
-Bill Sienkiewicz,0.6125557,digipa-high-impact
-Giocondo Albertolli,0.62441677,fineart
-Victor Nizovtsev,0.6242258,fineart
-Squeak Carnwath,0.62416434,digipa-high-impact
-Bill Viola,0.62409425,digipa-high-impact
-Annie Abernethie Pirie Quibell,0.6240767,fineart
-Jason Edmiston,0.62405366,fineart
-Al Capp,0.6239494,fineart
-Kobayashi Kiyochika,0.6239368,anime
-Albert Anker,0.62389827,fineart
-Iain Faulkner,0.62376785,fineart
-Todd Schorr,0.6237408,fineart
-Charles Ginner,0.62370133,fineart
-Emile Auguste Carolus-Duran,0.62353987,fineart
-John Philip Falter,0.623418,cartoon
-Chizuko Yoshida,0.6233001,fareast
-Anna Dittmann,0.62327325,cartoon
-Henry Snell Gamley,0.62319934,fineart
-Edmund Charles Tarbell,0.6230626,fineart
-Rob Gonsalves,0.62298363,fineart
-Gladys Dawson,0.6228511,fineart
-Tomma Abts,0.61153626,fineart
-Kate Beaton,0.53993124,digipa-high-impact
-Gustave Buchet,0.62243867,fineart
-Gareth Pugh,0.6223551,digipa-high-impact
-Caspar van Wittel,0.57871693,fineart
-Anton Otto Fischer,0.6222941,fineart
-Albert Guillaume,0.56529653,fineart
-Felix Octavius Carr Darley,0.62223387,fineart
-Bernard van Orley,0.62221646,fineart
-Edward John Poynter,0.60147405,fineart
-Walter Percy Day,0.62207425,fineart
-Franciszek Starowieyski,0.5709621,fineart
-Auguste Baud-Bovy,0.6219854,fineart
-Chris LaBrooy,0.45497298,digipa-low-impact
-Abraham de Vries,0.5859101,fineart
-Antoni Gaudi,0.62162614,fineart
-Joe Jusko,0.62156093,digipa-high-impact
-Lynda Barry,0.62154603,digipa-high-impact
-Michal Karcz,0.62154436,digipa-high-impact
-Raymond Briggs,0.62150294,fineart
-Herbert James Gunn,0.6210927,fineart
-Dwight William Tryon,0.620984,fineart
-Paul Henry,0.5752968,fineart
-Helio Oiticica,0.6203739,digipa-high-impact
-Sebastian Errazuriz,0.62036186,digipa-high-impact
-Lucian Freud,0.6203146,nudity
-Frank Auerbach,0.6201102,weird
-Andre-Charles Boulle,0.6200789,fineart
-Franz Fedier,0.5669752,fineart
-Austin Briggs,0.57675314,fineart
-Hugo Sánchez Bonilla,0.61978436,digipa-high-impact
-Caroline Chariot-Dayez,0.6195682,digipa-high-impact
-Bill Ward,0.61953044,digipa-high-impact
-Charles Bird King,0.6194487,fineart
-Adrian Ghenie,0.6193521,digipa-high-impact
-Agnes Cecile,0.6192814,digipa-high-impact
-Augustus John,0.6191995,fineart
-Jeffrey T. Larson,0.61913544,fineart
-Alexis Simon Belle,0.3190395,digipa-low-impact
-Jean-Baptiste Monge,0.5758537,fineart
-Adolf Bierbrauer,0.56129396,fineart
-Ayako Rokkaku,0.61891204,fareast
-Lisa Keene,0.54570895,digipa-high-impact
-Edmond Aman-Jean,0.57168096,fineart
-Marc Davis,0.61837333,cartoon
-Cerith Wyn Evans,0.61829346,digipa-high-impact
-George Wyllie,0.61829203,fineart
-George Luks,0.6182724,fineart
-William-Adolphe Bouguereau,0.618265,c
-Grigoriy Myasoyedov,0.61801606,fineart
-Hashimoto Gahō,0.61795104,fineart
-Charles Ragland Bunnell,0.61772746,fineart
-Ambrose McCarthy Patterson,0.61764514,fineart
-Bill Brauer,0.5824066,fineart
-Mikko Lagerstedt,0.591015,digipa-high-impact
-Koson Ohara,0.53635323,fineart
-Evaristo Baschenis,0.5857368,fineart
-Martin Ansin,0.5294119,fineart
-Cory Loftis,0.6168619,cartoon
-Joseph Stella,0.6166778,fineart
-André Pijet,0.5768274,fineart
-Jeff Wall,0.6162895,digipa-high-impact
-Eleanor Layfield Davis,0.6158844,fineart
-Saul Tepper,0.61579347,fineart
-Alex Hirsch,0.6157384,cartoon
-Alexandre Falguière,0.55011404,fineart
-Malcolm Liepke,0.6155646,fineart
-Georg Friedrich Schmidt,0.60364646,fineart
-Hendrik Kerstens,0.55099905,digipa-high-impact
-Félix Bódog Widder,0.6153954,fineart
-Marie Guillemine Benoist,0.61532974,fineart
-Kelly Mckernan,0.60047054,digipa-high-impact
-Ignacio Zuloaga,0.6151608,fineart
-Hubert van Ravesteyn,0.61489964,fineart
-Angus McKie,0.61487424,digipa-high-impact
-Colin Campbell Cooper,0.6147882,fineart
-Pieter Aertsen,0.61454165,fineart
-Jan Brett,0.6144608,fineart
-Kazuo Koike,0.61438507,fineart
-Edith Grace Wheatley,0.61428297,fineart
-Ogawa Kazumasa,0.61427975,fareast
-Giovanni Battista Cipriani,0.6022825,fineart
-André Bauchant,0.57124996,fineart
-George Abe,0.6140447,digipa-high-impact
-Georges Lemmen,0.6139967,scribbles
-Frank Leonard Brooks,0.6139327,fineart
-Gai Qi,0.613744,anime
-Frank Gehry,0.6136776,digipa-high-impact
-Anton Domenico Gabbiani,0.55471313,fineart
-Cassandra Austen,0.6135781,fineart
-Paul Gustav Fischer,0.613273,fineart
-Emiliano Di Cavalcanti,0.6131207,fineart
-Meryl McMaster,0.6129995,digipa-high-impact
-Domenico di Pace Beccafumi,0.6129922,fineart
-Ludwig Mies van der Rohe,0.6126692,fineart
-Étienne-Louis Boullée,0.6126158,fineart
-Dali,0.5928694,nudity
-Shinji Aramaki,0.61246127,anime
-Giovanni Fattori,0.59544694,fineart
-Bapu,0.6122084,c
-Raphael Lacoste,0.5539114,digipa-high-impact
-Scarlett Hooft Graafland,0.6119631,digipa-high-impact
-Rene Laloux,0.61190474,fineart
-Julius Horsthuis,0.59037095,fineart
-Gerald van Honthorst,0.6115939,fineart
-Dino Valls,0.611533,fineart
-Tony DiTerlizzi,0.6114657,cartoon
-Michael Cheval,0.61138546,anime
-Charles Schulz,0.6113759,digipa-high-impact
-Alvar Aalto,0.61122143,digipa-high-impact
-Gu Kaizhi,0.6110798,fareast
-Eugene von Guerard,0.6109776,fineart
-John Cassaday,0.610949,fineart
-Elizabeth Forbes,0.61092335,fineart
-Edmund Greacen,0.6109115,fineart
-Eugène Burnand,0.6107876,fineart
-Boris Grigoriev,0.6107853,scribbles
-Norman Rockwell,0.6107638,fineart
-Barthélemy Menn,0.61064315,fineart
-George Biddle,0.61058354,fineart
-Edgar Ainsworth,0.5525424,digipa-high-impact
-Alfred Leyman,0.5887217,fineart
-Tex Avery,0.6104007,cartoon
-Beatrice Ethel Lithiby,0.61030364,fineart
-Grace Pailthorpe,0.61026484,digipa-high-impact
-Brian Oldham,0.396231,digipa-low-impact
-Android Jones,0.61023116,fareast
-François Girardon,0.5830649,fineart
-Ib Eisner,0.61016303,digipa-high-impact
-Armand Point,0.610156,fineart
-Henri Alphonse Barnoin,0.59465057,fineart
-Jean Marc Nattier,0.60987425,fineart
-Francisco de Holanda,0.6091294,fineart
-Marco Mazzoni,0.60970783,fineart
-Esaias Boursse,0.6093308,fineart
-Alexander Deyneka,0.55000365,fineart
-John Totleben,0.60883725,fineart
-Al Feldstein,0.6087723,fineart
-Adam Hughes,0.60854626,anime
-Ernest Zobole,0.6085073,fineart
-Alex Gross,0.60837066,digipa-high-impact
-George Jamesone,0.6079673,fineart
-Frank Lloyd Wright,0.60793245,scribbles
-Brooke DiDonato,0.47680336,digipa-med-impact
-Hans Gude,0.60780364,fineart
-Ethel Schwabacher,0.60748273,fineart
-Gladys Kathleen Bell,0.60747695,fineart
-Adolf Fényes,0.54192233,fineart
-Carel Willink,0.58120143,fineart
-George Henry,0.6070727,digipa-high-impact
-Ronald Balfour,0.60697085,fineart
-Elsie Dalton Hewland,0.6067718,digipa-high-impact
-Alex Maleev,0.6067118,fineart
-Anish Kapoor,0.6067015,digipa-high-impact
-Aleksandr Ivanovich Laktionov,0.606544,fineart
-Kim Keever,0.6037775,digipa-high-impact
-Aleksi Briclot,0.46056762,fineart
-Raymond Leech,0.6062721,fineart
-Richard Eurich,0.6062664,fineart
-Phil Jimenez,0.60625625,cartoon
-Gao Cen,0.60618126,nudity
-Mike Deodato,0.6061201,cartoon
-Charles Haslewood Shannon,0.6060581,fineart
-Alexandre Jacovleff,0.3991747,digipa-low-impact
-André Beauneveu,0.584062,fineart
-Hiroshi Honda,0.60507596,digipa-high-impact
-Charles Joshua Chaplin,0.60498774,fineart
-Domenico Zampieri,0.6049726,fineart
-Gusukuma Seihō,0.60479784,fareast
-Nikolina Petolas,0.46318632,digipa-low-impact
-Casey Weldon,0.6047672,cartoon
-Elmyr de Hory,0.6046374,fineart
-Nan Goldin,0.6046119,digipa-high-impact
-Charles McAuley,0.6045995,fineart
-Archibald Skirving,0.6044234,fineart
-Elizabeth York Brunton,0.6043737,fineart
-Dugald Sutherland MacColl,0.6042907,fineart
-Titian,0.60426414,fineart
-Ignacy Witkiewicz,0.6042259,fineart
-Allie Brosh,0.6042061,digipa-high-impact
-H.P. Lovecraft,0.6039597,digipa-high-impact
-Andrée Ruellan,0.60395086,fineart
-Ralph McQuarrie,0.60380936,fineart
-Mead Schaeffer,0.6036558,fineart
-Henri-Julien Dumont,0.571257,fineart
-Kieron Gillen,0.6035093,fineart
-Maginel Wright Enright Barney,0.6034306,nudity
-Vincent Di Fate,0.6034131,fineart
-Briton Rivière,0.6032918,fineart
-Hajime Sorayama,0.60325956,nudity
-Béla Czóbel,0.6031023,fineart
-Edmund Blampied,0.603072,fineart
-E. Simms Campbell,0.6030443,fineart
-Hisui Sugiura,0.603034,fareast
-Alan Davis,0.6029676,fineart
-Glen Keane,0.60287905,cartoon
-Frank Holl,0.6027312,fineart
-Abbott Fuller Graves,0.6025608,fineart
-Albert Servaes,0.60250103,black-white
-Hovsep Pushman,0.5937487,fineart
-Brian M. Viveros,0.60233414,fineart
-Charles Fremont Conner,0.6023278,fineart
-Francesco Furini,0.6022654,digipa-high-impact
-Camille-Pierre Pambu Bodo,0.60191673,fineart
-Yasushi Nirasawa,0.6016714,nudity
-Charles Uzzell-Edwards,0.6014683,fineart
-Abram Efimovich Arkhipov,0.60128385,fineart
-Hedda Sterne,0.6011857,digipa-high-impact
-Ben Aronson,0.6011548,fineart
-Frank Frazetta,0.551121,nudity
-Elizabeth Durack,0.6010842,fineart
-Ian Miller,0.42153555,fareast
-Charlie Bowater,0.4410439,special
-Michael Carson,0.60039437,fineart
-Walter Langley,0.6002273,fineart
-Cornelis Anthonisz,0.6001956,fineart
-Dorothy Elizabeth Bradford,0.6001929,fineart
-J.C. Leyendecker,0.5791972,fineart
-Willem van Haecht,0.59990716,fineart
-Anna and Elena Balbusso,0.59955937,digipa-low-impact
-Harrison Fisher,0.59952044,fineart
-Bill Medcalf,0.59950054,fineart
-Edward Arthur Walton,0.59945667,fineart
-Alois Arnegger,0.5991994,fineart
-Ray Caesar,0.59902894,digipa-high-impact
-Karen Wallis,0.5990094,fineart
-Emmanuel Shiu,0.51082766,digipa-med-impact
-Thomas Struth,0.5988324,digipa-high-impact
-Barbara Longhi,0.5985706,fineart
-Richard Deacon,0.59851056,fineart
-Constantin Hansen,0.5984213,fineart
-Harold Shapinsky,0.5984175,fineart
-George Dionysus Ehret,0.5983857,fineart
-Doug Wildey,0.5983639,digipa-high-impact
-Fernand Toussaint,0.5982694,fineart
-Horatio Nelson Poole,0.5982614,fineart
-Caesar van Everdingen,0.5981566,fineart
-Eva Gonzalès,0.5981396,fineart
-Franz Vohwinkel,0.5448179,fineart
-Margaret Mee,0.5979592,fineart
-Francis Focer Brown,0.59779185,fineart
-Henry Moore,0.59767926,nudity
-Scott Listfield,0.58795893,fineart
-Nikolai Ge,0.5973643,fineart
-Jacek Yerka,0.58198756,fineart
-Margaret Brundage,0.5969077,fineart
-JC Leyendecker,0.5620243,fineart
-Ben Templesmith,0.5498991,digipa-high-impact
-Armin Hansen,0.59669334,anime
-Jean-Louis Prevost,0.5966897,fineart
-Daphne Allen,0.59666026,fineart
-Franz Karl Basler-Kopp,0.59663445,fineart
-"Henry Ives Cobb, Jr.",0.596385,fineart
-Michael Sowa,0.546285,fineart
-Anna Füssli,0.59600973,fineart
-György Rózsahegyi,0.59580946,fineart
-Luis Royo,0.59566617,fineart
-Émile Gallé,0.5955559,fineart
-Antonio Mora,0.5334297,digipa-high-impact
-Edward P. Beard Jr.,0.59543866,fineart
-Jessica Rossier,0.54958373,special
-André Thomkins,0.5343785,digipa-high-impact
-David Macbeth Sutherland,0.5949968,fineart
-Charles Liu,0.5949787,digipa-high-impact
-Edi Rama,0.5949226,digipa-high-impact
-Jacques Le Moyne,0.5948843,fineart
-Egbert van der Poel,0.59488285,fineart
-Georg Jensen,0.594782,digipa-high-impact
-Anne Sudworth,0.5947539,fineart
-Jan Pietersz Saenredam,0.59472525,fineart
-Henryk Stażewski,0.5945748,fineart
-André François,0.58402044,fineart
-Alexander Runciman,0.5944449,digipa-high-impact
-Thomas Kinkade,0.594391,fineart
-Robert Williams,0.5567989,digipa-high-impact
-George Gardner Symons,0.57431924,fineart
-D. Alexander Gregory,0.5334464,fineart
-Gerald Brom,0.52473724,fineart
-Robert Hagan,0.59406,fineart
-Ernest Crichlow,0.5940588,fineart
-Viviane Sassen,0.5939927,digipa-high-impact
-Enrique Simonet,0.5937546,fineart
-Esther Blaikie MacKinnon,0.593747,digipa-high-impact
-Jeff Kinney,0.59372896,scribbles
-Igor Morski,0.5936732,digipa-high-impact
-John Currin,0.5936216,fineart
-Bob Ringwood,0.5935273,digipa-high-impact
-Jordan Grimmer,0.44948143,digipa-low-impact
-François Barraud,0.5933471,fineart
-Helen Binyon,0.59331006,digipa-high-impact
-Brenda Chamberlain,0.5932333,fineart
-Candido Bido,0.59310603,fineart
-Abraham Storck,0.5929502,fineart
-Raphael,0.59278333,fineart
-Larry Sultan,0.59273386,digipa-high-impact
-Agostino Tassi,0.59265685,fineart
-Alexander V. Kuprin,0.5925917,fineart
-Frans Koppelaar,0.5658725,fineart
-Richard Corben,0.59251785,fineart
-David Gilmour Blythe,0.5924247,digipa-high-impact
-František Kaván,0.5924211,fineart
-Rob Liefeld,0.5921167,fineart
-Ernő Rubik,0.5920297,fineart
-Byeon Sang-byeok,0.59200096,fareast
-Johfra Bosschart,0.5919376,fineart
-Emil Lindenfeld,0.5761086,fineart
-Howard Mehring,0.5917471,fineart
-Gwenda Morgan,0.5915571,digipa-high-impact
-Henry Asencio,0.5915404,fineart
-"George Barret, Sr.",0.5914306,fineart
-Andrew Ferez,0.5911011,fineart
-Ed Brubaker,0.5910869,digipa-high-impact
-George Reid,0.59095883,digipa-high-impact
-Derek Gores,0.51769906,digipa-med-impact
-Charles Rollier,0.5539186,fineart
-Terry Oakes,0.590443,fineart
-Thomas Blackshear,0.5078616,fineart
-Albert Benois,0.5902705,nudity
-Krenz Cushart,0.59026587,special
-Jeff Koons,0.5902637,digipa-high-impact
-Akihiko Yoshida,0.5901294,special
-Anja Percival,0.45039332,digipa-low-impact
-Eduard von Steinle,0.59008586,fineart
-Alex Russell Flint,0.5900352,digipa-high-impact
-Edward Okuń,0.5897297,fineart
-Emma Lampert Cooper,0.5894849,fineart
-Stuart Haygarth,0.58132994,digipa-high-impact
-George French Angas,0.5434376,fineart
-Edmund F. Ward,0.5892848,fineart
-Eleanor Vere Boyle,0.58925456,digipa-high-impact
-Evelyn Cheston,0.58924586,fineart
-Edwin Dickinson,0.58921975,digipa-high-impact
-Christophe Vacher,0.47325426,fineart
-Anne Dewailly,0.58905107,fineart
-Gertrude Greene,0.5862596,digipa-high-impact
-Boris Groh,0.5888809,digipa-high-impact
-Douglas Smith,0.588804,digipa-high-impact
-Ian Hamilton Finlay,0.5887713,fineart
-Derek Jarman,0.5887292,digipa-high-impact
-Archibald Thorburn,0.5882001,fineart
-Gillis d'Hondecoeter,0.58813053,fineart
-I Ketut Soki,0.58801544,digipa-high-impact
-Alex Schomburg,0.46614102,digipa-low-impact
-Bastien L. Deharme,0.583349,special
-František Jakub Prokyš,0.58782333,fineart
-Jesper Ejsing,0.58782053,fineart
-Odd Nerdrum,0.53551745,digipa-high-impact
-Tom Lovell,0.5877577,fineart
-Ayami Kojima,0.5877416,fineart
-Peter Sculthorpe,0.5875696,fineart
-Bernard D’Andrea,0.5874042,fineart
-Denis Eden,0.58739066,digipa-high-impact
-Alfons Walde,0.58728385,fineart
-Jovana Rikalo,0.47006977,digipa-low-impact
-Franklin Booth,0.5870834,fineart
-Mat Collishaw,0.5870676,digipa-high-impact
-Joseph Lorusso,0.586858,fineart
-Helen Stevenson,0.454647,digipa-low-impact
-Delaunay,0.58657396,fineart
-H.R. Millar,0.58655745,fineart
-E. Charlton Fortune,0.586376,fineart
-Alson Skinner Clark,0.58631575,fineart
-Stan And Jan Berenstain,0.5862361,digipa-high-impact
-Howard Lyon,0.5862271,fineart
-John Blanche,0.586182,fineart
-Bernardo Cavallino,0.5858575,fineart
-Tomasz Alen Kopera,0.5216588,fineart
-Peter Gric,0.58583695,fineart
-Guo Pei,0.5857794,fareast
-James Turrell,0.5853901,digipa-high-impact
-Alexandr Averin,0.58533764,fineart
-Bertalan Székely,0.5548113,digipa-high-impact
-Brothers Hildebrandt,0.5850233,fineart
-Ed Roth,0.5849769,digipa-high-impact
-Enki Bilal,0.58492255,fineart
-Alan Lee,0.5848701,fineart
-Charles H. Woodbury,0.5848688,fineart
-André Charles Biéler,0.5847876,fineart
-Annie Rose Laing,0.5597829,fineart
-Matt Fraction,0.58463776,cartoon
-Charles Alston,0.58453286,fineart
-Frank Xavier Leyendecker,0.545465,fineart
-Alfred Richard Gurrey,0.584306,fineart
-Dan Mumford,0.5843051,cartoon
-Francisco Martín,0.5842005,fineart
-Alvaro Siza,0.58406967,digipa-high-impact
-Frank J. Girardin,0.5839858,fineart
-Henry Carr,0.58397424,digipa-high-impact
-Charles Furneaux,0.58394694,fineart
-Daniel F. Gerhartz,0.58389103,fineart
-Gilberto Soren Zaragoza,0.5448442,fineart
-Bart Sears,0.5838427,cartoon
-Allison Bechdel,0.58383805,digipa-high-impact
-Frank O'Meara,0.5837992,fineart
-Charles Codman,0.5836579,fineart
-Francisco Zúñiga,0.58359766,fineart
-Vladimir Kush,0.49075457,fineart
-Arnold Mesches,0.5834257,fineart
-Frank McKelvey,0.5831641,fineart
-Allen Butler Talcott,0.5830911,fineart
-Eric Zener,0.58300316,fineart
-Noah Bradley,0.44176096,digipa-low-impact
-Robert Childress,0.58289623,fineart
-Frances C. Fairman,0.5827239,fineart
-Kathryn Morris Trotter,0.465856,digipa-low-impact
-Everett Raymond Kinstler,0.5824819,fineart
-Edward Mitchell Bannister,0.5804899,fineart
-"George Barret, Jr.",0.5823128,fineart
-Greg Hildebrandt,0.4271311,fineart
-Anka Zhuravleva,0.5822078,digipa-high-impact
-Rolf Armstrong,0.58217514,fineart
-Eric Wallis,0.58191466,fineart
-Clemens Ascher,0.5480207,digipa-high-impact
-Hugo Kārlis Grotuss,0.5818766,fineart
-Albert Paris Gütersloh,0.5817827,fineart
-Hilda May Gordon,0.5817449,fineart
-Hendrik Martenszoon Sorgh,0.5817126,fineart
-Pipilotti Rist,0.5816868,digipa-high-impact
-Hiroyuki Tajima,0.5816242,fareast
-Igor Zenin,0.58159757,digipa-high-impact
-Genevieve Springston Lynch,0.4979099,digipa-med-impact
-Dan Witz,0.44476372,fineart
-David Roberts,0.5255326,fineart
-Frieke Janssens,0.5706969,digipa-high-impact
-Arnold Schoenberg,0.56520367,fineart
-Inoue Naohisa,0.5809933,fareast
-Elfriede Lohse-Wächtler,0.58097905,fineart
-Alex Ross,0.42460668,digipa-low-impact
-Robert Irwin,0.58078,c
-Charles Angrand,0.58077514,fineart
-Anne Nasmyth,0.54221964,fineart
-Henri Bellechose,0.5773891,fineart
-De Hirsh Margules,0.58059025,fineart
-Hiromitsu Takahashi,0.5805599,fareast
-Ilya Kuvshinov,0.5805521,special
-Cassius Marcellus Coolidge,0.5805516,c
-Dorothy Burroughes,0.5804835,fineart
-Emanuel de Witte,0.58027405,fineart
-George Herbert Baker,0.5799624,digipa-high-impact
-Cheng Zhengkui,0.57990086,fareast
-Bernard Fleetwood-Walker,0.57987773,digipa-high-impact
-Philippe Parreno,0.57985014,digipa-high-impact
-Thornton Oakley,0.57969713,fineart
-Greg Rutkowski,0.5203395,special
-Ike no Taiga,0.5795857,anime
-Eduardo Lefebvre Scovell,0.5795808,fineart
-Adolfo Müller-Ury,0.57944727,fineart
-Patrick Woodroffe,0.5228063,fineart
-Wim Crouwel,0.57933235,digipa-high-impact
-Colijn de Coter,0.5792779,fineart
-François Boquet,0.57924724,fineart
-Gerbrand van den Eeckhout,0.57897866,fineart
-Eugenio Granell,0.5392264,fineart
-Kuang Hong,0.5782304,digipa-high-impact
-Justin Gerard,0.46685404,fineart
-Tokujin Yoshioka,0.5779153,digipa-high-impact
-Alan Bean,0.57788515,fineart
-Ernest Biéler,0.5778079,fineart
-Martin Deschambault,0.44401115,digipa-low-impact
-Anna Boch,0.577735,fineart
-Jack Davis,0.5775291,fineart
-Félix Labisse,0.5775142,fineart
-Greg Simkins,0.5679761,fineart
-David Lynch,0.57751054,digipa-low-impact
-Eizō Katō,0.5774127,digipa-high-impact
-Grethe Jürgens,0.5773412,digipa-high-impact
-Heinrich Bichler,0.5770147,fineart
-Barbara Nasmyth,0.5446056,fineart
-Domenico Induno,0.5583946,fineart
-Gustave Baumann,0.5607866,fineart
-Mike Mayhew,0.5765857,cartoon
-Delmer J. Yoakum,0.576538,fineart
-Aykut Aydogdu,0.43111503,digipa-low-impact
-George Barker,0.5763551,fineart
-Ernő Grünbaum,0.57634187,fineart
-Eliseu Visconti,0.5763241,fineart
-Esao Andrews,0.5761547,fineart
-JennyBird Alcantara,0.49165845,digipa-med-impact
-Joan Tuset,0.5761051,fineart
-Angela Barrett,0.55976534,digipa-high-impact
-Syd Mead,0.5758396,fineart
-Ignacio Bazan-Lazcano,0.5757512,fineart
-Franciszek Kostrzewski,0.57570386,fineart
-Eero Järnefelt,0.57540673,fineart
-Loretta Lux,0.56217635,digipa-high-impact
-Gaudi,0.57519895,fineart
-Charles Gleyre,0.57490873,fineart
-Antoine Verney-Carron,0.56386137,fineart
-Albert Edelfelt,0.57466495,fineart
-Fabian Perez,0.57444525,fineart
-Kevin Sloan,0.5737548,fineart
-Stanislav Poltavsky,0.57434607,fineart
-Abraham Hondius,0.574326,fineart
-Tadao Ando,0.57429105,fareast
-Fyodor Slavyansky,0.49796474,digipa-med-impact
-David Brewster,0.57385933,digipa-high-impact
-Cliff Chiang,0.57375133,digipa-high-impact
-Drew Struzan,0.5317983,digipa-high-impact
-Henry O. Tanner,0.5736586,fineart
-Alberto Sughi,0.5736495,fineart
-Albert J. Welti,0.5736257,fineart
-Charles Mahoney,0.5735923,digipa-high-impact
-Exekias,0.5734506,fineart
-Felipe Seade,0.57342744,digipa-high-impact
-Henriette Wyeth,0.57330644,digipa-high-impact
-Harold Sandys Williamson,0.5443646,fineart
-Eddie Campbell,0.57329535,digipa-high-impact
-Gao Fenghan,0.5732926,fareast
-Cynthia Sheppard,0.51099646,fineart
-Henriette Grindat,0.573179,fineart
-Yasutomo Oka,0.5731342,fareast
-Celia Frances Bedford,0.57313216,fineart
-Les Edwards,0.42068473,fineart
-Edwin Deakin,0.5031717,fineart
-Eero Saarinen,0.5725142,digipa-high-impact
-Franciszek Smuglewicz,0.5722554,fineart
-Doris Blair,0.57221186,fineart
-Seb Mckinnon,0.51721895,digipa-med-impact
-Gregorio Lazzarini,0.57204294,fineart
-Gerard Sekoto,0.5719927,fineart
-Francis Ernest Jackson,0.5506009,fineart
-Simon Birch,0.57171595,digipa-high-impact
-Bayard Wu,0.57171166,fineart
-François Clouet,0.57162094,fineart
-Christopher Wren,0.5715372,fineart
-Evgeny Lushpin,0.5714827,special
-Art Green,0.5714495,digipa-high-impact
-Amy Judd,0.57142305,digipa-high-impact
-Art Brenner,0.42619684,digipa-low-impact
-Travis Louie,0.43916368,digipa-low-impact
-James Jean,0.5457318,digipa-high-impact
-Ewald Rübsamen,0.57083976,fineart
-Donato Giancola,0.57052535,fineart
-Carl Arnold Gonzenbach,0.5703996,fineart
-Bastien Lecouffe-Deharme,0.5201288,fineart
-Howard Chandler Christy,0.5702813,nudity
-Dean Cornwell,0.56977296,fineart
-Don Maitz,0.4743015,fineart
-James Montgomery Flagg,0.56974065,fineart
-Andreas Levers,0.42125136,digipa-low-impact
-Edgar Schofield Baum,0.56965977,fineart
-Alan Parry,0.5694952,digipa-high-impact
-An Zhengwen,0.56942475,fareast
-Alayna Lemmer,0.48293802,fineart
-Edward Marshall Boehm,0.5530143,fineart
-Henri Biva,0.54013556,nudity
-Fiona Rae,0.4646715,digipa-low-impact
-Elizabeth Jane Lloyd,0.5688463,digipa-high-impact
-Franklin Carmichael,0.5687844,digipa-high-impact
-Dionisius,0.56875896,fineart
-Edwin Georgi,0.56868523,fineart
-Jenny Saville,0.5686633,fineart
-Ernest Hébert,0.56859314,fineart
-Stephan Martiniere,0.56856346,digipa-high-impact
-Huang Binhong,0.56841767,fineart
-August Lemmer,0.5683548,fineart
-Camille Bouvagne,0.5678048,fineart
-Olga Skomorokhova,0.39401102,digipa-low-impact
-Sacha Goldberger,0.5675477,digipa-high-impact
-Hilda Annetta Walker,0.5675261,digipa-high-impact
-Harvey Pratt,0.51314723,digipa-med-impact
-Jean Bourdichon,0.5670543,fineart
-Noriyoshi Ohrai,0.56690073,fineart
-Kadir Nelson,0.5669006,n
-Ilya Ostroukhov,0.5668801,fineart
-Eugène Brands,0.56681967,fineart
-Achille Leonardi,0.56674325,fineart
-Franz Cižek,0.56670356,fineart
-George Paul Chalmers,0.5665988,digipa-high-impact
-Serge Marshennikov,0.5665971,digipa-high-impact
-Mike Worrall,0.56641084,fineart
-Dirck van Delen,0.5661764,fineart
-Peter Andrew Jones,0.5661655,fineart
-Rafael Albuquerque,0.56541103,fineart
-Daniel Buren,0.5654043,fineart
-Giuseppe Grisoni,0.5432699,fineart
-George Fiddes Watt,0.55861616,fineart
-Stan Lee,0.5651268,digipa-high-impact
-Dorning Rasbotham,0.56511617,fineart
-Albert Lynch,0.56497896,fineart
-Lorenz Hideyoshi,0.56494075,fineart
-Fenghua Zhong,0.56492203,fareast
-Caroline Lucy Scott,0.49190843,digipa-med-impact
-Victoria Crowe,0.5647996,digipa-high-impact
-Hasegawa Settan,0.5647092,fareast
-Dennis H. Farber,0.56453323,digipa-high-impact
-Dick Bickenbach,0.5644289,fineart
-Art Frahm,0.56439924,fineart
-Edith Edmonds,0.5643151,fineart
-Alfred Heber Hutty,0.56419206,fineart
-Henry Tonks,0.56410825,fineart
-Peter Howson,0.5640759,fineart
-Albert Dorne,0.56395364,fineart
-Arthur Adams,0.5639404,fineart
-Bernt Tunold,0.56383425,digipa-high-impact
-Gianluca Foli,0.5637317,digipa-high-impact
-Vittorio Matteo Corcos,0.5636767,fineart
-Béla Iványi-Grünwald,0.56355745,nudity
-Feng Zhu,0.5634973,fineart
-Sam Kieth,0.47251505,digipa-low-impact
-Charles Crodel,0.5633834,fineart
-Elsie Henderson,0.56310076,digipa-high-impact
-George Earl Ortman,0.56295705,fineart
-Tari Márk Dávid,0.562937,fineart
-Betty Merken,0.56281745,digipa-high-impact
-Cecile Walton,0.46672013,digipa-low-impact
-Bracha L. Ettinger,0.56237936,fineart
-Ken Fairclough,0.56230986,digipa-high-impact
-Phil Koch,0.56224954,digipa-high-impact
-George Pirie,0.56213045,digipa-high-impact
-Chad Knight,0.56194013,digipa-high-impact
-Béla Kondor,0.5427164,digipa-high-impact
-Barclay Shaw,0.53689134,digipa-high-impact
-Tim Hildebrandt,0.47194147,fineart
-Hermann Rüdisühli,0.56104004,digipa-high-impact
-Ian McQue,0.5342066,digipa-high-impact
-Yanjun Cheng,0.5607171,fineart
-Heinrich Hofmann,0.56060636,fineart
-Henry Raleigh,0.5605958,fineart
-Ernest Buckmaster,0.5605704,fineart
-Charles Ricketts,0.56055415,fineart
-Juergen Teller,0.56051147,digipa-high-impact
-Auguste Mambour,0.5604873,fineart
-Sean Yoro,0.5601486,digipa-high-impact
-Sheilah Beckett,0.55995446,digipa-high-impact
-Eugene Tertychnyi,0.5598978,fineart
-Dr. Seuss,0.5597466,c
-Adolf Wölfli,0.5372333,digipa-high-impact
-Enrique Tábara,0.559323,fineart
-Dionisio Baixeras Verdaguer,0.5590695,fineart
-Aleksander Gierymski,0.5590013,fineart
-Augustus Dunbier,0.55872476,fineart
-Adolf Born,0.55848217,fineart
-Chris Turnham,0.5584234,digipa-high-impact
-James C Christensen,0.55837405,fineart
-Daphne Fedarb,0.5582459,digipa-high-impact
-Andre Kohn,0.5581832,special
-Ron Mueck,0.5581811,nudity
-Glenn Fabry,0.55786383,fineart
-Elizabeth Polunin,0.5578102,digipa-high-impact
-Charles S. Kaelin,0.5577954,fineart
-Arthur Radebaugh,0.5577016,fineart
-Ai Yazawa,0.55768114,fareast
-Charles Roka,0.55762553,fineart
-Ai Weiwei,0.5576034,digipa-high-impact
-Dorothy Bradford,0.55760014,digipa-high-impact
-Alfred Leslie,0.557555,fineart
-Heinrich Herzig,0.5574423,fineart
-Eliot Hodgkin,0.55740607,digipa-high-impact
-Albert Kotin,0.55737317,fineart
-Carlo Carlone,0.55729353,fineart
-Chen Rong,0.5571221,fineart
-Ikuo Hirayama,0.5570225,digipa-high-impact
-Edward Corbett,0.55701995,nudity
-Eugeniusz Żak,0.556925,nudity
-Ettore Tito,0.556875,fineart
-Helene Knoop,0.5567731,fineart
-Amanda Sage,0.37731662,fareast
-Annick Bouvattier,0.54647046,fineart
-Harvey Dunn,0.55663586,fineart
-Hans Sandreuter,0.5562575,digipa-high-impact
-Ruan Jia,0.5398549,special
-Anton Räderscheidt,0.55618906,fineart
-Tyler Shields,0.4081434,digipa-low-impact
-Darek Zabrocki,0.49975997,digipa-med-impact
-Frank Montague Moore,0.5556432,fineart
-Greg Staples,0.5555332,fineart
-Endre Bálint,0.5553731,fineart
-Augustus Vincent Tack,0.5136602,fineart
-Marc Simonetti,0.48602036,fineart
-Carlo Randanini,0.55493265,digipa-high-impact
-Diego Dayer,0.5549119,fineart
-Kelly Freas,0.55476534,fineart
-Thomas Saliot,0.5139967,digipa-med-impact
-Gijsbert d'Hondecoeter,0.55455256,fineart
-Walter Kim,0.554521,digipa-high-impact
-Francesco Cozza,0.5155097,digipa-med-impact
-Bill Watterson,0.5542879,digipa-high-impact
-Mark Keathley,0.4824056,fineart
-Béni Ferenczy,0.55405354,digipa-high-impact
-Amadou Opa Bathily,0.5536976,n
-Giuseppe Antonio Petrini,0.55340284,fineart
-Enzo Cucchi,0.55331933,digipa-high-impact
-Adolf Schrödter,0.55316544,fineart
-George Benjamin Luks,0.548566,fineart
-Glenys Cour,0.55304,digipa-high-impact
-Andrew Robertson,0.5529603,digipa-high-impact
-Claude Rogers,0.55272067,digipa-high-impact
-Alexandre Antigna,0.5526737,fineart
-Aimé Barraud,0.55265915,digipa-high-impact
-György Vastagh,0.55258965,fineart
-Bruce Nauman,0.55257386,digipa-high-impact
-Benjamin Block,0.55251944,digipa-high-impact
-Gonzalo Endara Crow,0.552346,digipa-high-impact
-Dirck de Bray,0.55221736,fineart
-Gerald Kelley,0.5521059,digipa-high-impact
-Dave Gibbons,0.5520954,digipa-high-impact
-Béla Nagy Abodi,0.5520624,digipa-high-impact
-Faith 47,0.5517006,digipa-high-impact
-Anna Razumovskaya,0.5229187,digipa-med-impact
-Archibald Robertson,0.55129635,digipa-high-impact
-Louise Dahl-Wolfe,0.55120385,digipa-high-impact
-Simon Bisley,0.55119276,digipa-high-impact
-Eric Fischl,0.55107886,fineart
-Hu Zaobin,0.5510481,fareast
-Béla Pállik,0.5507963,digipa-high-impact
-Eugene J. Martin,0.55078864,fineart
-Friedrich Gauermann,0.55063415,fineart
-Fritz Baumann,0.5341434,fineart
-Michal Lisowski,0.5505639,fineart
-Paolo Roversi,0.5503342,digipa-high-impact
-Andrew Atroshenko,0.55009747,fineart
-Gyula Derkovits,0.5500315,fineart
-Hugh Adam Crawford,0.55000615,digipa-high-impact
-Béla Apáti Abkarovics,0.5499799,digipa-high-impact
-Paul Chadeisson,0.389151,digipa-low-impact
-Aurél Bernáth,0.54968774,fineart
-Albert Henry Krehbiel,0.54952574,fineart
-Piet Hein Eek,0.54918796,digipa-high-impact
-Yoshitaka Amano,0.5491855,fareast
-Antonio Rotta,0.54909515,fineart
-Józef Mehoffer,0.50760424,fineart
-Donald Sherwood,0.5490415,digipa-high-impact
-Catrin G Grosse,0.5489286,digipa-high-impact
-Arthur Webster Emerson,0.5478842,fineart
-Incarcerated Jerkfaces,0.5488423,digipa-high-impact
-Emanuel Büchel,0.5487217,fineart
-Andrew Loomis,0.54854584,fineart
-Charles Hopkinson,0.54853606,fineart
-Gabor Szikszai,0.5485203,digipa-high-impact
-Archibald Standish Hartrick,0.54850936,digipa-high-impact
-Aleksander Orłowski,0.546705,nudity
-Hans Hinterreiter,0.5483628,fineart
-Fred Williams,0.54544824,fineart
-Fred A. Precht,0.5481606,fineart
-Camille Souter,0.5213742,fineart
-Emil Fuchs,0.54807395,fineart
-Francesco Bonsignori,0.5478936,fineart
-H. R. (Hans Ruedi) Giger,0.547799,fineart
-Harriet Zeitlin,0.5477388,digipa-high-impact
-Christian Jane Fergusson,0.5396168,fineart
-Edward Kemble,0.5476892,fineart
-Bernard Aubertin,0.5475396,fineart
-Augustyn Mirys,0.5474162,fineart
-Alejandro Burdisio,0.47482288,special
-Erin Hanson,0.4343264,digipa-low-impact
-Amalia Lindegren,0.5471987,digipa-high-impact
-Alberto Seveso,0.47735062,fineart
-Bartholomeus Strobel,0.54703736,fineart
-Jim Davis,0.54703003,digipa-high-impact
-Antony Gormley,0.54696125,digipa-high-impact
-Charles Marion Russell,0.54696095,fineart
-George B. Sutherland,0.5467901,fineart
-Almada Negreiros,0.54670584,fineart
-Edward Armitage,0.54358315,fineart
-Bruno Walpoth,0.546167,digipa-high-impact
-Richard Hamilton,0.5461275,nudity
-Charles Harold Davis,0.5460415,digipa-high-impact
-Fernand Verhaegen,0.54601514,fineart
-Bernard Meninsky,0.5302034,digipa-high-impact
-Fede Galizia,0.5456873,digipa-high-impact
-Alfred Kelsner,0.5455753,nudity
-Fritz Puempin,0.5452847,fineart
-Alfred Charles Parker,0.54521024,fineart
-Ahmed Yacoubi,0.544767,digipa-high-impact
-Arthur B. Carles,0.54447794,fineart
-Alice Prin,0.54435575,digipa-high-impact
-Carl Gustaf Pilo,0.5443212,digipa-high-impact
-Ross Tran,0.5259248,special
-Hideyuki Kikuchi,0.544193,fareast
-Art Fitzpatrick,0.49847245,fineart
-Cherryl Fountain,0.5440454,fineart
-Skottie Young,0.5440119,cartoon
-NC Wyeth,0.54382974,digipa-high-impact
-Rudolf Freund,0.5437342,fineart
-Mort Kunstler,0.5433619,digipa-high-impact
-Ben Goossens,0.53002644,digipa-high-impact
-Andreas Rocha,0.49621177,special
-Gérard Ernest Schneider,0.5429964,fineart
-Francesco Filippini,0.5429598,digipa-high-impact
-Alejandro Jodorowsky,0.5429065,digipa-high-impact
-Friedrich Traffelet,0.5428817,fineart
-Honor C. Appleton,0.5428735,digipa-high-impact
-Jason A. Engle,0.542821,fineart
-Henry Otto Wix,0.54271996,fineart
-Gregory Manchess,0.54270375,fineart
-Ann Stookey,0.54269934,digipa-high-impact
-Henryk Rodakowski,0.542589,fineart
-Albert Welti,0.5425134,digipa-high-impact
-Gerard Houckgeest,0.5424413,digipa-high-impact
-Dorothy Hood,0.54226196,digipa-high-impact
-Frank Schoonover,0.51056194,fineart
-Erlund Hudson,0.5422107,digipa-high-impact
-Alexander Litovchenko,0.54210097,fineart
-Sakai Hōitsu,0.5420294,digipa-high-impact
-Benito Quinquela Martín,0.54194224,fineart
-David Watson Stevenson,0.54191554,fineart
-Ann Thetis Blacker,0.5416629,digipa-high-impact
-Frank DuMond,0.51004076,digipa-med-impact
-David Dougal Williams,0.5410126,digipa-high-impact
-Robert Mcginnis,0.54098356,fineart
-Ernest Briggs,0.5408636,fineart
-Ferenc Joachim,0.5408625,fineart
-Carlos Saenz de Tejada,0.47332364,digipa-low-impact
-David Burton-Richardson,0.49659324,digipa-med-impact
-Ernest Heber Thompson,0.54039246,digipa-high-impact
-Albert Bertelsen,0.54038215,nudity
-Giorgio Giulio Clovio,0.5403708,fineart
-Eugene Leroy,0.54019785,digipa-high-impact
-Anna Findlay,0.54018176,digipa-high-impact
-Roy Gjertson,0.54012,digipa-high-impact
-Charmion von Wiegand,0.5400893,fineart
-Arnold Bronckhorst,0.526247,fineart
-Boris Vallejo,0.487253,fineart
-Adélaïde Victoire Hall,0.539939,fineart
-Earl Norem,0.5398575,fineart
-Sanford Kossin,0.53977877,digipa-high-impact
-Aert de Gelder,0.519166,digipa-med-impact
-Carl Eugen Keel,0.539739,digipa-high-impact
-Francis Bourgeois,0.5397272,digipa-high-impact
-Bojan Jevtic,0.41141546,fineart
-Edward Avedisian,0.5393925,fineart
-Gao Xiang,0.5392419,fareast
-Charles Hinman,0.53911865,digipa-high-impact
-Frits Van den Berghe,0.53896487,fineart
-Carlo Martini,0.5384833,digipa-high-impact
-Elina Karimova,0.5384318,digipa-high-impact
-Anto Carte,0.4708289,digipa-low-impact
-Andrey Yefimovich Martynov,0.537721,fineart
-Frances Jetter,0.5376904,fineart
-Yuri Ivanovich Pimenov,0.5342793,fineart
-Gaston Anglade,0.537608,digipa-high-impact
-Albert Swinden,0.5375844,fineart
-Bob Byerley,0.5375774,fineart
-A.B. Frost,0.5375025,fineart
-Jaya Suberg,0.5372893,digipa-high-impact
-Josh Keyes,0.53654516,digipa-high-impact
-Juliana Huxtable,0.5364195,n
-Everett Warner,0.53641814,digipa-high-impact
-Hugh Kretschmer,0.45171157,digipa-low-impact
-Arnold Blanch,0.535774,fineart
-Ryan McGinley,0.53572595,digipa-high-impact
-Alfons Karpiński,0.53564656,fineart
-George Aleef,0.5355317,digipa-high-impact
-Hal Foster,0.5351446,fineart
-Stuart Immonen,0.53501946,digipa-high-impact
-Craig Thompson,0.5346844,digipa-high-impact
-Bartolomeo Vivarini,0.53465015,fineart
-Hermann Feierabend,0.5346168,digipa-high-impact
-Antonio Donghi,0.4610982,digipa-low-impact
-Adonna Khare,0.4858036,digipa-med-impact
-James Stokoe,0.5015107,digipa-med-impact
-Agustín Fernández,0.53403986,fineart
-Germán Londoño,0.5338712,fineart
-Emmanuelle Moureaux,0.5335641,digipa-high-impact
-Conrad Marca-Relli,0.5148334,digipa-med-impact
-Gyula Batthyány,0.5332407,fineart
-Francesco Raibolini,0.53314835,fineart
-Apelles,0.5166026,fineart
-Marat Latypov,0.45811993,fineart
-Andrei Markin,0.5328752,fineart
-Einar Hakonarson,0.5328311,digipa-high-impact
-Beatrice Huntington,0.5328165,digipa-high-impact
-Coppo di Marcovaldo,0.5327443,fineart
-Gregorio Prestopino,0.53250784,fineart
-A.D.M. Cooper,0.53244877,digipa-high-impact
-Horatio McCulloch,0.53244334,digipa-high-impact
-Wes Anderson,0.5318741,digipa-high-impact
-Moebius,0.53178746,digipa-high-impact
-Gerard Soest,0.53160626,fineart
-Charles Ellison,0.53152347,digipa-high-impact
-Wojciech Ostrycharz,0.5314213,fineart
-Doug Chiang,0.5313724,fineart
-Anne Savage,0.5310638,digipa-high-impact
-Cor Melchers,0.53099334,fineart
-Gordon Browne,0.5308195,digipa-high-impact
-Augustus Earle,0.49196815,fineart
-Carlos Francisco Chang Marín,0.5304734,fineart
-Larry Elmore,0.53032553,fineart
-Adolf Hölzel,0.5303149,fineart
-David Ligare,0.5301894,fineart
-Jan Luyken,0.52985555,fineart
-Earle Bergey,0.5298525,fineart
-David Ramsay Hay,0.52974963,digipa-high-impact
-Alfred East,0.5296565,digipa-high-impact
-A. R. Middleton Todd,0.50988734,fineart
-Giorgio De Vincenzi,0.5291678,fineart
-Hugh William Williams,0.5291014,digipa-high-impact
-Erwin Bowien,0.52895796,digipa-high-impact
-Victor Adame Minguez,0.5288686,fineart
-Yoji Shinkawa,0.5287015,anime
-Clara Weaver Parrish,0.5284487,digipa-high-impact
-Albert Eckhout,0.5284096,fineart
-Dorothy Coke,0.5282345,digipa-high-impact
-Jerzy Duda-Gracz,0.5279943,digipa-high-impact
-Byron Galvez,0.39178842,fareast
-Alson S. Clark,0.5278568,digipa-high-impact
-Adolf Ulric Wertmüller,0.5278296,digipa-high-impact
-Bruce Coville,0.5277226,digipa-high-impact
-Gong Kai,0.5276811,digipa-high-impact
-Andréi Arinouchkine,0.52763486,digipa-high-impact
-Florence Engelbach,0.5273161,digipa-high-impact
-Brian Froud,0.5270276,fineart
-Charles Thomson,0.5270127,digipa-high-impact
-Bessie Wheeler,0.5269164,digipa-high-impact
-Anton Lehmden,0.5268611,fineart
-Emilia Wilk,0.5264961,fineart
-Carl Eytel,0.52646196,digipa-high-impact
-Alfred Janes,0.5264481,digipa-high-impact
-Julie Bell,0.49962538,fineart
-Eugenio de Arriba,0.52613926,digipa-high-impact
-Samuel and Joseph Newsom,0.52595663,digipa-high-impact
-Hans Falk,0.52588874,digipa-high-impact
-Guillermo del Toro,0.52565175,digipa-high-impact
-Félix Arauz,0.52555984,digipa-high-impact
-Gyula Basch,0.52524436,digipa-high-impact
-Haroon Mirza,0.5252279,digipa-high-impact
-Du Jin,0.5249934,digipa-med-impact
-Harry Shoulberg,0.5249456,digipa-med-impact
-Arie Smit,0.5249027,fineart
-Ahmed Karahisari,0.4259451,digipa-low-impact
-Brian and Wendy Froud,0.5246335,fineart
-E. William Gollings,0.52461207,digipa-med-impact
-Bo Bartlett,0.51341593,digipa-med-impact
-Hans Burgkmair,0.52416867,digipa-med-impact
-David Macaulay,0.5241233,digipa-med-impact
-Benedetto Caliari,0.52370214,digipa-med-impact
-Eliott Lilly,0.5235398,digipa-med-impact
-Vincent Tanguay,0.48578292,digipa-med-impact
-Ada Hill Walker,0.52207166,fineart
-Christopher Wood,0.49360397,digipa-med-impact
-Kris Kuksi,0.43938053,digipa-low-impact
-Chen Yifei,0.5217867,fineart
-Margaux Valonia,0.5217782,digipa-med-impact
-Antoni Pitxot,0.40582713,digipa-low-impact
-Jhonen Vasquez,0.5216471,digipa-med-impact
-Emilio Grau Sala,0.52156484,fineart
-Henry B. Christian,0.52153796,fineart
-Jacques Nathan-Garamond,0.52144086,digipa-med-impact
-Eddie Mendoza,0.4949638,digipa-med-impact
-Grzegorz Rutkowski,0.48906532,special
-Beeple,0.40085253,digipa-low-impact
-Giorgio Cavallon,0.5209209,digipa-med-impact
-Godfrey Blow,0.52062386,digipa-med-impact
-Gabriel Dawe,0.5204431,fineart
-Emile Lahner,0.5202367,digipa-med-impact
-Steve Dillon,0.5201676,digipa-med-impact
-Lee Quinones,0.4626683,digipa-low-impact
-Hale Woodruff,0.52000225,digipa-med-impact
-Tom Hammick,0.5032626,digipa-med-impact
-Hamilton Sloan,0.5197798,digipa-med-impact
-Caesar Andrade Faini,0.51971483,digipa-med-impact
-Sam Spratt,0.48991,digipa-med-impact
-Chris Cold,0.4753577,fineart
-Alejandro Obregón,0.5190562,digipa-med-impact
-Dan Flavin,0.51901346,digipa-med-impact
-Arthur Sarnoff,0.5189428,fineart
-Elenore Abbott,0.5187141,digipa-med-impact
-Andrea Kowch,0.51822996,digipa-med-impact
-Demetrios Farmakopoulos,0.5181248,digipa-med-impact
-Alexis Grimou,0.41958088,digipa-low-impact
-Lesley Vance,0.5177536,digipa-med-impact
-Gyula Aggházy,0.517747,fineart
-Georgina Hunt,0.46105456,digipa-low-impact
-Christian W. Staudinger,0.4684662,digipa-low-impact
-Abraham Begeyn,0.5172538,digipa-med-impact
-Charles Mozley,0.5171356,digipa-med-impact
-Elias Ravanetti,0.38719344,digipa-low-impact
-Herman van Swanevelt,0.5168748,digipa-med-impact
-David Paton,0.4842217,digipa-med-impact
-Hans Werner Schmidt,0.51671976,digipa-med-impact
-Bob Ross,0.51628315,fineart
-Sou Fujimoto,0.5162528,fareast
-Balcomb Greene,0.5162045,digipa-med-impact
-Glen Angus,0.51609933,digipa-med-impact
-Buckminster Fuller,0.51607454,digipa-med-impact
-Andrei Ryabushkin,0.5158933,fineart
-Almeida Júnior,0.515856,digipa-med-impact
-Tim White,0.4182697,digipa-low-impact
-Hans Beat Wieland,0.51553553,digipa-med-impact
-Jakub Różalski,0.5154904,digipa-med-impact
-John Whitcomb,0.51523805,digipa-med-impact
-Dorothy King,0.5150925,digipa-med-impact
-Richard S. Johnson,0.51500344,fineart
-Aniello Falcone,0.51475304,digipa-med-impact
-Henning Jakob Henrik Lund,0.5147134,c
-Robert M Cunningham,0.5144858,digipa-med-impact
-Nick Knight,0.51447505,digipa-med-impact
-David Chipperfield,0.51424,digipa-med-impact
-Bartolomeo Cesi,0.5136737,digipa-med-impact
-Bettina Heinen-Ayech,0.51334465,digipa-med-impact
-Annabel Kidston,0.51327646,digipa-med-impact
-Charles Schridde,0.51308405,digipa-med-impact
-Samuel Earp,0.51305825,digipa-med-impact
-Eugene Montgomery,0.5128343,digipa-med-impact
-Alfred Parsons,0.5127445,digipa-med-impact
-Anton Möller,0.5127209,digipa-med-impact
-Craig Davison,0.499598,special
-Cricorps Grégoire,0.51267076,fineart
-Celia Fiennes,0.51266706,digipa-med-impact
-Raymond Swanland,0.41350424,fineart
-Howard Knotts,0.5122062,digipa-med-impact
-Helmut Federle,0.51201206,digipa-med-impact
-Tyler Edlin,0.44028252,digipa-high-impact
-Elwood H. Smith,0.5119027,digipa-med-impact
-Ralph Horsley,0.51142794,fineart
-Alexander Ivanov,0.4539051,digipa-low-impact
-Cedric Peyravernay,0.4200587,digipa-low-impact
-Annabel Eyres,0.51136214,digipa-med-impact
-Zack Snyder,0.51129746,digipa-med-impact
-Gentile Bellini,0.511102,digipa-med-impact
-Giovanni Pelliccioli,0.4868688,digipa-med-impact
-Fikret Muallâ Saygı,0.510694,digipa-med-impact
-Bauhaus,0.43454266,digipa-low-impact
-Charles Williams,0.510406,digipa-med-impact
-Georg Arnold-Graboné,0.5103381,digipa-med-impact
-Fedot Sychkov,0.47935224,digipa-med-impact
-Alberto Magnelli,0.5103212,digipa-med-impact
-Aloysius O'Kelly,0.5102891,digipa-med-impact
-Alexander McQueen,0.5101986,digipa-med-impact
-Cam Sykes,0.510071,digipa-med-impact
-George Lucas,0.510038,digipa-med-impact
-Eglon van der Neer,0.5099339,digipa-med-impact
-Christian August Lorentzen,0.50989646,digipa-med-impact
-Eleanor Best,0.50966686,digipa-med-impact
-Terry Redlin,0.474244,fineart
-Ken Kelly,0.4304738,fineart
-David Eugene Henry,0.48173362,fineart
-Shin Jeongho,0.5092497,fareast
-Flora Borsi,0.5091922,digipa-med-impact
-Berndnaut Smilde,0.50864,digipa-med-impact
-Art of Brom,0.45828784,fineart
-Ernő Tibor,0.50851977,digipa-med-impact
-Ancell Stronach,0.5084514,digipa-med-impact
-Helen Thomas Dranga,0.45412368,digipa-low-impact
-Anita Malfatti,0.5080986,digipa-med-impact
-Arnold Brügger,0.5080749,digipa-med-impact
-Edward Ben Avram,0.50778764,digipa-med-impact
-Antonio Ciseri,0.5073538,fineart
-Alyssa Monks,0.50734174,digipa-med-impact
-Chen Zhen,0.5071876,digipa-med-impact
-Francis Helps,0.50707847,digipa-med-impact
-Georg Karl Pfahler,0.50700235,digipa-med-impact
-Henry Woods,0.506811,digipa-med-impact
-Barbara Greg,0.50674164,digipa-med-impact
-Guan Daosheng,0.506712,fareast
-Guy Billout,0.5064906,digipa-med-impact
-Basuki Abdullah,0.50613165,digipa-med-impact
-Thomas Visscher,0.5059943,digipa-med-impact
-Edward Simmons,0.50598735,digipa-med-impact
-Arabella Rankin,0.50572735,digipa-med-impact
-Lady Pink,0.5056634,digipa-high-impact
-Christopher Williams,0.5052288,digipa-med-impact
-Fuyuko Matsui,0.5051116,fareast
-Edward Baird,0.5049874,digipa-med-impact
-Georges Stein,0.5049069,digipa-med-impact
-Alex Alemany,0.43974748,digipa-low-impact
-Emanuel Schongut,0.5047326,digipa-med-impact
-Hans Bol,0.5045265,digipa-med-impact
-Kurzgesagt,0.5043725,digipa-med-impact
-Harald Giersing,0.50410193,digipa-med-impact
-Antonín Slavíček,0.5040368,fineart
-Carl Rahl,0.5040115,digipa-med-impact
-Etienne Delessert,0.5037818,fineart
-Americo Makk,0.5034161,digipa-med-impact
-Fernand Pelez,0.5027561,digipa-med-impact
-Alexey Merinov,0.4469615,digipa-low-impact
-Caspar Netscher,0.5019529,digipa-med-impact
-Walt Disney,0.50178146,digipa-med-impact
-Qian Xuan,0.50150526,fareast
-Geoffrey Dyer,0.50120556,digipa-med-impact
-Andre Norton,0.5007602,digipa-med-impact
-Daphne McClure,0.5007391,digipa-med-impact
-Dieric Bouts,0.5005882,fineart
-Aguri Uchida,0.5005107,fareast
-Hugo Scheiber,0.50004864,digipa-med-impact
-Kenne Gregoire,0.46421963,digipa-low-impact
-Wolfgang Tillmans,0.4999767,fineart
-Carl-Henning Pedersen,0.4998986,digipa-med-impact
-Alison Debenham,0.4998683,digipa-med-impact
-Eppo Doeve,0.49975222,digipa-med-impact
-Christen Købke,0.49961317,digipa-med-impact
-Aron Demetz,0.49895018,digipa-med-impact
-Alesso Baldovinetti,0.49849576,digipa-med-impact
-Jimmy Lawlor,0.4475271,fineart
-Carl Walter Liner,0.49826378,fineart
-Gwenny Griffiths,0.45598924,digipa-low-impact
-David Cooke Gibson,0.4976222,digipa-med-impact
-Howard Butterworth,0.4974621,digipa-med-impact
-Bob Thompson,0.49743804,fineart
-Enguerrand Quarton,0.49711192,fineart
-Abdel Hadi Al Gazzar,0.49631482,digipa-med-impact
-Gu Zhengyi,0.49629828,digipa-med-impact
-Aleksander Kotsis,0.4953621,digipa-med-impact
-Alexander Sharpe Ross,0.49519226,digipa-med-impact
-Carlos Enríquez Gómez,0.49494863,digipa-med-impact
-Abed Abdi,0.4948855,digipa-med-impact
-Elaine Duillo,0.49474388,digipa-med-impact
-Anne Said,0.49473995,digipa-med-impact
-Istvan Banyai,0.4947369,digipa-med-impact
-Bouchta El Hayani,0.49455142,digipa-med-impact
-Chinwe Chukwuogo-Roy,0.49445248,n
-George Claessen,0.49412063,digipa-med-impact
-Axel Törneman,0.49401706,digipa-med-impact
-Avigdor Arikha,0.49384058,digipa-med-impact
-Gloria Stoll Karn,0.4937976,digipa-med-impact
-Alfredo Volpi,0.49367586,digipa-med-impact
-Raffaello Sanizo,0.49365884,digipa-med-impact
-Jeff Easley,0.49344411,digipa-med-impact
-Aileen Eagleton,0.49318358,digipa-med-impact
-Gaetano Sabatini,0.49307147,digipa-med-impact
-Bertalan Pór,0.4930132,digipa-med-impact
-Alfred Jensen,0.49291304,digipa-med-impact
-Huang Guangjian,0.49286693,fareast
-Emil Ferris,0.49282396,digipa-med-impact
-Derek Chittock,0.492694,digipa-med-impact
-Alonso Vázquez,0.49205148,digipa-med-impact
-Kelly Sue Deconnick,0.4919476,digipa-med-impact
-Clive Madgwick,0.4749857,fineart
-Edward George Handel Lucas,0.49166748,digipa-med-impact
-Dorothea Braby,0.49161923,digipa-med-impact
-Sangyeob Park,0.49150884,fareast
-Heinz Edelman,0.49140438,digipa-med-impact
-Mark Seliger,0.4912073,digipa-med-impact
-Camilo Egas,0.4586727,digipa-low-impact
-Craig Mullins,0.49085408,fineart
-Dong Kingman,0.49063343,digipa-med-impact
-Douglas Robertson Bisset,0.49031347,digipa-med-impact
-Blek Le Rat,0.49008566,digipa-med-impact
-Anton Ažbe,0.48984748,fineart
-Olafur Eliasson,0.48971075,digipa-med-impact
-Elinor Proby Adams,0.48967826,digipa-med-impact
-Cándido López,0.48915705,digipa-med-impact
-D. Howard Hitchcock,0.48902267,digipa-med-impact
-Cheng Jiasui,0.48889247,fareast
-Jean Nouvel,0.4888183,digipa-med-impact
-Bill Gekas,0.48848945,digipa-med-impact
-Hermione Hammond,0.48845994,digipa-med-impact
-Fernando Gerassi,0.48841453,digipa-med-impact
-Frank Barrington Craig,0.4883762,digipa-med-impact
-A. B. Jackson,0.4883623,digipa-med-impact
-Bernie D’Andrea,0.48813275,digipa-med-impact
-Clarice Beckett,0.487809,digipa-med-impact
-Dosso Dossi,0.48775777,digipa-med-impact
-Donald Roller Wilson,0.48767656,digipa-med-impact
-Ernest William Christmas,0.4876317,digipa-med-impact
-Aleksandr Gerasimov,0.48736423,digipa-med-impact
-Edward Clark,0.48703307,digipa-med-impact
-Georg Schrimpf,0.48697302,digipa-med-impact
-John Wilhelm,0.48696536,digipa-med-impact
-Aries Moross,0.4863676,digipa-med-impact
-Bill Lewis,0.48635158,digipa-med-impact
-Huang Ji,0.48611963,fareast
-F. Scott Hess,0.43634564,fineart
-Gao Qipei,0.4860631,fareast
-Albert Tucker,0.4854299,digipa-med-impact
-Barbara Balmer,0.48528513,fineart
-Anne Ryan,0.48511976,digipa-med-impact
-Helen Edwards,0.48484707,digipa-med-impact
-Alexander Bogen,0.48421195,digipa-med-impact
-David Annand,0.48418126,digipa-med-impact
-Du Qiong,0.48414314,fareast
-Fred Cress,0.4837878,digipa-med-impact
-David B. Mattingly,0.48370445,digipa-med-impact
-Hristofor Žefarović,0.4837008,digipa-med-impact
-Wim Wenders,0.44484183,digipa-low-impact
-Alexander Fedosav,0.48360944,digipa-med-impact
-Anne Rigney,0.48357943,digipa-med-impact
-Bertalan Karlovszky,0.48338628,digipa-med-impact
-George Frederick Harris,0.4833259,fineart
-Toshiharu Mizutani,0.48315164,fareast
-David McClellan,0.39739317,digipa-low-impact
-Eugeen Van Mieghem,0.48270774,digipa-med-impact
-Alexei Harlamoff,0.48255378,digipa-med-impact
-Jeff Legg,0.48249072,digipa-med-impact
-Elizabeth Murray,0.48227608,digipa-med-impact
-Hugo Heyrman,0.48213717,digipa-med-impact
-Adrian Paul Allinson,0.48211843,digipa-med-impact
-Altoon Sultan,0.4820177,digipa-med-impact
-Alice Mason,0.48188528,fareast
-Harriet Powers,0.48181778,digipa-med-impact
-Aaron Bohrod,0.48175076,digipa-med-impact
-Chris Saunders,0.41429797,digipa-low-impact
-Clara Miller Burd,0.47797233,digipa-med-impact
-David G. Sorensen,0.38101727,digipa-low-impact
-Iwan Baan,0.4806739,digipa-med-impact
-Anatoly Metlan,0.48020265,digipa-med-impact
-Alfons von Czibulka,0.4801954,digipa-med-impact
-Amedee Ozenfant,0.47950014,digipa-med-impact
-Valerie Hegarty,0.47947168,digipa-med-impact
-Hugo Anton Fisher,0.4793551,digipa-med-impact
-Antonio Roybal,0.4792729,digipa-med-impact
-Cui Zizhong,0.47902682,fareast
-F Scott Hess,0.42582104,fineart
-Julien Delval,0.47888556,digipa-med-impact
-Marcin Jakubowski,0.4788583,digipa-med-impact
-Anne Stokes,0.4786997,digipa-med-impact
-David Palumbo,0.47632077,fineart
-Hallsteinn Sigurðsson,0.47858906,digipa-med-impact
-Mike Campau,0.47850558,digipa-med-impact
-Giuseppe Avanzi,0.47846943,digipa-med-impact
-Harry Morley,0.47836518,digipa-med-impact
-Constance-Anne Parker,0.47832203,digipa-med-impact
-Albert Keller,0.47825447,digipa-med-impact
-Daniel Chodowiecki,0.47825167,digipa-med-impact
-Alasdair Grant Taylor,0.47802624,digipa-med-impact
-Maria Pascual Alberich,0.4779718,fineart
-Rebeca Saray,0.41697127,digipa-low-impact
-Ernő Bánk,0.47753686,digipa-med-impact
-Shaddy Safadi,0.47724134,digipa-med-impact
-André Castro,0.4771826,digipa-med-impact
-Amiet Cuno,0.41975892,digipa-low-impact
-Adi Granov,0.40670198,fineart
-Allen Williams,0.47675848,digipa-med-impact
-Anna Haifisch,0.47672725,digipa-med-impact
-Clovis Trouille,0.47669724,digipa-med-impact
-Jane Graverol,0.47655866,digipa-med-impact
-Conroy Maddox,0.47645602,digipa-med-impact
-Božidar Jakac,0.4763106,digipa-med-impact
-George Morrison,0.47533786,digipa-med-impact
-Douglas Bourgeois,0.47527707,digipa-med-impact
-Cao Zhibai,0.47476804,fareast
-Bradley Walker Tomlin,0.47462896,digipa-low-impact
-Dave Dorman,0.46852386,fineart
-Stevan Dohanos,0.47452107,fineart
-John Howe,0.44144905,fineart
-Fanny McIan,0.47406268,digipa-low-impact
-Bholekar Srihari,0.47387534,digipa-low-impact
-Giovanni Lanfranco,0.4737344,digipa-low-impact
-Fred Marcellino,0.47346023,digipa-low-impact
-Clyde Caldwell,0.47305286,fineart
-Haukur Halldórsson,0.47275954,digipa-low-impact
-Huang Gongwang,0.47269204,fareast
-Brothers Grimm,0.47249007,digipa-low-impact
-Ollie Hoff,0.47240657,digipa-low-impact
-RHADS,0.4722166,digipa-low-impact
-Constance Gordon-Cumming,0.47219282,digipa-low-impact
-Anne Mccaffrey,0.4719924,digipa-low-impact
-Henry Heerup,0.47190166,digipa-low-impact
-Adrian Smith,0.4716923,digipa-high-impact
-Harold Elliott,0.4714101,digipa-low-impact
-Eric Peterson,0.47106332,digipa-low-impact
-David Garner,0.47106326,digipa-low-impact
-Edward Hicks,0.4708863,digipa-low-impact
-Alfred Krupa,0.47052455,digipa-low-impact
-Breyten Breytenbach,0.4699338,digipa-low-impact
-Douglas Shuler,0.4695691,digipa-low-impact
-Elaine Hamilton,0.46941522,digipa-low-impact
-Kapwani Kiwanga,0.46917036,digipa-low-impact
-Dan Scott,0.46897763,digipa-low-impact
-Allan Brooks,0.46882123,digipa-low-impact
-Ian Fairweather,0.46878594,digipa-low-impact
-Arlington Nelson Lindenmuth,0.4683814,digipa-low-impact
-Russell Ayto,0.4681503,digipa-low-impact
-Allan Linder,0.46812692,digipa-low-impact
-Bohumil Kubista,0.4679809,digipa-low-impact
-Christopher Jin Baron,0.4677839,digipa-low-impact
-Eero Snellman,0.46777654,digipa-low-impact
-Christabel Dennison,0.4677633,digipa-low-impact
-Amelia Peláez,0.46764764,digipa-low-impact
-James Gurney,0.46740666,digipa-low-impact
-Carles Delclaux Is,0.46734855,digipa-low-impact
-George Papazov,0.42420334,digipa-low-impact
-Mark Brooks,0.4672415,fineart
-Anne Dunn,0.46722376,digipa-low-impact
-Klaus Wittmann,0.4670704,fineart
-Arvid Nyholm,0.46697336,digipa-low-impact
-Georg Scholz,0.46674117,digipa-low-impact
-David Spriggs,0.46671993,digipa-low-impact
-Ernest Morgan,0.4665036,digipa-low-impact
-Ella Guru,0.46619284,digipa-low-impact
-Helen Berman,0.46614346,digipa-low-impact
-Gen Paul,0.4658785,digipa-low-impact
-Auseklis Ozols,0.46569023,digipa-low-impact
-Amelia Robertson Hill,0.4654411,fineart
-Jim Lee,0.46544096,digipa-low-impact
-Anson Maddocks,0.46539295,digipa-low-impact
-Chen Hong,0.46516004,fareast
-Haddon Sundblom,0.46490777,digipa-low-impact
-Eva Švankmajerová,0.46454152,digipa-low-impact
-Antonio Cavallucci,0.4645282,digipa-low-impact
-Herve Groussin,0.40050638,digipa-low-impact
-Gwen Barnard,0.46400994,digipa-low-impact
-Grace English,0.4638674,digipa-low-impact
-Carl Critchlow,0.4636,digipa-low-impact
-Ayshia Taşkın,0.463412,digipa-low-impact
-Alison Watt,0.43141022,digipa-low-impact
-Andre de Krayewski,0.4628024,digipa-low-impact
-Hamish MacDonald,0.462645,digipa-low-impact
-Ni Chuanjing,0.46254826,fareast
-Frank Mason,0.46254665,digipa-low-impact
-Steve Henderson,0.43113405,fineart
-Eileen Aldridge,0.46210572,digipa-low-impact
-Brad Rigney,0.28446302,digipa-low-impact
-Ching Yeh,0.46177,fareast
-Bertram Brooker,0.46176457,digipa-low-impact
-Henry Bright,0.46150023,digipa-low-impact
-Claire Dalby,0.46117848,digipa-low-impact
-Brian Despain,0.41538632,digipa-low-impact
-Anna Maria Barbara Abesch,0.4611045,digipa-low-impact
-Bernardo Daddi,0.46088326,digipa-low-impact
-Abraham Mintchine,0.46088243,digipa-high-impact
-Alexander Carse,0.46078917,digipa-low-impact
-Doc Hammer,0.46075988,digipa-low-impact
-Yuumei,0.46072406,digipa-low-impact
-Teophilus Tetteh,0.46064255,n
-Bess Hamiti,0.46062252,digipa-low-impact
-Ceferí Olivé,0.46058378,digipa-low-impact
-Enrique Grau,0.46046937,digipa-low-impact
-Eleanor Hughes,0.46007007,digipa-low-impact
-Elizabeth Charleston,0.46001568,digipa-low-impact
-Félix Ziem,0.45987016,digipa-low-impact
-Eugeniusz Zak,0.45985222,digipa-low-impact
-Dain Yoon,0.45977795,fareast
-Gong Xian,0.4595083,digipa-low-impact
-Flavia Blois,0.45950204,digipa-low-impact
-Frederik Vermehren,0.45949826,digipa-low-impact
-Gang Se-hwang,0.45937777,digipa-low-impact
-Bjørn Wiinblad,0.45934483,digipa-low-impact
-Alex Horley-Orlandelli,0.42623433,digipa-low-impact
-Dr. Atl,0.459287,digipa-low-impact
-Hu Jieqing,0.45889485,fareast
-Amédée Ozenfant,0.4585215,digipa-low-impact
-Warren Ellis,0.4584044,digipa-low-impact
-Helen Dahm,0.45804346,digipa-low-impact
-Anne Geddes,0.45785287,digipa-low-impact
-Bikash Bhattacharjee,0.45775396,digipa-low-impact
-Phil Foglio,0.457582,digipa-low-impact
-Evelyn Abelson,0.4574563,digipa-low-impact
-Alan Moore,0.4573369,digipa-low-impact
-Josh Kao,0.45725146,fareast
-Bertil Nilsson,0.45724383,digipa-low-impact
-Hristofor Zhefarovich,0.457089,fineart
-Edward Bailey,0.45659882,digipa-low-impact
-Christopher Moeller,0.45648077,digipa-low-impact
-Dóra Keresztes,0.4558745,fineart
-Cory Arcangel,0.4558071,digipa-low-impact
-Aleksander Kobzdej,0.45552525,digipa-low-impact
-Tim Burton,0.45541722,digipa-high-impact
-Chen Jiru,0.4553378,fareast
-George Passantino,0.4552104,digipa-low-impact
-Fuller Potter,0.4552072,digipa-low-impact
-Warwick Globe,0.45516664,digipa-low-impact
-Heinz Anger,0.45466962,digipa-low-impact
-Elias Goldberg,0.45416242,digipa-low-impact
-tokyogenso,0.45406622,fareast
-Zeen Chin,0.45404464,digipa-low-impact
-Albert Koetsier,0.45385844,fineart
-Giuseppe Camuncoli,0.45377725,digipa-low-impact
-Elsie Vera Cole,0.45377362,digipa-low-impact
-Andreas Franke,0.4300047,digipa-low-impact
-Constantine Andreou,0.4533816,digipa-low-impact
-Elisabeth Collins,0.45337808,digipa-low-impact
-Ted Nasmith,0.45302224,fineart
-Antônio Parreiras,0.45269623,digipa-low-impact
-Gwilym Prichard,0.45256525,digipa-low-impact
-Fang Congyi,0.45240825,fareast
-Huang Ding,0.45233482,fareast
-Hans von Bartels,0.45200723,digipa-low-impact
-Peter Elson,0.4121406,fineart
-Fan Kuan,0.4513034,digipa-low-impact
-Dean Roger,0.45112592,digipa-low-impact
-Bernat Sanjuan,0.45074993,fareast
-Fletcher Martin,0.45055175,digipa-low-impact
-Gentile Tondino,0.45043385,digipa-low-impact
-Ei-Q,0.45038772,digipa-low-impact
-Chen Lin,0.45035738,fareast
-Ted Wallace,0.4500007,digipa-low-impact
-"Cornelisz Hendriksz Vroom, the Younger",0.4499252,digipa-low-impact
-Alpo Jaakola,0.44981295,digipa-low-impact
-Clark Voorhees,0.4495309,digipa-low-impact
-Cleve Gray,0.449188,digipa-low-impact
-Wolf Kahn,0.4489858,digipa-low-impact
-Choi Buk,0.44892842,fareast
-Frank Tinsley,0.4480373,digipa-low-impact
-George Bell,0.44779524,digipa-low-impact
-Fiona Stephenson,0.44761062,fineart
-Carlos Trillo Name,0.4470371,digipa-low-impact
-Jamie McKelvie,0.44696707,digipa-low-impact
-Dennis Flanders,0.44673377,digipa-low-impact
-Dulah Marie Evans,0.44662604,digipa-low-impact
-Hans Schwarz,0.4463275,digipa-low-impact
-Steve McCurry,0.44620228,digipa-low-impact
-Bedwyr Williams,0.44616276,digipa-low-impact
-Anton Graff,0.38569996,digipa-low-impact
-Leticia Gillett,0.44578317,digipa-low-impact
-Rafał Olbiński,0.44561762,digipa-low-impact
-Artgerm,0.44555497,fineart
-Adrienn Henczné Deák,0.445518,digipa-low-impact
-Gu Hongzhong,0.4454906,fareast
-Matt Groening,0.44518438,digipa-low-impact
-Sue Bryce,0.4447164,digipa-low-impact
-Armin Baumgarten,0.444061,digipa-low-impact
-Araceli Gilbert,0.44399196,digipa-low-impact
-Carey Morris,0.44388965,digipa-low-impact
-Ignat Bednarik,0.4438085,digipa-low-impact
-Frank Buchser,0.44373792,digipa-low-impact
-Ben Zoeller,0.44368798,digipa-low-impact
-Adam Szentpétery,0.4434548,fineart
-Gene Davis,0.44343877,digipa-low-impact
-Fei Danxu,0.4433627,fareast
-Andrei Kolkoutine,0.44328922,digipa-low-impact
-Bruce Onobrakpeya,0.42588046,n
-Christoph Amberger,0.38912287,digipa-low-impact
-"Fred Mitchell,",0.4432277,digipa-low-impact
-Klaus Burgle,0.44295216,digipa-low-impact
-Carl Hoppe,0.44270635,digipa-low-impact
-Caroline Gotch,0.44263047,digipa-low-impact
-Hans Mertens,0.44260004,digipa-low-impact
-Mandy Disher,0.44219893,fineart
-Sarah Lucas,0.4420507,digipa-low-impact
-Sydney Edmunds,0.44198513,digipa-low-impact
-Amos Ferguson,0.4418735,digipa-low-impact
-Alton Tobey,0.4416385,digipa-low-impact
-Clifford Ross,0.44139367,digipa-low-impact
-Henric Trenk,0.4412782,digipa-low-impact
-Claire Hummel,0.44119984,digipa-low-impact
-Norman Foster,0.4411899,digipa-low-impact
-Carmen Saldana,0.44076762,digipa-low-impact
-Michael Whelan,0.4372847,digipa-low-impact
-Carlos Berlanga,0.440354,digipa-low-impact
-Gilles Beloeil,0.43997732,digipa-low-impact
-Ashley Wood,0.4398396,digipa-low-impact
-David Allan,0.43969798,digipa-low-impact
-Mark Lovett,0.43922082,digipa-low-impact
-Jed Henry,0.43882954,digipa-low-impact
-Adam Bruce Thomson,0.43847767,digipa-low-impact
-Horst Antes,0.4384303,digipa-low-impact
-Fritz Glarner,0.43787453,digipa-low-impact
-Harold McCauley,0.43760818,digipa-low-impact
-Estuardo Maldonado,0.437594,digipa-low-impact
-Dai Jin,0.4375449,fareast
-Fabien Charuau,0.43688047,digipa-low-impact
-Chica Macnab,0.4365166,digipa-low-impact
-Jim Burns,0.3975072,digipa-low-impact
-Santiago Calatrava,0.43651623,digipa-low-impact
-Robert Maguire,0.40926617,digipa-low-impact
-Cliff Childs,0.43611953,digipa-low-impact
-Charles Martin,0.43582463,fareast
-Elbridge Ayer Burbank,0.43572164,digipa-low-impact
-Anita Kunz,0.4356005,digipa-low-impact
-Colin Geller,0.43559563,digipa-low-impact
-Allen Tupper True,0.43556124,digipa-low-impact
-Jef Wu,0.43555313,digipa-low-impact
-Jon McCoy,0.4147122,digipa-low-impact
-Cedric Seaut,0.43521535,digipa-low-impact
-Emily Shanks,0.43519047,digipa-low-impact
-Andrew Whem,0.43512022,digipa-low-impact
-Ibrahim Kodra,0.43471518,digipa-low-impact
-Harrington Mann,0.4345901,digipa-low-impact
-Jerry Siegel,0.43458986,digipa-low-impact
-Howard Kanovitz,0.4345178,digipa-low-impact
-Cicely Hey,0.43449926,digipa-low-impact
-Ben Thompson,0.43436068,digipa-low-impact
-Joe Bowler,0.43413073,digipa-low-impact
-Lori Earley,0.43389612,digipa-low-impact
-Arent Arentsz,0.43373522,digipa-low-impact
-David Bailly,0.43371305,digipa-low-impact
-Hans Arnold,0.4335214,digipa-low-impact
-Constance Copeman,0.4334836,digipa-low-impact
-Brent Heighton,0.4333118,fineart
-Eric Taylor,0.43312082,digipa-low-impact
-Aleksander Gine,0.4326849,digipa-low-impact
-Alexander Johnston,0.4326589,digipa-low-impact
-David Park,0.43235332,digipa-low-impact
-Balázs Diószegi,0.432244,digipa-low-impact
-Ed Binkley,0.43222216,digipa-low-impact
-Eric Dinyer,0.4321258,digipa-low-impact
-Susan Luo,0.43198025,fareast
-Cedric Seaut (Keos Masons),0.4317356,digipa-low-impact
-Lorena Alvarez Gómez,0.431683,digipa-low-impact
-Fred Ludekens,0.431662,digipa-low-impact
-David Begbie,0.4316218,digipa-low-impact
-Ai Xuan,0.43150818,fareast
-Felix-Kelly,0.43132153,digipa-low-impact
-Antonín Chittussi,0.431248,digipa-low-impact
-Ammi Phillips,0.43095884,digipa-low-impact
-Elke Vogelsang,0.43092483,digipa-low-impact
-Fathi Hassan,0.43090487,digipa-low-impact
-Angela Sung,0.391746,fareast
-Clément Serveau,0.43050706,digipa-low-impact
-Dong Yuan,0.4303865,fareast
-Hew Lorimer,0.43035403,digipa-low-impact
-David Finch,0.29487437,digipa-low-impact
-Bill Durgin,0.4300932,digipa-low-impact
-Alexander Robertson,0.4300743,digipa-low-impact
diff --git a/extensions-builtin/LDSR/ldsr_model_arch.py b/extensions-builtin/LDSR/ldsr_model_arch.py
index 0ad49f4e..bc11cc6e 100644
--- a/extensions-builtin/LDSR/ldsr_model_arch.py
+++ b/extensions-builtin/LDSR/ldsr_model_arch.py
@@ -1,7 +1,6 @@
import os
import gc
import time
-import warnings
import numpy as np
import torch
@@ -15,8 +14,6 @@ from ldm.models.diffusion.ddim import DDIMSampler
from ldm.util import instantiate_from_config, ismap
from modules import shared, sd_hijack
-warnings.filterwarnings("ignore", category=UserWarning)
-
cached_ldsr_model: torch.nn.Module = None
diff --git a/extensions-builtin/Lora/extra_networks_lora.py b/extensions-builtin/Lora/extra_networks_lora.py
new file mode 100644
index 00000000..8f2e753e
--- /dev/null
+++ b/extensions-builtin/Lora/extra_networks_lora.py
@@ -0,0 +1,20 @@
+from modules import extra_networks
+import lora
+
+class ExtraNetworkLora(extra_networks.ExtraNetwork):
+ def __init__(self):
+ super().__init__('lora')
+
+ def activate(self, p, params_list):
+ names = []
+ multipliers = []
+ for params in params_list:
+ assert len(params.items) > 0
+
+ names.append(params.items[0])
+ multipliers.append(float(params.items[1]) if len(params.items) > 1 else 1.0)
+
+ lora.load_loras(names, multipliers)
+
+ def deactivate(self, p):
+ pass
diff --git a/extensions-builtin/Lora/lora.py b/extensions-builtin/Lora/lora.py
new file mode 100644
index 00000000..da1797dc
--- /dev/null
+++ b/extensions-builtin/Lora/lora.py
@@ -0,0 +1,199 @@
+import glob
+import os
+import re
+import torch
+
+from modules import shared, devices, sd_models
+
+re_digits = re.compile(r"\d+")
+re_unet_down_blocks = re.compile(r"lora_unet_down_blocks_(\d+)_attentions_(\d+)_(.+)")
+re_unet_mid_blocks = re.compile(r"lora_unet_mid_block_attentions_(\d+)_(.+)")
+re_unet_up_blocks = re.compile(r"lora_unet_up_blocks_(\d+)_attentions_(\d+)_(.+)")
+re_text_block = re.compile(r"lora_te_text_model_encoder_layers_(\d+)_(.+)")
+
+
+def convert_diffusers_name_to_compvis(key):
+ def match(match_list, regex):
+ r = re.match(regex, key)
+ if not r:
+ return False
+
+ match_list.clear()
+ match_list.extend([int(x) if re.match(re_digits, x) else x for x in r.groups()])
+ return True
+
+ m = []
+
+ if match(m, re_unet_down_blocks):
+ return f"diffusion_model_input_blocks_{1 + m[0] * 3 + m[1]}_1_{m[2]}"
+
+ if match(m, re_unet_mid_blocks):
+ return f"diffusion_model_middle_block_1_{m[1]}"
+
+ if match(m, re_unet_up_blocks):
+ return f"diffusion_model_output_blocks_{m[0] * 3 + m[1]}_1_{m[2]}"
+
+ if match(m, re_text_block):
+ return f"transformer_text_model_encoder_layers_{m[0]}_{m[1]}"
+
+ return key
+
+
+class LoraOnDisk:
+ def __init__(self, name, filename):
+ self.name = name
+ self.filename = filename
+
+
+class LoraModule:
+ def __init__(self, name):
+ self.name = name
+ self.multiplier = 1.0
+ self.modules = {}
+ self.mtime = None
+
+
+class LoraUpDownModule:
+ def __init__(self):
+ self.up = None
+ self.down = None
+
+
+def assign_lora_names_to_compvis_modules(sd_model):
+ lora_layer_mapping = {}
+
+ for name, module in shared.sd_model.cond_stage_model.wrapped.named_modules():
+ lora_name = name.replace(".", "_")
+ lora_layer_mapping[lora_name] = module
+ module.lora_layer_name = lora_name
+
+ for name, module in shared.sd_model.model.named_modules():
+ lora_name = name.replace(".", "_")
+ lora_layer_mapping[lora_name] = module
+ module.lora_layer_name = lora_name
+
+ sd_model.lora_layer_mapping = lora_layer_mapping
+
+
+def load_lora(name, filename):
+ lora = LoraModule(name)
+ lora.mtime = os.path.getmtime(filename)
+
+ sd = sd_models.read_state_dict(filename)
+
+ keys_failed_to_match = []
+
+ for key_diffusers, weight in sd.items():
+ fullkey = convert_diffusers_name_to_compvis(key_diffusers)
+ key, lora_key = fullkey.split(".", 1)
+
+ sd_module = shared.sd_model.lora_layer_mapping.get(key, None)
+ if sd_module is None:
+ keys_failed_to_match.append(key_diffusers)
+ continue
+
+ if type(sd_module) == torch.nn.Linear:
+ module = torch.nn.Linear(weight.shape[1], weight.shape[0], bias=False)
+ elif type(sd_module) == torch.nn.Conv2d:
+ module = torch.nn.Conv2d(weight.shape[1], weight.shape[0], (1, 1), bias=False)
+ else:
+ assert False, f'Lora layer {key_diffusers} matched a layer with unsupported type: {type(sd_module).__name__}'
+
+ with torch.no_grad():
+ module.weight.copy_(weight)
+
+ module.to(device=devices.device, dtype=devices.dtype)
+
+ lora_module = lora.modules.get(key, None)
+ if lora_module is None:
+ lora_module = LoraUpDownModule()
+ lora.modules[key] = lora_module
+
+ if lora_key == "lora_up.weight":
+ lora_module.up = module
+ elif lora_key == "lora_down.weight":
+ lora_module.down = module
+ else:
+ assert False, f'Bad Lora layer name: {key_diffusers} - must end in lora_up.weight or lora_down.weight'
+
+ if len(keys_failed_to_match) > 0:
+ print(f"Failed to match keys when loading Lora {filename}: {keys_failed_to_match}")
+
+ return lora
+
+
+def load_loras(names, multipliers=None):
+ already_loaded = {}
+
+ for lora in loaded_loras:
+ if lora.name in names:
+ already_loaded[lora.name] = lora
+
+ loaded_loras.clear()
+
+ loras_on_disk = [available_loras.get(name, None) for name in names]
+ if any([x is None for x in loras_on_disk]):
+ list_available_loras()
+
+ loras_on_disk = [available_loras.get(name, None) for name in names]
+
+ for i, name in enumerate(names):
+ lora = already_loaded.get(name, None)
+
+ lora_on_disk = loras_on_disk[i]
+ if lora_on_disk is not None:
+ if lora is None or os.path.getmtime(lora_on_disk.filename) > lora.mtime:
+ lora = load_lora(name, lora_on_disk.filename)
+
+ if lora is None:
+ print(f"Couldn't find Lora with name {name}")
+ continue
+
+ lora.multiplier = multipliers[i] if multipliers else 1.0
+ loaded_loras.append(lora)
+
+
+def lora_forward(module, input, res):
+ if len(loaded_loras) == 0:
+ return res
+
+ lora_layer_name = getattr(module, 'lora_layer_name', None)
+ for lora in loaded_loras:
+ module = lora.modules.get(lora_layer_name, None)
+ if module is not None:
+ res = res + module.up(module.down(input)) * lora.multiplier
+
+ return res
+
+
+def lora_Linear_forward(self, input):
+ return lora_forward(self, input, torch.nn.Linear_forward_before_lora(self, input))
+
+
+def lora_Conv2d_forward(self, input):
+ return lora_forward(self, input, torch.nn.Conv2d_forward_before_lora(self, input))
+
+
+def list_available_loras():
+ available_loras.clear()
+
+ os.makedirs(shared.cmd_opts.lora_dir, exist_ok=True)
+
+ candidates = \
+ glob.glob(os.path.join(shared.cmd_opts.lora_dir, '**/*.pt'), recursive=True) + \
+ glob.glob(os.path.join(shared.cmd_opts.lora_dir, '**/*.safetensors'), recursive=True) + \
+ glob.glob(os.path.join(shared.cmd_opts.lora_dir, '**/*.ckpt'), recursive=True)
+
+ for filename in sorted(candidates):
+ if os.path.isdir(filename):
+ continue
+
+ name = os.path.splitext(os.path.basename(filename))[0]
+
+ available_loras[name] = LoraOnDisk(name, filename)
+
+
+available_loras = {}
+loaded_loras = []
+
+list_available_loras()
diff --git a/extensions-builtin/Lora/preload.py b/extensions-builtin/Lora/preload.py
new file mode 100644
index 00000000..863dc5c0
--- /dev/null
+++ b/extensions-builtin/Lora/preload.py
@@ -0,0 +1,6 @@
+import os
+from modules import paths
+
+
+def preload(parser):
+ parser.add_argument("--lora-dir", type=str, help="Path to directory with Lora networks.", default=os.path.join(paths.models_path, 'Lora'))
diff --git a/extensions-builtin/Lora/scripts/lora_script.py b/extensions-builtin/Lora/scripts/lora_script.py
new file mode 100644
index 00000000..60b9eb64
--- /dev/null
+++ b/extensions-builtin/Lora/scripts/lora_script.py
@@ -0,0 +1,30 @@
+import torch
+
+import lora
+import extra_networks_lora
+import ui_extra_networks_lora
+from modules import script_callbacks, ui_extra_networks, extra_networks
+
+
+def unload():
+ torch.nn.Linear.forward = torch.nn.Linear_forward_before_lora
+ torch.nn.Conv2d.forward = torch.nn.Conv2d_forward_before_lora
+
+
+def before_ui():
+ ui_extra_networks.register_page(ui_extra_networks_lora.ExtraNetworksPageLora())
+ extra_networks.register_extra_network(extra_networks_lora.ExtraNetworkLora())
+
+
+if not hasattr(torch.nn, 'Linear_forward_before_lora'):
+ torch.nn.Linear_forward_before_lora = torch.nn.Linear.forward
+
+if not hasattr(torch.nn, 'Conv2d_forward_before_lora'):
+ torch.nn.Conv2d_forward_before_lora = torch.nn.Conv2d.forward
+
+torch.nn.Linear.forward = lora.lora_Linear_forward
+torch.nn.Conv2d.forward = lora.lora_Conv2d_forward
+
+script_callbacks.on_model_loaded(lora.assign_lora_names_to_compvis_modules)
+script_callbacks.on_script_unloaded(unload)
+script_callbacks.on_before_ui(before_ui)
diff --git a/extensions-builtin/Lora/ui_extra_networks_lora.py b/extensions-builtin/Lora/ui_extra_networks_lora.py
new file mode 100644
index 00000000..54a80d36
--- /dev/null
+++ b/extensions-builtin/Lora/ui_extra_networks_lora.py
@@ -0,0 +1,36 @@
+import json
+import os
+import lora
+
+from modules import shared, ui_extra_networks
+
+
+class ExtraNetworksPageLora(ui_extra_networks.ExtraNetworksPage):
+ def __init__(self):
+ super().__init__('Lora')
+
+ def refresh(self):
+ lora.list_available_loras()
+
+ def list_items(self):
+ for name, lora_on_disk in lora.available_loras.items():
+ path, ext = os.path.splitext(lora_on_disk.filename)
+ previews = [path + ".png", path + ".preview.png"]
+
+ preview = None
+ for file in previews:
+ if os.path.isfile(file):
+ preview = "./file=" + file.replace('\\', '/') + "?mtime=" + str(os.path.getmtime(file))
+ break
+
+ yield {
+ "name": name,
+ "filename": path,
+ "preview": preview,
+ "prompt": json.dumps(f"<lora:{name}:") + " + opts.extra_networks_default_multiplier + " + json.dumps(">"),
+ "local_preview": path + ".png",
+ }
+
+ def allowed_directories_for_previews(self):
+ return [shared.cmd_opts.lora_dir]
+
diff --git a/extensions-builtin/prompt-bracket-checker/javascript/prompt-bracket-checker.js b/extensions-builtin/prompt-bracket-checker/javascript/prompt-bracket-checker.js
index eccfb0f9..4a85c8eb 100644
--- a/extensions-builtin/prompt-bracket-checker/javascript/prompt-bracket-checker.js
+++ b/extensions-builtin/prompt-bracket-checker/javascript/prompt-bracket-checker.js
@@ -4,16 +4,10 @@
// Counts open and closed brackets (round, square, curly) in the prompt and negative prompt text boxes in the txt2img and img2img tabs.
// If there's a mismatch, the keyword counter turns red and if you hover on it, a tooltip tells you what's wrong.
-function checkBrackets(evt) {
- textArea = evt.target;
- tabName = evt.target.parentElement.parentElement.id.split("_")[0];
- counterElt = document.querySelector('gradio-app').shadowRoot.querySelector('#' + tabName + '_token_counter');
-
- promptName = evt.target.parentElement.parentElement.id.includes('neg') ? ' negative' : '';
-
- errorStringParen = '(' + tabName + promptName + ' prompt) - Different number of opening and closing parentheses detected.\n';
- errorStringSquare = '[' + tabName + promptName + ' prompt] - Different number of opening and closing square brackets detected.\n';
- errorStringCurly = '{' + tabName + promptName + ' prompt} - Different number of opening and closing curly brackets detected.\n';
+function checkBrackets(evt, textArea, counterElt) {
+ errorStringParen = '(...) - Different number of opening and closing parentheses detected.\n';
+ errorStringSquare = '[...] - Different number of opening and closing square brackets detected.\n';
+ errorStringCurly = '{...} - Different number of opening and closing curly brackets detected.\n';
openBracketRegExp = /\(/g;
closeBracketRegExp = /\)/g;
@@ -86,22 +80,31 @@ function checkBrackets(evt) {
}
if(counterElt.title != '') {
- counterElt.style = 'color: #FF5555;';
+ counterElt.classList.add('error');
} else {
- counterElt.style = '';
+ counterElt.classList.remove('error');
}
}
+function setupBracketChecking(id_prompt, id_counter){
+ var textarea = gradioApp().querySelector("#" + id_prompt + " > label > textarea");
+ var counter = gradioApp().getElementById(id_counter)
+ textarea.addEventListener("input", function(evt){
+ checkBrackets(evt, textarea, counter)
+ });
+}
+
var shadowRootLoaded = setInterval(function() {
- var shadowTextArea = document.querySelector('gradio-app').shadowRoot.querySelectorAll('#txt2img_prompt > label > textarea');
- if(shadowTextArea.length < 1) {
- return false;
- }
+ var shadowRoot = document.querySelector('gradio-app').shadowRoot;
+ if(! shadowRoot) return false;
+
+ var shadowTextArea = shadowRoot.querySelectorAll('#txt2img_prompt > label > textarea');
+ if(shadowTextArea.length < 1) return false;
- clearInterval(shadowRootLoaded);
+ clearInterval(shadowRootLoaded);
- document.querySelector('gradio-app').shadowRoot.querySelector('#txt2img_prompt').onkeyup = checkBrackets;
- document.querySelector('gradio-app').shadowRoot.querySelector('#txt2img_neg_prompt').onkeyup = checkBrackets;
- document.querySelector('gradio-app').shadowRoot.querySelector('#img2img_prompt').onkeyup = checkBrackets;
- document.querySelector('gradio-app').shadowRoot.querySelector('#img2img_neg_prompt').onkeyup = checkBrackets;
+ setupBracketChecking('txt2img_prompt', 'txt2img_token_counter')
+ setupBracketChecking('txt2img_neg_prompt', 'txt2img_negative_token_counter')
+ setupBracketChecking('img2img_prompt', 'imgimg_token_counter')
+ setupBracketChecking('img2img_neg_prompt', 'img2img_negative_token_counter')
}, 1000);
diff --git a/extensions-builtin/roll-artist/scripts/roll-artist.py b/extensions-builtin/roll-artist/scripts/roll-artist.py
deleted file mode 100644
index c3bc1fd0..00000000
--- a/extensions-builtin/roll-artist/scripts/roll-artist.py
+++ /dev/null
@@ -1,50 +0,0 @@
-import random
-
-from modules import script_callbacks, shared
-import gradio as gr
-
-art_symbol = '\U0001f3a8' # 🎨
-global_prompt = None
-related_ids = {"txt2img_prompt", "txt2img_clear_prompt", "img2img_prompt", "img2img_clear_prompt" }
-
-
-def roll_artist(prompt):
- allowed_cats = set([x for x in shared.artist_db.categories() if len(shared.opts.random_artist_categories)==0 or x in shared.opts.random_artist_categories])
- artist = random.choice([x for x in shared.artist_db.artists if x.category in allowed_cats])
-
- return prompt + ", " + artist.name if prompt != '' else artist.name
-
-
-def add_roll_button(prompt):
- roll = gr.Button(value=art_symbol, elem_id="roll", visible=len(shared.artist_db.artists) > 0)
-
- roll.click(
- fn=roll_artist,
- _js="update_txt2img_tokens",
- inputs=[
- prompt,
- ],
- outputs=[
- prompt,
- ]
- )
-
-
-def after_component(component, **kwargs):
- global global_prompt
-
- elem_id = kwargs.get('elem_id', None)
- if elem_id not in related_ids:
- return
-
- if elem_id == "txt2img_prompt":
- global_prompt = component
- elif elem_id == "txt2img_clear_prompt":
- add_roll_button(global_prompt)
- elif elem_id == "img2img_prompt":
- global_prompt = component
- elif elem_id == "img2img_clear_prompt":
- add_roll_button(global_prompt)
-
-
-script_callbacks.on_after_component(after_component)
diff --git a/html/card-no-preview.png b/html/card-no-preview.png
new file mode 100644
index 00000000..e2beb269
--- /dev/null
+++ b/html/card-no-preview.png
Binary files differ
diff --git a/html/extra-networks-card.html b/html/extra-networks-card.html
new file mode 100644
index 00000000..1bdf1d27
--- /dev/null
+++ b/html/extra-networks-card.html
@@ -0,0 +1,11 @@
+<div class='card' {preview_html} onclick='return cardClicked({tabname}, {prompt}, {allow_negative_prompt})'>
+ <div class='actions'>
+ <div class='additional'>
+ <ul>
+ <a href="#" title="replace preview image with currently selected in gallery" onclick='return saveCardPreview(event, {tabname}, {local_preview})'>replace preview</a>
+ </ul>
+ </div>
+ <span class='name'>{name}</span>
+ </div>
+</div>
+
diff --git a/html/extra-networks-no-cards.html b/html/extra-networks-no-cards.html
new file mode 100644
index 00000000..389358d6
--- /dev/null
+++ b/html/extra-networks-no-cards.html
@@ -0,0 +1,8 @@
+<div class='nocards'>
+<h1>Nothing here. Add some content to the following directories:</h1>
+
+<ul>
+{dirs}
+</ul>
+</div>
+
diff --git a/javascript/edit-attention.js b/javascript/edit-attention.js
index b947cbec..619bb1fa 100644
--- a/javascript/edit-attention.js
+++ b/javascript/edit-attention.js
@@ -1,75 +1,96 @@
-addEventListener('keydown', (event) => {
+function keyupEditAttention(event){
let target = event.originalTarget || event.composedPath()[0];
- if (!target.matches("#toprow textarea.gr-text-input[placeholder]")) return;
+ if (!target.matches("[id*='_toprow'] textarea.gr-text-input[placeholder]")) return;
if (! (event.metaKey || event.ctrlKey)) return;
-
- let plus = "ArrowUp"
- let minus = "ArrowDown"
- if (event.key != plus && event.key != minus) return;
+ let isPlus = event.key == "ArrowUp"
+ let isMinus = event.key == "ArrowDown"
+ if (!isPlus && !isMinus) return;
let selectionStart = target.selectionStart;
let selectionEnd = target.selectionEnd;
- // If the user hasn't selected anything, let's select their current parenthesis block
- if (selectionStart === selectionEnd) {
+ let text = target.value;
+
+ function selectCurrentParenthesisBlock(OPEN, CLOSE){
+ if (selectionStart !== selectionEnd) return false;
+
// Find opening parenthesis around current cursor
- const before = target.value.substring(0, selectionStart);
- let beforeParen = before.lastIndexOf("(");
- if (beforeParen == -1) return;
- let beforeParenClose = before.lastIndexOf(")");
+ const before = text.substring(0, selectionStart);
+ let beforeParen = before.lastIndexOf(OPEN);
+ if (beforeParen == -1) return false;
+ let beforeParenClose = before.lastIndexOf(CLOSE);
while (beforeParenClose !== -1 && beforeParenClose > beforeParen) {
- beforeParen = before.lastIndexOf("(", beforeParen - 1);
- beforeParenClose = before.lastIndexOf(")", beforeParenClose - 1);
+ beforeParen = before.lastIndexOf(OPEN, beforeParen - 1);
+ beforeParenClose = before.lastIndexOf(CLOSE, beforeParenClose - 1);
}
// Find closing parenthesis around current cursor
- const after = target.value.substring(selectionStart);
- let afterParen = after.indexOf(")");
- if (afterParen == -1) return;
- let afterParenOpen = after.indexOf("(");
+ const after = text.substring(selectionStart);
+ let afterParen = after.indexOf(CLOSE);
+ if (afterParen == -1) return false;
+ let afterParenOpen = after.indexOf(OPEN);
while (afterParenOpen !== -1 && afterParen > afterParenOpen) {
- afterParen = after.indexOf(")", afterParen + 1);
- afterParenOpen = after.indexOf("(", afterParenOpen + 1);
+ afterParen = after.indexOf(CLOSE, afterParen + 1);
+ afterParenOpen = after.indexOf(OPEN, afterParenOpen + 1);
}
- if (beforeParen === -1 || afterParen === -1) return;
+ if (beforeParen === -1 || afterParen === -1) return false;
// Set the selection to the text between the parenthesis
- const parenContent = target.value.substring(beforeParen + 1, selectionStart + afterParen);
+ const parenContent = text.substring(beforeParen + 1, selectionStart + afterParen);
const lastColon = parenContent.lastIndexOf(":");
selectionStart = beforeParen + 1;
selectionEnd = selectionStart + lastColon;
target.setSelectionRange(selectionStart, selectionEnd);
- }
+ return true;
+ }
+
+ // If the user hasn't selected anything, let's select their current parenthesis block
+ if(! selectCurrentParenthesisBlock('<', '>')){
+ selectCurrentParenthesisBlock('(', ')')
+ }
event.preventDefault();
- if (selectionStart == 0 || target.value[selectionStart - 1] != "(") {
- target.value = target.value.slice(0, selectionStart) +
- "(" + target.value.slice(selectionStart, selectionEnd) + ":1.0)" +
- target.value.slice(selectionEnd);
-
- target.focus();
- target.selectionStart = selectionStart + 1;
- target.selectionEnd = selectionEnd + 1;
-
- } else {
- end = target.value.slice(selectionEnd + 1).indexOf(")") + 1;
- weight = parseFloat(target.value.slice(selectionEnd + 1, selectionEnd + 1 + end));
- if (isNaN(weight)) return;
- if (event.key == minus) weight -= 0.1;
- if (event.key == plus) weight += 0.1;
-
- weight = parseFloat(weight.toPrecision(12));
-
- target.value = target.value.slice(0, selectionEnd + 1) +
- weight +
- target.value.slice(selectionEnd + 1 + end - 1);
-
- target.focus();
- target.selectionStart = selectionStart;
- target.selectionEnd = selectionEnd;
- }
- // Since we've modified a Gradio Textbox component manually, we need to simulate an `input` DOM event to ensure its
- // internal Svelte data binding remains in sync.
- target.dispatchEvent(new Event("input", { bubbles: true }));
-});
+ closeCharacter = ')'
+ delta = opts.keyedit_precision_attention
+
+ if (selectionStart > 0 && text[selectionStart - 1] == '<'){
+ closeCharacter = '>'
+ delta = opts.keyedit_precision_extra
+ } else if (selectionStart == 0 || text[selectionStart - 1] != "(") {
+
+ // do not include spaces at the end
+ while(selectionEnd > selectionStart && text[selectionEnd-1] == ' '){
+ selectionEnd -= 1;
+ }
+ if(selectionStart == selectionEnd){
+ return
+ }
+
+ text = text.slice(0, selectionStart) + "(" + text.slice(selectionStart, selectionEnd) + ":1.0)" + text.slice(selectionEnd);
+
+ selectionStart += 1;
+ selectionEnd += 1;
+ }
+
+ end = text.slice(selectionEnd + 1).indexOf(closeCharacter) + 1;
+ weight = parseFloat(text.slice(selectionEnd + 1, selectionEnd + 1 + end));
+ if (isNaN(weight)) return;
+
+ weight += isPlus ? delta : -delta;
+ weight = parseFloat(weight.toPrecision(12));
+ if(String(weight).length == 1) weight += ".0"
+
+ text = text.slice(0, selectionEnd + 1) + weight + text.slice(selectionEnd + 1 + end - 1);
+
+ target.focus();
+ target.value = text;
+ target.selectionStart = selectionStart;
+ target.selectionEnd = selectionEnd;
+
+ updateInput(target)
+}
+
+addEventListener('keydown', (event) => {
+ keyupEditAttention(event);
+}); \ No newline at end of file
diff --git a/javascript/extensions.js b/javascript/extensions.js
index 59179ca6..ac6e35b9 100644
--- a/javascript/extensions.js
+++ b/javascript/extensions.js
@@ -29,7 +29,7 @@ function install_extension_from_index(button, url){
textarea = gradioApp().querySelector('#extension_to_install textarea')
textarea.value = url
- textarea.dispatchEvent(new Event("input", { bubbles: true }))
+ updateInput(textarea)
gradioApp().querySelector('#install_extension_button').click()
}
diff --git a/javascript/extraNetworks.js b/javascript/extraNetworks.js
new file mode 100644
index 00000000..c5a9adb3
--- /dev/null
+++ b/javascript/extraNetworks.js
@@ -0,0 +1,69 @@
+
+function setupExtraNetworksForTab(tabname){
+ gradioApp().querySelector('#'+tabname+'_extra_tabs').classList.add('extra-networks')
+
+ var tabs = gradioApp().querySelector('#'+tabname+'_extra_tabs > div')
+ var search = gradioApp().querySelector('#'+tabname+'_extra_search textarea')
+ var refresh = gradioApp().getElementById(tabname+'_extra_refresh')
+ var close = gradioApp().getElementById(tabname+'_extra_close')
+
+ search.classList.add('search')
+ tabs.appendChild(search)
+ tabs.appendChild(refresh)
+ tabs.appendChild(close)
+
+ search.addEventListener("input", function(evt){
+ searchTerm = search.value.toLowerCase()
+
+ gradioApp().querySelectorAll('#'+tabname+'_extra_tabs div.card').forEach(function(elem){
+ text = elem.querySelector('.name').textContent.toLowerCase()
+ elem.style.display = text.indexOf(searchTerm) == -1 ? "none" : ""
+ })
+ });
+}
+
+var activePromptTextarea = {};
+
+function setupExtraNetworks(){
+ setupExtraNetworksForTab('txt2img')
+ setupExtraNetworksForTab('img2img')
+
+ function registerPrompt(tabname, id){
+ var textarea = gradioApp().querySelector("#" + id + " > label > textarea");
+
+ if (! activePromptTextarea[tabname]){
+ activePromptTextarea[tabname] = textarea
+ }
+
+ textarea.addEventListener("focus", function(){
+ activePromptTextarea[tabname] = textarea;
+ });
+ }
+
+ registerPrompt('txt2img', 'txt2img_prompt')
+ registerPrompt('txt2img', 'txt2img_neg_prompt')
+ registerPrompt('img2img', 'img2img_prompt')
+ registerPrompt('img2img', 'img2img_neg_prompt')
+}
+
+onUiLoaded(setupExtraNetworks)
+
+function cardClicked(tabname, textToAdd, allowNegativePrompt){
+ var textarea = allowNegativePrompt ? activePromptTextarea[tabname] : gradioApp().querySelector("#" + tabname + "_prompt > label > textarea")
+
+ textarea.value = textarea.value + " " + textToAdd
+ updateInput(textarea)
+}
+
+function saveCardPreview(event, tabname, filename){
+ var textarea = gradioApp().querySelector("#" + tabname + '_preview_filename > label > textarea')
+ var button = gradioApp().getElementById(tabname + '_save_preview')
+
+ textarea.value = filename
+ updateInput(textarea)
+
+ button.click()
+
+ event.stopPropagation()
+ event.preventDefault()
+}
diff --git a/javascript/hints.js b/javascript/hints.js
index fa5e5ae8..3cf10e20 100644
--- a/javascript/hints.js
+++ b/javascript/hints.js
@@ -14,13 +14,14 @@ titles = {
"Seed": "A value that determines the output of random number generator - if you create an image with same parameters and seed as another image, you'll get the same result",
"\u{1f3b2}\ufe0f": "Set seed to -1, which will cause a new random number to be used every time",
"\u267b\ufe0f": "Reuse seed from last generation, mostly useful if it was randomed",
- "\u{1f3a8}": "Add a random artist to the prompt.",
"\u2199\ufe0f": "Read generation parameters from prompt or last generation if prompt is empty into user interface.",
"\u{1f4c2}": "Open images output directory",
"\u{1f4be}": "Save style",
"\U0001F5D1": "Clear prompt",
"\u{1f4cb}": "Apply selected styles to current prompt",
"\u{1f4d2}": "Paste available values into the field",
+ "\u{1f3b4}": "Show extra networks",
+
"Inpaint a part of image": "Draw a mask over an image, and the script will regenerate the masked area with content according to prompt",
"SD upscale": "Upscale image normally, split result into tiles, improve each tile using img2img, merge whole image back",
@@ -92,6 +93,7 @@ titles = {
"Weighted sum": "Result = A * (1 - M) + B * M",
"Add difference": "Result = A + (B - C) * M",
+ "No interpolation": "Result = A",
"Initialization text": "If the number of tokens is more than the number of vectors, some may be skipped.\nLeave the textbox empty to start with zeroed out vectors",
"Learning rate": "How fast should training go. Low values will take longer to train, high values may fail to converge (not generate accurate results) and/or may break the embedding (This has happened if you see Loss: nan in the training info textbox. If this happens, you need to manually restore your embedding from an older not-broken backup).\n\nYou can set a single numeric value, or multiple learning rates using the syntax:\n\n rate_1:max_steps_1, rate_2:max_steps_2, ...\n\nEG: 0.005:100, 1e-3:1000, 1e-5\n\nWill train with rate of 0.005 for first 100 steps, then 1e-3 until 1000 steps, then 1e-5 for all remaining steps.",
@@ -105,7 +107,10 @@ titles = {
"Hires steps": "Number of sampling steps for upscaled picture. If 0, uses same as for original.",
"Upscale by": "Adjusts the size of the image by multiplying the original width and height by the selected value. Ignored if either Resize width to or Resize height to are non-zero.",
"Resize width to": "Resizes image to this width. If 0, width is inferred from either of two nearby sliders.",
- "Resize height to": "Resizes image to this height. If 0, height is inferred from either of two nearby sliders."
+ "Resize height to": "Resizes image to this height. If 0, height is inferred from either of two nearby sliders.",
+ "Multiplier for extra networks": "When adding extra network such as Hypernetwork or Lora to prompt, use this multiplier for it.",
+ "Discard weights with matching name": "Regular expression; if weights's name matches it, the weights is not written to the resulting checkpoint. Use ^model_ema to discard EMA weights.",
+ "Extra networks tab order": "Comma-separated list of tab names; tabs listed here will appear in the extra networks UI first and in order lsited."
}
diff --git a/javascript/hires_fix.js b/javascript/hires_fix.js
index 07fba549..0629475f 100644
--- a/javascript/hires_fix.js
+++ b/javascript/hires_fix.js
@@ -1,6 +1,5 @@
function setInactive(elem, inactive){
- console.log(elem)
if(inactive){
elem.classList.add('inactive')
} else{
@@ -9,8 +8,6 @@ function setInactive(elem, inactive){
}
function onCalcResolutionHires(enable, width, height, hr_scale, hr_resize_x, hr_resize_y){
- console.log(enable, width, height, hr_scale, hr_resize_x, hr_resize_y)
-
hrUpscaleBy = gradioApp().getElementById('txt2img_hr_scale')
hrResizeX = gradioApp().getElementById('txt2img_hr_resize_x')
hrResizeY = gradioApp().getElementById('txt2img_hr_resize_y')
diff --git a/javascript/imageviewer.js b/javascript/imageviewer.js
index 1f29ad7b..aac2ee82 100644
--- a/javascript/imageviewer.js
+++ b/javascript/imageviewer.js
@@ -148,7 +148,15 @@ function showGalleryImage() {
if(e && e.parentElement.tagName == 'DIV'){
e.style.cursor='pointer'
e.style.userSelect='none'
- e.addEventListener('mousedown', function (evt) {
+
+ var isFirefox = isFirefox = navigator.userAgent.toLowerCase().indexOf('firefox') > -1
+
+ // For Firefox, listening on click first switched to next image then shows the lightbox.
+ // If you know how to fix this without switching to mousedown event, please.
+ // For other browsers the event is click to make it possiblr to drag picture.
+ var event = isFirefox ? 'mousedown' : 'click'
+
+ e.addEventListener(event, function (evt) {
if(!opts.js_modal_lightbox || evt.button != 0) return;
modalZoomSet(gradioApp().getElementById('modalImage'), opts.js_modal_lightbox_initially_zoomed)
evt.preventDefault()
diff --git a/javascript/localization.js b/javascript/localization.js
index f92d2d24..1a5a1dbb 100644
--- a/javascript/localization.js
+++ b/javascript/localization.js
@@ -10,10 +10,8 @@ ignore_ids_for_localization={
modelmerger_tertiary_model_name: 'OPTION',
train_embedding: 'OPTION',
train_hypernetwork: 'OPTION',
- txt2img_style_index: 'OPTION',
- txt2img_style2_index: 'OPTION',
- img2img_style_index: 'OPTION',
- img2img_style2_index: 'OPTION',
+ txt2img_styles: 'OPTION',
+ img2img_styles: 'OPTION',
setting_random_artist_categories: 'SPAN',
setting_face_restoration_model: 'SPAN',
setting_realesrgan_enabled_models: 'SPAN',
diff --git a/javascript/progressbar.js b/javascript/progressbar.js
index da6709bc..ff6d757b 100644
--- a/javascript/progressbar.js
+++ b/javascript/progressbar.js
@@ -81,8 +81,13 @@ function request(url, data, handler, errorHandler){
xhr.onreadystatechange = function () {
if (xhr.readyState === 4) {
if (xhr.status === 200) {
- var js = JSON.parse(xhr.responseText);
- handler(js)
+ try {
+ var js = JSON.parse(xhr.responseText);
+ handler(js)
+ } catch (error) {
+ console.error(error);
+ errorHandler()
+ }
} else{
errorHandler()
}
@@ -106,6 +111,19 @@ function formatTime(secs){
}
}
+function setTitle(progress){
+ var title = 'Stable Diffusion'
+
+ if(opts.show_progress_in_title && progress){
+ title = '[' + progress.trim() + '] ' + title;
+ }
+
+ if(document.title != title){
+ document.title = title;
+ }
+}
+
+
function randomId(){
return "task(" + Math.random().toString(36).slice(2, 7) + Math.random().toString(36).slice(2, 7) + Math.random().toString(36).slice(2, 7)+")"
}
@@ -117,7 +135,7 @@ function requestProgress(id_task, progressbarContainer, gallery, atEnd, onProgre
var dateStart = new Date()
var wasEverActive = false
var parentProgressbar = progressbarContainer.parentNode
- var parentGallery = gallery.parentNode
+ var parentGallery = gallery ? gallery.parentNode : null
var divProgress = document.createElement('div')
divProgress.className='progressDiv'
@@ -128,18 +146,21 @@ function requestProgress(id_task, progressbarContainer, gallery, atEnd, onProgre
divProgress.appendChild(divInner)
parentProgressbar.insertBefore(divProgress, progressbarContainer)
- var livePreview = document.createElement('div')
- livePreview.className='livePreview'
- parentGallery.insertBefore(livePreview, gallery)
+ if(parentGallery){
+ var livePreview = document.createElement('div')
+ livePreview.className='livePreview'
+ parentGallery.insertBefore(livePreview, gallery)
+ }
var removeProgressBar = function(){
+ setTitle("")
parentProgressbar.removeChild(divProgress)
- parentGallery.removeChild(livePreview)
+ if(parentGallery) parentGallery.removeChild(livePreview)
atEnd()
}
var fun = function(id_task, id_live_preview){
- request("/internal/progress", {"id_task": id_task, "id_live_preview": id_live_preview}, function(res){
+ request("./internal/progress", {"id_task": id_task, "id_live_preview": id_live_preview}, function(res){
if(res.completed){
removeProgressBar()
return
@@ -154,6 +175,7 @@ function requestProgress(id_task, progressbarContainer, gallery, atEnd, onProgre
progressText = ""
divInner.style.width = ((res.progress || 0) * 100.0) + '%'
+ divInner.style.background = res.progress ? "" : "transparent"
if(res.progress > 0){
progressText = ((res.progress || 0) * 100.0).toFixed(0) + '%'
@@ -161,8 +183,13 @@ function requestProgress(id_task, progressbarContainer, gallery, atEnd, onProgre
if(res.eta){
progressText += " ETA: " + formatTime(res.eta)
- } else if(res.textinfo){
- progressText += " " + res.textinfo
+ }
+
+
+ setTitle(progressText)
+
+ if(res.textinfo && res.textinfo.indexOf("\n") == -1){
+ progressText = res.textinfo + " " + progressText
}
divInner.textContent = progressText
@@ -182,8 +209,7 @@ function requestProgress(id_task, progressbarContainer, gallery, atEnd, onProgre
}
- if(res.live_preview){
-
+ if(res.live_preview && gallery){
var rect = gallery.getBoundingClientRect()
if(rect.width){
livePreview.style.width = rect.width + "px"
diff --git a/javascript/ui.js b/javascript/ui.js
index ecf97cb3..ba72623c 100644
--- a/javascript/ui.js
+++ b/javascript/ui.js
@@ -104,9 +104,11 @@ function create_tab_index_args(tabId, args){
return res
}
-function get_extras_tab_index(){
- const [,,...args] = [...arguments]
- return [get_tab_index('mode_extras'), get_tab_index('extras_resize_mode'), ...args]
+function get_img2img_tab_index() {
+ let res = args_to_array(arguments)
+ res.splice(-2)
+ res[0] = get_tab_index('mode_img2img')
+ return res
}
function create_submit_args(args){
@@ -165,6 +167,15 @@ function submit_img2img(){
return res
}
+function modelmerger(){
+ var id = randomId()
+ requestProgress(id, gradioApp().getElementById('modelmerger_results_panel'), null, function(){})
+
+ var res = create_submit_args(arguments)
+ res[0] = id
+ return res
+}
+
function ask_for_style_name(_, prompt_text, negative_prompt_text) {
name_ = prompt('Style name:')
@@ -180,8 +191,6 @@ function confirm_clear_prompt(prompt, negative_prompt) {
return [prompt, negative_prompt]
}
-
-
opts = {}
onUiUpdate(function(){
if(Object.keys(opts).length != 0) return;
@@ -189,8 +198,8 @@ onUiUpdate(function(){
json_elem = gradioApp().getElementById('settings_json')
if(json_elem == null) return;
- textarea = json_elem.querySelector('textarea')
- jsdata = textarea.value
+ var textarea = json_elem.querySelector('textarea')
+ var jsdata = textarea.value
opts = JSON.parse(jsdata)
executeCallbacks(optionsChangedCallbacks);
@@ -214,14 +223,29 @@ onUiUpdate(function(){
json_elem.parentElement.style.display="none"
- if (!txt2img_textarea) {
- txt2img_textarea = gradioApp().querySelector("#txt2img_prompt > label > textarea");
- txt2img_textarea?.addEventListener("input", () => update_token_counter("txt2img_token_button"));
- }
- if (!img2img_textarea) {
- img2img_textarea = gradioApp().querySelector("#img2img_prompt > label > textarea");
- img2img_textarea?.addEventListener("input", () => update_token_counter("img2img_token_button"));
- }
+ function registerTextarea(id, id_counter, id_button){
+ var prompt = gradioApp().getElementById(id)
+ var counter = gradioApp().getElementById(id_counter)
+ var textarea = gradioApp().querySelector("#" + id + " > label > textarea");
+
+ if(counter.parentElement == prompt.parentElement){
+ return
+ }
+
+
+ prompt.parentElement.insertBefore(counter, prompt)
+ counter.classList.add("token-counter")
+ prompt.parentElement.style.position = "relative"
+
+ textarea.addEventListener("input", function(){
+ update_token_counter(id_button);
+ });
+ }
+
+ registerTextarea('txt2img_prompt', 'txt2img_token_counter', 'txt2img_token_button')
+ registerTextarea('txt2img_neg_prompt', 'txt2img_negative_token_counter', 'txt2img_negative_token_button')
+ registerTextarea('img2img_prompt', 'img2img_token_counter', 'img2img_token_button')
+ registerTextarea('img2img_neg_prompt', 'img2img_negative_token_counter', 'img2img_negative_token_button')
show_all_pages = gradioApp().getElementById('settings_show_all_pages')
settings_tabs = gradioApp().querySelector('#settings div')
@@ -235,7 +259,6 @@ onUiUpdate(function(){
}
})
-
onOptionsChanged(function(){
elem = gradioApp().getElementById('sd_checkpoint_hash')
sd_checkpoint_hash = opts.sd_checkpoint_hash || ""
@@ -278,3 +301,11 @@ function restart_reload(){
return []
}
+
+// Simulate an `input` DOM event for Gradio Textbox component. Needed after you edit its contents in javascript, otherwise your edits
+// will only visible on web page and not sent to python.
+function updateInput(target){
+ let e = new Event("input", { bubbles: true })
+ Object.defineProperty(e, "target", {value: target})
+ target.dispatchEvent(e);
+}
diff --git a/launch.py b/launch.py
index f51f23f7..51c322c0 100644
--- a/launch.py
+++ b/launch.py
@@ -284,6 +284,8 @@ def tests(test_dir):
sys.argv.append("./test/test_files/empty.pt")
if "--skip-torch-cuda-test" not in sys.argv:
sys.argv.append("--skip-torch-cuda-test")
+ if "--disable-nan-check" not in sys.argv:
+ sys.argv.append("--disable-nan-check")
print(f"Launching Web UI in another process for testing with arguments: {' '.join(sys.argv[1:])}")
diff --git a/modules/api/api.py b/modules/api/api.py
index 9814bbc2..5d60fc0a 100644
--- a/modules/api/api.py
+++ b/modules/api/api.py
@@ -11,10 +11,9 @@ from fastapi.security import HTTPBasic, HTTPBasicCredentials
from secrets import compare_digest
import modules.shared as shared
-from modules import sd_samplers, deepbooru, sd_hijack, images, scripts, ui
+from modules import sd_samplers, deepbooru, sd_hijack, images, scripts, ui, postprocessing
from modules.api.models import *
from modules.processing import StableDiffusionProcessingTxt2Img, StableDiffusionProcessingImg2Img, process_images
-from modules.extras import run_extras
from modules.textual_inversion.textual_inversion import create_embedding, train_embedding
from modules.textual_inversion.preprocess import preprocess
from modules.hypernetworks.hypernetwork import create_hypernetwork, train_hypernetwork
@@ -45,10 +44,8 @@ def validate_sampler_name(name):
def setUpscalers(req: dict):
reqDict = vars(req)
- reqDict['extras_upscaler_1'] = upscaler_to_index(req.upscaler_1)
- reqDict['extras_upscaler_2'] = upscaler_to_index(req.upscaler_2)
- reqDict.pop('upscaler_1')
- reqDict.pop('upscaler_2')
+ reqDict['extras_upscaler_1'] = reqDict.pop('upscaler_1', None)
+ reqDict['extras_upscaler_2'] = reqDict.pop('upscaler_2', None)
return reqDict
def decode_base64_to_image(encoding):
@@ -126,8 +123,6 @@ class Api:
self.add_api_route("/sdapi/v1/face-restorers", self.get_face_restorers, methods=["GET"], response_model=List[FaceRestorerItem])
self.add_api_route("/sdapi/v1/realesrgan-models", self.get_realesrgan_models, methods=["GET"], response_model=List[RealesrganItem])
self.add_api_route("/sdapi/v1/prompt-styles", self.get_prompt_styles, methods=["GET"], response_model=List[PromptStyleItem])
- self.add_api_route("/sdapi/v1/artist-categories", self.get_artists_categories, methods=["GET"], response_model=List[str])
- self.add_api_route("/sdapi/v1/artists", self.get_artists, methods=["GET"], response_model=List[ArtistItem])
self.add_api_route("/sdapi/v1/embeddings", self.get_embeddings, methods=["GET"], response_model=EmbeddingsResponse)
self.add_api_route("/sdapi/v1/refresh-checkpoints", self.refresh_checkpoints, methods=["POST"])
self.add_api_route("/sdapi/v1/create/embedding", self.create_embedding, methods=["POST"], response_model=CreateResponse)
@@ -246,7 +241,7 @@ class Api:
reqDict['image'] = decode_base64_to_image(reqDict['image'])
with self.queue_lock:
- result = run_extras(extras_mode=0, image_folder="", input_dir="", output_dir="", save_output=False, **reqDict)
+ result = postprocessing.run_extras(extras_mode=0, image_folder="", input_dir="", output_dir="", save_output=False, **reqDict)
return ExtrasSingleImageResponse(image=encode_pil_to_base64(result[0][0]), html_info=result[1])
@@ -262,7 +257,7 @@ class Api:
reqDict.pop('imageList')
with self.queue_lock:
- result = run_extras(extras_mode=1, image="", input_dir="", output_dir="", save_output=False, **reqDict)
+ result = postprocessing.run_extras(extras_mode=1, image="", input_dir="", output_dir="", save_output=False, **reqDict)
return ExtrasBatchImagesResponse(images=list(map(encode_pil_to_base64, result[0])), html_info=result[1])
@@ -390,12 +385,6 @@ class Api:
return styleList
- def get_artists_categories(self):
- return shared.artist_db.cats
-
- def get_artists(self):
- return [{"name":x[0], "score":x[1], "category":x[2]} for x in shared.artist_db.artists]
-
def get_embeddings(self):
db = sd_hijack.model_hijack.embedding_db
@@ -480,7 +469,7 @@ class Api:
def train_hypernetwork(self, args: dict):
try:
shared.state.begin()
- initial_hypernetwork = shared.loaded_hypernetwork
+ shared.loaded_hypernetworks = []
apply_optimizations = shared.opts.training_xattention_optimizations
error = None
filename = ''
@@ -491,16 +480,15 @@ class Api:
except Exception as e:
error = e
finally:
- shared.loaded_hypernetwork = initial_hypernetwork
shared.sd_model.cond_stage_model.to(devices.device)
shared.sd_model.first_stage_model.to(devices.device)
if not apply_optimizations:
sd_hijack.apply_optimizations()
shared.state.end()
- return TrainResponse(info = "train embedding complete: filename: {filename} error: {error}".format(filename = filename, error = error))
+ return TrainResponse(info="train embedding complete: filename: {filename} error: {error}".format(filename=filename, error=error))
except AssertionError as msg:
shared.state.end()
- return TrainResponse(info = "train embedding error: {error}".format(error = error))
+ return TrainResponse(info="train embedding error: {error}".format(error=error))
def get_memory(self):
try:
diff --git a/modules/artists.py b/modules/artists.py
deleted file mode 100644
index 3612758b..00000000
--- a/modules/artists.py
+++ /dev/null
@@ -1,25 +0,0 @@
-import os.path
-import csv
-from collections import namedtuple
-
-Artist = namedtuple("Artist", ['name', 'weight', 'category'])
-
-
-class ArtistsDatabase:
- def __init__(self, filename):
- self.cats = set()
- self.artists = []
-
- if not os.path.exists(filename):
- return
-
- with open(filename, "r", newline='', encoding="utf8") as file:
- reader = csv.DictReader(file)
-
- for row in reader:
- artist = Artist(row["artist"], float(row["score"]), row["category"])
- self.artists.append(artist)
- self.cats.add(artist.category)
-
- def categories(self):
- return sorted(self.cats)
diff --git a/modules/devices.py b/modules/devices.py
index 6f034948..524ec7af 100644
--- a/modules/devices.py
+++ b/modules/devices.py
@@ -113,6 +113,9 @@ class NansException(Exception):
def test_for_nans(x, where):
from modules import shared
+ if shared.cmd_opts.disable_nan_check:
+ return
+
if not torch.all(torch.isnan(x)).item():
return
@@ -166,8 +169,10 @@ orig_Tensor_cumsum = torch.Tensor.cumsum
def cumsum_fix(input, cumsum_func, *args, **kwargs):
if input.device.type == 'mps':
output_dtype = kwargs.get('dtype', input.dtype)
- if any(output_dtype == broken_dtype for broken_dtype in [torch.bool, torch.int8, torch.int16, torch.int64]):
+ if output_dtype == torch.int64:
return cumsum_func(input.cpu(), *args, **kwargs).to(input.device)
+ elif cumsum_needs_bool_fix and output_dtype == torch.bool or cumsum_needs_int_fix and (output_dtype == torch.int8 or output_dtype == torch.int16):
+ return cumsum_func(input.to(torch.int32), *args, **kwargs).to(torch.int64)
return cumsum_func(input, *args, **kwargs)
@@ -178,9 +183,10 @@ if has_mps():
torch.nn.functional.layer_norm = layer_norm_fix
torch.Tensor.numpy = numpy_fix
elif version.parse(torch.__version__) > version.parse("1.13.1"):
- if not torch.Tensor([1,2]).to(torch.device("mps")).equal(torch.Tensor([1,1]).to(torch.device("mps")).cumsum(0, dtype=torch.int16)):
- torch.cumsum = lambda input, *args, **kwargs: ( cumsum_fix(input, orig_cumsum, *args, **kwargs) )
- torch.Tensor.cumsum = lambda self, *args, **kwargs: ( cumsum_fix(self, orig_Tensor_cumsum, *args, **kwargs) )
+ cumsum_needs_int_fix = not torch.Tensor([1,2]).to(torch.device("mps")).equal(torch.ShortTensor([1,1]).to(torch.device("mps")).cumsum(0))
+ cumsum_needs_bool_fix = not torch.BoolTensor([True,True]).to(device=torch.device("mps"), dtype=torch.int64).equal(torch.BoolTensor([True,False]).to(torch.device("mps")).cumsum(0))
+ torch.cumsum = lambda input, *args, **kwargs: ( cumsum_fix(input, orig_cumsum, *args, **kwargs) )
+ torch.Tensor.cumsum = lambda self, *args, **kwargs: ( cumsum_fix(self, orig_Tensor_cumsum, *args, **kwargs) )
orig_narrow = torch.narrow
torch.narrow = lambda *args, **kwargs: ( orig_narrow(*args, **kwargs).clone() )
diff --git a/modules/errors.py b/modules/errors.py
index a668c014..f6b80dbb 100644
--- a/modules/errors.py
+++ b/modules/errors.py
@@ -19,11 +19,23 @@ def display(e: Exception, task):
message = str(e)
if "copying a param with shape torch.Size([640, 1024]) from checkpoint, the shape in current model is torch.Size([640, 768])" in message:
print_error_explanation("""
-The most likely cause of this is you are trying to load Stable Diffusion 2.0 model without specifying its connfig file.
+The most likely cause of this is you are trying to load Stable Diffusion 2.0 model without specifying its config file.
See https://github.com/AUTOMATIC1111/stable-diffusion-webui/wiki/Features#stable-diffusion-20 for how to solve this.
""")
+already_displayed = {}
+
+
+def display_once(e: Exception, task):
+ if task in already_displayed:
+ return
+
+ display(e, task)
+
+ already_displayed[task] = 1
+
+
def run(code, task):
try:
code()
diff --git a/modules/extra_networks.py b/modules/extra_networks.py
new file mode 100644
index 00000000..1978673d
--- /dev/null
+++ b/modules/extra_networks.py
@@ -0,0 +1,147 @@
+import re
+from collections import defaultdict
+
+from modules import errors
+
+extra_network_registry = {}
+
+
+def initialize():
+ extra_network_registry.clear()
+
+
+def register_extra_network(extra_network):
+ extra_network_registry[extra_network.name] = extra_network
+
+
+class ExtraNetworkParams:
+ def __init__(self, items=None):
+ self.items = items or []
+
+
+class ExtraNetwork:
+ def __init__(self, name):
+ self.name = name
+
+ def activate(self, p, params_list):
+ """
+ Called by processing on every run. Whatever the extra network is meant to do should be activated here.
+ Passes arguments related to this extra network in params_list.
+ User passes arguments by specifying this in his prompt:
+
+ <name:arg1:arg2:arg3>
+
+ Where name matches the name of this ExtraNetwork object, and arg1:arg2:arg3 are any natural number of text arguments
+ separated by colon.
+
+ Even if the user does not mention this ExtraNetwork in his prompt, the call will stil be made, with empty params_list -
+ in this case, all effects of this extra networks should be disabled.
+
+ Can be called multiple times before deactivate() - each new call should override the previous call completely.
+
+ For example, if this ExtraNetwork's name is 'hypernet' and user's prompt is:
+
+ > "1girl, <hypernet:agm:1.1> <extrasupernet:master:12:13:14> <hypernet:ray>"
+
+ params_list will be:
+
+ [
+ ExtraNetworkParams(items=["agm", "1.1"]),
+ ExtraNetworkParams(items=["ray"])
+ ]
+
+ """
+ raise NotImplementedError
+
+ def deactivate(self, p):
+ """
+ Called at the end of processing for housekeeping. No need to do anything here.
+ """
+
+ raise NotImplementedError
+
+
+def activate(p, extra_network_data):
+ """call activate for extra networks in extra_network_data in specified order, then call
+ activate for all remaining registered networks with an empty argument list"""
+
+ for extra_network_name, extra_network_args in extra_network_data.items():
+ extra_network = extra_network_registry.get(extra_network_name, None)
+ if extra_network is None:
+ print(f"Skipping unknown extra network: {extra_network_name}")
+ continue
+
+ try:
+ extra_network.activate(p, extra_network_args)
+ except Exception as e:
+ errors.display(e, f"activating extra network {extra_network_name} with arguments {extra_network_args}")
+
+ for extra_network_name, extra_network in extra_network_registry.items():
+ args = extra_network_data.get(extra_network_name, None)
+ if args is not None:
+ continue
+
+ try:
+ extra_network.activate(p, [])
+ except Exception as e:
+ errors.display(e, f"activating extra network {extra_network_name}")
+
+
+def deactivate(p, extra_network_data):
+ """call deactivate for extra networks in extra_network_data in specified order, then call
+ deactivate for all remaining registered networks"""
+
+ for extra_network_name, extra_network_args in extra_network_data.items():
+ extra_network = extra_network_registry.get(extra_network_name, None)
+ if extra_network is None:
+ continue
+
+ try:
+ extra_network.deactivate(p)
+ except Exception as e:
+ errors.display(e, f"deactivating extra network {extra_network_name}")
+
+ for extra_network_name, extra_network in extra_network_registry.items():
+ args = extra_network_data.get(extra_network_name, None)
+ if args is not None:
+ continue
+
+ try:
+ extra_network.deactivate(p)
+ except Exception as e:
+ errors.display(e, f"deactivating unmentioned extra network {extra_network_name}")
+
+
+re_extra_net = re.compile(r"<(\w+):([^>]+)>")
+
+
+def parse_prompt(prompt):
+ res = defaultdict(list)
+
+ def found(m):
+ name = m.group(1)
+ args = m.group(2)
+
+ res[name].append(ExtraNetworkParams(items=args.split(":")))
+
+ return ""
+
+ prompt = re.sub(re_extra_net, found, prompt)
+
+ return prompt, res
+
+
+def parse_prompts(prompts):
+ res = []
+ extra_data = None
+
+ for prompt in prompts:
+ updated_prompt, parsed_extra_data = parse_prompt(prompt)
+
+ if extra_data is None:
+ extra_data = parsed_extra_data
+
+ res.append(updated_prompt)
+
+ return res, extra_data
+
diff --git a/modules/extra_networks_hypernet.py b/modules/extra_networks_hypernet.py
new file mode 100644
index 00000000..ff279a1f
--- /dev/null
+++ b/modules/extra_networks_hypernet.py
@@ -0,0 +1,21 @@
+from modules import extra_networks
+from modules.hypernetworks import hypernetwork
+
+
+class ExtraNetworkHypernet(extra_networks.ExtraNetwork):
+ def __init__(self):
+ super().__init__('hypernet')
+
+ def activate(self, p, params_list):
+ names = []
+ multipliers = []
+ for params in params_list:
+ assert len(params.items) > 0
+
+ names.append(params.items[0])
+ multipliers.append(float(params.items[1]) if len(params.items) > 1 else 1.0)
+
+ hypernetwork.load_hypernetworks(names, multipliers)
+
+ def deactivate(self, p):
+ pass
diff --git a/modules/extras.py b/modules/extras.py
index 22668fcd..36123aa5 100644
--- a/modules/extras.py
+++ b/modules/extras.py
@@ -1,230 +1,16 @@
-from __future__ import annotations
-import math
import os
-import sys
-import traceback
+import re
import shutil
-import numpy as np
-from PIL import Image
import torch
import tqdm
-from typing import Callable, List, OrderedDict, Tuple
-from functools import partial
-from dataclasses import dataclass
-
-from modules import processing, shared, images, devices, sd_models, sd_samplers
-from modules.shared import opts
-import modules.gfpgan_model
-from modules.ui import plaintext_to_html
-import modules.codeformer_model
+from modules import shared, images, sd_models, sd_vae
+from modules.ui_common import plaintext_to_html
import gradio as gr
import safetensors.torch
-class LruCache(OrderedDict):
- @dataclass(frozen=True)
- class Key:
- image_hash: int
- info_hash: int
- args_hash: int
-
- @dataclass
- class Value:
- image: Image.Image
- info: str
-
- def __init__(self, max_size: int = 5, *args, **kwargs):
- super().__init__(*args, **kwargs)
- self._max_size = max_size
-
- def get(self, key: LruCache.Key) -> LruCache.Value:
- ret = super().get(key)
- if ret is not None:
- self.move_to_end(key) # Move to end of eviction list
- return ret
-
- def put(self, key: LruCache.Key, value: LruCache.Value) -> None:
- self[key] = value
- while len(self) > self._max_size:
- self.popitem(last=False)
-
-
-cached_images: LruCache = LruCache(max_size=5)
-
-
-def run_extras(extras_mode, resize_mode, image, image_folder, input_dir, output_dir, show_extras_results, gfpgan_visibility, codeformer_visibility, codeformer_weight, upscaling_resize, upscaling_resize_w, upscaling_resize_h, upscaling_crop, extras_upscaler_1, extras_upscaler_2, extras_upscaler_2_visibility, upscale_first: bool, save_output: bool = True):
- devices.torch_gc()
-
- shared.state.begin()
- shared.state.job = 'extras'
-
- imageArr = []
- # Also keep track of original file names
- imageNameArr = []
- outputs = []
-
- if extras_mode == 1:
- #convert file to pillow image
- for img in image_folder:
- image = Image.open(img)
- imageArr.append(image)
- imageNameArr.append(os.path.splitext(img.orig_name)[0])
- elif extras_mode == 2:
- assert not shared.cmd_opts.hide_ui_dir_config, '--hide-ui-dir-config option must be disabled'
-
- if input_dir == '':
- return outputs, "Please select an input directory.", ''
- image_list = shared.listfiles(input_dir)
- for img in image_list:
- try:
- image = Image.open(img)
- except Exception:
- continue
- imageArr.append(image)
- imageNameArr.append(img)
- else:
- imageArr.append(image)
- imageNameArr.append(None)
-
- if extras_mode == 2 and output_dir != '':
- outpath = output_dir
- else:
- outpath = opts.outdir_samples or opts.outdir_extras_samples
-
- # Extra operation definitions
-
- def run_gfpgan(image: Image.Image, info: str) -> Tuple[Image.Image, str]:
- shared.state.job = 'extras-gfpgan'
- restored_img = modules.gfpgan_model.gfpgan_fix_faces(np.array(image, dtype=np.uint8))
- res = Image.fromarray(restored_img)
-
- if gfpgan_visibility < 1.0:
- res = Image.blend(image, res, gfpgan_visibility)
-
- info += f"GFPGAN visibility:{round(gfpgan_visibility, 2)}\n"
- return (res, info)
-
- def run_codeformer(image: Image.Image, info: str) -> Tuple[Image.Image, str]:
- shared.state.job = 'extras-codeformer'
- restored_img = modules.codeformer_model.codeformer.restore(np.array(image, dtype=np.uint8), w=codeformer_weight)
- res = Image.fromarray(restored_img)
-
- if codeformer_visibility < 1.0:
- res = Image.blend(image, res, codeformer_visibility)
-
- info += f"CodeFormer w: {round(codeformer_weight, 2)}, CodeFormer visibility:{round(codeformer_visibility, 2)}\n"
- return (res, info)
-
- def upscale(image, scaler_index, resize, mode, resize_w, resize_h, crop):
- shared.state.job = 'extras-upscale'
- upscaler = shared.sd_upscalers[scaler_index]
- res = upscaler.scaler.upscale(image, resize, upscaler.data_path)
- if mode == 1 and crop:
- cropped = Image.new("RGB", (resize_w, resize_h))
- cropped.paste(res, box=(resize_w // 2 - res.width // 2, resize_h // 2 - res.height // 2))
- res = cropped
- return res
-
- def run_prepare_crop(image: Image.Image, info: str) -> Tuple[Image.Image, str]:
- # Actual crop happens in run_upscalers_blend, this just sets upscaling_resize and adds info text
- nonlocal upscaling_resize
- if resize_mode == 1:
- upscaling_resize = max(upscaling_resize_w/image.width, upscaling_resize_h/image.height)
- crop_info = " (crop)" if upscaling_crop else ""
- info += f"Resize to: {upscaling_resize_w:g}x{upscaling_resize_h:g}{crop_info}\n"
- return (image, info)
-
- @dataclass
- class UpscaleParams:
- upscaler_idx: int
- blend_alpha: float
-
- def run_upscalers_blend(params: List[UpscaleParams], image: Image.Image, info: str) -> Tuple[Image.Image, str]:
- blended_result: Image.Image = None
- image_hash: str = hash(np.array(image.getdata()).tobytes())
- for upscaler in params:
- upscale_args = (upscaler.upscaler_idx, upscaling_resize, resize_mode,
- upscaling_resize_w, upscaling_resize_h, upscaling_crop)
- cache_key = LruCache.Key(image_hash=image_hash,
- info_hash=hash(info),
- args_hash=hash(upscale_args))
- cached_entry = cached_images.get(cache_key)
- if cached_entry is None:
- res = upscale(image, *upscale_args)
- info += f"Upscale: {round(upscaling_resize, 3)}, visibility: {upscaler.blend_alpha}, model:{shared.sd_upscalers[upscaler.upscaler_idx].name}\n"
- cached_images.put(cache_key, LruCache.Value(image=res, info=info))
- else:
- res, info = cached_entry.image, cached_entry.info
-
- if blended_result is None:
- blended_result = res
- else:
- blended_result = Image.blend(blended_result, res, upscaler.blend_alpha)
- return (blended_result, info)
-
- # Build a list of operations to run
- facefix_ops: List[Callable] = []
- facefix_ops += [run_gfpgan] if gfpgan_visibility > 0 else []
- facefix_ops += [run_codeformer] if codeformer_visibility > 0 else []
-
- upscale_ops: List[Callable] = []
- upscale_ops += [run_prepare_crop] if resize_mode == 1 else []
-
- if upscaling_resize != 0:
- step_params: List[UpscaleParams] = []
- step_params.append(UpscaleParams(upscaler_idx=extras_upscaler_1, blend_alpha=1.0))
- if extras_upscaler_2 != 0 and extras_upscaler_2_visibility > 0:
- step_params.append(UpscaleParams(upscaler_idx=extras_upscaler_2, blend_alpha=extras_upscaler_2_visibility))
-
- upscale_ops.append(partial(run_upscalers_blend, step_params))
-
- extras_ops: List[Callable] = (upscale_ops + facefix_ops) if upscale_first else (facefix_ops + upscale_ops)
-
- for image, image_name in zip(imageArr, imageNameArr):
- if image is None:
- return outputs, "Please select an input image.", ''
-
- shared.state.textinfo = f'Processing image {image_name}'
-
- existing_pnginfo = image.info or {}
-
- image = image.convert("RGB")
- info = ""
- # Run each operation on each image
- for op in extras_ops:
- image, info = op(image, info)
-
- if opts.use_original_name_batch and image_name is not None:
- basename = os.path.splitext(os.path.basename(image_name))[0]
- else:
- basename = ''
-
- if opts.enable_pnginfo: # append info before save
- image.info = existing_pnginfo
- image.info["extras"] = info
-
- if save_output:
- # Add upscaler name as a suffix.
- suffix = f"-{shared.sd_upscalers[extras_upscaler_1].name}" if shared.opts.use_upscaler_name_as_suffix else ""
- # Add second upscaler if applicable.
- if suffix and extras_upscaler_2 and extras_upscaler_2_visibility:
- suffix += f"-{shared.sd_upscalers[extras_upscaler_2].name}"
-
- images.save_image(image, path=outpath, basename=basename, seed=None, prompt=None, extension=opts.samples_format, info=info, short_filename=True,
- no_prompt=True, grid=False, pnginfo_section_name="extras", existing_info=existing_pnginfo, forced_filename=None, suffix=suffix)
-
- if extras_mode != 2 or show_extras_results :
- outputs.append(image)
-
- devices.torch_gc()
-
- return outputs, plaintext_to_html(info), ''
-
-def clear_cache():
- cached_images.clear()
-
def run_pnginfo(image):
if image is None:
@@ -251,7 +37,8 @@ def run_pnginfo(image):
def create_config(ckpt_result, config_source, a, b, c):
def config(x):
- return sd_models.find_checkpoint_config(x) if x else None
+ res = sd_models.find_checkpoint_config(x) if x else None
+ return res if res != shared.sd_default_config else None
if config_source == 0:
cfg = config(a) or config(b) or config(c)
@@ -274,10 +61,25 @@ def create_config(ckpt_result, config_source, a, b, c):
shutil.copyfile(cfg, checkpoint_filename)
-def run_modelmerger(primary_model_name, secondary_model_name, tertiary_model_name, interp_method, multiplier, save_as_half, custom_name, checkpoint_format, config_source):
+checkpoint_dict_skip_on_merge = ["cond_stage_model.transformer.text_model.embeddings.position_ids"]
+
+
+def to_half(tensor, enable):
+ if enable and tensor.dtype == torch.float:
+ return tensor.half()
+
+ return tensor
+
+
+def run_modelmerger(id_task, primary_model_name, secondary_model_name, tertiary_model_name, interp_method, multiplier, save_as_half, custom_name, checkpoint_format, config_source, bake_in_vae, discard_weights):
shared.state.begin()
shared.state.job = 'model-merge'
+ def fail(message):
+ shared.state.textinfo = message
+ shared.state.end()
+ return [*[gr.update() for _ in range(4)], message]
+
def weighted_sum(theta0, theta1, alpha):
return ((1 - alpha) * theta0) + (alpha * theta1)
@@ -287,57 +89,96 @@ def run_modelmerger(primary_model_name, secondary_model_name, tertiary_model_nam
def add_difference(theta0, theta1_2_diff, alpha):
return theta0 + (alpha * theta1_2_diff)
- primary_model_info = sd_models.checkpoints_list[primary_model_name]
- secondary_model_info = sd_models.checkpoints_list[secondary_model_name]
- tertiary_model_info = sd_models.checkpoints_list.get(tertiary_model_name, None)
- result_is_inpainting_model = False
+ def filename_weighted_sum():
+ a = primary_model_info.model_name
+ b = secondary_model_info.model_name
+ Ma = round(1 - multiplier, 2)
+ Mb = round(multiplier, 2)
+
+ return f"{Ma}({a}) + {Mb}({b})"
+
+ def filename_add_difference():
+ a = primary_model_info.model_name
+ b = secondary_model_info.model_name
+ c = tertiary_model_info.model_name
+ M = round(multiplier, 2)
+
+ return f"{a} + {M}({b} - {c})"
+
+ def filename_nothing():
+ return primary_model_info.model_name
theta_funcs = {
- "Weighted sum": (None, weighted_sum),
- "Add difference": (get_difference, add_difference),
+ "Weighted sum": (filename_weighted_sum, None, weighted_sum),
+ "Add difference": (filename_add_difference, get_difference, add_difference),
+ "No interpolation": (filename_nothing, None, None),
}
- theta_func1, theta_func2 = theta_funcs[interp_method]
+ filename_generator, theta_func1, theta_func2 = theta_funcs[interp_method]
+ shared.state.job_count = (1 if theta_func1 else 0) + (1 if theta_func2 else 0)
- if theta_func1 and not tertiary_model_info:
- shared.state.textinfo = "Failed: Interpolation method requires a tertiary model."
- shared.state.end()
- return ["Failed: Interpolation method requires a tertiary model."] + [gr.Dropdown.update(choices=sd_models.checkpoint_tiles()) for _ in range(4)]
+ if not primary_model_name:
+ return fail("Failed: Merging requires a primary model.")
+
+ primary_model_info = sd_models.checkpoints_list[primary_model_name]
+
+ if theta_func2 and not secondary_model_name:
+ return fail("Failed: Merging requires a secondary model.")
+
+ secondary_model_info = sd_models.checkpoints_list[secondary_model_name] if theta_func2 else None
+
+ if theta_func1 and not tertiary_model_name:
+ return fail(f"Failed: Interpolation method ({interp_method}) requires a tertiary model.")
- shared.state.textinfo = f"Loading {secondary_model_info.filename}..."
- print(f"Loading {secondary_model_info.filename}...")
- theta_1 = sd_models.read_state_dict(secondary_model_info.filename, map_location='cpu')
+ tertiary_model_info = sd_models.checkpoints_list[tertiary_model_name] if theta_func1 else None
+
+ result_is_inpainting_model = False
+
+ if theta_func2:
+ shared.state.textinfo = f"Loading B"
+ print(f"Loading {secondary_model_info.filename}...")
+ theta_1 = sd_models.read_state_dict(secondary_model_info.filename, map_location='cpu')
+ else:
+ theta_1 = None
if theta_func1:
+ shared.state.textinfo = f"Loading C"
print(f"Loading {tertiary_model_info.filename}...")
theta_2 = sd_models.read_state_dict(tertiary_model_info.filename, map_location='cpu')
+ shared.state.textinfo = 'Merging B and C'
+ shared.state.sampling_steps = len(theta_1.keys())
for key in tqdm.tqdm(theta_1.keys()):
+ if key in checkpoint_dict_skip_on_merge:
+ continue
+
if 'model' in key:
if key in theta_2:
t2 = theta_2.get(key, torch.zeros_like(theta_1[key]))
theta_1[key] = theta_func1(theta_1[key], t2)
else:
theta_1[key] = torch.zeros_like(theta_1[key])
+
+ shared.state.sampling_step += 1
del theta_2
+ shared.state.nextjob()
+
shared.state.textinfo = f"Loading {primary_model_info.filename}..."
print(f"Loading {primary_model_info.filename}...")
theta_0 = sd_models.read_state_dict(primary_model_info.filename, map_location='cpu')
print("Merging...")
-
- chckpoint_dict_skip_on_merge = ["cond_stage_model.transformer.text_model.embeddings.position_ids"]
-
+ shared.state.textinfo = 'Merging A and B'
+ shared.state.sampling_steps = len(theta_0.keys())
for key in tqdm.tqdm(theta_0.keys()):
- if 'model' in key and key in theta_1:
+ if theta_1 and 'model' in key and key in theta_1:
- if key in chckpoint_dict_skip_on_merge:
+ if key in checkpoint_dict_skip_on_merge:
continue
a = theta_0[key]
b = theta_1[key]
- shared.state.textinfo = f'Merging layer {key}'
# this enables merging an inpainting model (A) with another one (B);
# where normal model would have 4 channels, for latenst space, inpainting model would
# have another 4 channels for unmasked picture's latent space, plus one channel for mask, for a total of 9
@@ -352,36 +193,45 @@ def run_modelmerger(primary_model_name, secondary_model_name, tertiary_model_nam
else:
theta_0[key] = theta_func2(a, b, multiplier)
- if save_as_half:
- theta_0[key] = theta_0[key].half()
-
- # I believe this part should be discarded, but I'll leave it for now until I am sure
- for key in theta_1.keys():
- if 'model' in key and key not in theta_0:
+ theta_0[key] = to_half(theta_0[key], save_as_half)
- if key in chckpoint_dict_skip_on_merge:
- continue
+ shared.state.sampling_step += 1
- theta_0[key] = theta_1[key]
- if save_as_half:
- theta_0[key] = theta_0[key].half()
del theta_1
- ckpt_dir = shared.cmd_opts.ckpt_dir or sd_models.model_path
+ bake_in_vae_filename = sd_vae.vae_dict.get(bake_in_vae, None)
+ if bake_in_vae_filename is not None:
+ print(f"Baking in VAE from {bake_in_vae_filename}")
+ shared.state.textinfo = 'Baking in VAE'
+ vae_dict = sd_vae.load_vae_dict(bake_in_vae_filename, map_location='cpu')
+
+ for key in vae_dict.keys():
+ theta_0_key = 'first_stage_model.' + key
+ if theta_0_key in theta_0:
+ theta_0[theta_0_key] = to_half(vae_dict[key], save_as_half)
- filename = \
- primary_model_info.model_name + '_' + str(round(1-multiplier, 2)) + '-' + \
- secondary_model_info.model_name + '_' + str(round(multiplier, 2)) + '-' + \
- interp_method.replace(" ", "_") + \
- '-merged.' + \
- ("inpainting." if result_is_inpainting_model else "") + \
- checkpoint_format
+ del vae_dict
+
+ if save_as_half and not theta_func2:
+ for key in theta_0.keys():
+ theta_0[key] = to_half(theta_0[key], save_as_half)
+
+ if discard_weights:
+ regex = re.compile(discard_weights)
+ for key in list(theta_0):
+ if re.search(regex, key):
+ theta_0.pop(key, None)
+
+ ckpt_dir = shared.cmd_opts.ckpt_dir or sd_models.model_path
- filename = filename if custom_name == '' else (custom_name + '.' + checkpoint_format)
+ filename = filename_generator() if custom_name == '' else custom_name
+ filename += ".inpainting" if result_is_inpainting_model else ""
+ filename += "." + checkpoint_format
output_modelname = os.path.join(ckpt_dir, filename)
- shared.state.textinfo = f"Saving to {output_modelname}..."
+ shared.state.nextjob()
+ shared.state.textinfo = "Saving"
print(f"Saving to {output_modelname}...")
_, extension = os.path.splitext(output_modelname)
@@ -394,8 +244,8 @@ def run_modelmerger(primary_model_name, secondary_model_name, tertiary_model_nam
create_config(output_modelname, config_source, primary_model_info, secondary_model_info, tertiary_model_info)
- print("Checkpoint saved.")
- shared.state.textinfo = "Checkpoint saved to " + output_modelname
+ print(f"Checkpoint saved to {output_modelname}.")
+ shared.state.textinfo = "Checkpoint saved"
shared.state.end()
- return ["Checkpoint saved to " + output_modelname] + [gr.Dropdown.update(choices=sd_models.checkpoint_tiles()) for _ in range(4)]
+ return [*[gr.Dropdown.update(choices=sd_models.checkpoint_tiles()) for _ in range(4)], "Checkpoint saved to " + output_modelname]
diff --git a/modules/generation_parameters_copypaste.py b/modules/generation_parameters_copypaste.py
index a381ff59..46e12dc6 100644
--- a/modules/generation_parameters_copypaste.py
+++ b/modules/generation_parameters_copypaste.py
@@ -79,8 +79,6 @@ def integrate_settings_paste_fields(component_dict):
from modules import ui
settings_map = {
- 'sd_hypernetwork': 'Hypernet',
- 'sd_hypernetwork_strength': 'Hypernet strength',
'CLIP_stop_at_last_layers': 'Clip skip',
'inpainting_mask_weight': 'Conditional mask weight',
'sd_model_checkpoint': 'Model hash',
@@ -275,13 +273,9 @@ Steps: 20, Sampler: Euler a, CFG scale: 7, Seed: 965400086, Size: 512x512, Model
if "Clip skip" not in res:
res["Clip skip"] = "1"
- if "Hypernet strength" not in res:
- res["Hypernet strength"] = "1"
-
- if "Hypernet" in res:
- hypernet_name = res["Hypernet"]
- hypernet_hash = res.get("Hypernet hash", None)
- res["Hypernet"] = find_hypernetwork_key(hypernet_name, hypernet_hash)
+ hypernet = res.get("Hypernet", None)
+ if hypernet is not None:
+ res["Prompt"] += f"""<hypernet:{hypernet}:{res.get("Hypernet strength", "1.0")}>"""
if "Hires resize-1" not in res:
res["Hires resize-1"] = 0
diff --git a/modules/hypernetworks/hypernetwork.py b/modules/hypernetworks/hypernetwork.py
index c963fc40..503534e2 100644
--- a/modules/hypernetworks/hypernetwork.py
+++ b/modules/hypernetworks/hypernetwork.py
@@ -12,7 +12,7 @@ import torch
import tqdm
from einops import rearrange, repeat
from ldm.util import default
-from modules import devices, processing, sd_models, shared, sd_samplers, hashes
+from modules import devices, processing, sd_models, shared, sd_samplers, hashes, sd_hijack_checkpoint
from modules.textual_inversion import textual_inversion, logging
from modules.textual_inversion.learn_schedule import LearnRateScheduler
from torch import einsum
@@ -25,7 +25,6 @@ from statistics import stdev, mean
optimizer_dict = {optim_name : cls_obj for optim_name, cls_obj in inspect.getmembers(torch.optim, inspect.isclass) if optim_name != "Optimizer"}
class HypernetworkModule(torch.nn.Module):
- multiplier = 1.0
activation_dict = {
"linear": torch.nn.Identity,
"relu": torch.nn.ReLU,
@@ -41,6 +40,8 @@ class HypernetworkModule(torch.nn.Module):
add_layer_norm=False, activate_output=False, dropout_structure=None):
super().__init__()
+ self.multiplier = 1.0
+
assert layer_structure is not None, "layer_structure must not be None"
assert layer_structure[0] == 1, "Multiplier Sequence should start with size 1!"
assert layer_structure[-1] == 1, "Multiplier Sequence should end with size 1!"
@@ -115,7 +116,7 @@ class HypernetworkModule(torch.nn.Module):
state_dict[to] = x
def forward(self, x):
- return x + self.linear(x) * (HypernetworkModule.multiplier if not self.training else 1)
+ return x + self.linear(x) * (self.multiplier if not self.training else 1)
def trainables(self):
layer_structure = []
@@ -125,9 +126,6 @@ class HypernetworkModule(torch.nn.Module):
return layer_structure
-def apply_strength(value=None):
- HypernetworkModule.multiplier = value if value is not None else shared.opts.sd_hypernetwork_strength
-
#param layer_structure : sequence used for length, use_dropout : controlling boolean, last_layer_dropout : for compatibility check.
def parse_dropout_structure(layer_structure, use_dropout, last_layer_dropout):
if layer_structure is None:
@@ -192,6 +190,20 @@ class Hypernetwork:
for param in layer.parameters():
param.requires_grad = mode
+ def to(self, device):
+ for k, layers in self.layers.items():
+ for layer in layers:
+ layer.to(device)
+
+ return self
+
+ def set_multiplier(self, multiplier):
+ for k, layers in self.layers.items():
+ for layer in layers:
+ layer.multiplier = multiplier
+
+ return self
+
def eval(self):
for k, layers in self.layers.items():
for layer in layers:
@@ -269,11 +281,13 @@ class Hypernetwork:
self.optimizer_state_dict = None
if self.optimizer_state_dict:
self.optimizer_name = optimizer_saved_dict.get('optimizer_name', 'AdamW')
- print("Loaded existing optimizer from checkpoint")
- print(f"Optimizer name is {self.optimizer_name}")
+ if shared.opts.print_hypernet_extra:
+ print("Loaded existing optimizer from checkpoint")
+ print(f"Optimizer name is {self.optimizer_name}")
else:
self.optimizer_name = "AdamW"
- print("No saved optimizer exists in checkpoint")
+ if shared.opts.print_hypernet_extra:
+ print("No saved optimizer exists in checkpoint")
for size, sd in state_dict.items():
if type(size) == int:
@@ -306,23 +320,43 @@ def list_hypernetworks(path):
return res
-def load_hypernetwork(filename):
- path = shared.hypernetworks.get(filename, None)
- # Prevent any file named "None.pt" from being loaded.
- if path is not None and filename != "None":
- print(f"Loading hypernetwork {filename}")
- try:
- shared.loaded_hypernetwork = Hypernetwork()
- shared.loaded_hypernetwork.load(path)
+def load_hypernetwork(name):
+ path = shared.hypernetworks.get(name, None)
- except Exception:
- print(f"Error loading hypernetwork {path}", file=sys.stderr)
- print(traceback.format_exc(), file=sys.stderr)
- else:
- if shared.loaded_hypernetwork is not None:
- print("Unloading hypernetwork")
+ if path is None:
+ return None
+
+ hypernetwork = Hypernetwork()
+
+ try:
+ hypernetwork.load(path)
+ except Exception:
+ print(f"Error loading hypernetwork {path}", file=sys.stderr)
+ print(traceback.format_exc(), file=sys.stderr)
+ return None
+
+ return hypernetwork
+
+
+def load_hypernetworks(names, multipliers=None):
+ already_loaded = {}
+
+ for hypernetwork in shared.loaded_hypernetworks:
+ if hypernetwork.name in names:
+ already_loaded[hypernetwork.name] = hypernetwork
+
+ shared.loaded_hypernetworks.clear()
+
+ for i, name in enumerate(names):
+ hypernetwork = already_loaded.get(name, None)
+ if hypernetwork is None:
+ hypernetwork = load_hypernetwork(name)
+
+ if hypernetwork is None:
+ continue
- shared.loaded_hypernetwork = None
+ hypernetwork.set_multiplier(multipliers[i] if multipliers else 1.0)
+ shared.loaded_hypernetworks.append(hypernetwork)
def find_closest_hypernetwork_name(search: str):
@@ -336,18 +370,27 @@ def find_closest_hypernetwork_name(search: str):
return applicable[0]
-def apply_hypernetwork(hypernetwork, context, layer=None):
- hypernetwork_layers = (hypernetwork.layers if hypernetwork is not None else {}).get(context.shape[2], None)
+def apply_single_hypernetwork(hypernetwork, context_k, context_v, layer=None):
+ hypernetwork_layers = (hypernetwork.layers if hypernetwork is not None else {}).get(context_k.shape[2], None)
if hypernetwork_layers is None:
- return context, context
+ return context_k, context_v
if layer is not None:
layer.hyper_k = hypernetwork_layers[0]
layer.hyper_v = hypernetwork_layers[1]
- context_k = hypernetwork_layers[0](context)
- context_v = hypernetwork_layers[1](context)
+ context_k = hypernetwork_layers[0](context_k)
+ context_v = hypernetwork_layers[1](context_v)
+ return context_k, context_v
+
+
+def apply_hypernetworks(hypernetworks, context, layer=None):
+ context_k = context
+ context_v = context
+ for hypernetwork in hypernetworks:
+ context_k, context_v = apply_single_hypernetwork(hypernetwork, context_k, context_v, layer)
+
return context_k, context_v
@@ -357,7 +400,7 @@ def attention_CrossAttention_forward(self, x, context=None, mask=None):
q = self.to_q(x)
context = default(context, x)
- context_k, context_v = apply_hypernetwork(shared.loaded_hypernetwork, context, self)
+ context_k, context_v = apply_hypernetworks(shared.loaded_hypernetworks, context, self)
k = self.to_k(context_k)
v = self.to_v(context_v)
@@ -464,8 +507,9 @@ def train_hypernetwork(id_task, hypernetwork_name, learn_rate, batch_size, gradi
template_file = template_file.path
path = shared.hypernetworks.get(hypernetwork_name, None)
- shared.loaded_hypernetwork = Hypernetwork()
- shared.loaded_hypernetwork.load(path)
+ hypernetwork = Hypernetwork()
+ hypernetwork.load(path)
+ shared.loaded_hypernetworks = [hypernetwork]
shared.state.job = "train-hypernetwork"
shared.state.textinfo = "Initializing hypernetwork training..."
@@ -489,7 +533,6 @@ def train_hypernetwork(id_task, hypernetwork_name, learn_rate, batch_size, gradi
else:
images_dir = None
- hypernetwork = shared.loaded_hypernetwork
checkpoint = sd_models.select_checkpoint()
initial_step = hypernetwork.step or 0
@@ -575,6 +618,8 @@ def train_hypernetwork(id_task, hypernetwork_name, learn_rate, batch_size, gradi
pbar = tqdm.tqdm(total=steps - initial_step)
try:
+ sd_hijack_checkpoint.add()
+
for i in range((steps-initial_step) * gradient_step):
if scheduler.finished:
break
@@ -670,6 +715,8 @@ def train_hypernetwork(id_task, hypernetwork_name, learn_rate, batch_size, gradi
do_not_save_samples=True,
)
+ p.disable_extra_networks = True
+
if preview_from_txt2img:
p.prompt = preview_prompt
p.negative_prompt = preview_negative_prompt
@@ -724,6 +771,9 @@ Last saved image: {html.escape(last_saved_image)}<br/>
pbar.close()
hypernetwork.eval()
#report_statistics(loss_dict)
+ sd_hijack_checkpoint.remove()
+
+
filename = os.path.join(shared.cmd_opts.hypernetwork_dir, f'{hypernetwork_name}.pt')
hypernetwork.optimizer_name = optimizer_name
diff --git a/modules/hypernetworks/ui.py b/modules/hypernetworks/ui.py
index 81e3f519..76599f5a 100644
--- a/modules/hypernetworks/ui.py
+++ b/modules/hypernetworks/ui.py
@@ -9,6 +9,7 @@ from modules import devices, sd_hijack, shared
not_available = ["hardswish", "multiheadattention"]
keys = list(x for x in modules.hypernetworks.hypernetwork.HypernetworkModule.activation_dict.keys() if x not in not_available)
+
def create_hypernetwork(name, enable_sizes, overwrite_old, layer_structure=None, activation_func=None, weight_init=None, add_layer_norm=False, use_dropout=False, dropout_structure=None):
filename = modules.hypernetworks.hypernetwork.create_hypernetwork(name, enable_sizes, overwrite_old, layer_structure, activation_func, weight_init, add_layer_norm, use_dropout, dropout_structure)
@@ -16,8 +17,7 @@ def create_hypernetwork(name, enable_sizes, overwrite_old, layer_structure=None,
def train_hypernetwork(*args):
-
- initial_hypernetwork = shared.loaded_hypernetwork
+ shared.loaded_hypernetworks = []
assert not shared.cmd_opts.lowvram, 'Training models with lowvram is not possible'
@@ -34,7 +34,6 @@ Hypernetwork saved to {html.escape(filename)}
except Exception:
raise
finally:
- shared.loaded_hypernetwork = initial_hypernetwork
shared.sd_model.cond_stage_model.to(devices.device)
shared.sd_model.first_stage_model.to(devices.device)
sd_hijack.apply_optimizations()
diff --git a/modules/images.py b/modules/images.py
index c3a5fc8b..3b1c5f34 100644
--- a/modules/images.py
+++ b/modules/images.py
@@ -605,8 +605,9 @@ def read_info_from_image(image):
except ValueError:
exif_comment = exif_comment.decode('utf8', errors="ignore")
- items['exif comment'] = exif_comment
- geninfo = exif_comment
+ if exif_comment:
+ items['exif comment'] = exif_comment
+ geninfo = exif_comment
for field in ['jfif', 'jfif_version', 'jfif_unit', 'jfif_density', 'dpi', 'exif',
'loop', 'background', 'timestamp', 'duration']:
diff --git a/modules/img2img.py b/modules/img2img.py
index f4a03c57..2168c8e2 100644
--- a/modules/img2img.py
+++ b/modules/img2img.py
@@ -59,7 +59,7 @@ def process_batch(p, input_dir, output_dir, args):
processed_image.save(os.path.join(output_dir, filename))
-def img2img(id_task: str, mode: int, prompt: str, negative_prompt: str, prompt_style: str, prompt_style2: str, init_img, sketch, init_img_with_mask, inpaint_color_sketch, inpaint_color_sketch_orig, init_img_inpaint, init_mask_inpaint, steps: int, sampler_index: int, mask_blur: int, mask_alpha: float, inpainting_fill: int, restore_faces: bool, tiling: bool, n_iter: int, batch_size: int, cfg_scale: float, denoising_strength: float, seed: int, subseed: int, subseed_strength: float, seed_resize_from_h: int, seed_resize_from_w: int, seed_enable_extras: bool, height: int, width: int, resize_mode: int, inpaint_full_res: bool, inpaint_full_res_padding: int, inpainting_mask_invert: int, img2img_batch_input_dir: str, img2img_batch_output_dir: str, *args):
+def img2img(id_task: str, mode: int, prompt: str, negative_prompt: str, prompt_styles, init_img, sketch, init_img_with_mask, inpaint_color_sketch, inpaint_color_sketch_orig, init_img_inpaint, init_mask_inpaint, steps: int, sampler_index: int, mask_blur: int, mask_alpha: float, inpainting_fill: int, restore_faces: bool, tiling: bool, n_iter: int, batch_size: int, cfg_scale: float, denoising_strength: float, seed: int, subseed: int, subseed_strength: float, seed_resize_from_h: int, seed_resize_from_w: int, seed_enable_extras: bool, height: int, width: int, resize_mode: int, inpaint_full_res: bool, inpaint_full_res_padding: int, inpainting_mask_invert: int, img2img_batch_input_dir: str, img2img_batch_output_dir: str, *args):
is_batch = mode == 5
if mode == 0: # img2img
@@ -101,7 +101,7 @@ def img2img(id_task: str, mode: int, prompt: str, negative_prompt: str, prompt_s
outpath_grids=opts.outdir_grids or opts.outdir_img2img_grids,
prompt=prompt,
negative_prompt=negative_prompt,
- styles=[prompt_style, prompt_style2],
+ styles=prompt_styles,
seed=seed,
subseed=subseed,
subseed_strength=subseed_strength,
diff --git a/modules/interrogate.py b/modules/interrogate.py
index 738d8ff7..19938cbb 100644
--- a/modules/interrogate.py
+++ b/modules/interrogate.py
@@ -5,12 +5,13 @@ from collections import namedtuple
import re
import torch
+import torch.hub
from torchvision import transforms
from torchvision.transforms.functional import InterpolationMode
import modules.shared as shared
-from modules import devices, paths, lowvram, modelloader
+from modules import devices, paths, lowvram, modelloader, errors
blip_image_eval_size = 384
clip_model_name = 'ViT-L/14'
@@ -20,27 +21,59 @@ Category = namedtuple("Category", ["name", "topn", "items"])
re_topn = re.compile(r"\.top(\d+)\.")
+def download_default_clip_interrogate_categories(content_dir):
+ print("Downloading CLIP categories...")
+
+ tmpdir = content_dir + "_tmp"
+ try:
+ os.makedirs(tmpdir)
+
+ torch.hub.download_url_to_file("https://raw.githubusercontent.com/pharmapsychotic/clip-interrogator/main/clip_interrogator/data/artists.txt", os.path.join(tmpdir, "artists.txt"))
+ torch.hub.download_url_to_file("https://raw.githubusercontent.com/pharmapsychotic/clip-interrogator/main/clip_interrogator/data/flavors.txt", os.path.join(tmpdir, "flavors.top3.txt"))
+ torch.hub.download_url_to_file("https://raw.githubusercontent.com/pharmapsychotic/clip-interrogator/main/clip_interrogator/data/mediums.txt", os.path.join(tmpdir, "mediums.txt"))
+ torch.hub.download_url_to_file("https://raw.githubusercontent.com/pharmapsychotic/clip-interrogator/main/clip_interrogator/data/movements.txt", os.path.join(tmpdir, "movements.txt"))
+
+ os.rename(tmpdir, content_dir)
+
+ except Exception as e:
+ errors.display(e, "downloading default CLIP interrogate categories")
+ finally:
+ if os.path.exists(tmpdir):
+ os.remove(tmpdir)
+
+
class InterrogateModels:
blip_model = None
clip_model = None
clip_preprocess = None
- categories = None
dtype = None
running_on_cpu = None
def __init__(self, content_dir):
- self.categories = []
+ self.loaded_categories = None
+ self.content_dir = content_dir
self.running_on_cpu = devices.device_interrogate == torch.device("cpu")
- if os.path.exists(content_dir):
- for filename in os.listdir(content_dir):
+ def categories(self):
+ if self.loaded_categories is not None:
+ return self.loaded_categories
+
+ self.loaded_categories = []
+
+ if not os.path.exists(self.content_dir):
+ download_default_clip_interrogate_categories(self.content_dir)
+
+ if os.path.exists(self.content_dir):
+ for filename in os.listdir(self.content_dir):
m = re_topn.search(filename)
topn = 1 if m is None else int(m.group(1))
- with open(os.path.join(content_dir, filename), "r", encoding="utf8") as file:
+ with open(os.path.join(self.content_dir, filename), "r", encoding="utf8") as file:
lines = [x.strip() for x in file.readlines()]
- self.categories.append(Category(name=filename, topn=topn, items=lines))
+ self.loaded_categories.append(Category(name=filename, topn=topn, items=lines))
+
+ return self.loaded_categories
def load_blip_model(self):
import models.blip
@@ -139,7 +172,6 @@ class InterrogateModels:
shared.state.begin()
shared.state.job = 'interrogate'
try:
-
if shared.cmd_opts.lowvram or shared.cmd_opts.medvram:
lowvram.send_everything_to_cpu()
devices.torch_gc()
@@ -159,12 +191,7 @@ class InterrogateModels:
image_features /= image_features.norm(dim=-1, keepdim=True)
- if shared.opts.interrogate_use_builtin_artists:
- artist = self.rank(image_features, ["by " + artist.name for artist in shared.artist_db.artists])[0]
-
- res += ", " + artist[0]
-
- for name, topn, items in self.categories:
+ for name, topn, items in self.categories():
matches = self.rank(image_features, items, top_count=topn)
for match, score in matches:
if shared.opts.interrogate_return_ranks:
diff --git a/modules/postprocessing.py b/modules/postprocessing.py
new file mode 100644
index 00000000..8514fea7
--- /dev/null
+++ b/modules/postprocessing.py
@@ -0,0 +1,103 @@
+import os
+
+from PIL import Image
+
+from modules import shared, images, devices, scripts, scripts_postprocessing, ui_common, generation_parameters_copypaste
+from modules.shared import opts
+
+
+def run_postprocessing(extras_mode, image, image_folder, input_dir, output_dir, show_extras_results, *args, save_output: bool = True):
+ devices.torch_gc()
+
+ shared.state.begin()
+ shared.state.job = 'extras'
+
+ image_data = []
+ image_names = []
+ outputs = []
+
+ if extras_mode == 1:
+ for img in image_folder:
+ image = Image.open(img)
+ image_data.append(image)
+ image_names.append(os.path.splitext(img.orig_name)[0])
+ elif extras_mode == 2:
+ assert not shared.cmd_opts.hide_ui_dir_config, '--hide-ui-dir-config option must be disabled'
+ assert input_dir, 'input directory not selected'
+
+ image_list = shared.listfiles(input_dir)
+ for filename in image_list:
+ try:
+ image = Image.open(filename)
+ except Exception:
+ continue
+ image_data.append(image)
+ image_names.append(filename)
+ else:
+ assert image, 'image not selected'
+
+ image_data.append(image)
+ image_names.append(None)
+
+ if extras_mode == 2 and output_dir != '':
+ outpath = output_dir
+ else:
+ outpath = opts.outdir_samples or opts.outdir_extras_samples
+
+ infotext = ''
+
+ for image, name in zip(image_data, image_names):
+ shared.state.textinfo = name
+
+ existing_pnginfo = image.info or {}
+
+ pp = scripts_postprocessing.PostprocessedImage(image.convert("RGB"))
+
+ scripts.scripts_postproc.run(pp, args)
+
+ if opts.use_original_name_batch and name is not None:
+ basename = os.path.splitext(os.path.basename(name))[0]
+ else:
+ basename = ''
+
+ infotext = ", ".join([k if k == v else f'{k}: {generation_parameters_copypaste.quote(v)}' for k, v in pp.info.items() if v is not None])
+
+ if opts.enable_pnginfo:
+ pp.image.info = existing_pnginfo
+ pp.image.info["postprocessing"] = infotext
+
+ if save_output:
+ images.save_image(pp.image, path=outpath, basename=basename, seed=None, prompt=None, extension=opts.samples_format, info=pp.info, short_filename=True, no_prompt=True, grid=False, pnginfo_section_name="extras", existing_info=existing_pnginfo, forced_filename=None)
+
+ if extras_mode != 2 or show_extras_results:
+ outputs.append(pp.image)
+
+ devices.torch_gc()
+
+ return outputs, ui_common.plaintext_to_html(infotext), ''
+
+
+def run_extras(extras_mode, resize_mode, image, image_folder, input_dir, output_dir, show_extras_results, gfpgan_visibility, codeformer_visibility, codeformer_weight, upscaling_resize, upscaling_resize_w, upscaling_resize_h, upscaling_crop, extras_upscaler_1, extras_upscaler_2, extras_upscaler_2_visibility, upscale_first: bool, save_output: bool = True):
+ """old handler for API"""
+
+ args = scripts.scripts_postproc.create_args_for_run({
+ "Upscale": {
+ "upscale_mode": resize_mode,
+ "upscale_by": upscaling_resize,
+ "upscale_to_width": upscaling_resize_w,
+ "upscale_to_height": upscaling_resize_h,
+ "upscale_crop": upscaling_crop,
+ "upscaler_1_name": extras_upscaler_1,
+ "upscaler_2_name": extras_upscaler_2,
+ "upscaler_2_visibility": extras_upscaler_2_visibility,
+ },
+ "GFPGAN": {
+ "gfpgan_visibility": gfpgan_visibility,
+ },
+ "CodeFormer": {
+ "codeformer_visibility": codeformer_visibility,
+ "codeformer_weight": codeformer_weight,
+ },
+ })
+
+ return run_postprocessing(extras_mode, image, image_folder, input_dir, output_dir, show_extras_results, *args, save_output=save_output)
diff --git a/modules/processing.py b/modules/processing.py
index 9c3673de..bc541e2f 100644
--- a/modules/processing.py
+++ b/modules/processing.py
@@ -13,7 +13,7 @@ from skimage import exposure
from typing import Any, Dict, List, Optional
import modules.sd_hijack
-from modules import devices, prompt_parser, masking, sd_samplers, lowvram, generation_parameters_copypaste, script_callbacks
+from modules import devices, prompt_parser, masking, sd_samplers, lowvram, generation_parameters_copypaste, script_callbacks, extra_networks
from modules.sd_hijack import model_hijack
from modules.shared import opts, cmd_opts, state
import modules.shared as shared
@@ -140,6 +140,7 @@ class StableDiffusionProcessing:
self.override_settings = {k: v for k, v in (override_settings or {}).items() if k not in shared.restricted_opts}
self.override_settings_restore_afterwards = override_settings_restore_afterwards
self.is_using_inpainting_conditioning = False
+ self.disable_extra_networks = False
if not seed_enable_extras:
self.subseed = -1
@@ -438,9 +439,6 @@ def create_infotext(p, all_prompts, all_seeds, all_subseeds, comments=None, iter
"Size": f"{p.width}x{p.height}",
"Model hash": getattr(p, 'sd_model_hash', None if not opts.add_model_hash_to_info or not shared.sd_model.sd_model_hash else shared.sd_model.sd_model_hash),
"Model": (None if not opts.add_model_name_to_info or not shared.sd_model.sd_checkpoint_info.model_name else shared.sd_model.sd_checkpoint_info.model_name.replace(',', '').replace(':', '')),
- "Hypernet": (None if shared.loaded_hypernetwork is None else shared.loaded_hypernetwork.name),
- "Hypernet hash": (None if shared.loaded_hypernetwork is None else shared.loaded_hypernetwork.shorthash()),
- "Hypernet strength": (None if shared.loaded_hypernetwork is None or shared.opts.sd_hypernetwork_strength >= 1 else shared.opts.sd_hypernetwork_strength),
"Batch size": (None if p.batch_size < 2 else p.batch_size),
"Batch pos": (None if p.batch_size < 2 else position_in_batch),
"Variation seed": (None if p.subseed_strength == 0 else all_subseeds[index]),
@@ -468,14 +466,12 @@ def process_images(p: StableDiffusionProcessing) -> Processed:
try:
for k, v in p.override_settings.items():
setattr(opts, k, v)
- if k == 'sd_hypernetwork':
- shared.reload_hypernetworks() # make onchange call for changing hypernet
if k == 'sd_model_checkpoint':
- sd_models.reload_model_weights() # make onchange call for changing SD model
+ sd_models.reload_model_weights()
if k == 'sd_vae':
- sd_vae.reload_vae_weights() # make onchange call for changing VAE
+ sd_vae.reload_vae_weights()
res = process_images_inner(p)
@@ -484,9 +480,11 @@ def process_images(p: StableDiffusionProcessing) -> Processed:
if p.override_settings_restore_afterwards:
for k, v in stored_opts.items():
setattr(opts, k, v)
- if k == 'sd_hypernetwork': shared.reload_hypernetworks()
- if k == 'sd_model_checkpoint': sd_models.reload_model_weights()
- if k == 'sd_vae': sd_vae.reload_vae_weights()
+ if k == 'sd_model_checkpoint':
+ sd_models.reload_model_weights()
+
+ if k == 'sd_vae':
+ sd_vae.reload_vae_weights()
return res
@@ -535,13 +533,11 @@ def process_images_inner(p: StableDiffusionProcessing) -> Processed:
if os.path.exists(cmd_opts.embeddings_dir) and not p.do_not_reload_embeddings:
model_hijack.embedding_db.load_textual_inversion_embeddings()
+ _, extra_network_data = extra_networks.parse_prompts(p.all_prompts[0:1])
+
if p.scripts is not None:
p.scripts.process(p)
- with open(os.path.join(shared.script_path, "params.txt"), "w", encoding="utf8") as file:
- processed = Processed(p, [], p.seed, "")
- file.write(processed.infotext(p, 0))
-
infotexts = []
output_images = []
@@ -572,6 +568,13 @@ def process_images_inner(p: StableDiffusionProcessing) -> Processed:
with devices.autocast():
p.init(p.all_prompts, p.all_seeds, p.all_subseeds)
+ if not p.disable_extra_networks:
+ extra_networks.activate(p, extra_network_data)
+
+ with open(os.path.join(shared.script_path, "params.txt"), "w", encoding="utf8") as file:
+ processed = Processed(p, [], p.seed, "")
+ file.write(processed.infotext(p, 0))
+
if state.job_count == -1:
state.job_count = p.n_iter
@@ -592,6 +595,8 @@ def process_images_inner(p: StableDiffusionProcessing) -> Processed:
if len(prompts) == 0:
break
+ prompts, _ = extra_networks.parse_prompts(prompts)
+
if p.scripts is not None:
p.scripts.process_batch(p, batch_number=n, prompts=prompts, seeds=seeds, subseeds=subseeds)
@@ -681,6 +686,9 @@ def process_images_inner(p: StableDiffusionProcessing) -> Processed:
if opts.grid_save:
images.save_image(grid, p.outpath_grids, "grid", p.all_seeds[0], p.all_prompts[0], opts.grid_format, info=infotext(), short_filename=not opts.grid_extended_filename, p=p, grid=True)
+ if not p.disable_extra_networks:
+ extra_networks.deactivate(p, extra_network_data)
+
devices.torch_gc()
res = Processed(p, output_images, p.all_seeds[0], infotext(), comments="".join(["\n\n" + x for x in comments]), subseed=p.all_subseeds[0], index_of_first_image=index_of_first_image, infotexts=infotexts)
@@ -857,7 +865,8 @@ class StableDiffusionProcessingTxt2Img(StableDiffusionProcessing):
shared.state.nextjob()
- self.sampler = sd_samplers.create_sampler(self.sampler_name, self.sd_model)
+ img2img_sampler_name = self.sampler_name if self.sampler_name != 'PLMS' else 'DDIM' # PLMS does not support img2img so we just silently switch ot DDIM
+ self.sampler = sd_samplers.create_sampler(img2img_sampler_name, self.sd_model)
samples = samples[:, :, self.truncate_y//2:samples.shape[2]-(self.truncate_y+1)//2, self.truncate_x//2:samples.shape[3]-(self.truncate_x+1)//2]
diff --git a/modules/progress.py b/modules/progress.py
index 3327b883..c69ecf3d 100644
--- a/modules/progress.py
+++ b/modules/progress.py
@@ -67,10 +67,13 @@ def progressapi(req: ProgressRequest):
progress = 0
- if shared.state.job_count > 0:
- progress += shared.state.job_no / shared.state.job_count
- if shared.state.sampling_steps > 0:
- progress += 1 / shared.state.job_count * shared.state.sampling_step / shared.state.sampling_steps
+ job_count, job_no = shared.state.job_count, shared.state.job_no
+ sampling_steps, sampling_step = shared.state.sampling_steps, shared.state.sampling_step
+
+ if job_count > 0:
+ progress += job_no / job_count
+ if sampling_steps > 0 and job_count > 0:
+ progress += 1 / job_count * sampling_step / sampling_steps
progress = min(progress, 1)
diff --git a/modules/realesrgan_model.py b/modules/realesrgan_model.py
index 3ac0b97a..47f70251 100644
--- a/modules/realesrgan_model.py
+++ b/modules/realesrgan_model.py
@@ -38,13 +38,13 @@ class UpscalerRealESRGAN(Upscaler):
return img
info = self.load_model(path)
- if not os.path.exists(info.data_path):
+ if not os.path.exists(info.local_data_path):
print("Unable to load RealESRGAN model: %s" % info.name)
return img
upsampler = RealESRGANer(
scale=info.scale,
- model_path=info.data_path,
+ model_path=info.local_data_path,
model=info.model(),
half=not cmd_opts.no_half,
tile=opts.ESRGAN_tile,
@@ -58,17 +58,13 @@ class UpscalerRealESRGAN(Upscaler):
def load_model(self, path):
try:
- info = None
- for scaler in self.scalers:
- if scaler.data_path == path:
- info = scaler
+ info = next(iter([scaler for scaler in self.scalers if scaler.data_path == path]), None)
if info is None:
print(f"Unable to find model info: {path}")
return None
- model_file = load_file_from_url(url=info.data_path, model_dir=self.model_path, progress=True)
- info.data_path = model_file
+ info.local_data_path = load_file_from_url(url=info.data_path, model_dir=self.model_path, progress=True)
return info
except Exception as e:
print(f"Error making Real-ESRGAN models list: {e}", file=sys.stderr)
diff --git a/modules/script_callbacks.py b/modules/script_callbacks.py
index a9e19236..4bb45ec7 100644
--- a/modules/script_callbacks.py
+++ b/modules/script_callbacks.py
@@ -73,6 +73,7 @@ callback_map = dict(
callbacks_image_grid=[],
callbacks_infotext_pasted=[],
callbacks_script_unloaded=[],
+ callbacks_before_ui=[],
)
@@ -189,6 +190,14 @@ def script_unloaded_callback():
report_exception(c, 'script_unloaded')
+def before_ui_callback():
+ for c in reversed(callback_map['callbacks_before_ui']):
+ try:
+ c.callback()
+ except Exception:
+ report_exception(c, 'before_ui')
+
+
def add_callback(callbacks, fun):
stack = [x for x in inspect.stack() if x.filename != __file__]
filename = stack[0].filename if len(stack) > 0 else 'unknown file'
@@ -313,3 +322,9 @@ def on_script_unloaded(callback):
the script did should be reverted here"""
add_callback(callback_map['callbacks_script_unloaded'], callback)
+
+
+def on_before_ui(callback):
+ """register a function to be called before the UI is created."""
+
+ add_callback(callback_map['callbacks_before_ui'], callback)
diff --git a/modules/scripts.py b/modules/scripts.py
index 4ffc369b..03907a63 100644
--- a/modules/scripts.py
+++ b/modules/scripts.py
@@ -7,7 +7,7 @@ from collections import namedtuple
import gradio as gr
from modules.processing import StableDiffusionProcessing
-from modules import shared, paths, script_callbacks, extensions, script_loading
+from modules import shared, paths, script_callbacks, extensions, script_loading, scripts_postprocessing
AlwaysVisible = object()
@@ -150,8 +150,10 @@ def basedir():
return current_basedir
-scripts_data = []
ScriptFile = namedtuple("ScriptFile", ["basedir", "filename", "path"])
+
+scripts_data = []
+postprocessing_scripts_data = []
ScriptClassData = namedtuple("ScriptClassData", ["script_class", "path", "basedir", "module"])
@@ -190,23 +192,31 @@ def list_files_with_name(filename):
def load_scripts():
global current_basedir
scripts_data.clear()
+ postprocessing_scripts_data.clear()
script_callbacks.clear_callbacks()
scripts_list = list_scripts("scripts", ".py")
syspath = sys.path
+ def register_scripts_from_module(module):
+ for key, script_class in module.__dict__.items():
+ if type(script_class) != type:
+ continue
+
+ if issubclass(script_class, Script):
+ scripts_data.append(ScriptClassData(script_class, scriptfile.path, scriptfile.basedir, module))
+ elif issubclass(script_class, scripts_postprocessing.ScriptPostprocessing):
+ postprocessing_scripts_data.append(ScriptClassData(script_class, scriptfile.path, scriptfile.basedir, module))
+
for scriptfile in sorted(scripts_list):
try:
if scriptfile.basedir != paths.script_path:
sys.path = [scriptfile.basedir] + sys.path
current_basedir = scriptfile.basedir
- module = script_loading.load_module(scriptfile.path)
-
- for key, script_class in module.__dict__.items():
- if type(script_class) == type and issubclass(script_class, Script):
- scripts_data.append(ScriptClassData(script_class, scriptfile.path, scriptfile.basedir, module))
+ script_module = script_loading.load_module(scriptfile.path)
+ register_scripts_from_module(script_module)
except Exception:
print(f"Error loading script: {scriptfile.filename}", file=sys.stderr)
@@ -413,6 +423,7 @@ class ScriptRunner:
scripts_txt2img = ScriptRunner()
scripts_img2img = ScriptRunner()
+scripts_postproc = scripts_postprocessing.ScriptPostprocessingRunner()
scripts_current: ScriptRunner = None
@@ -423,12 +434,13 @@ def reload_script_body_only():
def reload_scripts():
- global scripts_txt2img, scripts_img2img
+ global scripts_txt2img, scripts_img2img, scripts_postproc
load_scripts()
scripts_txt2img = ScriptRunner()
scripts_img2img = ScriptRunner()
+ scripts_postproc = scripts_postprocessing.ScriptPostprocessingRunner()
def IOComponent_init(self, *args, **kwargs):
diff --git a/modules/scripts_postprocessing.py b/modules/scripts_postprocessing.py
new file mode 100644
index 00000000..25de02d0
--- /dev/null
+++ b/modules/scripts_postprocessing.py
@@ -0,0 +1,147 @@
+import os
+import gradio as gr
+
+from modules import errors, shared
+
+
+class PostprocessedImage:
+ def __init__(self, image):
+ self.image = image
+ self.info = {}
+
+
+class ScriptPostprocessing:
+ filename = None
+ controls = None
+ args_from = None
+ args_to = None
+
+ order = 1000
+ """scripts will be ordred by this value in postprocessing UI"""
+
+ name = None
+ """this function should return the title of the script."""
+
+ group = None
+ """A gr.Group component that has all script's UI inside it"""
+
+ def ui(self):
+ """
+ This function should create gradio UI elements. See https://gradio.app/docs/#components
+ The return value should be a dictionary that maps parameter names to components used in processing.
+ Values of those components will be passed to process() function.
+ """
+
+ pass
+
+ def process(self, pp: PostprocessedImage, **args):
+ """
+ This function is called to postprocess the image.
+ args contains a dictionary with all values returned by components from ui()
+ """
+
+ pass
+
+ def image_changed(self):
+ pass
+
+
+def wrap_call(func, filename, funcname, *args, default=None, **kwargs):
+ try:
+ res = func(*args, **kwargs)
+ return res
+ except Exception as e:
+ errors.display(e, f"calling {filename}/{funcname}")
+
+ return default
+
+
+class ScriptPostprocessingRunner:
+ def __init__(self):
+ self.scripts = None
+ self.ui_created = False
+
+ def initialize_scripts(self, scripts_data):
+ self.scripts = []
+
+ for script_class, path, basedir, script_module in scripts_data:
+ script: ScriptPostprocessing = script_class()
+ script.filename = path
+
+ self.scripts.append(script)
+
+ def create_script_ui(self, script, inputs):
+ script.args_from = len(inputs)
+ script.args_to = len(inputs)
+
+ script.controls = wrap_call(script.ui, script.filename, "ui")
+
+ for control in script.controls.values():
+ control.custom_script_source = os.path.basename(script.filename)
+
+ inputs += list(script.controls.values())
+ script.args_to = len(inputs)
+
+ def scripts_in_preferred_order(self):
+ if self.scripts is None:
+ import modules.scripts
+ self.initialize_scripts(modules.scripts.postprocessing_scripts_data)
+
+ scripts_order = [x.lower().strip() for x in shared.opts.postprocessing_scipts_order.split(",")]
+
+ def script_score(name):
+ name = name.lower()
+ for i, possible_match in enumerate(scripts_order):
+ if possible_match in name:
+ return i
+
+ return len(self.scripts)
+
+ script_scores = {script.name: (script_score(script.name), script.order, script.name, original_index) for original_index, script in enumerate(self.scripts)}
+
+ return sorted(self.scripts, key=lambda x: script_scores[x.name])
+
+ def setup_ui(self):
+ inputs = []
+
+ for script in self.scripts_in_preferred_order():
+ with gr.Box() as group:
+ self.create_script_ui(script, inputs)
+
+ script.group = group
+
+ self.ui_created = True
+ return inputs
+
+ def run(self, pp: PostprocessedImage, args):
+ for script in self.scripts_in_preferred_order():
+ shared.state.job = script.name
+
+ script_args = args[script.args_from:script.args_to]
+
+ process_args = {}
+ for (name, component), value in zip(script.controls.items(), script_args):
+ process_args[name] = value
+
+ script.process(pp, **process_args)
+
+ def create_args_for_run(self, scripts_args):
+ if not self.ui_created:
+ with gr.Blocks(analytics_enabled=False):
+ self.setup_ui()
+
+ scripts = self.scripts_in_preferred_order()
+ args = [None] * max([x.args_to for x in scripts])
+
+ for script in scripts:
+ script_args_dict = scripts_args.get(script.name, None)
+ if script_args_dict is not None:
+
+ for i, name in enumerate(script.controls):
+ args[script.args_from + i] = script_args_dict.get(name, None)
+
+ return args
+
+ def image_changed(self):
+ for script in self.scripts_in_preferred_order():
+ script.image_changed()
diff --git a/modules/sd_disable_initialization.py b/modules/sd_disable_initialization.py
index c72d8efc..e90aa9fe 100644
--- a/modules/sd_disable_initialization.py
+++ b/modules/sd_disable_initialization.py
@@ -41,7 +41,9 @@ class DisableInitialization:
return self.create_model_and_transforms(*args, pretrained=None, **kwargs)
def CLIPTextModel_from_pretrained(pretrained_model_name_or_path, *model_args, **kwargs):
- return self.CLIPTextModel_from_pretrained(None, *model_args, config=pretrained_model_name_or_path, state_dict={}, **kwargs)
+ res = self.CLIPTextModel_from_pretrained(None, *model_args, config=pretrained_model_name_or_path, state_dict={}, **kwargs)
+ res.name_or_path = pretrained_model_name_or_path
+ return res
def transformers_modeling_utils_load_pretrained_model(*args, **kwargs):
args = args[0:3] + ('/', ) + args[4:] # resolved_archive_file; must set it to something to prevent what seems to be a bug
diff --git a/modules/sd_hijack.py b/modules/sd_hijack.py
index 6b0d95af..f9652d21 100644
--- a/modules/sd_hijack.py
+++ b/modules/sd_hijack.py
@@ -70,9 +70,10 @@ def undo_optimizations():
def fix_checkpoint():
- ldm.modules.attention.BasicTransformerBlock.forward = sd_hijack_checkpoint.BasicTransformerBlock_forward
- ldm.modules.diffusionmodules.openaimodel.ResBlock.forward = sd_hijack_checkpoint.ResBlock_forward
- ldm.modules.diffusionmodules.openaimodel.AttentionBlock.forward = sd_hijack_checkpoint.AttentionBlock_forward
+ """checkpoints are now added and removed in embedding/hypernet code, since torch doesn't want
+ checkpoints to be added when not training (there's a warning)"""
+
+ pass
class StableDiffusionModelHijack:
@@ -106,8 +107,6 @@ class StableDiffusionModelHijack:
self.optimization_method = apply_optimizations()
self.clip = m.cond_stage_model
-
- fix_checkpoint()
def flatten(el):
flattened = [flatten(children) for children in el.children()]
diff --git a/modules/sd_hijack_checkpoint.py b/modules/sd_hijack_checkpoint.py
index 5712972f..2604d969 100644
--- a/modules/sd_hijack_checkpoint.py
+++ b/modules/sd_hijack_checkpoint.py
@@ -1,10 +1,46 @@
from torch.utils.checkpoint import checkpoint
+import ldm.modules.attention
+import ldm.modules.diffusionmodules.openaimodel
+
+
def BasicTransformerBlock_forward(self, x, context=None):
return checkpoint(self._forward, x, context)
+
def AttentionBlock_forward(self, x):
return checkpoint(self._forward, x)
+
def ResBlock_forward(self, x, emb):
- return checkpoint(self._forward, x, emb) \ No newline at end of file
+ return checkpoint(self._forward, x, emb)
+
+
+stored = []
+
+
+def add():
+ if len(stored) != 0:
+ return
+
+ stored.extend([
+ ldm.modules.attention.BasicTransformerBlock.forward,
+ ldm.modules.diffusionmodules.openaimodel.ResBlock.forward,
+ ldm.modules.diffusionmodules.openaimodel.AttentionBlock.forward
+ ])
+
+ ldm.modules.attention.BasicTransformerBlock.forward = BasicTransformerBlock_forward
+ ldm.modules.diffusionmodules.openaimodel.ResBlock.forward = ResBlock_forward
+ ldm.modules.diffusionmodules.openaimodel.AttentionBlock.forward = AttentionBlock_forward
+
+
+def remove():
+ if len(stored) == 0:
+ return
+
+ ldm.modules.attention.BasicTransformerBlock.forward = stored[0]
+ ldm.modules.diffusionmodules.openaimodel.ResBlock.forward = stored[1]
+ ldm.modules.diffusionmodules.openaimodel.AttentionBlock.forward = stored[2]
+
+ stored.clear()
+
diff --git a/modules/sd_hijack_optimizations.py b/modules/sd_hijack_optimizations.py
index cdc63ed7..74452709 100644
--- a/modules/sd_hijack_optimizations.py
+++ b/modules/sd_hijack_optimizations.py
@@ -9,7 +9,7 @@ from torch import einsum
from ldm.util import default
from einops import rearrange
-from modules import shared
+from modules import shared, errors
from modules.hypernetworks import hypernetwork
from .sub_quadratic_attention import efficient_dot_product_attention
@@ -44,7 +44,7 @@ def split_cross_attention_forward_v1(self, x, context=None, mask=None):
q_in = self.to_q(x)
context = default(context, x)
- context_k, context_v = hypernetwork.apply_hypernetwork(shared.loaded_hypernetwork, context)
+ context_k, context_v = hypernetwork.apply_hypernetworks(shared.loaded_hypernetworks, context)
k_in = self.to_k(context_k)
v_in = self.to_v(context_v)
del context, context_k, context_v, x
@@ -78,7 +78,7 @@ def split_cross_attention_forward(self, x, context=None, mask=None):
q_in = self.to_q(x)
context = default(context, x)
- context_k, context_v = hypernetwork.apply_hypernetwork(shared.loaded_hypernetwork, context)
+ context_k, context_v = hypernetwork.apply_hypernetworks(shared.loaded_hypernetworks, context)
k_in = self.to_k(context_k)
v_in = self.to_v(context_v)
@@ -203,7 +203,7 @@ def split_cross_attention_forward_invokeAI(self, x, context=None, mask=None):
q = self.to_q(x)
context = default(context, x)
- context_k, context_v = hypernetwork.apply_hypernetwork(shared.loaded_hypernetwork, context)
+ context_k, context_v = hypernetwork.apply_hypernetworks(shared.loaded_hypernetworks, context)
k = self.to_k(context_k) * self.scale
v = self.to_v(context_v)
del context, context_k, context_v, x
@@ -225,7 +225,7 @@ def sub_quad_attention_forward(self, x, context=None, mask=None):
q = self.to_q(x)
context = default(context, x)
- context_k, context_v = hypernetwork.apply_hypernetwork(shared.loaded_hypernetwork, context)
+ context_k, context_v = hypernetwork.apply_hypernetworks(shared.loaded_hypernetworks, context)
k = self.to_k(context_k)
v = self.to_v(context_v)
del context, context_k, context_v, x
@@ -279,18 +279,34 @@ def sub_quad_attention(q, k, v, q_chunk_size=1024, kv_chunk_size=None, kv_chunk_
)
+def get_xformers_flash_attention_op(q, k, v):
+ if not shared.cmd_opts.xformers_flash_attention:
+ return None
+
+ try:
+ flash_attention_op = xformers.ops.MemoryEfficientAttentionFlashAttentionOp
+ fw, bw = flash_attention_op
+ if fw.supports(xformers.ops.fmha.Inputs(query=q, key=k, value=v, attn_bias=None)):
+ return flash_attention_op
+ except Exception as e:
+ errors.display_once(e, "enabling flash attention")
+
+ return None
+
+
def xformers_attention_forward(self, x, context=None, mask=None):
h = self.heads
q_in = self.to_q(x)
context = default(context, x)
- context_k, context_v = hypernetwork.apply_hypernetwork(shared.loaded_hypernetwork, context)
+ context_k, context_v = hypernetwork.apply_hypernetworks(shared.loaded_hypernetworks, context)
k_in = self.to_k(context_k)
v_in = self.to_v(context_v)
q, k, v = map(lambda t: rearrange(t, 'b n (h d) -> b n h d', h=h), (q_in, k_in, v_in))
del q_in, k_in, v_in
- out = xformers.ops.memory_efficient_attention(q, k, v, attn_bias=None)
+
+ out = xformers.ops.memory_efficient_attention(q, k, v, attn_bias=None, op=get_xformers_flash_attention_op(q, k, v))
out = rearrange(out, 'b n h d -> b n (h d)', h=h)
return self.to_out(out)
@@ -365,7 +381,7 @@ def xformers_attnblock_forward(self, x):
q = q.contiguous()
k = k.contiguous()
v = v.contiguous()
- out = xformers.ops.memory_efficient_attention(q, k, v)
+ out = xformers.ops.memory_efficient_attention(q, k, v, op=get_xformers_flash_attention_op(q, k, v))
out = rearrange(out, 'b (h w) c -> b c h w', h=h)
out = self.proj_out(out)
return x + out
diff --git a/modules/sd_models.py b/modules/sd_models.py
index 6a681cef..12083848 100644
--- a/modules/sd_models.py
+++ b/modules/sd_models.py
@@ -41,14 +41,16 @@ class CheckpointInfo:
if name.startswith("\\") or name.startswith("/"):
name = name[1:]
- self.title = name
+ self.name = name
self.model_name = os.path.splitext(name.replace("/", "_").replace("\\", "_"))[0]
self.hash = model_hash(filename)
- self.sha256 = hashes.sha256_from_cache(self.filename, "checkpoint/" + self.title)
+ self.sha256 = hashes.sha256_from_cache(self.filename, "checkpoint/" + name)
self.shorthash = self.sha256[0:10] if self.sha256 else None
- self.ids = [self.hash, self.model_name, self.title, f'{name} [{self.hash}]'] + ([self.shorthash, self.sha256] if self.shorthash else [])
+ self.title = name if self.shorthash is None else f'{name} [{self.shorthash}]'
+
+ self.ids = [self.hash, self.model_name, self.title, name, f'{name} [{self.hash}]'] + ([self.shorthash, self.sha256, f'{self.name} [{self.shorthash}]'] if self.shorthash else [])
def register(self):
checkpoints_list[self.title] = self
@@ -56,13 +58,15 @@ class CheckpointInfo:
checkpoint_alisases[id] = self
def calculate_shorthash(self):
- self.sha256 = hashes.sha256(self.filename, "checkpoint/" + self.title)
+ self.sha256 = hashes.sha256(self.filename, "checkpoint/" + self.name)
self.shorthash = self.sha256[0:10]
if self.shorthash not in self.ids:
self.ids += [self.shorthash, self.sha256]
self.register()
+ self.title = f'{self.name} [{self.shorthash}]'
+
return self.shorthash
@@ -225,7 +229,10 @@ def read_state_dict(checkpoint_file, print_global_state=False, map_location=None
def load_model_weights(model, checkpoint_info: CheckpointInfo):
+ title = checkpoint_info.title
sd_model_hash = checkpoint_info.calculate_shorthash()
+ if checkpoint_info.title != title:
+ shared.opts.data["sd_model_checkpoint"] = checkpoint_info.title
cache_enabled = shared.opts.sd_checkpoint_cache > 0
diff --git a/modules/sd_vae.py b/modules/sd_vae.py
index b2af2ce7..4ce238b8 100644
--- a/modules/sd_vae.py
+++ b/modules/sd_vae.py
@@ -72,6 +72,13 @@ def refresh_vae_list():
os.path.join(shared.cmd_opts.ckpt_dir, '**/*.vae.safetensors'),
]
+ if shared.cmd_opts.vae_dir is not None and os.path.isdir(shared.cmd_opts.vae_dir):
+ paths += [
+ os.path.join(shared.cmd_opts.vae_dir, '**/*.ckpt'),
+ os.path.join(shared.cmd_opts.vae_dir, '**/*.pt'),
+ os.path.join(shared.cmd_opts.vae_dir, '**/*.safetensors'),
+ ]
+
candidates = []
for path in paths:
candidates += glob.iglob(path, recursive=True)
@@ -113,6 +120,12 @@ def resolve_vae(checkpoint_file):
return None, None
+def load_vae_dict(filename, map_location):
+ vae_ckpt = sd_models.read_state_dict(filename, map_location=map_location)
+ vae_dict_1 = {k: v for k, v in vae_ckpt.items() if k[0:4] != "loss" and k not in vae_ignore_keys}
+ return vae_dict_1
+
+
def load_vae(model, vae_file=None, vae_source="from unknown source"):
global vae_dict, loaded_vae_file
# save_settings = False
@@ -130,8 +143,7 @@ def load_vae(model, vae_file=None, vae_source="from unknown source"):
print(f"Loading VAE weights {vae_source}: {vae_file}")
store_base_vae(model)
- vae_ckpt = sd_models.read_state_dict(vae_file, map_location=shared.weight_load_location)
- vae_dict_1 = {k: v for k, v in vae_ckpt.items() if k[0:4] != "loss" and k not in vae_ignore_keys}
+ vae_dict_1 = load_vae_dict(vae_file, map_location=shared.weight_load_location)
_load_vae_dict(model, vae_dict_1)
if cache_enabled:
diff --git a/modules/shared.py b/modules/shared.py
index 483c4c62..a644c0be 100644
--- a/modules/shared.py
+++ b/modules/shared.py
@@ -9,7 +9,6 @@ from PIL import Image
import gradio as gr
import tqdm
-import modules.artists
import modules.interrogate
import modules.memmon
import modules.styles
@@ -20,12 +19,15 @@ from modules.paths import models_path, script_path, sd_path
demo = None
+sd_default_config = os.path.join(script_path, "configs/v1-inference.yaml")
sd_model_file = os.path.join(script_path, 'model.ckpt')
default_sd_model_file = sd_model_file
+
parser = argparse.ArgumentParser()
-parser.add_argument("--config", type=str, default=os.path.join(script_path, "configs/v1-inference.yaml"), help="path to config which constructs model",)
+parser.add_argument("--config", type=str, default=sd_default_config, help="path to config which constructs model",)
parser.add_argument("--ckpt", type=str, default=sd_model_file, help="path to checkpoint of stable diffusion model; if specified, this checkpoint will be added to the list of checkpoints and loaded",)
parser.add_argument("--ckpt-dir", type=str, default=None, help="Path to directory with stable diffusion checkpoints")
+parser.add_argument("--vae-dir", type=str, default=None, help="Path to directory with VAE files")
parser.add_argument("--gfpgan-dir", type=str, help="GFPGAN directory", default=('./src/gfpgan' if os.path.exists('./src/gfpgan') else './GFPGAN'))
parser.add_argument("--gfpgan-model", type=str, help="GFPGAN model file name", default=None)
parser.add_argument("--no-half", action='store_true', help="do not switch the model to 16-bit floats")
@@ -55,6 +57,7 @@ parser.add_argument("--realesrgan-models-path", type=str, help="Path to director
parser.add_argument("--clip-models-path", type=str, help="Path to directory with CLIP model file(s).", default=None)
parser.add_argument("--xformers", action='store_true', help="enable xformers for cross attention layers")
parser.add_argument("--force-enable-xformers", action='store_true', help="enable xformers for cross attention layers regardless of whether the checking code thinks you can run it; do not make bug reports if this fails to work")
+parser.add_argument("--xformers-flash-attention", action='store_true', help="enable xformers with Flash Attention to improve reproducibility (supported for SD2.x or variant only)")
parser.add_argument("--deepdanbooru", action='store_true', help="does not do anything")
parser.add_argument("--opt-split-attention", action='store_true', help="force-enables Doggettx's cross-attention layer optimization. By default, it's on for torch cuda.")
parser.add_argument("--opt-sub-quad-attention", action='store_true', help="enable memory efficient sub-quadratic cross-attention layer optimization")
@@ -64,6 +67,7 @@ parser.add_argument("--sub-quad-chunk-threshold", type=int, help="the percentage
parser.add_argument("--opt-split-attention-invokeai", action='store_true', help="force-enables InvokeAI's cross-attention layer optimization. By default, it's on when cuda is unavailable.")
parser.add_argument("--opt-split-attention-v1", action='store_true', help="enable older version of split attention optimization that does not consume all the VRAM it can find")
parser.add_argument("--disable-opt-split-attention", action='store_true', help="force-disables cross-attention layer optimization")
+parser.add_argument("--disable-nan-check", action='store_true', help="do not check if produced images/latent spaces have nans; useful for running without a checkpoint in CI")
parser.add_argument("--use-cpu", nargs='+', help="use CPU as torch device for specified modules", default=[], type=str.lower)
parser.add_argument("--listen", action='store_true', help="launch gradio with 0.0.0.0 as server name, allowing to respond to network requests")
parser.add_argument("--port", type=int, help="launch gradio with given server port, you need root/admin rights for ports < 1024, defaults to 7860 if available", default=None)
@@ -97,6 +101,8 @@ parser.add_argument("--cors-allow-origins-regex", type=str, help="Allowed CORS o
parser.add_argument("--tls-keyfile", type=str, help="Partially enables TLS, requires --tls-certfile to fully function", default=None)
parser.add_argument("--tls-certfile", type=str, help="Partially enables TLS, requires --tls-keyfile to fully function", default=None)
parser.add_argument("--server-name", type=str, help="Sets hostname of server", default=None)
+parser.add_argument("--gradio-queue", action='store_true', help="Uses gradio queue; experimental option; breaks restart UI button")
+
script_loading.preload_extensions(extensions.extensions_dir, parser)
script_loading.preload_extensions(extensions.extensions_builtin_dir, parser)
@@ -142,7 +148,7 @@ config_filename = cmd_opts.ui_settings_file
os.makedirs(cmd_opts.hypernetwork_dir, exist_ok=True)
hypernetworks = {}
-loaded_hypernetwork = None
+loaded_hypernetworks = []
def reload_hypernetworks():
@@ -150,8 +156,6 @@ def reload_hypernetworks():
global hypernetworks
hypernetworks = hypernetwork.list_hypernetworks(cmd_opts.hypernetwork_dir)
- hypernetwork.load_hypernetwork(opts.sd_hypernetwork)
-
class State:
@@ -252,8 +256,6 @@ class State:
state = State()
state.server_start = time.time()
-artist_db = modules.artists.ArtistsDatabase(os.path.join(script_path, 'artists.csv'))
-
styles_filename = cmd_opts.styles_file
prompt_styles = modules.styles.StyleDatabase(styles_filename)
@@ -368,6 +370,7 @@ options_templates.update(options_section(('face-restoration', "Face restoration"
}))
options_templates.update(options_section(('system', "System"), {
+ "show_warnings": OptionInfo(False, "Show warnings in console."),
"memmon_poll_rate": OptionInfo(8, "VRAM usage polls per second during generation. Set to 0 to disable.", gr.Slider, {"minimum": 0, "maximum": 40, "step": 1}),
"samples_log_stdout": OptionInfo(False, "Always print all generation info to standard output"),
"multiple_tqdm": OptionInfo(True, "Add a second progress bar to the console that shows progress for an entire job."),
@@ -395,10 +398,8 @@ options_templates.update(options_section(('sd', "Stable Diffusion"), {
"sd_vae_checkpoint_cache": OptionInfo(0, "VAE Checkpoints to cache in RAM", gr.Slider, {"minimum": 0, "maximum": 10, "step": 1}),
"sd_vae": OptionInfo("Automatic", "SD VAE", gr.Dropdown, lambda: {"choices": ["Automatic", "None"] + list(sd_vae.vae_dict)}, refresh=sd_vae.refresh_vae_list),
"sd_vae_as_default": OptionInfo(True, "Ignore selected VAE for stable diffusion checkpoints that have their own .vae.pt next to them"),
- "sd_hypernetwork": OptionInfo("None", "Hypernetwork", gr.Dropdown, lambda: {"choices": ["None"] + [x for x in hypernetworks.keys()]}, refresh=reload_hypernetworks),
- "sd_hypernetwork_strength": OptionInfo(1.0, "Hypernetwork strength", gr.Slider, {"minimum": 0.0, "maximum": 1.0, "step": 0.001}),
"inpainting_mask_weight": OptionInfo(1.0, "Inpainting conditioning mask strength", gr.Slider, {"minimum": 0.0, "maximum": 1.0, "step": 0.01}),
- "initial_noise_multiplier": OptionInfo(1.0, "Noise multiplier for img2img", gr.Slider, {"minimum": 0.5, "maximum": 1.5, "step": 0.01 }),
+ "initial_noise_multiplier": OptionInfo(1.0, "Noise multiplier for img2img", gr.Slider, {"minimum": 0.5, "maximum": 1.5, "step": 0.01}),
"img2img_color_correction": OptionInfo(False, "Apply color correction to img2img results to match original colors."),
"img2img_fix_steps": OptionInfo(False, "With img2img, do exactly the amount of steps the slider specifies (normally you'd do less with less denoising)."),
"img2img_background_color": OptionInfo("#ffffff", "With img2img, fill image's transparent parts with this color.", ui_components.FormColorPicker, {}),
@@ -406,8 +407,8 @@ options_templates.update(options_section(('sd', "Stable Diffusion"), {
"enable_emphasis": OptionInfo(True, "Emphasis: use (text) to make model pay more attention to text and [text] to make it pay less attention"),
"enable_batch_seeds": OptionInfo(True, "Make K-diffusion samplers produce same images in a batch as when making a single image"),
"comma_padding_backtrack": OptionInfo(20, "Increase coherency by padding from the last comma within n tokens when using more than 75 tokens", gr.Slider, {"minimum": 0, "maximum": 74, "step": 1 }),
- 'CLIP_stop_at_last_layers': OptionInfo(1, "Clip skip", gr.Slider, {"minimum": 1, "maximum": 12, "step": 1}),
- "random_artist_categories": OptionInfo([], "Allowed categories for random artists selection when using the Roll button", gr.CheckboxGroup, {"choices": artist_db.categories()}),
+ "CLIP_stop_at_last_layers": OptionInfo(1, "Clip skip", gr.Slider, {"minimum": 1, "maximum": 12, "step": 1}),
+ "extra_networks_default_multiplier": OptionInfo(1.0, "Multiplier for extra networks", gr.Slider, {"minimum": 0.0, "maximum": 1.0, "step": 0.01}),
}))
options_templates.update(options_section(('compatibility', "Compatibility"), {
@@ -418,7 +419,6 @@ options_templates.update(options_section(('compatibility', "Compatibility"), {
options_templates.update(options_section(('interrogate', "Interrogate Options"), {
"interrogate_keep_models_in_memory": OptionInfo(False, "Interrogate: keep models in VRAM"),
- "interrogate_use_builtin_artists": OptionInfo(True, "Interrogate: use artists from artists.csv"),
"interrogate_return_ranks": OptionInfo(False, "Interrogate: include ranks of model tags matches in results (Has no effect on caption-based interrogators)."),
"interrogate_clip_num_beams": OptionInfo(1, "Interrogate: num_beams for BLIP", gr.Slider, {"minimum": 1, "maximum": 16, "step": 1}),
"interrogate_clip_min_length": OptionInfo(24, "Interrogate: minimum description length (excluding artists, etc..)", gr.Slider, {"minimum": 1, "maximum": 128, "step": 1}),
@@ -444,10 +444,13 @@ options_templates.update(options_section(('ui', "User interface"), {
"js_modal_lightbox_initially_zoomed": OptionInfo(True, "Show images zoomed in by default in full page image viewer"),
"show_progress_in_title": OptionInfo(True, "Show generation progress in window title."),
"samplers_in_dropdown": OptionInfo(True, "Use dropdown for sampler selection instead of radio group"),
- "dimensions_and_batch_together": OptionInfo(True, "Show Witdth/Height and Batch sliders in same row"),
- 'quicksettings': OptionInfo("sd_model_checkpoint", "Quicksettings list"),
- 'ui_reorder': OptionInfo(", ".join(ui_reorder_categories), "txt2img/img2img UI item order"),
- 'localization': OptionInfo("None", "Localization (requires restart)", gr.Dropdown, lambda: {"choices": ["None"] + list(localization.localizations.keys())}, refresh=lambda: localization.list_localizations(cmd_opts.localizations_dir)),
+ "dimensions_and_batch_together": OptionInfo(True, "Show Width/Height and Batch sliders in same row"),
+ "keyedit_precision_attention": OptionInfo(0.1, "Ctrl+up/down precision when editing (attention:1.1)", gr.Slider, {"minimum": 0.01, "maximum": 0.2, "step": 0.001}),
+ "keyedit_precision_extra": OptionInfo(0.05, "Ctrl+up/down precision when editing <extra networks:0.9>", gr.Slider, {"minimum": 0.01, "maximum": 0.2, "step": 0.001}),
+ "quicksettings": OptionInfo("sd_model_checkpoint", "Quicksettings list"),
+ "ui_reorder": OptionInfo(", ".join(ui_reorder_categories), "txt2img/img2img UI item order"),
+ "ui_extra_networks_tab_reorder": OptionInfo("", "Extra networks tab order"),
+ "localization": OptionInfo("None", "Localization (requires restart)", gr.Dropdown, lambda: {"choices": ["None"] + list(localization.localizations.keys())}, refresh=lambda: localization.list_localizations(cmd_opts.localizations_dir)),
}))
options_templates.update(options_section(('ui', "Live previews"), {
@@ -472,6 +475,11 @@ options_templates.update(options_section(('sampler-params', "Sampler parameters"
'always_discard_next_to_last_sigma': OptionInfo(False, "Always discard next-to-last sigma"),
}))
+options_templates.update(options_section(('postprocessing', "Postprocessing"), {
+ 'postprocessing_scipts_order': OptionInfo("upscale, gfpgan, codeformer", "Postprocessing operation order"),
+ 'upscaling_max_images_in_cache': OptionInfo(5, "Maximum number of images in upscaling cache", gr.Slider, {"minimum": 0, "maximum": 10, "step": 1}),
+}))
+
options_templates.update(options_section((None, "Hidden options"), {
"disabled_extensions": OptionInfo([], "Disable those extensions"),
"sd_checkpoint_hash": OptionInfo("", "SHA256 hash of the current checkpoint"),
@@ -657,3 +665,17 @@ mem_mon.start()
def listfiles(dirname):
filenames = [os.path.join(dirname, x) for x in sorted(os.listdir(dirname)) if not x.startswith(".")]
return [file for file in filenames if os.path.isfile(file)]
+
+
+def html_path(filename):
+ return os.path.join(script_path, "html", filename)
+
+
+def html(filename):
+ path = html_path(filename)
+
+ if os.path.exists(path):
+ with open(path, encoding="utf8") as file:
+ return file.read()
+
+ return ""
diff --git a/modules/styles.py b/modules/styles.py
index ce6e71ca..990d5623 100644
--- a/modules/styles.py
+++ b/modules/styles.py
@@ -40,12 +40,18 @@ def apply_styles_to_prompt(prompt, styles):
class StyleDatabase:
def __init__(self, path: str):
self.no_style = PromptStyle("None", "", "")
- self.styles = {"None": self.no_style}
+ self.styles = {}
+ self.path = path
- if not os.path.exists(path):
+ self.reload()
+
+ def reload(self):
+ self.styles.clear()
+
+ if not os.path.exists(self.path):
return
- with open(path, "r", encoding="utf-8-sig", newline='') as file:
+ with open(self.path, "r", encoding="utf-8-sig", newline='') as file:
reader = csv.DictReader(file)
for row in reader:
# Support loading old CSV format with "name, text"-columns
diff --git a/modules/textual_inversion/preprocess.py b/modules/textual_inversion/preprocess.py
index 64abff4d..c0ac11d3 100644
--- a/modules/textual_inversion/preprocess.py
+++ b/modules/textual_inversion/preprocess.py
@@ -12,7 +12,7 @@ from modules.shared import opts, cmd_opts
from modules.textual_inversion import autocrop
-def preprocess(id_task, process_src, process_dst, process_width, process_height, preprocess_txt_action, process_flip, process_split, process_caption, process_caption_deepbooru=False, split_threshold=0.5, overlap_ratio=0.2, process_focal_crop=False, process_focal_crop_face_weight=0.9, process_focal_crop_entropy_weight=0.3, process_focal_crop_edges_weight=0.5, process_focal_crop_debug=False):
+def preprocess(id_task, process_src, process_dst, process_width, process_height, preprocess_txt_action, process_flip, process_split, process_caption, process_caption_deepbooru=False, split_threshold=0.5, overlap_ratio=0.2, process_focal_crop=False, process_focal_crop_face_weight=0.9, process_focal_crop_entropy_weight=0.3, process_focal_crop_edges_weight=0.5, process_focal_crop_debug=False, process_multicrop=None, process_multicrop_mindim=None, process_multicrop_maxdim=None, process_multicrop_minarea=None, process_multicrop_maxarea=None, process_multicrop_objective=None, process_multicrop_threshold=None):
try:
if process_caption:
shared.interrogator.load()
@@ -20,7 +20,7 @@ def preprocess(id_task, process_src, process_dst, process_width, process_height,
if process_caption_deepbooru:
deepbooru.model.start()
- preprocess_work(process_src, process_dst, process_width, process_height, preprocess_txt_action, process_flip, process_split, process_caption, process_caption_deepbooru, split_threshold, overlap_ratio, process_focal_crop, process_focal_crop_face_weight, process_focal_crop_entropy_weight, process_focal_crop_edges_weight, process_focal_crop_debug)
+ preprocess_work(process_src, process_dst, process_width, process_height, preprocess_txt_action, process_flip, process_split, process_caption, process_caption_deepbooru, split_threshold, overlap_ratio, process_focal_crop, process_focal_crop_face_weight, process_focal_crop_entropy_weight, process_focal_crop_edges_weight, process_focal_crop_debug, process_multicrop, process_multicrop_mindim, process_multicrop_maxdim, process_multicrop_minarea, process_multicrop_maxarea, process_multicrop_objective, process_multicrop_threshold)
finally:
@@ -109,8 +109,30 @@ def split_pic(image, inverse_xy, width, height, overlap_ratio):
splitted = image.crop((0, y, to_w, y + to_h))
yield splitted
-
-def preprocess_work(process_src, process_dst, process_width, process_height, preprocess_txt_action, process_flip, process_split, process_caption, process_caption_deepbooru=False, split_threshold=0.5, overlap_ratio=0.2, process_focal_crop=False, process_focal_crop_face_weight=0.9, process_focal_crop_entropy_weight=0.3, process_focal_crop_edges_weight=0.5, process_focal_crop_debug=False):
+# not using torchvision.transforms.CenterCrop because it doesn't allow float regions
+def center_crop(image: Image, w: int, h: int):
+ iw, ih = image.size
+ if ih / h < iw / w:
+ sw = w * ih / h
+ box = (iw - sw) / 2, 0, iw - (iw - sw) / 2, ih
+ else:
+ sh = h * iw / w
+ box = 0, (ih - sh) / 2, iw, ih - (ih - sh) / 2
+ return image.resize((w, h), Image.Resampling.LANCZOS, box)
+
+
+def multicrop_pic(image: Image, mindim, maxdim, minarea, maxarea, objective, threshold):
+ iw, ih = image.size
+ err = lambda w, h: 1-(lambda x: x if x < 1 else 1/x)(iw/ih/(w/h))
+ wh = max(((w, h) for w in range(mindim, maxdim+1, 64) for h in range(mindim, maxdim+1, 64)
+ if minarea <= w * h <= maxarea and err(w, h) <= threshold),
+ key= lambda wh: (wh[0]*wh[1], -err(*wh))[::1 if objective=='Maximize area' else -1],
+ default=None
+ )
+ return wh and center_crop(image, *wh)
+
+
+def preprocess_work(process_src, process_dst, process_width, process_height, preprocess_txt_action, process_flip, process_split, process_caption, process_caption_deepbooru=False, split_threshold=0.5, overlap_ratio=0.2, process_focal_crop=False, process_focal_crop_face_weight=0.9, process_focal_crop_entropy_weight=0.3, process_focal_crop_edges_weight=0.5, process_focal_crop_debug=False, process_multicrop=None, process_multicrop_mindim=None, process_multicrop_maxdim=None, process_multicrop_minarea=None, process_multicrop_maxarea=None, process_multicrop_objective=None, process_multicrop_threshold=None):
width = process_width
height = process_height
src = os.path.abspath(process_src)
@@ -194,6 +216,14 @@ def preprocess_work(process_src, process_dst, process_width, process_height, pre
save_pic(focal, index, params, existing_caption=existing_caption)
process_default_resize = False
+ if process_multicrop:
+ cropped = multicrop_pic(img, process_multicrop_mindim, process_multicrop_maxdim, process_multicrop_minarea, process_multicrop_maxarea, process_multicrop_objective, process_multicrop_threshold)
+ if cropped is not None:
+ save_pic(cropped, index, params, existing_caption=existing_caption)
+ else:
+ print(f"skipped {img.width}x{img.height} image {filename} (can't find suitable size within error threshold)")
+ process_default_resize = False
+
if process_default_resize:
img = images.resize_image(1, img, width, height)
save_pic(img, index, params, existing_caption=existing_caption)
diff --git a/modules/textual_inversion/textual_inversion.py b/modules/textual_inversion/textual_inversion.py
index 7e4a6d24..4e90f690 100644
--- a/modules/textual_inversion/textual_inversion.py
+++ b/modules/textual_inversion/textual_inversion.py
@@ -15,7 +15,7 @@ import numpy as np
from PIL import Image, PngImagePlugin
from torch.utils.tensorboard import SummaryWriter
-from modules import shared, devices, sd_hijack, processing, sd_models, images, sd_samplers
+from modules import shared, devices, sd_hijack, processing, sd_models, images, sd_samplers, sd_hijack_checkpoint
import modules.textual_inversion.dataset
from modules.textual_inversion.learn_schedule import LearnRateScheduler
@@ -50,6 +50,7 @@ class Embedding:
self.sd_checkpoint = None
self.sd_checkpoint_name = None
self.optimizer_state_dict = None
+ self.filename = None
def save(self, filename):
embedding_data = {
@@ -182,6 +183,7 @@ class EmbeddingDatabase:
embedding.sd_checkpoint_name = data.get('sd_checkpoint_name', None)
embedding.vectors = vec.shape[0]
embedding.shape = vec.shape[-1]
+ embedding.filename = path
if self.expected_shape == -1 or self.expected_shape == embedding.shape:
self.register_embedding(embedding, shared.sd_model)
@@ -452,6 +454,8 @@ def train_embedding(id_task, embedding_name, learn_rate, batch_size, gradient_st
pbar = tqdm.tqdm(total=steps - initial_step)
try:
+ sd_hijack_checkpoint.add()
+
for i in range((steps-initial_step) * gradient_step):
if scheduler.finished:
break
@@ -617,9 +621,11 @@ Last saved image: {html.escape(last_saved_image)}<br/>
pbar.close()
shared.sd_model.first_stage_model.to(devices.device)
shared.parallel_processing_allowed = old_parallel_processing_allowed
+ sd_hijack_checkpoint.remove()
return embedding, filename
+
def save_embedding(embedding, optimizer, checkpoint, embedding_name, filename, remove_cached_checksum=True):
old_embedding_name = embedding.name
old_sd_checkpoint = embedding.sd_checkpoint if hasattr(embedding, "sd_checkpoint") else None
diff --git a/modules/txt2img.py b/modules/txt2img.py
index ca5d4550..e945fd69 100644
--- a/modules/txt2img.py
+++ b/modules/txt2img.py
@@ -8,13 +8,13 @@ import modules.processing as processing
from modules.ui import plaintext_to_html
-def txt2img(id_task: str, prompt: str, negative_prompt: str, prompt_style: str, prompt_style2: str, steps: int, sampler_index: int, restore_faces: bool, tiling: bool, n_iter: int, batch_size: int, cfg_scale: float, seed: int, subseed: int, subseed_strength: float, seed_resize_from_h: int, seed_resize_from_w: int, seed_enable_extras: bool, height: int, width: int, enable_hr: bool, denoising_strength: float, hr_scale: float, hr_upscaler: str, hr_second_pass_steps: int, hr_resize_x: int, hr_resize_y: int, *args):
+def txt2img(id_task: str, prompt: str, negative_prompt: str, prompt_styles, steps: int, sampler_index: int, restore_faces: bool, tiling: bool, n_iter: int, batch_size: int, cfg_scale: float, seed: int, subseed: int, subseed_strength: float, seed_resize_from_h: int, seed_resize_from_w: int, seed_enable_extras: bool, height: int, width: int, enable_hr: bool, denoising_strength: float, hr_scale: float, hr_upscaler: str, hr_second_pass_steps: int, hr_resize_x: int, hr_resize_y: int, *args):
p = StableDiffusionProcessingTxt2Img(
sd_model=shared.sd_model,
outpath_samples=opts.outdir_samples or opts.outdir_txt2img_samples,
outpath_grids=opts.outdir_grids or opts.outdir_txt2img_grids,
prompt=prompt,
- styles=[prompt_style, prompt_style2],
+ styles=prompt_styles,
negative_prompt=negative_prompt,
seed=seed,
subseed=subseed,
diff --git a/modules/ui.py b/modules/ui.py
index 20b66165..85ae62c7 100644
--- a/modules/ui.py
+++ b/modules/ui.py
@@ -5,12 +5,12 @@ import mimetypes
import os
import platform
import random
-import subprocess as sp
import sys
import tempfile
import time
import traceback
from functools import partial, reduce
+import warnings
import gradio as gr
import gradio.routes
@@ -19,7 +19,7 @@ import numpy as np
from PIL import Image, PngImagePlugin
from modules.call_queue import wrap_gradio_gpu_call, wrap_queued_call, wrap_gradio_call
-from modules import sd_hijack, sd_models, localization, script_callbacks, ui_extensions, deepbooru
+from modules import sd_hijack, sd_models, localization, script_callbacks, ui_extensions, deepbooru, sd_vae, extra_networks, postprocessing, ui_components, ui_common, ui_postprocessing
from modules.ui_components import FormRow, FormGroup, ToolButton, FormHTML
from modules.paths import script_path
@@ -40,6 +40,9 @@ from modules.sd_samplers import samplers, samplers_for_img2img
from modules.textual_inversion import textual_inversion
import modules.hypernetworks.ui
from modules.generation_parameters_copypaste import image_from_url_text
+import modules.extras
+
+warnings.filterwarnings("default" if opts.show_warnings else "ignore", category=UserWarning)
# this is a fix for Windows users. Without it, javascript files will be served with text/html content-type and the browser will not show any UI
mimetypes.init()
@@ -72,6 +75,7 @@ css_hide_progressbar = """
.wrap .m-12::before { content:"Loading..." }
.wrap .z-20 svg { display:none!important; }
.wrap .z-20::before { content:"Loading..." }
+.wrap.cover-bg .z-20::before { content:"" }
.progress-bar { display:none!important; }
.meta-text { display:none!important; }
.meta-text-center { display:none!important; }
@@ -82,86 +86,22 @@ css_hide_progressbar = """
random_symbol = '\U0001f3b2\ufe0f' # 🎲️
reuse_symbol = '\u267b\ufe0f' # ♻️
paste_symbol = '\u2199\ufe0f' # ↙
-folder_symbol = '\U0001f4c2' # 📂
refresh_symbol = '\U0001f504' # 🔄
save_style_symbol = '\U0001f4be' # 💾
apply_style_symbol = '\U0001f4cb' # 📋
clear_prompt_symbol = '\U0001F5D1' # 🗑️
+extra_networks_symbol = '\U0001F3B4' # 🎴
def plaintext_to_html(text):
- text = "<p>" + "<br>\n".join([f"{html.escape(x)}" for x in text.split('\n')]) + "</p>"
- return text
+ return ui_common.plaintext_to_html(text)
+
def send_gradio_gallery_to_image(x):
if len(x) == 0:
return None
return image_from_url_text(x[0])
-def save_files(js_data, images, do_make_zip, index):
- import csv
- filenames = []
- fullfns = []
-
- #quick dictionary to class object conversion. Its necessary due apply_filename_pattern requiring it
- class MyObject:
- def __init__(self, d=None):
- if d is not None:
- for key, value in d.items():
- setattr(self, key, value)
-
- data = json.loads(js_data)
-
- p = MyObject(data)
- path = opts.outdir_save
- save_to_dirs = opts.use_save_to_dirs_for_ui
- extension: str = opts.samples_format
- start_index = 0
-
- if index > -1 and opts.save_selected_only and (index >= data["index_of_first_image"]): # ensures we are looking at a specific non-grid picture, and we have save_selected_only
-
- images = [images[index]]
- start_index = index
-
- os.makedirs(opts.outdir_save, exist_ok=True)
-
- with open(os.path.join(opts.outdir_save, "log.csv"), "a", encoding="utf8", newline='') as file:
- at_start = file.tell() == 0
- writer = csv.writer(file)
- if at_start:
- writer.writerow(["prompt", "seed", "width", "height", "sampler", "cfgs", "steps", "filename", "negative_prompt"])
-
- for image_index, filedata in enumerate(images, start_index):
- image = image_from_url_text(filedata)
-
- is_grid = image_index < p.index_of_first_image
- i = 0 if is_grid else (image_index - p.index_of_first_image)
-
- fullfn, txt_fullfn = save_image(image, path, "", seed=p.all_seeds[i], prompt=p.all_prompts[i], extension=extension, info=p.infotexts[image_index], grid=is_grid, p=p, save_to_dirs=save_to_dirs)
-
- filename = os.path.relpath(fullfn, path)
- filenames.append(filename)
- fullfns.append(fullfn)
- if txt_fullfn:
- filenames.append(os.path.basename(txt_fullfn))
- fullfns.append(txt_fullfn)
-
- writer.writerow([data["prompt"], data["seed"], data["width"], data["height"], data["sampler_name"], data["cfg_scale"], data["steps"], filenames[0], data["negative_prompt"]])
-
- # Make Zip
- if do_make_zip:
- zip_filepath = os.path.join(path, "images.zip")
-
- from zipfile import ZipFile
- with ZipFile(zip_filepath, "w") as zip_file:
- for i in range(len(fullfns)):
- with open(fullfns[i], mode="rb") as f:
- zip_file.writestr(filenames[i], f.read())
- fullfns.insert(0, zip_filepath)
-
- return gr.File.update(value=fullfns, visible=True), plaintext_to_html(f"Saved: {filenames[0]}")
-
-
def visit(x, func, path=""):
if hasattr(x, 'children'):
for c in x.children:
@@ -180,7 +120,7 @@ def add_style(name: str, prompt: str, negative_prompt: str):
# reserialize all styles every time we save them
shared.prompt_styles.save_styles(shared.styles_filename)
- return [gr.Dropdown.update(visible=True, choices=list(shared.prompt_styles.styles)) for _ in range(4)]
+ return [gr.Dropdown.update(visible=True, choices=list(shared.prompt_styles.styles)) for _ in range(2)]
def calc_resolution_hires(enable, width, height, hr_scale, hr_resize_x, hr_resize_y):
@@ -197,22 +137,44 @@ def calc_resolution_hires(enable, width, height, hr_scale, hr_resize_x, hr_resiz
return f"resize: from <span class='resolution'>{p.width}x{p.height}</span> to <span class='resolution'>{p.hr_resize_x or p.hr_upscale_to_x}x{p.hr_resize_y or p.hr_upscale_to_y}</span>"
-def apply_styles(prompt, prompt_neg, style1_name, style2_name):
- prompt = shared.prompt_styles.apply_styles_to_prompt(prompt, [style1_name, style2_name])
- prompt_neg = shared.prompt_styles.apply_negative_styles_to_prompt(prompt_neg, [style1_name, style2_name])
+def apply_styles(prompt, prompt_neg, styles):
+ prompt = shared.prompt_styles.apply_styles_to_prompt(prompt, styles)
+ prompt_neg = shared.prompt_styles.apply_negative_styles_to_prompt(prompt_neg, styles)
+
+ return [gr.Textbox.update(value=prompt), gr.Textbox.update(value=prompt_neg), gr.Dropdown.update(value=[])]
+
+
+def process_interrogate(interrogation_function, mode, ii_input_dir, ii_output_dir, *ii_singles):
+ if mode in {0, 1, 3, 4}:
+ return [interrogation_function(ii_singles[mode]), None]
+ elif mode == 2:
+ return [interrogation_function(ii_singles[mode]["image"]), None]
+ elif mode == 5:
+ assert not shared.cmd_opts.hide_ui_dir_config, "Launched with --hide-ui-dir-config, batch img2img disabled"
+ images = shared.listfiles(ii_input_dir)
+ print(f"Will process {len(images)} images.")
+ if ii_output_dir != "":
+ os.makedirs(ii_output_dir, exist_ok=True)
+ else:
+ ii_output_dir = ii_input_dir
+
+ for image in images:
+ img = Image.open(image)
+ filename = os.path.basename(image)
+ left, _ = os.path.splitext(filename)
+ print(interrogation_function(img), file=open(os.path.join(ii_output_dir, left + ".txt"), 'a'))
- return [gr.Textbox.update(value=prompt), gr.Textbox.update(value=prompt_neg), gr.Dropdown.update(value="None"), gr.Dropdown.update(value="None")]
+ return [gr.update(), None]
def interrogate(image):
prompt = shared.interrogator.interrogate(image.convert("RGB"))
-
- return gr_show(True) if prompt is None else prompt
+ return gr.update() if prompt is None else prompt
def interrogate_deepbooru(image):
prompt = deepbooru.model.tag(image)
- return gr_show(True) if prompt is None else prompt
+ return gr.update() if prompt is None else prompt
def create_seed_inputs(target_interface):
@@ -299,6 +261,8 @@ def connect_reuse_seed(seed: gr.Number, reuse_seed: gr.Button, generation_info:
def update_token_counter(text, steps):
try:
+ text, _ = extra_networks.parse_prompt(text)
+
_, prompt_flat_list, _ = prompt_parser.get_multicond_prompt_list([text])
prompt_schedules = prompt_parser.get_learned_conditioning_prompt_schedules(prompt_flat_list, steps)
@@ -310,43 +274,23 @@ def update_token_counter(text, steps):
flat_prompts = reduce(lambda list1, list2: list1+list2, prompt_schedules)
prompts = [prompt_text for step, prompt_text in flat_prompts]
token_count, max_length = max([model_hijack.get_prompt_lengths(prompt) for prompt in prompts], key=lambda args: args[0])
- style_class = ' class="red"' if (token_count > max_length) else ""
- return f"<span {style_class}>{token_count}/{max_length}</span>"
+ return f"<span class='gr-box gr-text-input'>{token_count}/{max_length}</span>"
def create_toprow(is_img2img):
id_part = "img2img" if is_img2img else "txt2img"
- with gr.Row(elem_id="toprow"):
- with gr.Column(scale=6):
+ with gr.Row(elem_id=f"{id_part}_toprow", variant="compact"):
+ with gr.Column(elem_id=f"{id_part}_prompt_container", scale=6):
with gr.Row():
with gr.Column(scale=80):
with gr.Row():
- prompt = gr.Textbox(label="Prompt", elem_id=f"{id_part}_prompt", show_label=False, lines=2,
- placeholder="Prompt (press Ctrl+Enter or Alt+Enter to generate)"
- )
+ prompt = gr.Textbox(label="Prompt", elem_id=f"{id_part}_prompt", show_label=False, lines=3, placeholder="Prompt (press Ctrl+Enter or Alt+Enter to generate)")
with gr.Row():
with gr.Column(scale=80):
with gr.Row():
- negative_prompt = gr.Textbox(label="Negative prompt", elem_id=f"{id_part}_neg_prompt", show_label=False, lines=2,
- placeholder="Negative prompt (press Ctrl+Enter or Alt+Enter to generate)"
- )
-
- with gr.Column(scale=1, elem_id="roll_col"):
- paste = gr.Button(value=paste_symbol, elem_id="paste")
- save_style = gr.Button(value=save_style_symbol, elem_id="style_create")
- prompt_style_apply = gr.Button(value=apply_style_symbol, elem_id="style_apply")
- clear_prompt_button = gr.Button(value=clear_prompt_symbol, elem_id=f"{id_part}_clear_prompt")
- token_counter = gr.HTML(value="<span></span>", elem_id=f"{id_part}_token_counter")
- token_button = gr.Button(visible=False, elem_id=f"{id_part}_token_button")
-
- clear_prompt_button.click(
- fn=lambda *x: x,
- _js="confirm_clear_prompt",
- inputs=[prompt, negative_prompt],
- outputs=[prompt, negative_prompt],
- )
+ negative_prompt = gr.Textbox(label="Negative prompt", elem_id=f"{id_part}_neg_prompt", show_label=False, lines=2, placeholder="Negative prompt (press Ctrl+Enter or Alt+Enter to generate)")
button_interrogate = None
button_deepbooru = None
@@ -355,7 +299,7 @@ def create_toprow(is_img2img):
button_interrogate = gr.Button('Interrogate\nCLIP', elem_id="interrogate")
button_deepbooru = gr.Button('Interrogate\nDeepBooru', elem_id="deepbooru")
- with gr.Column(scale=1):
+ with gr.Column(scale=1, elem_id=f"{id_part}_actions_column"):
with gr.Row(elem_id=f"{id_part}_generate_box"):
interrupt = gr.Button('Interrupt', elem_id=f"{id_part}_interrupt")
skip = gr.Button('Skip', elem_id=f"{id_part}_skip")
@@ -373,14 +317,30 @@ def create_toprow(is_img2img):
outputs=[],
)
- with gr.Row():
- with gr.Column(scale=1, elem_id="style_pos_col"):
- prompt_style = gr.Dropdown(label="Style 1", elem_id=f"{id_part}_style_index", choices=[k for k, v in shared.prompt_styles.styles.items()], value=next(iter(shared.prompt_styles.styles.keys())))
+ with gr.Row(elem_id=f"{id_part}_tools"):
+ paste = ToolButton(value=paste_symbol, elem_id="paste")
+ clear_prompt_button = ToolButton(value=clear_prompt_symbol, elem_id=f"{id_part}_clear_prompt")
+ extra_networks_button = ToolButton(value=extra_networks_symbol, elem_id=f"{id_part}_extra_networks")
+ prompt_style_apply = ToolButton(value=apply_style_symbol, elem_id=f"{id_part}_style_apply")
+ save_style = ToolButton(value=save_style_symbol, elem_id=f"{id_part}_style_create")
+
+ token_counter = gr.HTML(value="<span></span>", elem_id=f"{id_part}_token_counter")
+ token_button = gr.Button(visible=False, elem_id=f"{id_part}_token_button")
+ negative_token_counter = gr.HTML(value="<span></span>", elem_id=f"{id_part}_negative_token_counter")
+ negative_token_button = gr.Button(visible=False, elem_id=f"{id_part}_negative_token_button")
+
+ clear_prompt_button.click(
+ fn=lambda *x: x,
+ _js="confirm_clear_prompt",
+ inputs=[prompt, negative_prompt],
+ outputs=[prompt, negative_prompt],
+ )
- with gr.Column(scale=1, elem_id="style_neg_col"):
- prompt_style2 = gr.Dropdown(label="Style 2", elem_id=f"{id_part}_style2_index", choices=[k for k, v in shared.prompt_styles.styles.items()], value=next(iter(shared.prompt_styles.styles.keys())))
+ with gr.Row(elem_id=f"{id_part}_styles_row"):
+ prompt_styles = gr.Dropdown(label="Styles", elem_id=f"{id_part}_styles", choices=[k for k, v in shared.prompt_styles.styles.items()], value=[], multiselect=True)
+ create_refresh_button(prompt_styles, shared.prompt_styles.reload, lambda: {"choices": [k for k, v in shared.prompt_styles.styles.items()]}, f"refresh_{id_part}_styles")
- return prompt, prompt_style, negative_prompt, prompt_style2, submit, button_interrogate, button_deepbooru, prompt_style_apply, save_style, paste, token_counter, token_button
+ return prompt, prompt_styles, negative_prompt, submit, button_interrogate, button_deepbooru, prompt_style_apply, save_style, paste, extra_networks_button, token_counter, token_button, negative_token_counter, negative_token_button
def setup_progressbar(*args, **kwargs):
@@ -417,21 +377,7 @@ def apply_setting(key, value):
opts.data_labels[key].onchange()
opts.save(shared.config_filename)
- return value
-
-
-def update_generation_info(args):
- generation_info, html_info, img_index = args
- try:
- generation_info = json.loads(generation_info)
- if img_index < 0 or img_index >= len(generation_info["infotexts"]):
- return html_info
- return plaintext_to_html(generation_info["infotexts"][img_index])
- except Exception:
- pass
- # if the json parse or anything else fails, just return the old html_info
- return html_info
-
+ return getattr(opts, key)
def create_refresh_button(refresh_component, refresh_method, refreshed_args, elem_id):
def refresh():
@@ -453,107 +399,7 @@ def create_refresh_button(refresh_component, refresh_method, refreshed_args, ele
def create_output_panel(tabname, outdir):
- def open_folder(f):
- if not os.path.exists(f):
- print(f'Folder "{f}" does not exist. After you create an image, the folder will be created.')
- return
- elif not os.path.isdir(f):
- print(f"""
-WARNING
-An open_folder request was made with an argument that is not a folder.
-This could be an error or a malicious attempt to run code on your computer.
-Requested path was: {f}
-""", file=sys.stderr)
- return
-
- if not shared.cmd_opts.hide_ui_dir_config:
- path = os.path.normpath(f)
- if platform.system() == "Windows":
- os.startfile(path)
- elif platform.system() == "Darwin":
- sp.Popen(["open", path])
- elif "microsoft-standard-WSL2" in platform.uname().release:
- sp.Popen(["wsl-open", path])
- else:
- sp.Popen(["xdg-open", path])
-
- with gr.Column(variant='panel', elem_id=f"{tabname}_results"):
- with gr.Group(elem_id=f"{tabname}_gallery_container"):
- result_gallery = gr.Gallery(label='Output', show_label=False, elem_id=f"{tabname}_gallery").style(grid=4)
-
- generation_info = None
- with gr.Column():
- with gr.Row(elem_id=f"image_buttons_{tabname}"):
- open_folder_button = gr.Button(folder_symbol, elem_id="hidden_element" if shared.cmd_opts.hide_ui_dir_config else f'open_folder_{tabname}')
-
- if tabname != "extras":
- save = gr.Button('Save', elem_id=f'save_{tabname}')
- save_zip = gr.Button('Zip', elem_id=f'save_zip_{tabname}')
-
- buttons = parameters_copypaste.create_buttons(["img2img", "inpaint", "extras"])
-
- open_folder_button.click(
- fn=lambda: open_folder(opts.outdir_samples or outdir),
- inputs=[],
- outputs=[],
- )
-
- if tabname != "extras":
- with gr.Row():
- download_files = gr.File(None, file_count="multiple", interactive=False, show_label=False, visible=False, elem_id=f'download_files_{tabname}')
-
- with gr.Group():
- html_info = gr.HTML(elem_id=f'html_info_{tabname}')
- html_log = gr.HTML(elem_id=f'html_log_{tabname}')
-
- generation_info = gr.Textbox(visible=False, elem_id=f'generation_info_{tabname}')
- if tabname == 'txt2img' or tabname == 'img2img':
- generation_info_button = gr.Button(visible=False, elem_id=f"{tabname}_generation_info_button")
- generation_info_button.click(
- fn=update_generation_info,
- _js="(x, y) => [x, y, selected_gallery_index()]",
- inputs=[generation_info, html_info],
- outputs=[html_info],
- preprocess=False
- )
-
- save.click(
- fn=wrap_gradio_call(save_files),
- _js="(x, y, z, w) => [x, y, false, selected_gallery_index()]",
- inputs=[
- generation_info,
- result_gallery,
- html_info,
- html_info,
- ],
- outputs=[
- download_files,
- html_log,
- ]
- )
-
- save_zip.click(
- fn=wrap_gradio_call(save_files),
- _js="(x, y, z, w) => [x, y, true, selected_gallery_index()]",
- inputs=[
- generation_info,
- result_gallery,
- html_info,
- html_info,
- ],
- outputs=[
- download_files,
- html_log,
- ]
- )
-
- else:
- html_info_x = gr.HTML(elem_id=f'html_info_x_{tabname}')
- html_info = gr.HTML(elem_id=f'html_info_{tabname}')
- html_log = gr.HTML(elem_id=f'html_log_{tabname}')
-
- parameters_copypaste.bind_buttons(buttons, result_gallery, "txt2img" if tabname == "txt2img" else None)
- return result_gallery, generation_info if tabname != "extras" else html_info_x, html_info, html_log
+ return ui_common.create_output_panel(tabname, outdir)
def create_sampler_and_steps_selection(choices, tabname):
@@ -576,6 +422,16 @@ def ordered_ui_categories():
yield category
+def get_value_for_setting(key):
+ value = getattr(opts, key)
+
+ info = opts.data_labels[key]
+ args = info.component_args() if callable(info.component_args) else info.component_args or {}
+ args = {k: v for k, v in args.items() if k not in {'precision'}}
+
+ return gr.update(value=value, **args)
+
+
def create_ui():
import modules.img2img
import modules.txt2img
@@ -588,13 +444,17 @@ def create_ui():
modules.scripts.scripts_txt2img.initialize_scripts(is_img2img=False)
with gr.Blocks(analytics_enabled=False) as txt2img_interface:
- txt2img_prompt, txt2img_prompt_style, txt2img_negative_prompt, txt2img_prompt_style2, submit, _, _,txt2img_prompt_style_apply, txt2img_save_style, txt2img_paste, token_counter, token_button = create_toprow(is_img2img=False)
+ txt2img_prompt, txt2img_prompt_styles, txt2img_negative_prompt, submit, _, _, txt2img_prompt_style_apply, txt2img_save_style, txt2img_paste, extra_networks_button, token_counter, token_button, negative_token_counter, negative_token_button = create_toprow(is_img2img=False)
dummy_component = gr.Label(visible=False)
- txt_prompt_img = gr.File(label="", elem_id="txt2img_prompt_image", file_count="single", type="bytes", visible=False)
+ txt_prompt_img = gr.File(label="", elem_id="txt2img_prompt_image", file_count="single", type="binary", visible=False)
+
+ with FormRow(variant='compact', elem_id="txt2img_extra_networks", visible=False) as extra_networks:
+ from modules import ui_extra_networks
+ extra_networks_ui = ui_extra_networks.create_ui(extra_networks, extra_networks_button, 'txt2img')
with gr.Row().style(equal_height=False):
- with gr.Column(variant='panel', elem_id="txt2img_settings"):
+ with gr.Column(variant='compact', elem_id="txt2img_settings"):
for category in ordered_ui_categories():
if category == "sampler":
steps, sampler_index = create_sampler_and_steps_selection(samplers, "txt2img")
@@ -617,7 +477,7 @@ def create_ui():
seed, reuse_seed, subseed, reuse_subseed, subseed_strength, seed_resize_from_h, seed_resize_from_w, seed_checkbox = create_seed_inputs('txt2img')
elif category == "checkboxes":
- with FormRow(elem_id="txt2img_checkboxes"):
+ with FormRow(elem_id="txt2img_checkboxes", variant="compact"):
restore_faces = gr.Checkbox(label='Restore faces', value=False, visible=len(shared.face_restorers) > 1, elem_id="txt2img_restore_faces")
tiling = gr.Checkbox(label='Tiling', value=False, elem_id="txt2img_tiling")
enable_hr = gr.Checkbox(label='Hires. fix', value=False, elem_id="txt2img_enable_hr")
@@ -625,12 +485,12 @@ def create_ui():
elif category == "hires_fix":
with FormGroup(visible=False, elem_id="txt2img_hires_fix") as hr_options:
- with FormRow(elem_id="txt2img_hires_fix_row1"):
+ with FormRow(elem_id="txt2img_hires_fix_row1", variant="compact"):
hr_upscaler = gr.Dropdown(label="Upscaler", elem_id="txt2img_hr_upscaler", choices=[*shared.latent_upscale_modes, *[x.name for x in shared.sd_upscalers]], value=shared.latent_upscale_default_mode)
hr_second_pass_steps = gr.Slider(minimum=0, maximum=150, step=1, label='Hires steps', value=0, elem_id="txt2img_hires_steps")
denoising_strength = gr.Slider(minimum=0.0, maximum=1.0, step=0.01, label='Denoising strength', value=0.7, elem_id="txt2img_denoising_strength")
- with FormRow(elem_id="txt2img_hires_fix_row2"):
+ with FormRow(elem_id="txt2img_hires_fix_row2", variant="compact"):
hr_scale = gr.Slider(minimum=1.0, maximum=4.0, step=0.05, label="Upscale by", value=2.0, elem_id="txt2img_hr_scale")
hr_resize_x = gr.Slider(minimum=0, maximum=2048, step=8, label="Resize width to", value=0, elem_id="txt2img_hr_resize_x")
hr_resize_y = gr.Slider(minimum=0, maximum=2048, step=8, label="Resize height to", value=0, elem_id="txt2img_hr_resize_y")
@@ -674,8 +534,7 @@ def create_ui():
dummy_component,
txt2img_prompt,
txt2img_negative_prompt,
- txt2img_prompt_style,
- txt2img_prompt_style2,
+ txt2img_prompt_styles,
steps,
sampler_index,
restore_faces,
@@ -765,17 +624,24 @@ def create_ui():
]
token_button.click(fn=wrap_queued_call(update_token_counter), inputs=[txt2img_prompt, steps], outputs=[token_counter])
+ negative_token_button.click(fn=wrap_queued_call(update_token_counter), inputs=[txt2img_negative_prompt, steps], outputs=[negative_token_counter])
+
+ ui_extra_networks.setup_ui(extra_networks_ui, txt2img_gallery)
modules.scripts.scripts_current = modules.scripts.scripts_img2img
modules.scripts.scripts_img2img.initialize_scripts(is_img2img=True)
with gr.Blocks(analytics_enabled=False) as img2img_interface:
- img2img_prompt, img2img_prompt_style, img2img_negative_prompt, img2img_prompt_style2, submit, img2img_interrogate, img2img_deepbooru, img2img_prompt_style_apply, img2img_save_style, img2img_paste,token_counter, token_button = create_toprow(is_img2img=True)
+ img2img_prompt, img2img_prompt_styles, img2img_negative_prompt, submit, img2img_interrogate, img2img_deepbooru, img2img_prompt_style_apply, img2img_save_style, img2img_paste, extra_networks_button, token_counter, token_button, negative_token_counter, negative_token_button = create_toprow(is_img2img=True)
- img2img_prompt_img = gr.File(label="", elem_id="img2img_prompt_image", file_count="single", type="bytes", visible=False)
+ img2img_prompt_img = gr.File(label="", elem_id="img2img_prompt_image", file_count="single", type="binary", visible=False)
+
+ with FormRow(variant='compact', elem_id="img2img_extra_networks", visible=False) as extra_networks:
+ from modules import ui_extra_networks
+ extra_networks_ui_img2img = ui_extra_networks.create_ui(extra_networks, extra_networks_button, 'img2img')
with FormRow().style(equal_height=False):
- with gr.Column(variant='panel', elem_id="img2img_settings"):
+ with gr.Column(variant='compact', elem_id="img2img_settings"):
copy_image_buttons = []
copy_image_destinations = {}
@@ -875,7 +741,7 @@ def create_ui():
seed, reuse_seed, subseed, reuse_subseed, subseed_strength, seed_resize_from_h, seed_resize_from_w, seed_checkbox = create_seed_inputs('img2img')
elif category == "checkboxes":
- with FormRow(elem_id="img2img_checkboxes"):
+ with FormRow(elem_id="img2img_checkboxes", variant="compact"):
restore_faces = gr.Checkbox(label='Restore faces', value=False, visible=len(shared.face_restorers) > 1, elem_id="img2img_restore_faces")
tiling = gr.Checkbox(label='Tiling', value=False, elem_id="img2img_tiling")
@@ -943,8 +809,7 @@ def create_ui():
dummy_component,
img2img_prompt,
img2img_negative_prompt,
- img2img_prompt_style,
- img2img_prompt_style2,
+ img2img_prompt_styles,
init_img,
sketch,
init_img_with_mask,
@@ -983,23 +848,36 @@ def create_ui():
show_progress=False,
)
+ interrogate_args = dict(
+ _js="get_img2img_tab_index",
+ inputs=[
+ dummy_component,
+ img2img_batch_input_dir,
+ img2img_batch_output_dir,
+ init_img,
+ sketch,
+ init_img_with_mask,
+ inpaint_color_sketch,
+ init_img_inpaint,
+ ],
+ outputs=[img2img_prompt, dummy_component],
+ )
+
img2img_prompt.submit(**img2img_args)
submit.click(**img2img_args)
img2img_interrogate.click(
- fn=interrogate,
- inputs=[init_img],
- outputs=[img2img_prompt],
+ fn=lambda *args: process_interrogate(interrogate, *args),
+ **interrogate_args,
)
img2img_deepbooru.click(
- fn=interrogate_deepbooru,
- inputs=[init_img],
- outputs=[img2img_prompt],
+ fn=lambda *args: process_interrogate(interrogate_deepbooru, *args),
+ **interrogate_args,
)
prompts = [(txt2img_prompt, txt2img_negative_prompt), (img2img_prompt, img2img_negative_prompt)]
- style_dropdowns = [(txt2img_prompt_style, txt2img_prompt_style2), (img2img_prompt_style, img2img_prompt_style2)]
+ style_dropdowns = [txt2img_prompt_styles, img2img_prompt_styles]
style_js_funcs = ["update_txt2img_tokens", "update_img2img_tokens"]
for button, (prompt, negative_prompt) in zip([txt2img_save_style, img2img_save_style], prompts):
@@ -1009,18 +887,21 @@ def create_ui():
# Have to pass empty dummy component here, because the JavaScript and Python function have to accept
# the same number of parameters, but we only know the style-name after the JavaScript prompt
inputs=[dummy_component, prompt, negative_prompt],
- outputs=[txt2img_prompt_style, img2img_prompt_style, txt2img_prompt_style2, img2img_prompt_style2],
+ outputs=[txt2img_prompt_styles, img2img_prompt_styles],
)
- for button, (prompt, negative_prompt), (style1, style2), js_func in zip([txt2img_prompt_style_apply, img2img_prompt_style_apply], prompts, style_dropdowns, style_js_funcs):
+ for button, (prompt, negative_prompt), styles, js_func in zip([txt2img_prompt_style_apply, img2img_prompt_style_apply], prompts, style_dropdowns, style_js_funcs):
button.click(
fn=apply_styles,
_js=js_func,
- inputs=[prompt, negative_prompt, style1, style2],
- outputs=[prompt, negative_prompt, style1, style2],
+ inputs=[prompt, negative_prompt, styles],
+ outputs=[prompt, negative_prompt, styles],
)
token_button.click(fn=update_token_counter, inputs=[img2img_prompt, steps], outputs=[token_counter])
+ negative_token_button.click(fn=wrap_queued_call(update_token_counter), inputs=[txt2img_negative_prompt, steps], outputs=[negative_token_counter])
+
+ ui_extra_networks.setup_ui(extra_networks_ui_img2img, img2img_gallery)
img2img_paste_fields = [
(img2img_prompt, "Prompt"),
@@ -1047,86 +928,7 @@ def create_ui():
modules.scripts.scripts_current = None
with gr.Blocks(analytics_enabled=False) as extras_interface:
- with gr.Row().style(equal_height=False):
- with gr.Column(variant='panel'):
- with gr.Tabs(elem_id="mode_extras"):
- with gr.TabItem('Single Image', elem_id="extras_single_tab"):
- extras_image = gr.Image(label="Source", source="upload", interactive=True, type="pil", elem_id="extras_image")
-
- with gr.TabItem('Batch Process', elem_id="extras_batch_process_tab"):
- image_batch = gr.File(label="Batch Process", file_count="multiple", interactive=True, type="file", elem_id="extras_image_batch")
-
- with gr.TabItem('Batch from Directory', elem_id="extras_batch_directory_tab"):
- extras_batch_input_dir = gr.Textbox(label="Input directory", **shared.hide_dirs, placeholder="A directory on the same machine where the server is running.", elem_id="extras_batch_input_dir")
- extras_batch_output_dir = gr.Textbox(label="Output directory", **shared.hide_dirs, placeholder="Leave blank to save images to the default path.", elem_id="extras_batch_output_dir")
- show_extras_results = gr.Checkbox(label='Show result images', value=True, elem_id="extras_show_extras_results")
-
- submit = gr.Button('Generate', elem_id="extras_generate", variant='primary')
-
- with gr.Tabs(elem_id="extras_resize_mode"):
- with gr.TabItem('Scale by', elem_id="extras_scale_by_tab"):
- upscaling_resize = gr.Slider(minimum=1.0, maximum=8.0, step=0.05, label="Resize", value=4, elem_id="extras_upscaling_resize")
- with gr.TabItem('Scale to', elem_id="extras_scale_to_tab"):
- with gr.Group():
- with gr.Row():
- upscaling_resize_w = gr.Number(label="Width", value=512, precision=0, elem_id="extras_upscaling_resize_w")
- upscaling_resize_h = gr.Number(label="Height", value=512, precision=0, elem_id="extras_upscaling_resize_h")
- upscaling_crop = gr.Checkbox(label='Crop to fit', value=True, elem_id="extras_upscaling_crop")
-
- with gr.Group():
- extras_upscaler_1 = gr.Radio(label='Upscaler 1', elem_id="extras_upscaler_1", choices=[x.name for x in shared.sd_upscalers], value=shared.sd_upscalers[0].name, type="index")
-
- with gr.Group():
- extras_upscaler_2 = gr.Radio(label='Upscaler 2', elem_id="extras_upscaler_2", choices=[x.name for x in shared.sd_upscalers], value=shared.sd_upscalers[0].name, type="index")
- extras_upscaler_2_visibility = gr.Slider(minimum=0.0, maximum=1.0, step=0.001, label="Upscaler 2 visibility", value=1, elem_id="extras_upscaler_2_visibility")
-
- with gr.Group():
- gfpgan_visibility = gr.Slider(minimum=0.0, maximum=1.0, step=0.001, label="GFPGAN visibility", value=0, interactive=modules.gfpgan_model.have_gfpgan, elem_id="extras_gfpgan_visibility")
-
- with gr.Group():
- codeformer_visibility = gr.Slider(minimum=0.0, maximum=1.0, step=0.001, label="CodeFormer visibility", value=0, interactive=modules.codeformer_model.have_codeformer, elem_id="extras_codeformer_visibility")
- codeformer_weight = gr.Slider(minimum=0.0, maximum=1.0, step=0.001, label="CodeFormer weight (0 = maximum effect, 1 = minimum effect)", value=0, interactive=modules.codeformer_model.have_codeformer, elem_id="extras_codeformer_weight")
-
- with gr.Group():
- upscale_before_face_fix = gr.Checkbox(label='Upscale Before Restoring Faces', value=False, elem_id="extras_upscale_before_face_fix")
-
- result_images, html_info_x, html_info, html_log = create_output_panel("extras", opts.outdir_extras_samples)
-
- submit.click(
- fn=wrap_gradio_gpu_call(modules.extras.run_extras, extra_outputs=[None, '']),
- _js="get_extras_tab_index",
- inputs=[
- dummy_component,
- dummy_component,
- extras_image,
- image_batch,
- extras_batch_input_dir,
- extras_batch_output_dir,
- show_extras_results,
- gfpgan_visibility,
- codeformer_visibility,
- codeformer_weight,
- upscaling_resize,
- upscaling_resize_w,
- upscaling_resize_h,
- upscaling_crop,
- extras_upscaler_1,
- extras_upscaler_2,
- extras_upscaler_2_visibility,
- upscale_before_face_fix,
- ],
- outputs=[
- result_images,
- html_info_x,
- html_info,
- ]
- )
- parameters_copypaste.add_paste_fields("extras", extras_image, None)
-
- extras_image.change(
- fn=modules.extras.clear_cache,
- inputs=[], outputs=[]
- )
+ ui_postprocessing.create_ui()
with gr.Blocks(analytics_enabled=False) as pnginfo_interface:
with gr.Row().style(equal_height=False):
@@ -1147,12 +949,21 @@ def create_ui():
outputs=[html, generation_info, html2],
)
+ def update_interp_description(value):
+ interp_description_css = "<p style='margin-bottom: 2.5em'>{}</p>"
+ interp_descriptions = {
+ "No interpolation": interp_description_css.format("No interpolation will be used. Requires one model; A. Allows for format conversion and VAE baking."),
+ "Weighted sum": interp_description_css.format("A weighted sum will be used for interpolation. Requires two models; A and B. The result is calculated as A * (1 - M) + B * M"),
+ "Add difference": interp_description_css.format("The difference between the last two models will be added to the first. Requires three models; A, B and C. The result is calculated as A + (B - C) * M")
+ }
+ return interp_descriptions[value]
+
with gr.Blocks(analytics_enabled=False) as modelmerger_interface:
with gr.Row().style(equal_height=False):
- with gr.Column(variant='panel'):
- gr.HTML(value="<p>A merger of the two checkpoints will be generated in your <b>checkpoint</b> directory.</p>")
+ with gr.Column(variant='compact'):
+ interp_description = gr.HTML(value=update_interp_description("Weighted sum"), elem_id="modelmerger_interp_description")
- with FormRow():
+ with FormRow(elem_id="modelmerger_models"):
primary_model_name = gr.Dropdown(modules.sd_models.checkpoint_tiles(), elem_id="modelmerger_primary_model_name", label="Primary model (A)")
create_refresh_button(primary_model_name, modules.sd_models.list_models, lambda: {"choices": modules.sd_models.checkpoint_tiles()}, "refresh_checkpoint_A")
@@ -1164,24 +975,37 @@ def create_ui():
custom_name = gr.Textbox(label="Custom Name (Optional)", elem_id="modelmerger_custom_name")
interp_amount = gr.Slider(minimum=0.0, maximum=1.0, step=0.05, label='Multiplier (M) - set to 0 to get model A', value=0.3, elem_id="modelmerger_interp_amount")
- interp_method = gr.Radio(choices=["Weighted sum", "Add difference"], value="Weighted sum", label="Interpolation Method", elem_id="modelmerger_interp_method")
+ interp_method = gr.Radio(choices=["No interpolation", "Weighted sum", "Add difference"], value="Weighted sum", label="Interpolation Method", elem_id="modelmerger_interp_method")
+ interp_method.change(fn=update_interp_description, inputs=[interp_method], outputs=[interp_description])
with FormRow():
checkpoint_format = gr.Radio(choices=["ckpt", "safetensors"], value="ckpt", label="Checkpoint format", elem_id="modelmerger_checkpoint_format")
save_as_half = gr.Checkbox(value=False, label="Save as float16", elem_id="modelmerger_save_as_half")
- config_source = gr.Radio(choices=["A, B or C", "B", "C", "Don't"], value="A, B or C", label="Copy config from", type="index", elem_id="modelmerger_config_method")
+ with FormRow():
+ with gr.Column():
+ config_source = gr.Radio(choices=["A, B or C", "B", "C", "Don't"], value="A, B or C", label="Copy config from", type="index", elem_id="modelmerger_config_method")
- modelmerger_merge = gr.Button(elem_id="modelmerger_merge", value="Merge", variant='primary')
+ with gr.Column():
+ with FormRow():
+ bake_in_vae = gr.Dropdown(choices=["None"] + list(sd_vae.vae_dict), value="None", label="Bake in VAE", elem_id="modelmerger_bake_in_vae")
+ create_refresh_button(bake_in_vae, sd_vae.refresh_vae_list, lambda: {"choices": ["None"] + list(sd_vae.vae_dict)}, "modelmerger_refresh_bake_in_vae")
- with gr.Column(variant='panel'):
- submit_result = gr.Textbox(elem_id="modelmerger_result", show_label=False)
+ with FormRow():
+ discard_weights = gr.Textbox(value="", label="Discard weights with matching name", elem_id="modelmerger_discard_weights")
+
+ with gr.Row():
+ modelmerger_merge = gr.Button(elem_id="modelmerger_merge", value="Merge", variant='primary')
+
+ with gr.Column(variant='compact', elem_id="modelmerger_results_container"):
+ with gr.Group(elem_id="modelmerger_results_panel"):
+ modelmerger_result = gr.HTML(elem_id="modelmerger_result", show_label=False)
with gr.Blocks(analytics_enabled=False) as train_interface:
with gr.Row().style(equal_height=False):
gr.HTML(value="<p style='margin-bottom: 0.7em'>See <b><a href=\"https://github.com/AUTOMATIC1111/stable-diffusion-webui/wiki/Textual-Inversion\">wiki</a></b> for detailed explanation.</p>")
- with gr.Row().style(equal_height=False):
+ with gr.Row(variant="compact").style(equal_height=False):
with gr.Tabs(elem_id="train_tabs"):
with gr.Tab(label="Create embedding"):
@@ -1226,6 +1050,7 @@ def create_ui():
process_flip = gr.Checkbox(label='Create flipped copies', elem_id="train_process_flip")
process_split = gr.Checkbox(label='Split oversized images', elem_id="train_process_split")
process_focal_crop = gr.Checkbox(label='Auto focal point crop', elem_id="train_process_focal_crop")
+ process_multicrop = gr.Checkbox(label='Auto-sized crop', elem_id="train_process_multicrop")
process_caption = gr.Checkbox(label='Use BLIP for caption', elem_id="train_process_caption")
process_caption_deepbooru = gr.Checkbox(label='Use deepbooru for caption', visible=True, elem_id="train_process_caption_deepbooru")
@@ -1238,7 +1063,19 @@ def create_ui():
process_focal_crop_entropy_weight = gr.Slider(label='Focal point entropy weight', value=0.15, minimum=0.0, maximum=1.0, step=0.05, elem_id="train_process_focal_crop_entropy_weight")
process_focal_crop_edges_weight = gr.Slider(label='Focal point edges weight', value=0.5, minimum=0.0, maximum=1.0, step=0.05, elem_id="train_process_focal_crop_edges_weight")
process_focal_crop_debug = gr.Checkbox(label='Create debug image', elem_id="train_process_focal_crop_debug")
-
+
+ with gr.Column(visible=False) as process_multicrop_col:
+ gr.Markdown('Each image is center-cropped with an automatically chosen width and height.')
+ with gr.Row():
+ process_multicrop_mindim = gr.Slider(minimum=64, maximum=2048, step=8, label="Dimension lower bound", value=384, elem_id="train_process_multicrop_mindim")
+ process_multicrop_maxdim = gr.Slider(minimum=64, maximum=2048, step=8, label="Dimension upper bound", value=768, elem_id="train_process_multicrop_maxdim")
+ with gr.Row():
+ process_multicrop_minarea = gr.Slider(minimum=64*64, maximum=2048*2048, step=1, label="Area lower bound", value=64*64, elem_id="train_process_multicrop_minarea")
+ process_multicrop_maxarea = gr.Slider(minimum=64*64, maximum=2048*2048, step=1, label="Area upper bound", value=640*640, elem_id="train_process_multicrop_maxarea")
+ with gr.Row():
+ process_multicrop_objective = gr.Radio(["Maximize area", "Minimize error"], value="Maximize area", label="Resizing objective", elem_id="train_process_multicrop_objective")
+ process_multicrop_threshold = gr.Slider(minimum=0, maximum=1, step=0.01, label="Error threshold", value=0.1, elem_id="train_process_multicrop_threshold")
+
with gr.Row():
with gr.Column(scale=3):
gr.HTML(value="")
@@ -1260,6 +1097,12 @@ def create_ui():
outputs=[process_focal_crop_row],
)
+ process_multicrop.change(
+ fn=lambda show: gr_show(show),
+ inputs=[process_multicrop],
+ outputs=[process_multicrop_col],
+ )
+
def get_textual_inversion_template_names():
return sorted([x for x in textual_inversion.textual_inversion_templates])
@@ -1379,6 +1222,13 @@ def create_ui():
process_focal_crop_entropy_weight,
process_focal_crop_edges_weight,
process_focal_crop_debug,
+ process_multicrop,
+ process_multicrop_mindim,
+ process_multicrop_maxdim,
+ process_multicrop_minarea,
+ process_multicrop_maxarea,
+ process_multicrop_objective,
+ process_multicrop_threshold,
],
outputs=[
ti_output,
@@ -1532,7 +1382,7 @@ def create_ui():
opts.save(shared.config_filename)
- return gr.update(value=value), opts.dumpjson()
+ return get_value_for_setting(key), opts.dumpjson()
with gr.Blocks(analytics_enabled=False) as settings_interface:
with gr.Row():
@@ -1550,6 +1400,7 @@ def create_ui():
previous_section = None
current_tab = None
+ current_row = None
with gr.Tabs(elem_id="settings"):
for i, (k, item) in enumerate(opts.data_labels.items()):
section_must_be_skipped = item.section[0] is None
@@ -1558,10 +1409,14 @@ def create_ui():
elem_id, text = item.section
if current_tab is not None:
+ current_row.__exit__()
current_tab.__exit__()
+ gr.Group()
current_tab = gr.TabItem(elem_id="settings_{}".format(elem_id), label=text)
current_tab.__enter__()
+ current_row = gr.Column(variant='compact')
+ current_row.__enter__()
previous_section = item.section
@@ -1576,6 +1431,7 @@ def create_ui():
components.append(component)
if current_tab is not None:
+ current_row.__exit__()
current_tab.__exit__()
with gr.TabItem("Actions"):
@@ -1583,10 +1439,8 @@ def create_ui():
download_localization = gr.Button(value='Download localization template', elem_id="download_localization")
reload_script_bodies = gr.Button(value='Reload custom script bodies (No ui updates, No restart)', variant='secondary', elem_id="settings_reload_script_bodies")
- if os.path.exists("html/licenses.html"):
- with open("html/licenses.html", encoding="utf8") as file:
- with gr.TabItem("Licenses"):
- gr.HTML(file.read(), elem_id="licenses")
+ with gr.TabItem("Licenses"):
+ gr.HTML(shared.html("licenses.html"), elem_id="licenses")
gr.Button(value="Show all pages", elem_id="settings_show_all_pages")
@@ -1657,7 +1511,7 @@ def create_ui():
interfaces += [(extensions_interface, "Extensions", "extensions")]
with gr.Blocks(css=css, analytics_enabled=False, title="Stable Diffusion") as demo:
- with gr.Row(elem_id="quicksettings"):
+ with gr.Row(elem_id="quicksettings", variant="compact"):
for i, k, item in sorted(quicksettings_list, key=lambda x: quicksettings_names.get(x[1], x[0])):
component = create_setting_component(k, is_quicksettings=True)
component_dict[k] = component
@@ -1673,11 +1527,9 @@ def create_ui():
if os.path.exists(os.path.join(script_path, "notification.mp3")):
audio_notification = gr.Audio(interactive=False, value=os.path.join(script_path, "notification.mp3"), elem_id="audio_notification", visible=False)
- if os.path.exists("html/footer.html"):
- with open("html/footer.html", encoding="utf8") as file:
- footer = file.read()
- footer = footer.format(versions=versions_html())
- gr.HTML(footer, elem_id="footer")
+ footer = shared.html("footer.html")
+ footer = footer.format(versions=versions_html())
+ gr.HTML(footer, elem_id="footer")
text_settings = gr.Textbox(elem_id="settings_json", value=lambda: opts.dumpjson(), visible=False)
settings_submit.click(
@@ -1698,7 +1550,7 @@ def create_ui():
component_keys = [k for k in opts.data_labels.keys() if k in component_dict]
def get_settings_values():
- return [getattr(opts, key) for key in component_keys]
+ return [get_value_for_setting(key) for key in component_keys]
demo.load(
fn=get_settings_values,
@@ -1713,12 +1565,15 @@ def create_ui():
print("Error loading/saving model file:", file=sys.stderr)
print(traceback.format_exc(), file=sys.stderr)
modules.sd_models.list_models() # to remove the potentially missing models from the list
- return [f"Error merging checkpoints: {e}"] + [gr.Dropdown.update(choices=modules.sd_models.checkpoint_tiles()) for _ in range(4)]
+ return [*[gr.Dropdown.update(choices=modules.sd_models.checkpoint_tiles()) for _ in range(4)], f"Error merging checkpoints: {e}"]
return results
+ modelmerger_merge.click(fn=lambda: '', inputs=[], outputs=[modelmerger_result])
modelmerger_merge.click(
- fn=modelmerger,
+ fn=wrap_gradio_gpu_call(modelmerger, extra_outputs=lambda: [gr.update() for _ in range(4)]),
+ _js='modelmerger',
inputs=[
+ dummy_component,
primary_model_name,
secondary_model_name,
tertiary_model_name,
@@ -1728,13 +1583,15 @@ def create_ui():
custom_name,
checkpoint_format,
config_source,
+ bake_in_vae,
+ discard_weights,
],
outputs=[
- submit_result,
primary_model_name,
secondary_model_name,
tertiary_model_name,
component_dict['sd_model_checkpoint'],
+ modelmerger_result,
]
)
@@ -1766,7 +1623,10 @@ def create_ui():
if saved_value is None:
ui_settings[key] = getattr(obj, field)
elif condition and not condition(saved_value):
- print(f'Warning: Bad ui setting value: {key}: {saved_value}; Default value "{getattr(obj, field)}" will be used instead.')
+ pass
+
+ # this warning is generally not useful;
+ # print(f'Warning: Bad ui setting value: {key}: {saved_value}; Default value "{getattr(obj, field)}" will be used instead.')
else:
setattr(obj, field, saved_value)
if init_field is not None:
@@ -1794,7 +1654,13 @@ def create_ui():
apply_field(x, 'value')
if type(x) == gr.Dropdown:
- apply_field(x, 'value', lambda val: val in x.choices, getattr(x, 'init_field', None))
+ def check_dropdown(val):
+ if getattr(x, 'multiselect', False):
+ return all([value in x.choices for value in val])
+ else:
+ return val in x.choices
+
+ apply_field(x, 'value', check_dropdown, getattr(x, 'init_field', None))
visit(txt2img_interface, loadsave, "txt2img")
visit(img2img_interface, loadsave, "img2img")
@@ -1806,28 +1672,27 @@ def create_ui():
with open(ui_config_file, "w", encoding="utf8") as file:
json.dump(ui_settings, file, indent=4)
+ # Required as a workaround for change() event not triggering when loading values from ui-config.json
+ interp_description.value = update_interp_description(interp_method.value)
+
return demo
def reload_javascript():
- with open(os.path.join(script_path, "script.js"), "r", encoding="utf8") as jsfile:
- javascript = f'<script>{jsfile.read()}</script>'
-
- scripts_list = modules.scripts.list_scripts("javascript", ".js")
-
- for basedir, filename, path in scripts_list:
- with open(path, "r", encoding="utf8") as jsfile:
- javascript += f"\n<!-- {filename} --><script>{jsfile.read()}</script>"
+ head = f'<script type="text/javascript" src="file={os.path.abspath("script.js")}"></script>\n'
+ inline = f"{localization.localization_js(shared.opts.localization)};"
if cmd_opts.theme is not None:
- javascript += f"\n<script>set_theme('{cmd_opts.theme}');</script>\n"
+ inline += f"set_theme('{cmd_opts.theme}');"
+
+ for script in modules.scripts.list_scripts("javascript", ".js"):
+ head += f'<script type="text/javascript" src="file={script.path}"></script>\n'
- javascript += f"\n<script>{localization.localization_js(shared.opts.localization)}</script>"
+ head += f'<script type="text/javascript">{inline}</script>\n'
def template_response(*args, **kwargs):
res = shared.GradioTemplateResponseOriginal(*args, **kwargs)
- res.body = res.body.replace(
- b'</head>', f'{javascript}</head>'.encode("utf8"))
+ res.body = res.body.replace(b'</head>', f'{head}</head>'.encode("utf8"))
res.init_headers()
return res
diff --git a/modules/ui_common.py b/modules/ui_common.py
new file mode 100644
index 00000000..9405ac1f
--- /dev/null
+++ b/modules/ui_common.py
@@ -0,0 +1,202 @@
+import json
+import html
+import os
+import platform
+import sys
+
+import gradio as gr
+import subprocess as sp
+
+from modules import call_queue, shared
+from modules.generation_parameters_copypaste import image_from_url_text
+import modules.images
+
+folder_symbol = '\U0001f4c2' # 📂
+
+
+def update_generation_info(generation_info, html_info, img_index):
+ try:
+ generation_info = json.loads(generation_info)
+ if img_index < 0 or img_index >= len(generation_info["infotexts"]):
+ return html_info, gr.update()
+ return plaintext_to_html(generation_info["infotexts"][img_index]), gr.update()
+ except Exception:
+ pass
+ # if the json parse or anything else fails, just return the old html_info
+ return html_info, gr.update()
+
+
+def plaintext_to_html(text):
+ text = "<p>" + "<br>\n".join([f"{html.escape(x)}" for x in text.split('\n')]) + "</p>"
+ return text
+
+
+def save_files(js_data, images, do_make_zip, index):
+ import csv
+ filenames = []
+ fullfns = []
+
+ #quick dictionary to class object conversion. Its necessary due apply_filename_pattern requiring it
+ class MyObject:
+ def __init__(self, d=None):
+ if d is not None:
+ for key, value in d.items():
+ setattr(self, key, value)
+
+ data = json.loads(js_data)
+
+ p = MyObject(data)
+ path = shared.opts.outdir_save
+ save_to_dirs = shared.opts.use_save_to_dirs_for_ui
+ extension: str = shared.opts.samples_format
+ start_index = 0
+
+ if index > -1 and shared.opts.save_selected_only and (index >= data["index_of_first_image"]): # ensures we are looking at a specific non-grid picture, and we have save_selected_only
+
+ images = [images[index]]
+ start_index = index
+
+ os.makedirs(shared.opts.outdir_save, exist_ok=True)
+
+ with open(os.path.join(shared.opts.outdir_save, "log.csv"), "a", encoding="utf8", newline='') as file:
+ at_start = file.tell() == 0
+ writer = csv.writer(file)
+ if at_start:
+ writer.writerow(["prompt", "seed", "width", "height", "sampler", "cfgs", "steps", "filename", "negative_prompt"])
+
+ for image_index, filedata in enumerate(images, start_index):
+ image = image_from_url_text(filedata)
+
+ is_grid = image_index < p.index_of_first_image
+ i = 0 if is_grid else (image_index - p.index_of_first_image)
+
+ fullfn, txt_fullfn = modules.images.save_image(image, path, "", seed=p.all_seeds[i], prompt=p.all_prompts[i], extension=extension, info=p.infotexts[image_index], grid=is_grid, p=p, save_to_dirs=save_to_dirs)
+
+ filename = os.path.relpath(fullfn, path)
+ filenames.append(filename)
+ fullfns.append(fullfn)
+ if txt_fullfn:
+ filenames.append(os.path.basename(txt_fullfn))
+ fullfns.append(txt_fullfn)
+
+ writer.writerow([data["prompt"], data["seed"], data["width"], data["height"], data["sampler_name"], data["cfg_scale"], data["steps"], filenames[0], data["negative_prompt"]])
+
+ # Make Zip
+ if do_make_zip:
+ zip_filepath = os.path.join(path, "images.zip")
+
+ from zipfile import ZipFile
+ with ZipFile(zip_filepath, "w") as zip_file:
+ for i in range(len(fullfns)):
+ with open(fullfns[i], mode="rb") as f:
+ zip_file.writestr(filenames[i], f.read())
+ fullfns.insert(0, zip_filepath)
+
+ return gr.File.update(value=fullfns, visible=True), plaintext_to_html(f"Saved: {filenames[0]}")
+
+
+def create_output_panel(tabname, outdir):
+ from modules import shared
+ import modules.generation_parameters_copypaste as parameters_copypaste
+
+ def open_folder(f):
+ if not os.path.exists(f):
+ print(f'Folder "{f}" does not exist. After you create an image, the folder will be created.')
+ return
+ elif not os.path.isdir(f):
+ print(f"""
+WARNING
+An open_folder request was made with an argument that is not a folder.
+This could be an error or a malicious attempt to run code on your computer.
+Requested path was: {f}
+""", file=sys.stderr)
+ return
+
+ if not shared.cmd_opts.hide_ui_dir_config:
+ path = os.path.normpath(f)
+ if platform.system() == "Windows":
+ os.startfile(path)
+ elif platform.system() == "Darwin":
+ sp.Popen(["open", path])
+ elif "microsoft-standard-WSL2" in platform.uname().release:
+ sp.Popen(["wsl-open", path])
+ else:
+ sp.Popen(["xdg-open", path])
+
+ with gr.Column(variant='panel', elem_id=f"{tabname}_results"):
+ with gr.Group(elem_id=f"{tabname}_gallery_container"):
+ result_gallery = gr.Gallery(label='Output', show_label=False, elem_id=f"{tabname}_gallery").style(grid=4)
+
+ generation_info = None
+ with gr.Column():
+ with gr.Row(elem_id=f"image_buttons_{tabname}"):
+ open_folder_button = gr.Button(folder_symbol, elem_id="hidden_element" if shared.cmd_opts.hide_ui_dir_config else f'open_folder_{tabname}')
+
+ if tabname != "extras":
+ save = gr.Button('Save', elem_id=f'save_{tabname}')
+ save_zip = gr.Button('Zip', elem_id=f'save_zip_{tabname}')
+
+ buttons = parameters_copypaste.create_buttons(["img2img", "inpaint", "extras"])
+
+ open_folder_button.click(
+ fn=lambda: open_folder(shared.opts.outdir_samples or outdir),
+ inputs=[],
+ outputs=[],
+ )
+
+ if tabname != "extras":
+ with gr.Row():
+ download_files = gr.File(None, file_count="multiple", interactive=False, show_label=False, visible=False, elem_id=f'download_files_{tabname}')
+
+ with gr.Group():
+ html_info = gr.HTML(elem_id=f'html_info_{tabname}')
+ html_log = gr.HTML(elem_id=f'html_log_{tabname}')
+
+ generation_info = gr.Textbox(visible=False, elem_id=f'generation_info_{tabname}')
+ if tabname == 'txt2img' or tabname == 'img2img':
+ generation_info_button = gr.Button(visible=False, elem_id=f"{tabname}_generation_info_button")
+ generation_info_button.click(
+ fn=update_generation_info,
+ _js="function(x, y, z){ return [x, y, selected_gallery_index()] }",
+ inputs=[generation_info, html_info, html_info],
+ outputs=[html_info, html_info],
+ )
+
+ save.click(
+ fn=call_queue.wrap_gradio_call(save_files),
+ _js="(x, y, z, w) => [x, y, false, selected_gallery_index()]",
+ inputs=[
+ generation_info,
+ result_gallery,
+ html_info,
+ html_info,
+ ],
+ outputs=[
+ download_files,
+ html_log,
+ ],
+ show_progress=False,
+ )
+
+ save_zip.click(
+ fn=call_queue.wrap_gradio_call(save_files),
+ _js="(x, y, z, w) => [x, y, true, selected_gallery_index()]",
+ inputs=[
+ generation_info,
+ result_gallery,
+ html_info,
+ html_info,
+ ],
+ outputs=[
+ download_files,
+ html_log,
+ ]
+ )
+
+ else:
+ html_info_x = gr.HTML(elem_id=f'html_info_x_{tabname}')
+ html_info = gr.HTML(elem_id=f'html_info_{tabname}')
+ html_log = gr.HTML(elem_id=f'html_log_{tabname}')
+
+ parameters_copypaste.bind_buttons(buttons, result_gallery, "txt2img" if tabname == "txt2img" else None)
+ return result_gallery, generation_info if tabname != "extras" else html_info_x, html_info, html_log
diff --git a/modules/ui_components.py b/modules/ui_components.py
index 97acff06..9aec3097 100644
--- a/modules/ui_components.py
+++ b/modules/ui_components.py
@@ -11,6 +11,16 @@ class ToolButton(gr.Button, gr.components.FormComponent):
return "button"
+class ToolButtonTop(gr.Button, gr.components.FormComponent):
+ """Small button with single emoji as text, with extra margin at top, fits inside gradio forms"""
+
+ def __init__(self, **kwargs):
+ super().__init__(variant="tool-top", **kwargs)
+
+ def get_block_name(self):
+ return "button"
+
+
class FormRow(gr.Row, gr.components.FormComponent):
"""Same as gr.Row but fits inside gradio forms"""
@@ -37,3 +47,4 @@ class FormColorPicker(gr.ColorPicker, gr.components.FormComponent):
def get_block_name(self):
return "colorpicker"
+
diff --git a/modules/ui_extra_networks.py b/modules/ui_extra_networks.py
new file mode 100644
index 00000000..af2b8071
--- /dev/null
+++ b/modules/ui_extra_networks.py
@@ -0,0 +1,171 @@
+import os.path
+
+from modules import shared
+import gradio as gr
+import json
+
+from modules.generation_parameters_copypaste import image_from_url_text
+
+extra_pages = []
+
+
+def register_page(page):
+ """registers extra networks page for the UI; recommend doing it in on_before_ui() callback for extensions"""
+
+ extra_pages.append(page)
+
+
+class ExtraNetworksPage:
+ def __init__(self, title):
+ self.title = title
+ self.name = title.lower()
+ self.card_page = shared.html("extra-networks-card.html")
+ self.allow_negative_prompt = False
+
+ def refresh(self):
+ pass
+
+ def create_html(self, tabname):
+ items_html = ''
+
+ for item in self.list_items():
+ items_html += self.create_html_for_item(item, tabname)
+
+ if items_html == '':
+ dirs = "".join([f"<li>{x}</li>" for x in self.allowed_directories_for_previews()])
+ items_html = shared.html("extra-networks-no-cards.html").format(dirs=dirs)
+
+ res = f"""
+<div id='{tabname}_{self.name}_cards' class='extra-network-cards'>
+{items_html}
+</div>
+"""
+
+ return res
+
+ def list_items(self):
+ raise NotImplementedError()
+
+ def allowed_directories_for_previews(self):
+ return []
+
+ def create_html_for_item(self, item, tabname):
+ preview = item.get("preview", None)
+
+ args = {
+ "preview_html": "style='background-image: url(" + json.dumps(preview) + ")'" if preview else '',
+ "prompt": item["prompt"],
+ "tabname": json.dumps(tabname),
+ "local_preview": json.dumps(item["local_preview"]),
+ "name": item["name"],
+ "allow_negative_prompt": "true" if self.allow_negative_prompt else "false",
+ }
+
+ return self.card_page.format(**args)
+
+
+def intialize():
+ extra_pages.clear()
+
+
+class ExtraNetworksUi:
+ def __init__(self):
+ self.pages = None
+ self.stored_extra_pages = None
+
+ self.button_save_preview = None
+ self.preview_target_filename = None
+
+ self.tabname = None
+
+
+def pages_in_preferred_order(pages):
+ tab_order = [x.lower().strip() for x in shared.opts.ui_extra_networks_tab_reorder.split(",")]
+
+ def tab_name_score(name):
+ name = name.lower()
+ for i, possible_match in enumerate(tab_order):
+ if possible_match in name:
+ return i
+
+ return len(pages)
+
+ tab_scores = {page.name: (tab_name_score(page.name), original_index) for original_index, page in enumerate(pages)}
+
+ return sorted(pages, key=lambda x: tab_scores[x.name])
+
+
+def create_ui(container, button, tabname):
+ ui = ExtraNetworksUi()
+ ui.pages = []
+ ui.stored_extra_pages = pages_in_preferred_order(extra_pages.copy())
+ ui.tabname = tabname
+
+ with gr.Tabs(elem_id=tabname+"_extra_tabs") as tabs:
+ for page in ui.stored_extra_pages:
+ with gr.Tab(page.title):
+ page_elem = gr.HTML(page.create_html(ui.tabname))
+ ui.pages.append(page_elem)
+
+ filter = gr.Textbox('', show_label=False, elem_id=tabname+"_extra_search", placeholder="Search...", visible=False)
+ button_refresh = gr.Button('Refresh', elem_id=tabname+"_extra_refresh")
+ button_close = gr.Button('Close', elem_id=tabname+"_extra_close")
+
+ ui.button_save_preview = gr.Button('Save preview', elem_id=tabname+"_save_preview", visible=False)
+ ui.preview_target_filename = gr.Textbox('Preview save filename', elem_id=tabname+"_preview_filename", visible=False)
+
+ button.click(fn=lambda: gr.update(visible=True), inputs=[], outputs=[container])
+ button_close.click(fn=lambda: gr.update(visible=False), inputs=[], outputs=[container])
+
+ def refresh():
+ res = []
+
+ for pg in ui.stored_extra_pages:
+ pg.refresh()
+ res.append(pg.create_html(ui.tabname))
+
+ return res
+
+ button_refresh.click(fn=refresh, inputs=[], outputs=ui.pages)
+
+ return ui
+
+
+def path_is_parent(parent_path, child_path):
+ parent_path = os.path.abspath(parent_path)
+ child_path = os.path.abspath(child_path)
+
+ return os.path.commonpath([parent_path]) == os.path.commonpath([parent_path, child_path])
+
+
+def setup_ui(ui, gallery):
+ def save_preview(index, images, filename):
+ if len(images) == 0:
+ print("There is no image in gallery to save as a preview.")
+ return [page.create_html(ui.tabname) for page in ui.stored_extra_pages]
+
+ index = int(index)
+ index = 0 if index < 0 else index
+ index = len(images) - 1 if index >= len(images) else index
+
+ img_info = images[index if index >= 0 else 0]
+ image = image_from_url_text(img_info)
+
+ is_allowed = False
+ for extra_page in ui.stored_extra_pages:
+ if any([path_is_parent(x, filename) for x in extra_page.allowed_directories_for_previews()]):
+ is_allowed = True
+ break
+
+ assert is_allowed, f'writing to {filename} is not allowed'
+
+ image.save(filename)
+
+ return [page.create_html(ui.tabname) for page in ui.stored_extra_pages]
+
+ ui.button_save_preview.click(
+ fn=save_preview,
+ _js="function(x, y, z){console.log(x, y, z); return [selected_gallery_index(), y, z]}",
+ inputs=[ui.preview_target_filename, gallery, ui.preview_target_filename],
+ outputs=[*ui.pages]
+ )
diff --git a/modules/ui_extra_networks_hypernets.py b/modules/ui_extra_networks_hypernets.py
new file mode 100644
index 00000000..65d000cf
--- /dev/null
+++ b/modules/ui_extra_networks_hypernets.py
@@ -0,0 +1,35 @@
+import json
+import os
+
+from modules import shared, ui_extra_networks
+
+
+class ExtraNetworksPageHypernetworks(ui_extra_networks.ExtraNetworksPage):
+ def __init__(self):
+ super().__init__('Hypernetworks')
+
+ def refresh(self):
+ shared.reload_hypernetworks()
+
+ def list_items(self):
+ for name, path in shared.hypernetworks.items():
+ path, ext = os.path.splitext(path)
+ previews = [path + ".png", path + ".preview.png"]
+
+ preview = None
+ for file in previews:
+ if os.path.isfile(file):
+ preview = "./file=" + file.replace('\\', '/') + "?mtime=" + str(os.path.getmtime(file))
+ break
+
+ yield {
+ "name": name,
+ "filename": path,
+ "preview": preview,
+ "prompt": json.dumps(f"<hypernet:{name}:") + " + opts.extra_networks_default_multiplier + " + json.dumps(">"),
+ "local_preview": path + ".png",
+ }
+
+ def allowed_directories_for_previews(self):
+ return [shared.cmd_opts.hypernetwork_dir]
+
diff --git a/modules/ui_extra_networks_textual_inversion.py b/modules/ui_extra_networks_textual_inversion.py
new file mode 100644
index 00000000..dbd23d2d
--- /dev/null
+++ b/modules/ui_extra_networks_textual_inversion.py
@@ -0,0 +1,33 @@
+import json
+import os
+
+from modules import ui_extra_networks, sd_hijack
+
+
+class ExtraNetworksPageTextualInversion(ui_extra_networks.ExtraNetworksPage):
+ def __init__(self):
+ super().__init__('Textual Inversion')
+ self.allow_negative_prompt = True
+
+ def refresh(self):
+ sd_hijack.model_hijack.embedding_db.load_textual_inversion_embeddings(force_reload=True)
+
+ def list_items(self):
+ for embedding in sd_hijack.model_hijack.embedding_db.word_embeddings.values():
+ path, ext = os.path.splitext(embedding.filename)
+ preview_file = path + ".preview.png"
+
+ preview = None
+ if os.path.isfile(preview_file):
+ preview = "./file=" + preview_file.replace('\\', '/') + "?mtime=" + str(os.path.getmtime(preview_file))
+
+ yield {
+ "name": embedding.name,
+ "filename": embedding.filename,
+ "preview": preview,
+ "prompt": json.dumps(embedding.name),
+ "local_preview": path + ".preview.png",
+ }
+
+ def allowed_directories_for_previews(self):
+ return list(sd_hijack.model_hijack.embedding_db.embedding_dirs)
diff --git a/modules/ui_postprocessing.py b/modules/ui_postprocessing.py
new file mode 100644
index 00000000..b418d955
--- /dev/null
+++ b/modules/ui_postprocessing.py
@@ -0,0 +1,57 @@
+import gradio as gr
+from modules import scripts_postprocessing, scripts, shared, gfpgan_model, codeformer_model, ui_common, postprocessing, call_queue
+import modules.generation_parameters_copypaste as parameters_copypaste
+
+
+def create_ui():
+ tab_index = gr.State(value=0)
+
+ with gr.Row().style(equal_height=False, variant='compact'):
+ with gr.Column(variant='compact'):
+ with gr.Tabs(elem_id="mode_extras"):
+ with gr.TabItem('Single Image', elem_id="extras_single_tab") as tab_single:
+ extras_image = gr.Image(label="Source", source="upload", interactive=True, type="pil", elem_id="extras_image")
+
+ with gr.TabItem('Batch Process', elem_id="extras_batch_process_tab") as tab_batch:
+ image_batch = gr.File(label="Batch Process", file_count="multiple", interactive=True, type="file", elem_id="extras_image_batch")
+
+ with gr.TabItem('Batch from Directory', elem_id="extras_batch_directory_tab") as tab_batch_dir:
+ extras_batch_input_dir = gr.Textbox(label="Input directory", **shared.hide_dirs, placeholder="A directory on the same machine where the server is running.", elem_id="extras_batch_input_dir")
+ extras_batch_output_dir = gr.Textbox(label="Output directory", **shared.hide_dirs, placeholder="Leave blank to save images to the default path.", elem_id="extras_batch_output_dir")
+ show_extras_results = gr.Checkbox(label='Show result images', value=True, elem_id="extras_show_extras_results")
+
+ submit = gr.Button('Generate', elem_id="extras_generate", variant='primary')
+
+ script_inputs = scripts.scripts_postproc.setup_ui()
+
+ with gr.Column():
+ result_images, html_info_x, html_info, html_log = ui_common.create_output_panel("extras", shared.opts.outdir_extras_samples)
+
+ tab_single.select(fn=lambda: 0, inputs=[], outputs=[tab_index])
+ tab_batch.select(fn=lambda: 1, inputs=[], outputs=[tab_index])
+ tab_batch_dir.select(fn=lambda: 2, inputs=[], outputs=[tab_index])
+
+ submit.click(
+ fn=call_queue.wrap_gradio_gpu_call(postprocessing.run_postprocessing, extra_outputs=[None, '']),
+ inputs=[
+ tab_index,
+ extras_image,
+ image_batch,
+ extras_batch_input_dir,
+ extras_batch_output_dir,
+ show_extras_results,
+ *script_inputs
+ ],
+ outputs=[
+ result_images,
+ html_info_x,
+ html_info,
+ ]
+ )
+
+ parameters_copypaste.add_paste_fields("extras", extras_image, None)
+
+ extras_image.change(
+ fn=scripts.scripts_postproc.image_changed,
+ inputs=[], outputs=[]
+ )
diff --git a/modules/upscaler.py b/modules/upscaler.py
index 231680cb..a5bf5acb 100644
--- a/modules/upscaler.py
+++ b/modules/upscaler.py
@@ -95,6 +95,7 @@ class UpscalerData:
def __init__(self, name: str, path: str, upscaler: Upscaler = None, scale: int = 4, model=None):
self.name = name
self.data_path = path
+ self.local_data_path = path
self.scaler = upscaler
self.scale = scale
self.model = model
diff --git a/requirements.txt b/requirements.txt
index e1dbf8e5..ef5e3472 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -5,7 +5,7 @@ fairscale==0.4.4
fonts
font-roboto
gfpgan
-gradio==3.15.0
+gradio==3.16.2
invisible-watermark
numpy
omegaconf
diff --git a/requirements_versions.txt b/requirements_versions.txt
index d2899292..f97ad765 100644
--- a/requirements_versions.txt
+++ b/requirements_versions.txt
@@ -3,7 +3,7 @@ transformers==4.19.2
accelerate==0.12.0
basicsr==1.4.2
gfpgan==1.3.8
-gradio==3.15.0
+gradio==3.16.2
numpy==1.23.3
Pillow==9.4.0
realesrgan==0.3.0
diff --git a/script.js b/script.js
index 3345e32b..97e0bfcf 100644
--- a/script.js
+++ b/script.js
@@ -13,6 +13,7 @@ function get_uiCurrentTabContent() {
}
uiUpdateCallbacks = []
+uiLoadedCallbacks = []
uiTabChangeCallbacks = []
optionsChangedCallbacks = []
let uiCurrentTab = null
@@ -20,6 +21,9 @@ let uiCurrentTab = null
function onUiUpdate(callback){
uiUpdateCallbacks.push(callback)
}
+function onUiLoaded(callback){
+ uiLoadedCallbacks.push(callback)
+}
function onUiTabChange(callback){
uiTabChangeCallbacks.push(callback)
}
@@ -38,8 +42,15 @@ function executeCallbacks(queue, m) {
queue.forEach(function(x){runCallback(x, m)})
}
+var executedOnLoaded = false;
+
document.addEventListener("DOMContentLoaded", function() {
var mutationObserver = new MutationObserver(function(m){
+ if(!executedOnLoaded && gradioApp().querySelector('#txt2img_prompt')){
+ executedOnLoaded = true;
+ executeCallbacks(uiLoadedCallbacks);
+ }
+
executeCallbacks(uiUpdateCallbacks, m);
const newTab = get_uiCurrentTab();
if ( newTab && ( newTab !== uiCurrentTab ) ) {
@@ -53,7 +64,7 @@ document.addEventListener("DOMContentLoaded", function() {
/**
* Add a ctrl+enter as a shortcut to start a generation
*/
- document.addEventListener('keydown', function(e) {
+document.addEventListener('keydown', function(e) {
var handled = false;
if (e.key !== undefined) {
if((e.key == "Enter" && (e.metaKey || e.ctrlKey || e.altKey))) handled = true;
diff --git a/scripts/postprocessing_codeformer.py b/scripts/postprocessing_codeformer.py
new file mode 100644
index 00000000..a7d80d40
--- /dev/null
+++ b/scripts/postprocessing_codeformer.py
@@ -0,0 +1,36 @@
+from PIL import Image
+import numpy as np
+
+from modules import scripts_postprocessing, codeformer_model
+import gradio as gr
+
+from modules.ui_components import FormRow
+
+
+class ScriptPostprocessingCodeFormer(scripts_postprocessing.ScriptPostprocessing):
+ name = "CodeFormer"
+ order = 3000
+
+ def ui(self):
+ with FormRow():
+ codeformer_visibility = gr.Slider(minimum=0.0, maximum=1.0, step=0.001, label="CodeFormer visibility", value=0, elem_id="extras_codeformer_visibility")
+ codeformer_weight = gr.Slider(minimum=0.0, maximum=1.0, step=0.001, label="CodeFormer weight (0 = maximum effect, 1 = minimum effect)", value=0, elem_id="extras_codeformer_weight")
+
+ return {
+ "codeformer_visibility": codeformer_visibility,
+ "codeformer_weight": codeformer_weight,
+ }
+
+ def process(self, pp: scripts_postprocessing.PostprocessedImage, codeformer_visibility, codeformer_weight):
+ if codeformer_visibility == 0:
+ return
+
+ restored_img = codeformer_model.codeformer.restore(np.array(pp.image, dtype=np.uint8), w=codeformer_weight)
+ res = Image.fromarray(restored_img)
+
+ if codeformer_visibility < 1.0:
+ res = Image.blend(pp.image, res, codeformer_visibility)
+
+ pp.image = res
+ pp.info["CodeFormer visibility"] = round(codeformer_visibility, 3)
+ pp.info["CodeFormer weight"] = round(codeformer_weight, 3)
diff --git a/scripts/postprocessing_gfpgan.py b/scripts/postprocessing_gfpgan.py
new file mode 100644
index 00000000..d854f3f7
--- /dev/null
+++ b/scripts/postprocessing_gfpgan.py
@@ -0,0 +1,33 @@
+from PIL import Image
+import numpy as np
+
+from modules import scripts_postprocessing, gfpgan_model
+import gradio as gr
+
+from modules.ui_components import FormRow
+
+
+class ScriptPostprocessingGfpGan(scripts_postprocessing.ScriptPostprocessing):
+ name = "GFPGAN"
+ order = 2000
+
+ def ui(self):
+ with FormRow():
+ gfpgan_visibility = gr.Slider(minimum=0.0, maximum=1.0, step=0.001, label="GFPGAN visibility", value=0, elem_id="extras_gfpgan_visibility")
+
+ return {
+ "gfpgan_visibility": gfpgan_visibility,
+ }
+
+ def process(self, pp: scripts_postprocessing.PostprocessedImage, gfpgan_visibility):
+ if gfpgan_visibility == 0:
+ return
+
+ restored_img = gfpgan_model.gfpgan_fix_faces(np.array(pp.image, dtype=np.uint8))
+ res = Image.fromarray(restored_img)
+
+ if gfpgan_visibility < 1.0:
+ res = Image.blend(pp.image, res, gfpgan_visibility)
+
+ pp.image = res
+ pp.info["GFPGAN visibility"] = round(gfpgan_visibility, 3)
diff --git a/scripts/postprocessing_upscale.py b/scripts/postprocessing_upscale.py
new file mode 100644
index 00000000..095d29b2
--- /dev/null
+++ b/scripts/postprocessing_upscale.py
@@ -0,0 +1,106 @@
+from PIL import Image
+import numpy as np
+
+from modules import scripts_postprocessing, shared
+import gradio as gr
+
+from modules.ui_components import FormRow
+
+
+upscale_cache = {}
+
+
+class ScriptPostprocessingUpscale(scripts_postprocessing.ScriptPostprocessing):
+ name = "Upscale"
+ order = 1000
+
+ def ui(self):
+ selected_tab = gr.State(value=0)
+
+ with gr.Tabs(elem_id="extras_resize_mode"):
+ with gr.TabItem('Scale by', elem_id="extras_scale_by_tab") as tab_scale_by:
+ upscaling_resize = gr.Slider(minimum=1.0, maximum=8.0, step=0.05, label="Resize", value=4, elem_id="extras_upscaling_resize")
+
+ with gr.TabItem('Scale to', elem_id="extras_scale_to_tab") as tab_scale_to:
+ with FormRow():
+ upscaling_resize_w = gr.Number(label="Width", value=512, precision=0, elem_id="extras_upscaling_resize_w")
+ upscaling_resize_h = gr.Number(label="Height", value=512, precision=0, elem_id="extras_upscaling_resize_h")
+ upscaling_crop = gr.Checkbox(label='Crop to fit', value=True, elem_id="extras_upscaling_crop")
+
+ with FormRow():
+ extras_upscaler_1 = gr.Dropdown(label='Upscaler 1', elem_id="extras_upscaler_1", choices=[x.name for x in shared.sd_upscalers], value=shared.sd_upscalers[0].name)
+
+ with FormRow():
+ extras_upscaler_2 = gr.Dropdown(label='Upscaler 2', elem_id="extras_upscaler_2", choices=[x.name for x in shared.sd_upscalers], value=shared.sd_upscalers[0].name)
+ extras_upscaler_2_visibility = gr.Slider(minimum=0.0, maximum=1.0, step=0.001, label="Upscaler 2 visibility", value=0.0, elem_id="extras_upscaler_2_visibility")
+
+ tab_scale_by.select(fn=lambda: 0, inputs=[], outputs=[selected_tab])
+ tab_scale_to.select(fn=lambda: 1, inputs=[], outputs=[selected_tab])
+
+ return {
+ "upscale_mode": selected_tab,
+ "upscale_by": upscaling_resize,
+ "upscale_to_width": upscaling_resize_w,
+ "upscale_to_height": upscaling_resize_h,
+ "upscale_crop": upscaling_crop,
+ "upscaler_1_name": extras_upscaler_1,
+ "upscaler_2_name": extras_upscaler_2,
+ "upscaler_2_visibility": extras_upscaler_2_visibility,
+ }
+
+ def upscale(self, image, info, upscaler, upscale_mode, upscale_by, upscale_to_width, upscale_to_height, upscale_crop):
+ if upscale_mode == 1:
+ upscale_by = max(upscale_to_width/image.width, upscale_to_height/image.height)
+ info["Postprocess upscale to"] = f"{upscale_to_width}x{upscale_to_height}"
+ else:
+ info["Postprocess upscale by"] = upscale_by
+
+ cache_key = (hash(np.array(image.getdata()).tobytes()), upscaler.name, upscale_mode, upscale_by, upscale_to_width, upscale_to_height, upscale_crop)
+ cached_image = upscale_cache.pop(cache_key, None)
+
+ if cached_image is not None:
+ image = cached_image
+ else:
+ image = upscaler.scaler.upscale(image, upscale_by, upscaler.data_path)
+
+ upscale_cache[cache_key] = image
+ if len(upscale_cache) > shared.opts.upscaling_max_images_in_cache:
+ upscale_cache.pop(next(iter(upscale_cache), None), None)
+
+ if upscale_mode == 1 and upscale_crop:
+ cropped = Image.new("RGB", (upscale_to_width, upscale_to_height))
+ cropped.paste(image, box=(upscale_to_width // 2 - image.width // 2, upscale_to_height // 2 - image.height // 2))
+ image = cropped
+ info["Postprocess crop to"] = f"{image.width}x{image.height}"
+
+ return image
+
+ def process(self, pp: scripts_postprocessing.PostprocessedImage, upscale_mode=1, upscale_by=2.0, upscale_to_width=None, upscale_to_height=None, upscale_crop=False, upscaler_1_name=None, upscaler_2_name=None, upscaler_2_visibility=0.0):
+ if upscaler_1_name == "None":
+ upscaler_1_name = None
+
+ upscaler1 = next(iter([x for x in shared.sd_upscalers if x.name == upscaler_1_name]), None)
+ assert upscaler1 or (upscaler_1_name is None), f'could not find upscaler named {upscaler_1_name}'
+
+ if not upscaler1:
+ return
+
+ if upscaler_2_name == "None":
+ upscaler_2_name = None
+
+ upscaler2 = next(iter([x for x in shared.sd_upscalers if x.name == upscaler_2_name and x.name != "None"]), None)
+ assert upscaler2 or (upscaler_2_name is None), f'could not find upscaler named {upscaler_2_name}'
+
+ upscaled_image = self.upscale(pp.image, pp.info, upscaler1, upscale_mode, upscale_by, upscale_to_width, upscale_to_height, upscale_crop)
+ pp.info[f"Postprocess upscaler"] = upscaler1.name
+
+ if upscaler2 and upscaler_2_visibility > 0:
+ second_upscale = self.upscale(pp.image, pp.info, upscaler2, upscale_mode, upscale_by, upscale_to_width, upscale_to_height, upscale_crop)
+ upscaled_image = Image.blend(upscaled_image, second_upscale, upscaler_2_visibility)
+
+ pp.info[f"Postprocess upscaler 2"] = upscaler2.name
+
+ pp.image = upscaled_image
+
+ def image_changed(self):
+ upscale_cache.clear()
diff --git a/scripts/prompts_from_file.py b/scripts/prompts_from_file.py
index f3e711d7..76dc5778 100644
--- a/scripts/prompts_from_file.py
+++ b/scripts/prompts_from_file.py
@@ -116,7 +116,7 @@ class Script(scripts.Script):
checkbox_iterate_batch = gr.Checkbox(label="Use same random seed for all lines", value=False, elem_id=self.elem_id("checkbox_iterate_batch"))
prompt_txt = gr.Textbox(label="List of prompt inputs", lines=1, elem_id=self.elem_id("prompt_txt"))
- file = gr.File(label="Upload prompt inputs", type='bytes', elem_id=self.elem_id("file"))
+ file = gr.File(label="Upload prompt inputs", type='binary', elem_id=self.elem_id("file"))
file.change(fn=load_prompt_file, inputs=[file], outputs=[file, prompt_txt, prompt_txt])
diff --git a/scripts/xy_grid.py b/scripts/xy_grid.py
index 6629f5d5..1a452355 100644
--- a/scripts/xy_grid.py
+++ b/scripts/xy_grid.py
@@ -11,7 +11,6 @@ import modules.scripts as scripts
import gradio as gr
from modules import images, paths, sd_samplers, processing, sd_models, sd_vae
-from modules.hypernetworks import hypernetwork
from modules.processing import process_images, Processed, StableDiffusionProcessingTxt2Img
from modules.shared import opts, cmd_opts, state
import modules.shared as shared
@@ -94,28 +93,6 @@ def confirm_checkpoints(p, xs):
raise RuntimeError(f"Unknown checkpoint: {x}")
-def apply_hypernetwork(p, x, xs):
- if x.lower() in ["", "none"]:
- name = None
- else:
- name = hypernetwork.find_closest_hypernetwork_name(x)
- if not name:
- raise RuntimeError(f"Unknown hypernetwork: {x}")
- hypernetwork.load_hypernetwork(name)
-
-
-def apply_hypernetwork_strength(p, x, xs):
- hypernetwork.apply_strength(x)
-
-
-def confirm_hypernetworks(p, xs):
- for x in xs:
- if x.lower() in ["", "none"]:
- continue
- if not hypernetwork.find_closest_hypernetwork_name(x):
- raise RuntimeError(f"Unknown hypernetwork: {x}")
-
-
def apply_clip_skip(p, x, xs):
opts.data["CLIP_stop_at_last_layers"] = x
@@ -188,12 +165,16 @@ class AxisOption:
self.confirm = confirm
self.cost = cost
self.choices = choices
- self.is_img2img = False
class AxisOptionImg2Img(AxisOption):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
+ self.is_img2img = True
+
+class AxisOptionTxt2Img(AxisOption):
+ def __init__(self, *args, **kwargs):
+ super().__init__(*args, **kwargs)
self.is_img2img = False
@@ -203,13 +184,13 @@ axis_options = [
AxisOption("Var. seed", int, apply_field("subseed")),
AxisOption("Var. strength", float, apply_field("subseed_strength")),
AxisOption("Steps", int, apply_field("steps")),
+ AxisOptionTxt2Img("Hires steps", int, apply_field("hr_second_pass_steps")),
AxisOption("CFG Scale", float, apply_field("cfg_scale")),
AxisOption("Prompt S/R", str, apply_prompt, format_value=format_value),
AxisOption("Prompt order", str_permutations, apply_order, format_value=format_value_join_list),
- AxisOption("Sampler", str, apply_sampler, format_value=format_value, confirm=confirm_samplers, choices=lambda: [x.name for x in sd_samplers.samplers]),
+ AxisOptionTxt2Img("Sampler", str, apply_sampler, format_value=format_value, confirm=confirm_samplers, choices=lambda: [x.name for x in sd_samplers.samplers]),
+ AxisOptionImg2Img("Sampler", str, apply_sampler, format_value=format_value, confirm=confirm_samplers, choices=lambda: [x.name for x in sd_samplers.samplers_for_img2img]),
AxisOption("Checkpoint name", str, apply_checkpoint, format_value=format_value, confirm=confirm_checkpoints, cost=1.0, choices=lambda: list(sd_models.checkpoints_list)),
- AxisOption("Hypernetwork", str, apply_hypernetwork, format_value=format_value, confirm=confirm_hypernetworks, cost=0.2, choices=lambda: list(shared.hypernetworks)),
- AxisOption("Hypernet str.", float, apply_hypernetwork_strength),
AxisOption("Sigma Churn", float, apply_field("s_churn")),
AxisOption("Sigma min", float, apply_field("s_tmin")),
AxisOption("Sigma max", float, apply_field("s_tmax")),
@@ -217,8 +198,8 @@ axis_options = [
AxisOption("Eta", float, apply_field("eta")),
AxisOption("Clip skip", int, apply_clip_skip),
AxisOption("Denoising", float, apply_field("denoising_strength")),
- AxisOption("Hires upscaler", str, apply_field("hr_upscaler"), choices=lambda: [x.name for x in shared.sd_upscalers]),
- AxisOption("Cond. Image Mask Weight", float, apply_field("inpainting_mask_weight")),
+ AxisOptionTxt2Img("Hires upscaler", str, apply_field("hr_upscaler"), choices=lambda: [*shared.latent_upscale_modes, *[x.name for x in shared.sd_upscalers]]),
+ AxisOptionImg2Img("Cond. Image Mask Weight", float, apply_field("inpainting_mask_weight")),
AxisOption("VAE", str, apply_vae, cost=0.7, choices=lambda: list(sd_vae.vae_dict)),
AxisOption("Styles", str, apply_styles, choices=lambda: list(shared.prompt_styles.styles)),
]
@@ -291,7 +272,6 @@ def draw_xy_grid(p, xs, ys, x_labels, y_labels, cell, draw_legend, include_lone_
class SharedSettingsStackHelper(object):
def __enter__(self):
self.CLIP_stop_at_last_layers = opts.CLIP_stop_at_last_layers
- self.hypernetwork = opts.sd_hypernetwork
self.vae = opts.sd_vae
def __exit__(self, exc_type, exc_value, tb):
@@ -299,9 +279,6 @@ class SharedSettingsStackHelper(object):
modules.sd_models.reload_model_weights()
modules.sd_vae.reload_vae_weights()
- hypernetwork.load_hypernetwork(self.hypernetwork)
- hypernetwork.apply_strength()
-
opts.data["CLIP_stop_at_last_layers"] = self.CLIP_stop_at_last_layers
@@ -317,42 +294,41 @@ class Script(scripts.Script):
return "X/Y plot"
def ui(self, is_img2img):
- current_axis_options = [x for x in axis_options if type(x) == AxisOption or x.is_img2img and is_img2img]
+ self.current_axis_options = [x for x in axis_options if type(x) == AxisOption or x.is_img2img == is_img2img]
with gr.Row():
with gr.Column(scale=19):
with gr.Row():
- x_type = gr.Dropdown(label="X type", choices=[x.label for x in current_axis_options], value=current_axis_options[1].label, type="index", elem_id=self.elem_id("x_type"))
+ x_type = gr.Dropdown(label="X type", choices=[x.label for x in self.current_axis_options], value=self.current_axis_options[1].label, type="index", elem_id=self.elem_id("x_type"))
x_values = gr.Textbox(label="X values", lines=1, elem_id=self.elem_id("x_values"))
fill_x_button = ToolButton(value=fill_values_symbol, elem_id="xy_grid_fill_x_tool_button", visible=False)
with gr.Row():
- y_type = gr.Dropdown(label="Y type", choices=[x.label for x in current_axis_options], value=current_axis_options[0].label, type="index", elem_id=self.elem_id("y_type"))
+ y_type = gr.Dropdown(label="Y type", choices=[x.label for x in self.current_axis_options], value=self.current_axis_options[0].label, type="index", elem_id=self.elem_id("y_type"))
y_values = gr.Textbox(label="Y values", lines=1, elem_id=self.elem_id("y_values"))
fill_y_button = ToolButton(value=fill_values_symbol, elem_id="xy_grid_fill_y_tool_button", visible=False)
- with gr.Row(variant="compact"):
+ with gr.Row(variant="compact", elem_id="axis_options"):
draw_legend = gr.Checkbox(label='Draw legend', value=True, elem_id=self.elem_id("draw_legend"))
include_lone_images = gr.Checkbox(label='Include Separate Images', value=False, elem_id=self.elem_id("include_lone_images"))
no_fixed_seeds = gr.Checkbox(label='Keep -1 for seeds', value=False, elem_id=self.elem_id("no_fixed_seeds"))
swap_axes_button = gr.Button(value="Swap axes", elem_id="xy_grid_swap_axes_button")
def swap_axes(x_type, x_values, y_type, y_values):
- nonlocal current_axis_options
- return current_axis_options[y_type].label, y_values, current_axis_options[x_type].label, x_values
+ return self.current_axis_options[y_type].label, y_values, self.current_axis_options[x_type].label, x_values
swap_args = [x_type, x_values, y_type, y_values]
swap_axes_button.click(swap_axes, inputs=swap_args, outputs=swap_args)
def fill(x_type):
- axis = axis_options[x_type]
+ axis = self.current_axis_options[x_type]
return ", ".join(axis.choices()) if axis.choices else gr.update()
fill_x_button.click(fn=fill, inputs=[x_type], outputs=[x_values])
fill_y_button.click(fn=fill, inputs=[y_type], outputs=[y_values])
def select_axis(x_type):
- return gr.Button.update(visible=axis_options[x_type].choices is not None)
+ return gr.Button.update(visible=self.current_axis_options[x_type].choices is not None)
x_type.change(fn=select_axis, inputs=[x_type], outputs=[fill_x_button])
y_type.change(fn=select_axis, inputs=[y_type], outputs=[fill_y_button])
@@ -427,10 +403,10 @@ class Script(scripts.Script):
return valslist
- x_opt = axis_options[x_type]
+ x_opt = self.current_axis_options[x_type]
xs = process_axis(x_opt, x_values)
- y_opt = axis_options[y_type]
+ y_opt = self.current_axis_options[y_type]
ys = process_axis(y_opt, y_values)
def fix_axis_seeds(axis_opt, axis_list):
@@ -451,10 +427,21 @@ class Script(scripts.Script):
total_steps = p.steps * len(xs) * len(ys)
if isinstance(p, StableDiffusionProcessingTxt2Img) and p.enable_hr:
- total_steps *= 2
+ if x_opt.label == "Hires steps":
+ total_steps += sum(xs) * len(ys)
+ elif y_opt.label == "Hires steps":
+ total_steps += sum(ys) * len(xs)
+ elif p.hr_second_pass_steps:
+ total_steps += p.hr_second_pass_steps * len(xs) * len(ys)
+ else:
+ total_steps *= 2
+
+ total_steps *= p.n_iter
- print(f"X/Y plot will create {len(xs) * len(ys) * p.n_iter} images on a {len(xs)}x{len(ys)} grid. (Total steps to process: {total_steps * p.n_iter})")
- shared.total_tqdm.updateTotal(total_steps * p.n_iter)
+ image_cell_count = p.n_iter * p.batch_size
+ cell_console_text = f"; {image_cell_count} images per cell" if image_cell_count > 1 else ""
+ print(f"X/Y plot will create {len(xs) * len(ys) * image_cell_count} images on a {len(xs)}x{len(ys)} grid{cell_console_text}. (Total steps to process: {total_steps})")
+ shared.total_tqdm.updateTotal(total_steps)
grid_infotext = [None]
diff --git a/style.css b/style.css
index 97f9402a..bf8260d7 100644
--- a/style.css
+++ b/style.css
@@ -2,12 +2,26 @@
max-width: 100%;
}
-#txt2img_token_counter {
- height: 0px;
+.token-counter{
+ position: absolute;
+ display: inline-block;
+ right: 2em;
+ min-width: 0 !important;
+ width: auto;
+ z-index: 100;
}
-#img2img_token_counter {
- height: 0px;
+.token-counter.error span{
+ box-shadow: 0 0 0.0 0.3em rgba(255,0,0,0.15), inset 0 0 0.6em rgba(255,0,0,0.075);
+ border: 2px solid rgba(255,0,0,0.4) !important;
+}
+
+.token-counter div{
+ display: inline;
+}
+
+.token-counter span{
+ padding: 0.1em 0.75em;
}
#sh{
@@ -20,7 +34,7 @@
padding-right: 0.25em;
margin: 0.1em 0;
opacity: 0%;
- cursor: default;
+ cursor: default;
}
.output-html p {margin: 0 0.5em;}
@@ -110,29 +124,22 @@
height: 100%;
}
-#roll_col{
- min-width: unset !important;
- flex-grow: 0 !important;
- padding: 0.4em 0;
+#txt2img_actions_column, #img2img_actions_column{
+ gap: 0;
}
-#roll_col > button {
- min-width: 2em;
- min-height: 2em;
- max-width: 2em;
- max-height: 2em;
- flex-grow: 0;
- padding-left: 0.25em;
- padding-right: 0.25em;
- margin: 0.1em 0;
+#txt2img_tools, #img2img_tools{
+ gap: 0.4em;
}
#interrogate_col{
min-width: 0 !important;
max-width: 8em !important;
+ margin-right: 1em;
+ gap: 0;
}
#interrogate, #deepbooru{
- margin: 0em 0.25em 0.9em 0.25em;
+ margin: 0em 0.25em 0.5em 0.25em;
min-width: 8em;
max-width: 8em;
}
@@ -141,8 +148,25 @@
min-width: 8em !important;
}
-#txt2img_style_index, #txt2img_style2_index, #img2img_style_index, #img2img_style2_index{
- margin-top: 1em;
+#txt2img_styles_row, #img2img_styles_row{
+ gap: 0.25em;
+}
+
+#txt2img_styles_row > button, #img2img_styles_row > button{
+ margin: 0;
+}
+
+#txt2img_styles, #img2img_styles{
+ padding: 0;
+}
+
+#txt2img_styles > label > div, #img2img_styles > label > div{
+ min-height: 3.2em;
+}
+
+#txt2img_styles ul, #img2img_styles ul{
+ max-height: 35em;
+ z-index: 2000;
}
.gr-form{
@@ -154,12 +178,6 @@
margin-bottom: 0;
}
-#toprow div{
- border: none;
- gap: 0;
- background: transparent;
-}
-
#resize_mode{
flex: 1.5;
}
@@ -221,7 +239,10 @@ fieldset span.text-gray-500, .gr-block.gr-box span.text-gray-500, label.block s
.dark fieldset span.text-gray-500, .dark .gr-block.gr-box span.text-gray-500, .dark label.block span{
background-color: rgb(31, 41, 55);
- box-shadow: 6px 0 6px 0px rgb(31, 41, 55), -6px 0 6px 0px rgb(31, 41, 55);
+ box-shadow: none;
+ border: 1px solid rgba(128, 128, 128, 0.1);
+ border-radius: 6px;
+ padding: 0.1em 0.5em;
}
#txt2img_column_batch, #img2img_column_batch{
@@ -286,30 +307,15 @@ input[type="range"]{
}
/* more gradio's garbage cleanup */
-.min-h-\[4rem\] {
- min-height: unset !important;
-}
-
-#txt2img_progressbar, #img2img_progressbar, #ti_progressbar{
- position: absolute;
- z-index: 1000;
- right: 0;
- padding-left: 5px;
- padding-right: 5px;
- display: block;
-}
-
-#txt2img_progress_row, #img2img_progress_row{
- margin-bottom: 10px;
- margin-top: -18px;
-}
+.min-h-\[4rem\] { min-height: unset !important; }
+.min-h-\[6rem\] { min-height: unset !important; }
.progressDiv{
position: absolute;
height: 20px;
top: -20px;
background: #b4c0cc;
- border-radius: 8px !important;
+ border-radius: 3px !important;
}
.dark .progressDiv{
@@ -325,9 +331,10 @@ input[type="range"]{
line-height: 20px;
padding: 0 8px 0 0;
text-align: right;
- border-radius: 8px;
+ border-radius: 3px;
overflow: visible;
white-space: nowrap;
+ padding: 0 0.5em;
}
.livePreview{
@@ -392,7 +399,7 @@ input[type="range"]{
grid-area: tile;
}
-.modalClose,
+.modalClose,
.modalZoom,
.modalTileImage {
color: white;
@@ -531,30 +538,21 @@ input[type="range"]{
gap: 0.4em;
}
-#quicksettings > div{
- border: none;
- background: none;
- flex: unset;
- gap: 1em;
-}
-
-#quicksettings > div > div{
- max-width: 32em;
+#quicksettings > div, #quicksettings > fieldset{
+ max-width: 24em;
min-width: 24em;
padding: 0;
+ border: none;
+ box-shadow: none;
+ background: none;
}
-#quicksettings > div > div > div > div > label > span {
+#quicksettings > div > div > div > label > span {
position: relative;
margin-right: 9em;
margin-bottom: -1em;
}
-#quicksettings > div > div > label > span {
- position: relative;
- margin-bottom: -1em;
-}
-
canvas[key="mask"] {
z-index: 12 !important;
filter: invert();
@@ -591,7 +589,7 @@ canvas[key="mask"] {
/* Extensions */
-#tab_extensions table``{
+#tab_extensions table{
border-collapse: collapse;
}
@@ -640,13 +638,31 @@ canvas[key="mask"] {
background-color: rgb(31 41 55 / var(--tw-bg-opacity));
}
-.gr-button-tool{
+.gr-button-tool, .gr-button-tool-top{
max-width: 2.5em;
min-width: 2.5em !important;
height: 2.4em;
- margin: 0.55em 0.7em 0.55em 0;
}
+.gr-button-tool{
+ margin: 0.6em 0em 0.55em 0;
+}
+
+.gr-button-tool-top, #settings .gr-button-tool{
+ margin: 1.6em 0.7em 0.55em 0;
+}
+
+
+#modelmerger_results_container{
+ margin-top: 1em;
+ overflow: visible;
+}
+
+#modelmerger_models{
+ gap: 0;
+}
+
+
#quicksettings .gr-button-tool{
margin: 0;
}
@@ -689,16 +705,65 @@ footer {
font-weight: bold;
}
-#txt2img_checkboxes > div > div{
+#txt2img_checkboxes, #img2img_checkboxes{
+ margin-bottom: 0.5em;
+ margin-left: 0em;
+}
+#txt2img_checkboxes > div, #img2img_checkboxes > div{
flex: 0;
white-space: nowrap;
min-width: auto;
}
+#txt2img_hires_fix{
+ margin-left: -0.8em;
+}
+
+#img2img_copy_to_img2img, #img2img_copy_to_sketch, #img2img_copy_to_inpaint, #img2img_copy_to_inpaint_sketch{
+ margin-left: 0em;
+}
+
+#axis_options {
+ margin-left: 0em;
+}
.inactive{
opacity: 0.5;
}
+[id*='_prompt_container']{
+ gap: 0;
+}
+
+[id*='_prompt_container'] > div{
+ margin: -0.4em 0 0 0;
+}
+
+.gr-compact {
+ border: none;
+}
+
+.dark .gr-compact{
+ background-color: rgb(31 41 55 / var(--tw-bg-opacity));
+ margin-left: 0.8em;
+}
+
+.gr-compact{
+ overflow: visible;
+}
+
+.gr-compact > *{
+}
+
+.gr-compact .gr-block, .gr-compact .gr-form{
+ border: none;
+ box-shadow: none;
+}
+
+.gr-compact .gr-box{
+ border-radius: .5rem !important;
+ border-width: 1px !important;
+}
+
#mode_img2img > div > div{
gap: 0 !important;
}
@@ -717,81 +782,92 @@ footer {
line-height: 2.4em;
}
-/* The following handles localization for right-to-left (RTL) languages like Arabic.
-The rtl media type will only be activated by the logic in javascript/localization.js.
-If you change anything above, you need to make sure it is RTL compliant by just running
-your changes through converters like https://cssjanus.github.io/ or https://rtlcss.com/.
-Then, you will need to add the RTL counterpart only if needed in the rtl section below.*/
-@media rtl {
- /* this part was added manually */
- :host {
- direction: rtl;
- }
- select, .file-preview, .gr-text-input, .output-html:has(.performance), #ti_progress {
- direction: ltr;
- }
- #script_list > label > select,
- #x_type > label > select,
- #y_type > label > select {
- direction: rtl;
- }
- .gr-radio, .gr-checkbox{
- margin-left: 0.25em;
- }
+.extra-networks > div > [id *= '_extra_']{
+ margin: 0.3em;
+}
+
+
+
+#txt2img_extra_networks .search, #img2img_extra_networks .search{
+ display: inline-block;
+ max-width: 16em;
+ margin: 0.3em;
+}
+
+.extra-network-cards .nocards{
+ margin: 1.25em 0.5em 0.5em 0.5em;
+}
+
+.extra-network-cards .nocards h1{
+ font-size: 1.5em;
+ margin-bottom: 1em;
+}
+
+.extra-network-cards .nocards li{
+ margin-left: 0.5em;
+}
+
+.extra-network-cards .card{
+ display: inline-block;
+ margin: 0.5em;
+ width: 16em;
+ height: 24em;
+ box-shadow: 0 0 5px rgba(128, 128, 128, 0.5);
+ border-radius: 0.2em;
+ position: relative;
+
+ background-size: auto 100%;
+ background-position: center;
+ overflow: hidden;
+ cursor: pointer;
+
+ background-image: url('./file=html/card-no-preview.png')
+}
+
+.extra-network-cards .card:hover{
+ box-shadow: 0 0 2px 0.3em rgba(0, 128, 255, 0.35);
+}
+
+.extra-network-cards .card .actions .additional{
+ display: none;
+}
+
+.extra-network-cards .card .actions{
+ position: absolute;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ padding: 0.5em;
+ color: white;
+ background: rgba(0,0,0,0.5);
+ box-shadow: 0 0 0.25em 0.25em rgba(0,0,0,0.5);
+ text-shadow: 0 0 0.2em black;
+}
+
+.extra-network-cards .card .actions:hover{
+ box-shadow: 0 0 0.75em 0.75em rgba(0,0,0,0.5) !important;
+}
+
+.extra-network-cards .card .actions .name{
+ font-size: 1.7em;
+ font-weight: bold;
+ line-break: anywhere;
+}
+
+.extra-network-cards .card .actions:hover .additional{
+ display: block;
+}
+
+.extra-network-cards .card ul{
+ margin: 0.25em 0 0.75em 0.25em;
+ cursor: unset;
+}
+
+.extra-network-cards .card ul a{
+ cursor: pointer;
+}
+
+.extra-network-cards .card ul a:hover{
+ color: red;
+}
- /* automatically generated with few manual modifications */
- .performance .time {
- margin-right: unset;
- margin-left: 0;
- }
- .justify-center.overflow-x-scroll {
- justify-content: right;
- }
- .justify-center.overflow-x-scroll button:first-of-type {
- margin-left: unset;
- margin-right: auto;
- }
- .justify-center.overflow-x-scroll button:last-of-type {
- margin-right: unset;
- margin-left: auto;
- }
- #settings fieldset span.text-gray-500, #settings .gr-block.gr-box span.text-gray-500, #settings label.block span{
- margin-right: unset;
- margin-left: 8em;
- }
- #txt2img_progressbar, #img2img_progressbar, #ti_progressbar{
- right: unset;
- left: 0;
- }
- .progressDiv .progress{
- padding: 0 0 0 8px;
- text-align: left;
- }
- #lightboxModal{
- left: unset;
- right: 0;
- }
- .modalPrev, .modalNext{
- border-radius: 3px 0 0 3px;
- }
- .modalNext {
- right: unset;
- left: 0;
- border-radius: 0 3px 3px 0;
- }
- #imageARPreview{
- left:unset;
- right:0px;
- }
- #txt2img_skip, #img2img_skip{
- right: unset;
- left: 0px;
- }
- #context-menu{
- box-shadow:-1px 1px 2px #CE6400;
- }
- .gr-box > div > div > input.gr-text-input{
- right: unset;
- left: 0.5em;
- }
-} \ No newline at end of file
diff --git a/test/basic_features/utils_test.py b/test/basic_features/utils_test.py
index 94e00253..0bfc28a0 100644
--- a/test/basic_features/utils_test.py
+++ b/test/basic_features/utils_test.py
@@ -12,8 +12,6 @@ class UtilsTests(unittest.TestCase):
self.url_face_restorers = "http://localhost:7860/sdapi/v1/face-restorers"
self.url_realesrgan_models = "http://localhost:7860/sdapi/v1/realesrgan-models"
self.url_prompt_styles = "http://localhost:7860/sdapi/v1/prompt-styles"
- self.url_artist_categories = "http://localhost:7860/sdapi/v1/artist-categories"
- self.url_artists = "http://localhost:7860/sdapi/v1/artists"
self.url_embeddings = "http://localhost:7860/sdapi/v1/embeddings"
def test_options_get(self):
@@ -56,15 +54,9 @@ class UtilsTests(unittest.TestCase):
def test_prompt_styles(self):
self.assertEqual(requests.get(self.url_prompt_styles).status_code, 200)
-
- def test_artist_categories(self):
- self.assertEqual(requests.get(self.url_artist_categories).status_code, 200)
-
- def test_artists(self):
- self.assertEqual(requests.get(self.url_artists).status_code, 200)
def test_embeddings(self):
- self.assertEqual(requests.get(self.url_artists).status_code, 200)
+ self.assertEqual(requests.get(self.url_embeddings).status_code, 200)
if __name__ == "__main__":
unittest.main()
diff --git a/webui.py b/webui.py
index 4624fe18..7cf5885e 100644
--- a/webui.py
+++ b/webui.py
@@ -9,18 +9,19 @@ from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
from fastapi.middleware.gzip import GZipMiddleware
-from modules import import_hook, errors
+from modules import import_hook, errors, extra_networks
+from modules import extra_networks_hypernet, ui_extra_networks_hypernets, ui_extra_networks_textual_inversion
from modules.call_queue import wrap_queued_call, queue_lock, wrap_gradio_gpu_call
from modules.paths import script_path
import torch
+
# Truncate version number of nightly/local build of PyTorch to not cause exceptions with CodeFormer or Safetensors
if ".dev" in torch.__version__ or "+git" in torch.__version__:
torch.__version__ = re.search(r'[\d.]+[\d]', torch.__version__).group(0)
-from modules import shared, devices, sd_samplers, upscaler, extensions, localization, ui_tempdir
+from modules import shared, devices, sd_samplers, upscaler, extensions, localization, ui_tempdir, ui_extra_networks
import modules.codeformer_model as codeformer
-import modules.extras
import modules.face_restoration
import modules.gfpgan_model as gfpgan
import modules.img2img
@@ -84,10 +85,17 @@ def initialize():
shared.opts.onchange("sd_model_checkpoint", wrap_queued_call(lambda: modules.sd_models.reload_model_weights()))
shared.opts.onchange("sd_vae", wrap_queued_call(lambda: modules.sd_vae.reload_vae_weights()), call=False)
shared.opts.onchange("sd_vae_as_default", wrap_queued_call(lambda: modules.sd_vae.reload_vae_weights()), call=False)
- shared.opts.onchange("sd_hypernetwork", wrap_queued_call(lambda: shared.reload_hypernetworks()))
- shared.opts.onchange("sd_hypernetwork_strength", modules.hypernetworks.hypernetwork.apply_strength)
shared.opts.onchange("temp_dir", ui_tempdir.on_tmpdir_changed)
+ shared.reload_hypernetworks()
+
+ ui_extra_networks.intialize()
+ ui_extra_networks.register_page(ui_extra_networks_textual_inversion.ExtraNetworksPageTextualInversion())
+ ui_extra_networks.register_page(ui_extra_networks_hypernets.ExtraNetworksPageHypernetworks())
+
+ extra_networks.initialize()
+ extra_networks.register_extra_network(extra_networks_hypernet.ExtraNetworkHypernet())
+
if cmd_opts.tls_keyfile is not None and cmd_opts.tls_keyfile is not None:
try:
@@ -156,9 +164,14 @@ def webui():
if shared.opts.clean_temp_dir_at_start:
ui_tempdir.cleanup_tmpdr()
+ modules.script_callbacks.before_ui_callback()
+
shared.demo = modules.ui.create_ui()
- app, local_url, share_url = shared.demo.queue(default_enabled=False).launch(
+ if cmd_opts.gradio_queue:
+ shared.demo.queue(64)
+
+ app, local_url, share_url = shared.demo.launch(
share=cmd_opts.share,
server_name=server_name,
server_port=cmd_opts.port,
@@ -188,7 +201,6 @@ def webui():
create_api(app)
modules.script_callbacks.app_started_callback(shared.demo, app)
- modules.script_callbacks.app_started_callback(shared.demo, app)
wait_on_server(shared.demo)
print('Restarting UI...')
@@ -210,6 +222,15 @@ def webui():
modules.sd_models.list_models()
+ shared.reload_hypernetworks()
+
+ ui_extra_networks.intialize()
+ ui_extra_networks.register_page(ui_extra_networks_textual_inversion.ExtraNetworksPageTextualInversion())
+ ui_extra_networks.register_page(ui_extra_networks_hypernets.ExtraNetworksPageHypernetworks())
+
+ extra_networks.initialize()
+ extra_networks.register_extra_network(extra_networks_hypernet.ExtraNetworkHypernet())
+
if __name__ == "__main__":
if cmd_opts.nowebui:
diff --git a/webui.sh b/webui.sh
index 6e07778f..8cdad22d 100755
--- a/webui.sh
+++ b/webui.sh
@@ -104,6 +104,23 @@ then
fi
# Check prerequisites
+gpu_info=$(lspci 2>/dev/null | grep VGA)
+case "$gpu_info" in
+ *"Navi 1"*|*"Navi 2"*) export HSA_OVERRIDE_GFX_VERSION=10.3.0
+ ;;
+ *"Renoir"*) export HSA_OVERRIDE_GFX_VERSION=9.0.0
+ printf "\n%s\n" "${delimiter}"
+ printf "Experimental support for Renoir: make sure to have at least 4GB of VRAM and 10GB of RAM or enable cpu mode: --use-cpu all --no-half"
+ printf "\n%s\n" "${delimiter}"
+ ;;
+ *)
+ ;;
+esac
+if echo "$gpu_info" | grep -q "AMD" && [[ -z "${TORCH_COMMAND}" ]]
+then
+ export TORCH_COMMAND="pip install torch torchvision --extra-index-url https://download.pytorch.org/whl/rocm5.2"
+fi
+
for preq in "${GIT}" "${python_cmd}"
do
if ! hash "${preq}" &>/dev/null
@@ -164,16 +181,6 @@ then
else
printf "\n%s\n" "${delimiter}"
printf "Launching launch.py..."
- printf "\n%s\n" "${delimiter}"
- gpu_info=$(lspci | grep VGA)
- if echo "$gpu_info" | grep -q "AMD"
- then
- if [[ -z "${TORCH_COMMAND}" ]]
- then
- export TORCH_COMMAND="pip install torch torchvision --extra-index-url https://download.pytorch.org/whl/rocm5.2"
- fi
- HSA_OVERRIDE_GFX_VERSION=10.3.0 exec "${python_cmd}" "${LAUNCH_SCRIPT}" "$@"
- else
- exec "${python_cmd}" "${LAUNCH_SCRIPT}" "$@"
- fi
+ printf "\n%s\n" "${delimiter}"
+ exec "${python_cmd}" "${LAUNCH_SCRIPT}" "$@"
fi