2025. 11. 25. 21:34ㆍAI & DS
해당 코드는 https://github.com/DropThe8bit/EverTale_AI 에서 확인하실 수 있습니다!
오늘은 ControlNet + LoRA + Stable Diffusion을 이용해서
스케치를 추출해 이미지를 생성하는 방법을 알아보겠습니다.
우선, Stable Diffusion에 왜 ControlNet 과 LoRA를 추가해야하는 걸까?
의문이 드실 수 있습니다.
Stable Diffusion은 기본적으로 "텍스트 프롬프트 → 이미지"를 만드는 모델입니다.
예를 들어 "귀여운 고양이 마법사가 하늘을 나는 일러스트" 같은 문장을 넣으면,
모델이 알아서 구도, 포즈, 스타일까지 전부 결정해 버립니다.
이게 장점이자 단점인데요!
텍스트만으로 다양한 이미지를 만들 수 있지만,
구도나 포즈를 정확히 통제하기 어렵고
같은 캐릭터를 여러 장 생성하면 매번 얼굴/스타일이 조금씩 달라지죠.

prompt += ", tribal panther make up, blue on red, side profile, looking away, serious eyes"
prompt += " 50mm portrait photography, hard rim lighting photography--beta --ar 2:3 --beta --upbeta"
HuggingFace Stable Diffusion의 사용법의 설명을 보시면
텍스트 입력만으로
위와 같이 같은 프롬프트에 다양한 구도와 포즈 얼굴이 생성되는 걸 알 수 있어요!
따라서, 우리는 ControlNet과 LoRA를 결합하여
1. ControlNet을 통해 아이의 스케치의 선을 추출하고,
2. LoRA를 통해서 캐릭터의 일관성을 높여볼거에요!
1. 먼저 파이프라인을 설정해줍니다
1-1. ControlNet

lllyasviel/sd-controlnet-scribble 이 모델은 아래 공식 이미지에서 알 수 있듯이 그림선을 추출해줍니다


1-2. Stable Diffusion 모델

Lykno/dreamshaper-8 은 유명한 Stable Diffusion 모델 중 하나인데요!
버전 업그레이드를 거듭해온 모델입니다!
제가 사용한 v8 모델은 최신 모델로 리얼리즘과 애니메이션 둘 다 일정수준이상의 성능을 내는 하이브리드 모델입니다.
https://huggingface.co/Lykon/dreamshaper-8
1-3. LoRA

LoRA 모델은 아주 다양한 종류가 존재합니다.
원하는 느낌에 가장 적합한 이미지들을 학습시킨 모델을 선택해주시면 됩니다.

civitai 사이트에 들어가 보시면 다양한 LoRA 모델을 확인할 수 있습니다!
저는 아래의 anime-screencap-stype-lora 모델을 선택했습니다
https://civitai.com/models/4982/anime-screencap-style-lora

LoRA 적용전 뭉개지거나 기형적으로 나왔던 이목구비가 개선되기를 기대해봅시다!
다시봐도 LoRA 적용 전 얼굴은 깨지고 살짝 무섭네요...

2. 스케치 이미지 준비하기
이제 사용할 스케치 이미지를 준비해볼게요

저는 푸릇푸릇한 자연 배경에
뒷 배경엔 나무가 있고,
나비가 날아다니고,
중앙에 요정 소녀를 배치하고 싶어요
(저의 부족한 그림 실력은 눈 감아주세요ㅠㅠ)
3. 프롬프트 입력하기
프롬프트의 구성은 크게 2가지로 나뉩니다.
1. 이미지 퀄리티를 올리기위한 기본 프롬프트
2. 내가 그린 스케치를 설명하는 프롬프트
3. 제외하고 싶은 부정 프롬프트
3-1. 이미지 퀄리티를 올리기 위한 기본 프롬프트
whimsical mood, ((adventurous whimsical tone)), magical atmosphere, soft pastel palette,
sense of discovery, wonder, child friendly, storybook, ultra detailed, dreamy cheerful atmosphere,
anime style, anime face, soft light, pastel color, soft shading, masterpiece, best quality
저는 이렇게 기본 프롬프트를 구성했어요.
저는 동화책과 같은 실사보다는 따뜻한 그림체를 만들고 싶어서 위 처럼 구성했어요!
3-2. 내가 그린 스케치를 설명하는 프롬프트
Diagonal path fairy, trees and grass, butterflies fluttering
StableDiffusion 모델은 아무래도 다른 AI 모델들이 그렇듯이
영어 프롬프트에서 최적화 성능을 내기 때문에 영어 프롬프트를 입력해줍니다!
3-3. 제외하고 싶은 부정 프롬프트
"nsfw, nudity, naked, explicit, erotic, sensual, suggestive, sexual, cleavage, lingerie, underwear, "
"swimsuit, bikini, see-through, revealing outfit, exposed skin, body focus, fetish, lewd, "
"kissing, intimate pose, provocative pose, bed scene, bedroom suggestive, "
"adult content, 18+, hentai, porn, obscene, "
"bad anatomy, bad hands, extra fingers, lowres, blurry, deformed, mutated, cropped, poorly drawn, asymmetrical eyes"
부정 프롬프트도 아주 중요한 부분이에요
왜냐하면 nsfw, nudity, sexaul 같은 부정 프롬프트를 넣어서
성인물 이미지나 부적절한 이미지를 필터링 할 수 있어요
학습용 이미지는 다양한 종류의 방대한 이미지를 학습하기 때문에
부적절한 이미지를 프롬프팅 과정에서 걸러주는 것이 중요해요!
특히, 애니메이션 이미지의 경우엔 신체가 강조된 경우가 많기 때문에
타겟에 따라서 입력해주어야해요!
또 중요한 부분이
bad hands, extra fingers 와 같은 신체의 기형을 막아주는
프롬프트를 입력해야해요
왜냐하면 손가락, 발가락 같은 부분은 AI가 디데일하게 생성하기가 어려울 수 있어요
그래서 프롬프팅 과정에서 이 부분을 중심으로 신경을 써라!
하고 한번더 인지시켜주는 거랍니다!
4. 파이프라인을 로드 및 실행 - 이미지를 생성

