Closed xram64 closed 2 years ago
Also, I'd recommend checking out the gr.HTML
or gr.Markdown
components for this if you haven't, since they'll give you a lot more control than gr.Textbox
.
ENORMOUS thanks for the tips! I tried reading up on it, asking on Discord and basically got 0 recommendations on how to get rid of those. Now it all looks and works much better. This will help the next version enormously. Delay it, but help it as well.
I was getting some decent results with hiding the elements, but then decided to follow your advice of moving onto Markdown. Then decided to split the elements into tabs so it takes up less space and info isn't in the way once users know it. And in the end it all became rather nice, but also basically impossible for me to figure out how to properly mark those elements so they are hidden. My experience with Gradio, Python and even github is basically a week, so...
Would be it be possible for you to have a look here https://github.com/some9000/StylePile/tree/Beta and give some hints on hiding that whole panel? So far I either get no reaction at all, error messages or straight up crashes on entire system (when trying to tag the entire panel). Thank you in advance.
Gradio has some pretty horrible documentation, so if it doesn't make any sense it's probably not your fault lol
Tabs are weird because they don't have a visible
property themselves, but what I found to work is to wrap them in a Group
, which does have a visible
property. Then the name for the Group
component, as well as anything else that isn't a Tab/Row/Column, should be passed to the return of ui()
and the params of run()
.
Your Markdown
component needs a name too so it can be passed in (e.g. poHelpText = gr.Markdown(...)
).
Also, a safer way to reference your image files might be to use the script_path
variable from the UI module that holds the root UI directory. So if you add from modules.paths import script_path
and from os import path
at the top, you can use something like value=path.join(script_path, "scripts", "StyleGuide.png")
.
Just as a suggestion, it might be a good idea to start using a scripts/StylePile/
folder to put the images into, so they're not just sitting loose in the scripts folder. This would also give you a place to put other stuff in the future. For instance, some of the tag dicts at the top (Artists
, ResultStyle
, etc.) might be easier to manage if they were broken out into a separate text file and just read into the script, so they could be changed or swapped in/out easily without changing the script itself.
I'll paste the full ui()
function and other changes that worked for me below.
from os import path
from modules.paths import script_path
ui()
def ui(self, is_img2img):
with gr.Group() as TabContainer:
with gr.Tab("StylePile"):
with gr.Row():
poResultType = gr.Dropdown(list(ResultType.keys()), label="Image type", value="Not set")
poResultColors = gr.Dropdown(list(ResultColors.keys()), label="Colors", value="Not set")
poImageView = gr.Dropdown(list(ImageView.keys()), label="View", value="Not set")
poFocusOn = gr.Dropdown(list(FocusOn.keys()),label = "Focus on", value="No focus")
with gr.Row():
with gr.Column():
poResultStyle = gr.Radio(list(ResultStyle.keys()), label="Visual style", value="Not set")
with gr.Column():
poArtist = gr.Radio(list(Artists.keys()),label="Artist", value="Not set")
with gr.Tab("Help"):
poHelpText = gr.Markdown(
"""
## Hello, StylePile here.
### Introduction
**StylePile** is basically a mix and match system for adding elements to prompts that affect the style of the result. Hence the name. By default, these elements are placed in a specific way and given strength values, so the result sort-of evolves. I have generated hundreds of images for each main **Image type** and tweaked the keywords to attempt giving expected results most of the time. Certainly, your suggestions for improvements are very welcome.
### Workflow
For example, if you select the **Drawing** image type, then almost all results will look like drawings. Setting **Colors** will change the general use of color, and setting **View** will attempt to change how the subject is viewed. Attempt, because view appears to be the least reliable keyword. These elements are placed in order of influence.
Moving on, adding a **Visual style** will affect how that drawing looks. Either it will be more realistic or artistic or look like a comic book etc. In general, this is a really strong element for getting the look you want. Beyond that, you can select an **Artist** and that will have an influence on the general look of the result. Examples of both these selections can be seen on respective tabs to the right of this one.
You can, and should, freely mix and match these settings to get different results. Classic painting styles affected or affecting 3D look quite interesting. If it feels like the style is too weak, raise CFG scale to 15, 20 or more.
### Hints
Parenthesis can be added to make parts of the prompt stronger. So (((cute))) kitten will make it extra cute (try it out). This is also important if a style is affecting your original prompt too much. Make that prompt stronger by adding parenthesis around it, like this: ((promt)).
Prompts can be split like [A|B] to sequentially use terms one after another on each step. [cat|dog] will produce a hybrid catdog.
And using [A:B:0.4] will switch to other terms after the first one has been active for a certain percentage of steps. [cat:dog:0.4] will build a cat 40% of the time and then start turning it into a dog. This needs more steps to work properly.
### Conclusion
I made this because manually changing keywords, looking up possible styles, etc was a pain. It is meant as a fun tool to explore possibilities and make learning Stable Diffusion easier. If you have some ideas or, better yet, would like to contribute in some way just visit https://github.com/some9000/StylePile
""")
with gr.Tab("Visual Style examples") as StyleTab:
poVisualStyleHint = gr.Image(show_label=False,interactive=False,value=path.join(script_path, "scripts", "StyleGuide.png"))
with gr.Tab("Artist examples") as ArtistTab:
poArtistHint = gr.Image(show_label=False,interactive=False,value=path.join(script_path, "scripts", "Artists.png"))
return [poResultType, poResultStyle, poResultColors, poImageView, poFocusOn, poArtist, poHelpText, poVisualStyleHint, poArtistHint, TabContainer]
run()
def run(self, p, poResultType, poResultStyle, poResultColors, poImageView, poFocusOn, poArtist, poHelpText, poVisualStyleHint, poArtistHint, TabContainer):
Update: Just pulled latest SD update and now groups seem broken... AttributeError: 'Group' object has no attribute 'preprocess' It works without the groups, gives that error message with them. No code changes on this side. Well, hopefully they can fix this.
Awesome, that works really well and has fixed the main problem before next release. As for external data - I guess Focus on could be placed outside in the form of a text file. Since the other elements have multiple levels and that just increases chances of something breaking/confusing users (the idea still is that is is newcomer (like me) friendly).
Thanks, this has been massive help and I have learned along the way. Wish there was some way to change styling on elements to make all the selections smaller. But, guess gradio just felt giant radio buttons are the way to go. Tried all the CSS stuff in their documentation and nothing worked.
Well, let's get closer to that release. Now it's almost the hardest part, which is docs.
Updated the beta branch with these changes.
Yeah, so far I have tried again and failed again. All other elements work when assigned as values (and there are some neat new elements), but this just doesn't work, even after latest updates.
And that sort of prohibits releasing a new version so I just keep adding features. Will need to generate like 100 thumbnails soon...
Also, I have added a discussion about improving the code, in case you don't mind having a look.
FYI, you can fix this by just adding
poTempText
to both the return list ofui()
and the params list ofrun()
. You don't need to do anything with it beyond that, it just needs to be there. Because of how the Web UI loads scripts, all components are visible at first, and only set to be hidden once they're loaded. But if you don't provide a component in theui()
returns, the UI doesn't know to hide it.