서론
이 장은 이미지위에 Text를 쓰는 방법에 대해서 설명한다.
목차
텍스트 색상 설정하기
컬러 이미지의 경우 보통 3개의 채널(R,G,B)로 구성되어 있는데, RGB의 조합으로 색상을 만들 수 있다.
나는 일일이 확인하기 귀찮아서 Enum이라는 것을 사용해 색상 입력을 쉽게하도록 했다.
예를들어 빨강색의 RGB 값으로 접근하고 싶다면 Color.Red.value 등의 형태로 접근하면된다.
class Color(Enum) :
Red = (255, 0, 0)
Green = (0, 255, 0)
Blue = (0, 0, 255)
Yellow = (255, 255, 0)
White = (255, 255, 255)
Orange = (255, 165, 0)
경로 설정하기
이미지에 Text를 쓰기 위해 재료가될 이미지의 경로를 읽어들이고 저장할 경로를 따로 설정해준다.
# 이미지 파일 경로
path = "./fire_sample/"
image_paths = glob.glob(path+"*.jpg")
# save directory
save_dir = './predict'
os.makedirs(save_dir,exist_ok=True)
Text 설정
Text의 크기를 고정시켜서 쓰게 되면 이미지 크기가 너무 크면 작게 보일 것이고 작으면 너무 크게 보일 것이다. 이를 위해서 이미지 크기에 따라 텍스트의 크기를 설정해주는 것이 좋다.
또한 텍스트를 쓰기 위해서는 쓰려는 텍스트의 .ttf 의 확장자를 가지는 폰트 파일이 필요하다.
따라서 먼저 이미지의 크기를 구하고 원하는 비율을 곱해주어 폰트의 크기를 설정해주자.
for i, image_path in enumerate(image_paths) :
# 이미지 불러오기
print(f"Read Image: {image_path}")
im = Image.open(image_path)
# 이미지 크기 구하기
w, h = im.size
# 이미지 크기에 따른 글자 크기 설정
font_size = int(min(w, h)*0.1)
# 폰트 설정
font=ImageFont.truetype("./font/D2Coding.ttf", font_size)
# 색상 설정
color = Color.Red.value
# text 내용
text_context = "Hello World"
🙌 만약 색상을 직접 주거나 랜덤으로 주고 싶다면 아래처럼 작성한다.
# color = (0, 0, 0) 텍스트 색상을 흰색으로 고정 설정
# color = (random.randint(10, 255), random.randint(10, 255), random.randint(10, 255)) # 텍스트 색상을 랜덤으로 설정
Text 위치 설정하기
Text의 색상 폰트 등의 설정이 끝났다면 이제 이 Text를 어디에 위치할 것인지 설정해야한다.
하지만 Text의 내용이 길어짐에 따라 Text의 길이가 달라지니 이 또한 dynamic하게 구현해줘야 한다.
Text의 길이는 어떤 내용이냐에 따라 달라짐으로 그 크기를 먼저 구해준다.
# text 길이에 따른 텍스트의 크기 구하기
text_width, text_height = ImageDraw.Draw(im).textsize(text_context, font=font)
나는 Text를 우측 상단에 넣는 것을 기준으로 포지셔닝 하겠다.
따라서 Text가 너무 우측 상단에 딱 붙을 수 있으니 이미지 가로 세로의 길이 중에서 값이 더 작은 길이에 대해 1%정도 띄워준다.
# 텍스트의 위치가 이미지의 가쪽으로 부터 얕간 띄워지게 조율
x, y = w - text_width - min(w,h)*0.01, min(w,h)*0.01
Text 좌표는 Text의 좌상단을 기준으로 한다.

Text 배경 설정하기
이미지의 색상에 따라서 Text가 안 보일수 있다. 이를 위해 뒤에 배경을 설정해줄 것이다.
배경은 Text의 크기보다 좀 더 커야 함으로 나는 2%의 비율로 설정해줬다.
box_x1, box_y1: 좌측 상단의 좌표box_x2, box_y2: rectangle의 width, height
# 텍스트 배경 그리기 (검정색 배경)
box_x1, box_y1 = x - x*0.02, y - y*0.02
box_x2, box_y2 = x + text_width + x*0.01, y + text_height + y*0.5

그리기
위치 설정이 끝났으면 배경을 그려야 한다. fill의 경우는 배경의 색상 RGB parameter이며 (0, 0, 0)은 검정을 의미한다.
주의할 점은 배경을 먼저 그리고 난 후에 Text를 그려야 Text가 배경 위에 나타나게 된다.
# 배경을 그린다.
draw_rect = ImageDraw.Draw(im)
draw_rect.rectangle((box_x1, box_y1, box_x2, box_y2), fill=(0, 0, 0))
배경을 그리고 난 후 Text를 그린다.
# 텍스트(글자) 쓰기
draw = ImageDraw.Draw(im)
draw.text((x, y), text_context, font=font, fill=color))
그린 이미지를 저장해준다.
# 저장할 이미지 경로+이름 설정 (save_dir/이미지명_i.jpg)
save_image_name = save_dir+'/'+image_path.split('/')[-1].split('.')[0]+'_'+str(i)+'.jpg'
im.save(save_image_name)
전체 코드
from PIL import Image
from PIL import Image, ImageFont, ImageDraw
from IPython.display import display
import glob
from enum import Enum
import os
class Color(Enum) :
Red = (255, 0, 0)
Green = (0, 255, 0)
Blue = (0, 0, 255)
Yellow = (255, 255, 0)
White = (255, 255, 255)
Orange = (255, 165, 0)
# 이미지 파일 경로
path = "./fire_sample/"
image_paths = glob.glob(path+"*.jpg")
# save directory
save_dir = './predict'
os.makedirs(save_dir,exist_ok=True)
for i, image_path in enumerate(image_paths) :
# 이미지 불러오기
print(f"Read Image: {image_path}")
im = Image.open(image_path)
# 이미지 크기 구하기
w, h = im.size
# 글자 크기 설정
font_size = int(min(w, h)*0.1)
# 폰트 설정
font=ImageFont.truetype("./font/D2Coding.ttf", font_size)
# 색상 설정
color = Color.Red.value
# text 내용
text_context = "Hello World"
# text 길이에 따른 텍스트의 크기 구하기
text_width, text_height = ImageDraw.Draw(im).textsize(text_context, font=font)
# 텍스트의 위치가 이미지의 가쪽으로 부터 얕간 띄워지게 조율
x, y = w - text_width - min(w,h)*0.01, min(w,h)*0.01
# color = (0, 0, 0) 텍스트 색상을 흰색으로 고정 설정
# color = (random.randint(10, 255), random.randint(10, 255), random.randint(10, 255)) # 텍스트 색상을 랜덤으로 설정
# 텍스트뒤에 배경 그리기 (검정색 배경)
draw_rect = ImageDraw.Draw(im)
box_x1, box_y1 = x - x*0.02, y - y*0.02
box_x2, box_y2 = x + text_width + x*0.01, y + text_height + y*0.5
draw_rect.rectangle((box_x1, box_y1, box_x2, box_y2), fill=(0, 0, 0))
# 텍스트(글자) 쓰기
draw = ImageDraw.Draw(im)
draw.text((x, y), text_context, font=font, fill=color)
# 저장할 이미지 경로+이름 설정 (save_dir/이미지명_i.jpg)
save_image_name = save_dir+'/'+image_path.split('/')[-1].split('.')[0]+'_'+str(i)+'.jpg'
im.save(save_image_name)결과
왼쪽은 Original Image이고 오른쪽은 그리기 한 후의 이미지다.


Comment