이제 최종 파이프라인을 구성하고 실행해 이미지를 생성해볼거에요
위 코드에서
1. sketch_image에 위에서 준비한 스케치 이미지가 들어가고
2. prompt에는 우리가 설정한 긍정 프롬프트(1,2 프롬프트가 들어가고)
3. negative_prompt에는 제거하고 싶은 부정 프롬프트가 들어가요
그리고 image의 사이즈도 설정할 수 있답니다!
width, height를 통해서 설정할 수 있고 저는 1024, 1024로 설정해주었어요
값이 높을 수록 해상도가 높고 정교한 이미지가 생성돼요
가진 컴퓨터의 GPU 스펙에 따라서 이미지 생성시간이 오래걸릴 수 있으니
768, 768 정도로 설정해주셔도 됩니다!
또 하이퍼파라미터를 설정해주어야하는데요
guidance_scale은 프롬프트를 얼마나 강하게 반영할지
controlnet_conditioning_scale은 스케치를 얼마나 강하게 반영할지를
결정하는 하이퍼파라미터에요
저는 0.5 단위로 실험을 해보고 최종적으로 12.5, 0.8로 설정해주었습니다!




확실히 LoRA를 적용하고 나니 LoRA 모델의 이목구비가 잘 적용되었네요!
첫번째 이미지 부터 guidance_scale을 12.5, 12, 11.5, 11로 설정했는데 11에서는 이미지가 무너지는 것을 확인할 수 있습니다
제가 그린 그림의 결과도 볼까요?



대각선 길과, 풀, 나비, 그리고 배경의 나무들도 잘 구현이 되었네요!
얼굴이 작게 그려진 경우는 크게 그려진 그림보다 확실히 퀄리티가 낮지만,
그래도 LoRA 적용 전보다는 뚜렷하게 표현이 되고 있는것 같아요
아래는 제가 다양하게 실험해본 결과인데, 함께 첨부해볼게요!



Magical girls waving, heart background, star-shaped hats, school interior, clean outlines,
((warm cheerful tone)), playful cooperative mood, bright friendly colors, laughter and smiles,
child friendly, storybook, ultra detailed, dreamy cheerful atmosphere, anime style, anime face,
soft light, pastel color, soft shading, masterpiece, best quality
배경은 그림 실력의 한계로 Stable Diffusion에게 바닷속으로 만들어달라고 요청했어요😅



처음엔 HuggingFace가 뭔지
모델은 어떻게 로드하고 파이프라인은 어떻게 구성해야할지 어렵게만 느껴지지만
일단 시도해보면 재밌고 수월하게 구현하실 수 있답니다 🥰
(+팁) API로 구현하시면 당연히 서비스에서도 사용이 가능합니다ㅎㅎ
아이가 업로드한 스케치 + 캐릭터 정보를 이용해서 AI가 캐릭터 이미지를 만들어주는 API

1. 클라이언트에서 스케치 이미지와 이름/나이/성격 같은 정보를 POST로 보냅니다.
2. FastAPI 엔드포인트(/init-character-image)가 이 요청을 받습니다.
3. 이미지를 바이트로 읽어서 서비스 레이어의 generate_init_character_image() 함수에 넘깁니다.
4. 이 함수 안에서
- 이미지를 전처리하고
- 텍스트 프롬프트를 만들고
- Stable Diffusion + ControlNet + LoRA 파이프라인으로 이미지를 생성한 뒤
- S3에 업로드하고 URL을 반환합니다.
5. 최종적으로 API는 {"image_url": "..."} 형태의 JSON을 응답으로 돌려줍니다.
실제 이미지 생성의 핵심인 Stable Diffusion + ControlNet + LoRA를 호출하는 핵심 함수

이 함수는 아이가 그린 스케치 한 장을 “완성 캐릭터 일러스트”로 바꿔 주는 핵심 로직이라고 볼 수 있습니다!
먼저 클라이언트에서 넘어온 스케치 이미지와
주인공 정보을 합쳐서 캐릭터 전용 프롬프트를 한 문장으로 만들어 줍니다.
스케치는 PIL 이미지로 열어서 RGB로 변환하고,
Stable Diffusion이 가장 잘 동작하는 512×512 사이즈로 맞춰 줍니다
그다음 torch.inference_mode()와 amp_autocast() 컨텍스트 안에서
미리 준비해 둔 pipe(Stable Diffusion + ControlNet 파이프라인)를 호출합니다.
이때 우리가 만든 프롬프트와
네거티브 프롬프트,
스케치 이미지,
스텝 수(50),
guidance_scale,
controlnet_conditioning_scale
같은 하이퍼파라미터를 함께 넘겨서
스케치를 따라가면서도 프롬프트 느낌을 잘 살린 이미지를 뽑아내도록 합니다.
생성된 이미지 중 첫 번째 결과를 PNG로 인코딩해서 메모리 버퍼에 저장하고,
마지막으로 S3에 업로드한 뒤 그 이미지 URL을 반환합니다.
이 한 함수가
스케치 → AI 생성 캐릭터 이미지 → 클라이언트가 바로 쓸 수 있는 URL까지를
처리하는 파이프라인입니다!
🥰도움이 되셨기를 바랍니다🥰