혼자 만들면서 공부하는 파이썬 커리큘럼
혼자 만들면서 공부하는 파이썬 - 예스24
“파이썬을 배워서 어디에 활용할 수 있을지 궁금했나요?”나의 신용카드 내역 분석, 우리 아파트 실거래가 시각화해보기, 맛집 지도 웹 앱 만들기 등 생활 속 15가지 파이썬 프로젝트를 직접 완
www.yes24.com
https://www.yes24.com/product/goods/142258696
2주차(25.07.07 - 07.13) Chapter 03 이미지 콜라주
기본미션
▶ Ch.03(03-1, 03-2) 이미지 가공(크기 변경, 합성) 후 결과 화면 캡처하기
[03-1 이미지 불러오기]
[03-2 이미지 가공하기]
PIL.Image 모듈의 함수 open(), new()를 사용하여 생성된 Image 객채는
다음과 같은 속성을 갖음(이미지의 크기, 형식, 모드 확인 가능)
속성 데이터 타입 설명
Image.filename 문자열 이미지 파일의 경로
Image.format 문자열 이미지 파일의 형식(PNG, JPG)
Image.mode 문자열 이미지의 색상 모드
Image.size 튜플(가로,세로) 이미지의 픽셀 단위 사이즈
Image.info 딕셔너리 이미지와 관련된 데이터
추가미션
▶ Ch.03(03-3) 이미지 콜라주 실행 결과 화면 캡처하기
그리고
[응용하기1]
아이언맨 이미지 16장을 4x4 콜라주로 생성 : 기존 코드를 활용
[응용하기2]
아이언맨 이미지 16장을 4x4 콜라주로 생성 : 클로드 코드 수정하기(폰트 변경, 이미지 랜덤 배열 추가)
from pathlib import Path
from PIL import Image, ImageOps, ImageDraw, ImageFont, ImageEnhance
import os
import random
WORK_DIR = Path(__file__).parent
IMG_DIR, IN_DIR, OUT_DIR = WORK_DIR / "ironman", WORK_DIR / "input", WORK_DIR / "output"
def create_directories():
"""필요한 디렉토리들을 생성합니다."""
for directory in [IMG_DIR, IN_DIR, OUT_DIR]:
directory.mkdir(exist_ok=True)
def apply_dark_filter(img):
"""이미지에 어두운 필터를 적용합니다."""
# 밝기 조절 (0.7 = 30% 어둡게)
brightness_enhancer = ImageEnhance.Brightness(img)
img = brightness_enhancer.enhance(0.7)
# 대비 강화 (1.2 = 20% 대비 증가)
contrast_enhancer = ImageEnhance.Contrast(img)
img = contrast_enhancer.enhance(1.2)
# 색상 채도 조절 (0.9 = 10% 채도 감소로 더 시네마틱하게)
color_enhancer = ImageEnhance.Color(img)
img = color_enhancer.enhance(0.9)
return img
def create_collage():
"""4x4 아이언맨 콜라주를 생성합니다."""
ROWS, COLS = 4, 4
W_IMG, H_IMG = 400, 400
W_BG, H_BG = COLS * W_IMG, ROWS * H_IMG
# 배경 이미지 생성
img_bg = Image.new(mode="RGB", size=(W_BG, H_BG), color=(15, 15, 15)) # 더 어두운 배경
# 이미지 파일들을 가져오기
image_extensions = ['*.jpg', '*.jpeg', '*.png', '*.bmp']
image_paths = []
for ext in image_extensions:
image_paths.extend(Path(IMG_DIR).glob(ext))
if len(image_paths) == 0:
print(f"경고: {IMG_DIR} 디렉토리에 이미지 파일이 없습니다.")
return None
# 이미지 경로들을 랜덤으로 섞기
random.shuffle(image_paths)
print(f"총 {len(image_paths)}개의 이미지를 랜덤으로 배치합니다.")
# 이미지 배치
for idx, path in enumerate(image_paths[:16]): # 최대 16장까지만
try:
img = Image.open(path)
img_fit = ImageOps.fit(img, (W_IMG, H_IMG), method=Image.Resampling.LANCZOS)
# 각 이미지에 어두운 필터 적용
img_fit = apply_dark_filter(img_fit)
# 이미지에 미묘한 테두리 효과 추가
img_with_border = ImageOps.expand(img_fit, border=2, fill=(80, 80, 80))
img_fit = img_with_border.resize((W_IMG, H_IMG), Image.Resampling.LANCZOS)
# 위치 계산
col = idx % COLS
row = idx // COLS
start_x = col * W_IMG
start_y = row * H_IMG
img_bg.paste(img_fit, box=(start_x, start_y))
print(f"이미지 배치: {path.name} -> 위치 ({row+1}, {col+1})")
except Exception as e:
print(f"이미지 처리 중 오류 발생: {path} - {e}")
return img_bg
def add_hero_text(img_raw):
"""이미지 중앙에 'I am Iron man' 텍스트를 추가합니다."""
text = "I am Iron man"
# 폰트 크기를 더 크게 설정
font_size = 140
font_path = IN_DIR / "Pretendard-Bold.ttf"
# 폰트 파일 존재 확인
if not font_path.exists():
print(f"경고: 폰트 파일을 찾을 수 없습니다: {font_path}")
print("시스템 기본 폰트를 사용합니다.")
try:
font = ImageFont.truetype("arial.ttf", size=font_size)
except:
font = ImageFont.load_default()
else:
font = ImageFont.truetype(str(font_path), size=font_size)
# 텍스트 크기 계산
bbox = font.getbbox(text)
text_width = bbox[2] - bbox[0]
text_height = bbox[3] - bbox[1]
WIDTH, HEIGHT = img_raw.size
# 텍스트를 중앙에 배치하기 위한 좌표 계산
text_x = (WIDTH - text_width) // 2
text_y = (HEIGHT - text_height) // 2
# 텍스트 배경을 위한 패딩
pad = 40
bg_x1 = text_x - pad
bg_y1 = text_y - pad
bg_x2 = text_x + text_width + pad
bg_y2 = text_y + text_height + pad
# 반투명 배경 생성
img_bg = Image.new("RGBA", size=img_raw.size, color=(0, 0, 0, 0))
draw_bg = ImageDraw.Draw(img_bg)
# 그라데이션 효과를 위한 배경 (더 세련된 디자인)
draw_bg.rounded_rectangle(
xy=(bg_x1, bg_y1, bg_x2, bg_y2),
radius=20,
fill=(0, 0, 0, 180) # 반투명 검은색
)
# 테두리 효과 추가
draw_bg.rounded_rectangle(
xy=(bg_x1, bg_y1, bg_x2, bg_y2),
radius=20,
outline=(220, 20, 60, 200), # 아이언맨 테마 빨간색
width=3
)
# 이미지 합성
img_final = Image.alpha_composite(img_raw.convert("RGBA"), img_bg)
draw_final = ImageDraw.Draw(img_final)
# 텍스트에 그림자 효과 추가
shadow_offset = 3
draw_final.text(
xy=(text_x + shadow_offset, text_y + shadow_offset),
text=text,
fill=(0, 0, 0, 150), # 그림자
font=font
)
# 메인 텍스트 추가
draw_final.text(
xy=(text_x, text_y),
text=text,
fill=(255, 215, 0), # 금색
font=font
)
return img_final
def main():
"""메인 실행 함수"""
print("🦾 아이언맨 콜라주 생성을 시작합니다...")
# 랜덤 시드 설정 (매번 다른 배치를 원한다면 이 줄을 주석처리)
# random.seed(42) # 같은 배치를 원할 때 주석 해제
# 디렉토리 생성
create_directories()
# 콜라주 생성
collage_img = create_collage()
if collage_img is None:
print("❌ 콜라주 생성에 실패했습니다.")
return
# 기본 콜라주 저장
basic_output = OUT_DIR / f"{Path(__file__).stem}_basic.jpg"
collage_img.save(basic_output, quality=95)
print(f"📸 기본 콜라주 저장: {basic_output}")
# 텍스트 추가된 최종 이미지 생성
final_img = add_hero_text(collage_img)
final_output = OUT_DIR / f"{Path(__file__).stem}_final.jpg"
final_img.convert("RGB").save(final_output, quality=95)
print(f"✨ 최종 이미지 저장: {final_output}")
print("🎉 아이언맨 콜라주 생성이 완료되었습니다! 🦾")
print("💡 팁: 다시 실행하면 이미지가 랜덤으로 다시 배치됩니다!")
if __name__ == "__main__":
main()
'혼공학습단(한빛미디어)' 카테고리의 다른 글
[혼공단14기] 혼자 만들면서 공부하는 파이썬 - 4주차 (7) | 2025.07.25 |
---|---|
[혼공단14기] 혼자 만들면서 공부하는 파이썬 - 3주차 (2) | 2025.07.19 |
[혼공단14기] 혼자 만들면서 공부하는 파이썬 - 1주차 (1) | 2025.07.05 |
[혼공단] 한빛미디어 - 혼공학습단 14기 start (2) | 2025.07.04 |
[혼공단] 혼공학습단 13기 활동 회고(25. 1. 6 ~ 25. 2. 23) (1) | 2025.02.23 |