{"id":1382,"date":"2024-05-27T12:00:00","date_gmt":"2024-05-27T19:00:00","guid":{"rendered":"https:\/\/letsbuildroboticswithshadow8472.com\/?p=1382"},"modified":"2024-05-27T03:11:32","modified_gmt":"2024-05-27T10:11:32","slug":"self-hosted-ai-consistent-characters-part-1","status":"publish","type":"post","link":"https:\/\/letsbuildroboticswithshadow8472.com\/index.php\/2024\/05\/27\/self-hosted-ai-consistent-characters-part-1\/","title":{"rendered":"Self-Hosted AI Consistent Characters: Part 1"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\">Good Morning from my Robotics Lab! This is Shadow_8472, and today I am on a quest to generate consistent characters using AI. Let\u2019s get started!<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">It all started with wanting to learn how to make my own \u201cconsistent characters\u201d I can summon with a keyword in my prompt. Before I can train the AI to make one, my subject needs consistent source pictures. One way to do that is to chop up a character sheet with multiple angles of the same character all generated at once. Expect all that in a future post. It sounded like a reasonable goal until I discovered just how many moving parts I needed just to approach.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">In particular, my first goal is Ms. T, a Sonic OC (Original Character) by my sister, but once I figure out a successful workflow, it shouldn\u2019t be too hard to make more.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">A1111<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Automatic1111 (A1111) is the go-to StableDiffusion (SD) image generation web interface for the vast majority of tutorials out there. While it\u2019s not the easiest SD WebUI, A1111 is approachable by patient AI noobs and EasyDiffusion graduates alike. It exposes a bit many controls by default, but it packs enough power to keep a SD adept busy for a while. I also found Forge, an A1111 fork reportedly having extra features, bug fixes, grudging Linux support, and needs a virtual environment. At the top, I found ComfyUI, which lets you design and share custom workflows.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">As a warm up exercise, I found a SonicDiffusion, a SD model geared for Sonic characters, generated a bunch of Ms. T portraits, and saved my favorites. Talking with my sister, I began cherry picking for details the model doesn\u2019t control for, such as \u201ccyclopse\u201d designs where the eyes join at the whites vs. separate eyes (Hedgehogs are usually cyclopses, but not in the live action movies). SonicDiffusion \u2013to my knowledge\u2013 lacks a keyword to force this distinction. Eventually, my expectations outpaced my ability to prompt, and I had to move on.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">ControlNet<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">A major contribution to A1111\u2019s versatility is its ecosystem of extensions. Of interest this week is ControlNet, a tool to include visual data in a StableDiffusion prompt for precision results. As of writing, I\u2019m looking at 21 controller types \u2013 each needing a model to work. I downloaded the ones for Canny, Depth, and OpenPose to get started.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">My first thought was to use an Xbox One Kinect (AKA Kinect v2) I bought from someone in my area a few Thanksgivings ago. If it works, I can easily pose for ControlNet. Long story short: I spent a couple days either last week or the week before tossing code back and forth with a self-hosted AI chatbot in SillyTavern with no dice. The open source Linux driver for the Kinect v2 just isn\u2019t maintained for Ubuntu 22.04 and distros built on it. I couldn\u2019t even get it to turn on its infrared LED\u2019s (visible by my PinePhone\u2019s camera) because of broken linkages in the header files or something. Pro tip: Don\u2019t argue with a delusional LLM unless you can straighten it out in a reply or two. On the plus side, the AI did help me approach this job where I\u2019d expect to have taken weeks to months without it. If\/when I return, I expect to bodge it with Podman, but I may need to update the driver anyway if the kernel matters.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Even if I did get the Kinect to work, I doubt it would have been the miracle I was hoping for. Sonic style characters (Mobians) have different proportions than humans \u2013 most notably everything from the shoulders up. I ended up finding an embedding for making turnaround\/character sheets, but it was again trained to make humans and I got inconsistent results compared to before. I did find a turnaround template for chibi characters that gave me OK-ish results running it through Canny, but Ms. T kept generating facing the wrong way.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">On another session, I decided to try making Ms. T up in Sonic Forces. I installed it (ProtonDB: Platinum) and loaded my 100% save. I put Ms. T on a white background in GIMP and gave it to ControlNet. Unsurprisingly, OpenPose is not a Sonic fan. It\u2019s trained on human data (now with animals!), but a cartoon kept returning blank outputs until I used a preprocessor called dw_openpose_full, which \u2013while it still doesn\u2019t like cartoon animal people\u2013 did cooperate on Ms. T\u2019s right hand. Most every node else I dragged into place manually. I then demonstrated an ability to pose her left leg.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Character Sheet<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">From there, I opened OBS to record an .MP4 file. I used FFmpg to convert to .gif and loaded it in GIMP to\u2026 my computer slowed to a crawl, but it did comply without a major crash. I tried to crop and delete removed pixels\u2026 another slowdown, GIMP crashed. I adjusted OBS to record just my region of interest. 500+ frames was still a no-fly when each layer only has the changes from the last. I found options to record as .gif and record as slowly as I want. I then separated out my frames with FFmpg, making sure to have a new directory:<\/p>\n\n\n\n<pre class=\"wp-block-verse\">ffmpeg -i fileName.gif -vf fps=1 frame_%04d.jpg<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">I chose ten frames and arranged them in a 5&#215;2 grid in GIMP. I then manually aligned OpenPose skeletons for each and sent that off to ControlNet. Immediately, my results improved. I got another big boost by using my grid of .gif frames, but in both cases Ms. T kept eyes and feet facing toward the viewer \u2013 even when her skeleton was pointed the other way. My next thought was to clean up the background on the grid, but compression artifacts got in the way.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Start over. I made a new character with joint visibility and background removal in mind. She looked ridiculous running through a level, but I got her knee placement by moving diagonal toward the camera and jumping. I then put eight new screenshots in a grid. Select-by-color had the background cleared in a minute. I then used Canny for silhouettes intending to reinforce OpenPose. I still got characters generating the wrong way.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Takeaway<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">This week has had a lot of interplay between study and play. While it\u2019s fun to run the AI and cherry pick what comes out, the prospect of better consistently keeps me coming back to improve my \u201cjungle gym\u201d as I prepare to generate LoRa training images.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Final Question<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">The challenge that broke this topic into multiple parts is getting characters to face away from the viewer. Have you ever gotten this effect while making character sheets?<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">I look forward to hearing from you in the comments below or on my <a href=\"https:\/\/letsbuildroboticswithshadow8472.com\/index.php\/discord-invite\/\" target=\"_blank\" rel=\"noreferrer noopener\">Socials<\/a>!<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Good Morning from my Robotics Lab! This is Shadow_8472, and today I am on a quest to generate consistent characters using AI. Let\u2019s get started! It all started with wanting to learn how to make my own \u201cconsistent characters\u201d I can summon with a keyword in my prompt. Before I can train the AI to &hellip; <\/p>\n<p class=\"link-more\"><a href=\"https:\/\/letsbuildroboticswithshadow8472.com\/index.php\/2024\/05\/27\/self-hosted-ai-consistent-characters-part-1\/\" class=\"more-link\">Continue reading<span class=\"screen-reader-text\"> &#8220;Self-Hosted AI Consistent Characters: Part 1&#8221;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_bbp_topic_count":0,"_bbp_reply_count":0,"_bbp_total_topic_count":0,"_bbp_total_reply_count":0,"_bbp_voice_count":0,"_bbp_anonymous_reply_count":0,"_bbp_forum_subforum_count":0,"footnotes":""},"categories":[268,355,365],"tags":[272,368,367,366,369,271],"class_list":["post-1382","post","type-post","status-publish","format-standard","hentry","category-ai-image-generation","category-artificial-intelligence","category-image-generation","tag-ai-art","tag-character-sheet","tag-consistent-character","tag-controlnet","tag-openpose","tag-stable-diffusion"],"_links":{"self":[{"href":"https:\/\/letsbuildroboticswithshadow8472.com\/index.php\/wp-json\/wp\/v2\/posts\/1382","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/letsbuildroboticswithshadow8472.com\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/letsbuildroboticswithshadow8472.com\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/letsbuildroboticswithshadow8472.com\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/letsbuildroboticswithshadow8472.com\/index.php\/wp-json\/wp\/v2\/comments?post=1382"}],"version-history":[{"count":1,"href":"https:\/\/letsbuildroboticswithshadow8472.com\/index.php\/wp-json\/wp\/v2\/posts\/1382\/revisions"}],"predecessor-version":[{"id":1383,"href":"https:\/\/letsbuildroboticswithshadow8472.com\/index.php\/wp-json\/wp\/v2\/posts\/1382\/revisions\/1383"}],"wp:attachment":[{"href":"https:\/\/letsbuildroboticswithshadow8472.com\/index.php\/wp-json\/wp\/v2\/media?parent=1382"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/letsbuildroboticswithshadow8472.com\/index.php\/wp-json\/wp\/v2\/categories?post=1382"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/letsbuildroboticswithshadow8472.com\/index.php\/wp-json\/wp\/v2\/tags?post=1382"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}