코에이 삼국지 시리즈의 묘미 중 하나는 본인이 만든 신무장으로 역사 속에서 플레이할 수 있는 점입니다.
하지만 막상 신무장을 만들다보면 유비, 손권, 조조와 같은 주역 인물보다는 떨어지는 조연 수준의 일러스트로 캐릭터를 생성해야하는 것이 매번 아쉬운 점입니다.
요즘은 대 AI의 시대, Stable Diffusion을 활용하여 고품질의 삼국지 13 신무장 일러스트를 만들고 이를 게임에 적용시켜보겠습니다.
1. 학습 데이터 준비
GIGO(Garbage In Garbage Out)라는 말이 있듯, 모델 학습에 있어서 가장 중요한 부분은 학습할 데이터의 준비입니다.
LoRA 학습의 목표는 인게임 일러스트와 비슷한 작화로 주역 인물급의 고품질 일러스트를 생성하는 것입니다.
따라서 삼국지 게임에서 실제로 사용되고 있는 장수들의 데이터를 학습 이미지로 준비합니다.
외국에서 사용하고 있는 RPGViewer 등의 프로그램을 활용하거나 웹에 공개되어있는 일러스트들을 크롤링하여 학습 데이터를 모아줍니다.
저의 경우 학습 이미지가 위와 같은 3단 구성으로 나왔습니다.
이런 이미지가 1000장 가량 있기에 학습에 사용하기 전 우선 전처리 작업을 하겠습니다.
1) 3단 이미지를 분리 후 학습에 사용할 1장만 추출
from PIL import Image
import os
def split_image(image_path, output_folder):
# 이미지 열기
img = Image.open(image_path)
width, height = img.size
# 삼등분 위치 계산
split_width = width // 3
left_img_coordinates = (0, 0, split_width, height)
# 이미지 삼등분 중 가장 왼쪽 이미지만 저장
left_img = img.crop(left_img_coordinates)
output_path = os.path.join(output_folder, f'{os.path.splitext(os.path.basename(image_path))[0]}_left_part.png')
left_img.save(output_path)
input_folder = 'images'
output_folder = 'split_images'
if not os.path.exists(output_folder):
os.makedirs(output_folder)
# 입력 폴더에서 모든 이미지 파일을 처리
for file in os.listdir(input_folder):
if file.lower().endswith(('.png', '.jpg', '.jpeg', '.bmp')):
image_path = os.path.join(input_folder, file)
split_image(image_path, output_folder)
동일한 크기의 이미지가 좌우로 정렬되어있기에 주어진 이미지의 픽셀을 가로로 3등분하여 이 영역을 바탕으로 분할을 진행합니다.
파이썬 코드를 활용하여 작업을 진행하며 pillow 라이브러리가 필요하므로 먼저 명령프롬프트에서 "pip install pillow"를 입력해 설치를 해줍니다.
input_folder, output_folder는 파이썬 코드가 저장된 디렉토리를 시작 영역으로 하여 폴더의 주소를 지정해주면됩니다.
분할을 마치고 보니 크롤링한 파일의 이름이 너무 길어서 가독성이 떨어지므로 아래 코드를 통해 파일의 이름을 "1,2,3..." 의 형태로 바꿔줍니다.
input_folder의 입력값을 본인의 디렉토리 주소에 맞게 수정하는 것도 잊지 않습니다.
import os
def rename_files(input_folder):
files = os.listdir(input_folder)
for index, file in enumerate(sorted(files), start=1):
file_extension = os.path.splitext(file)[1]
old_file_path = os.path.join(input_folder, file)
new_file_path = os.path.join(input_folder, f'{index}{file_extension}')
os.rename(old_file_path, new_file_path)
input_folder = 'your_folder'
rename_files(input_folder)
2) 태깅 작업
학습에 사용할 이미지가 준비되었으면 이제 태깅을 할 차례입니다.
태깅을 하는 방법에는 여러가지가 있으나 저는 Stable Diffusion WebUI의 확장기능으로 제공하는 Tagger를 사용했습니다.
Tagger를 사용하면 아래와 같이 학습 이미지를 설명하는 태깅 파일이 txt 포맷으로 같은 폴더 안에 저장됩니다.
파일을 확인하면 "1boy, male_focus, facial_hair, solo, weapon, sword, cape, helmet, armor, beard, mustache, looking_at_viewer"의 꼴로 태깅작업이 되어있습니다.
3) 학습할 데이터 추출
제가 크롤링한 이미지 파일이 1000개가 넘기에 이를 다 학습에 사용하는 것은 비효율적입니다.
따라서 저는 이 중에서 100개의 학습 데이터를 임의로 추출해서 다른 폴더에 저장하겠습니다.
import os
import random
from shutil import copy2
def copy_random_files(source_folder, target_folder, num_samples=100):
max_number = 0
# 파일 이름에서 가장 큰 번호 찾기
for file in os.listdir(source_folder):
basename, ext = os.path.splitext(file)
if ext.lower() in {'.txt', '.png'}:
try:
num = int(basename)
max_number = max(max_number, num)
except ValueError:
pass
# num_samples 개의 고유한 숫자 무작위 선택
random_samples = random.sample(range(1, max_number + 1), num_samples)
# 선택한 숫자에 해당하는 txt와 png 파일 복사
for num in random_samples:
txt_file = f"{num}.txt"
png_file = f"{num}.png"
if os.path.exists(os.path.join(source_folder, txt_file)) and os.path.exists(os.path.join(source_folder, png_file)):
copy2(os.path.join(source_folder, txt_file), os.path.join(target_folder, txt_file))
copy2(os.path.join(source_folder, png_file), os.path.join(target_folder, png_file))
print(f"Copied: {txt_file}, {png_file}")
source_folder = "source_folder"
target_folder = "target_folder"
if not os.path.exists(target_folder):
os.makedirs(target_folder)
copy_random_files(source_folder, target_folder)
이전에 파일 이름을 "1,2,3,..."의 형태로 정리해놓았기에 이를 활용하여 코드를 작성합니다.
처음 분할할 때와 마찬가지로 "source_folder, target_folder"의 값만 적절히 수정해줍니다.
코드를 파이썬에서 실행하면 아래와 같이 학습할 데이터가 태깅된 상태로 새로운 폴더에 정리됩니다.
'심심풀이 > AI 이미지' 카테고리의 다른 글
삼국지 여성 신무장 이미지(bmp) 샘플 (0) | 2023.08.16 |
---|---|
Stable Diffusion을 활용한 삼국지 13 신무장 편집-이미지 가공 및 적용 (0) | 2023.04.23 |
Stable Diffusion을 활용한 삼국지 13 신무장 편집-이미지 생성 (0) | 2023.04.23 |
Stable Diffusion을 활용한 삼국지 13 신무장 편집-LoRA 학습 (2) (0) | 2023.04.23 |