시 자판기 - 당신에게 어울리는 인생 시를 선정해 드립니다.
문학 동아리를 인솔하시는 선생님의 아이디어를 기술적으로 구현하기 위해 생성형 AI의 힘을 얻어 제작하였습니다. 버튼을 누르면 '인생 네 컷'처럼 사진이 촬영되고, 사진에 어울리는 시를 한 편 찾아 사진 아래에 흑백 감열지로 출력해 주는 프로그램입니다.
import tkinter as tk
import random
import cv2
from PIL import Image, ImageTk, ImageDraw, ImageFont
import datetime
import os
import pdfkit
import win32print
import win32api
def load_poems(file_path):
with open(file_path, 'r', encoding='utf-8') as file:
content = file.read()
poems = content.split('</시>')
poems = [poem.strip() + '</시>' for poem in poems if poem.strip()]
return poems
def display_random_poem():
selected_poem = random.choice(poems)
poem_label.config(text=selected_poem)
canvas.itemconfig(button_text, text="")
start_countdown(3, selected_poem)
def get_timestamp():
now = datetime.datetime.now()
return f"'{now.year % 100} {now.month} {now.day}'"
def start_countdown(count, selected_poem):
if count > 0:
canvas.delete("countdown")
canvas_image = Image.new("RGBA", (600, 400), (255, 255, 255, 0))
draw = ImageDraw.Draw(canvas_image)
draw.text((300 - 12, 250 - 24), str(count), font=pil_font, fill=(255, 0, 0, 255))
img_tk = ImageTk.PhotoImage(canvas_image)
canvas.create_image(0, 0, anchor=tk.NW, image=img_tk, tags="countdown")
canvas.image = img_tk
root.after(1000, start_countdown, count - 1, selected_poem)
else:
canvas.delete("countdown")
capture_and_display_photo(selected_poem)
def capture_and_display_photo(poem_content):
cap = cv2.VideoCapture(0)
ret, frame = cap.read()
cap.release()
if ret:
resized_frame = cv2.resize(frame, (320, 240))
gray_frame = cv2.cvtColor(resized_frame, cv2.COLOR_BGR2GRAY)
img_pil = Image.fromarray(gray_frame)
draw = ImageDraw.Draw(img_pil)
timestamp = get_timestamp()
draw.text((10, 10), timestamp, font=pil_font, fill=(255))
save_image_and_html(img_pil, poem_content)
img_tk = ImageTk.PhotoImage(img_pil)
photo_label.config(image=img_tk)
photo_label.image = img_tk
canvas.itemconfig(button_text, text="나만의 작품 선택하기")
def save_image_and_html(image, poem_content):
image_filename = f"photo_{datetime.datetime.now().strftime('%Y%m%d%H%M%S')}.png"
abs_image_path = os.path.abspath(image_filename)
image.save(abs_image_path)
html_filename = "photo_and_poem.html"
html_content = f"""
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>사진과 시</title>
<style>
body, html {{
width: 150px;
height: 750px;
margin: 0;
padding: 0;
display: flex;
flex-direction: column;
align-items: center;
background-color: #f0f0f0;
font-family: Arial, sans-serif;
}}
img {{
max-width: 150px;
max-height: 250px;
}}
p {{
width: 150px;
text-align: left;
padding: 10px;
font-size: 14px;
line-height: 1.5;
color: #333;
}}
</style>
</head>
<body>
<!-- 사진을 표시 -->
<img src="file:///{abs_image_path}" alt="Captured Photo">
<!-- 시 내용을 텍스트로 표시 -->
<p>{poem_content.replace('<br>', '<br/>')}</p>
</body>
</html>
"""
with open(html_filename, "w", encoding='utf-8') as html_file:
html_file.write(html_content)
path_wkhtmltopdf = r"C:\Program Files\wkhtmltopdf\bin\wkhtmltopdf.exe"
pdfkit_config = pdfkit.configuration(wkhtmltopdf=path_wkhtmltopdf)
pdf_filename = html_filename.replace(".html", ".pdf")
pdfkit.from_file(html_filename, pdf_filename, configuration=pdfkit_config, options={"enable-local-file-access": ""})
print_pdf(pdf_filename)
def print_pdf(pdf_filename):
abs_path = os.path.abspath(pdf_filename)
printer_name = win32print.GetDefaultPrinter()
win32api.ShellExecute(0, "print", abs_path, None, ".", 0)
def create_round_button(canvas, text, command, x, y, r):
global button_circle, button_text
button_circle = canvas.create_oval(x-r, y-r, x+r, y+r, fill="lightblue", outline="blue")
button_text = canvas.create_text(x, y, text=text, font=("Arial", 12, "bold"), fill="black")
def on_click(event):
command()
canvas.tag_bind(button_circle, "<Button-1>", on_click)
canvas.tag_bind(button_text, "<Button-1>", on_click)
# GUI 생성
root = tk.Tk()
root.title("랜덤 시 선택기")
root.geometry("600x600")
title_font = tkFont.Font(family="Arial", size=32, weight="bold")
pil_font = ImageFont.truetype("C:/Windows/Fonts/arial.ttf", 20)
title_label = tk.Label(root, text="시 자판기", font=title_font, pady=20)
title_label.pack()
canvas = tk.Canvas(root, width=600, height=400)
canvas.pack()
create_round_button(canvas, "나를 위한 시", display_random_poem, 300, 250, 50)
poem_label = tk.Label(root, text="", wraplength=500, justify="left", padx=10, pady=10)
poem_label.pack(pady=20)
poems = load_poems('C:\\Users\\poem.txt')
photo_label = tk.Label(root)
photo_label.pack(pady=10)
root.mainloop()
댓글
댓글 쓰기