DINKIssTyle (61.♡.73.102)
2025년 3월 18일 AM 10:12 · 수정됨(11:22)
ekGemma 3의 소개를 보면, 아래와 같은 내용이 있습니다.
예비 인간 선호도 평가가 무엇인지 모르겠지만 o3-mini를 능가한다는 말이 있더라구요.
오프라인 로컬 LLM이 o3-mini 만큼 한다구요??
세계 최고의 단일 가속기 모델로 구축: Gemma 3는 크기에 비해 최첨단 성능을 제공하며, LMArena 리더보드에서 예비 인간 선호도 평가에서 Llama3-405B, DeepSeek-V3 및 o3-mini를 능가합니다. 이를 통해 단일 GPU 또는 TPU 호스트에 적합한 매력적인 사용자 경험을 만들 수 있습니다.
그러면 녀석들이 잘하는 분야인 코딩을 시켜봅시다.
o3-mini와 Gemma 3, 종목은 파이썬 스크립트 작성!
프롬프트는 이렇습니다.
"파이썬 스크립트를 작성하세요. GUI 창 위에 열기 버튼을 좌상단에 위치하게 하세요. 열기 버튼을 누르면 .webp 파일을 불러옵니다. 불러온 webp 파일을 열기 버튼 우상단을 축으로 우하단으로 200px 미리보기 창에 표시합니다. 단 불러온 Webp는 애니메이션일 가능성도 고려해야합니다."
o3-mini 입니다.
다음은 Tkinter와 Pillow(PIL)를 사용하여 요구사항을 구현한 예제 코드입니다. 이 스크립트는 GUI 창 좌상단에 “열기” 버튼을 배치하고, 버튼 클릭 시 .webp 파일을 선택하여 200×200 픽셀 미리보기 창에 표시합니다. 불러온 파일이 애니메이션 WebP일 경우, 프레임을 순차적으로 업데이트하여 애니메이션을 재생합니다.
import tkinter as tk
from tkinter import filedialog
from PIL import Image, ImageTk, ImageSequence
class WebpViewer:
def __init__(self, master):
self.master = master
master.title("WebP Viewer")
master.geometry("500x500") # 창 크기 조정은 필요에 따라
# "열기" 버튼을 좌상단에 배치
self.open_button = tk.Button(master, text="열기", command=self.open_file)
self.open_button.place(x=0, y=0)
# 미리보기 레이블 (미리보기 창 위치는 버튼의 우상단을 기준으로)
# 버튼의 크기를 고려하여 좌표를 조정합니다.
self.preview_label = tk.Label(master, width=200, height=200, bg="gray")
# 버튼의 너비를 얻은 후, 버튼 우측에 배치
self.master.update_idletasks() # 레이아웃 업데이트
btn_width = self.open_button.winfo_width()
self.preview_label.place(x=btn_width, y=0, width=200, height=200)
# 애니메이션 관련 변수
self.frames = []
self.frame_index = 0
self.delay = 100
self.animating = False
def open_file(self):
# 파일 다이얼로그로 webp 파일 선택
file_path = filedialog.askopenfilename(filetypes=[("WebP files", "*.webp")])
if not file_path:
return
# 이미지 열기
try:
im = Image.open(file_path)
except Exception as e:
print("이미지를 열 수 없습니다:", e)
return
# 미리보기 창 크기에 맞게 리사이즈 (비율 유지)
def resize_frame(frame):
frame = frame.copy()
frame.thumbnail((200, 200), Image.ANTIALIAS)
return ImageTk.PhotoImage(frame)
self.frames = []
self.frame_index = 0
# 애니메이션인지 체크
if getattr(im, "is_animated", False) and im.n_frames > 1:
# 모든 프레임을 리스트에 저장합니다.
for frame in ImageSequence.Iterator(im):
self.frames.append(resize_frame(frame))
# 프레임 딜레이를 이미지의 info에서 가져옴 (없으면 100ms)
self.delay = im.info.get('duration', 100)
self.animating = True
self.show_frame()
else:
# 정적 이미지인 경우
photo = resize_frame(im)
self.preview_label.configure(image=photo)
self.preview_label.image = photo # 참조 유지
self.animating = False
def show_frame(self):
if not self.animating:
return
# 현재 프레임을 설정
frame = self.frames[self.frame_index]
self.preview_label.configure(image=frame)
self.preview_label.image = frame # 참조 유지
# 다음 프레임으로 업데이트
self.frame_index = (self.frame_index + 1) % len(self.frames)
self.master.after(self.delay, self.show_frame)
if __name__ == "__main__":
root = tk.Tk()
app = WebpViewer(root)
root.mainloop()
코드 설명
•GUI 배치:
•open_button은 place()를 사용하여 좌상단 (0, 0)에 위치시켰습니다.
•preview_label은 버튼의 너비를 고려하여 버튼의 우상단을 기준으로 (버튼 너비, 0)에 위치시키고, 크기를 200×200으로 지정하였습니다.
•파일 열기 및 이미지 처리:
•파일 다이얼로그를 통해 선택된 .webp 파일을 PIL.Image.open으로 엽니다.
•이미지가 애니메이션인 경우(im.is_animated), ImageSequence.Iterator를 사용해 모든 프레임을 리스트에 저장하고, after() 메서드로 프레임을 주기적으로 업데이트합니다.
•정적 이미지인 경우, 단일 프레임을 미리보기 창에 표시합니다.
이 스크립트를 실행하면, GUI 창이 나타나며 “열기” 버튼을 눌러 .webp 파일을 선택하고, 200px 크기의 미리보기 창에 이미지(또는 애니메이션)가 표시됩니다.
Gemma 3 입니다.
import tkinter as tk
from tkinter import filedialog
from PIL import Image, ImageTk
import webp
class WebpViewer:
def __init__(self, master):
self.master = master
master.title("WebP Viewer")
# 열기 버튼
self.open_button = tk.Button(master, text="열기", command=self.open_webp)
self.open_button.pack(side=tk.LEFT)
# 미리보기 레이블 (초기에는 비어있음)
self.preview_label = tk.Label(master)
self.preview_label.pack(side=tk.RIGHT)
self.webp_image = None # WebP 이미지 객체를 저장할 변수
self.photo_images = [] # 애니메이션 프레임들을 저장할 리스트
def open_webp(self):
file_path = filedialog.askopenfilename(filetypes=[("WebP files", "*.webp")])
if file_path:
try:
# WebP 파일 로드 및 처리
self.load_webp(file_path)
except Exception as e:
print(f"Error loading WebP: {e}")
tk.messagebox.showerror("오류", f"WebP 파일을 불러오는 중 오류가 발생했습니다: {e}")
def load_webp(self, file_path):
try:
# PIL을 사용하여 WebP 이미지 로드 (애니메이션 지원)
img = Image.open(file_path)
if img.format == 'WEBP':
if len(img.info.get('loop', 0)) > 0: # 애니메이션 확인
print("애니메이션 WebP 파일입니다.")
self.display_animated_webp(img)
else:
print("정적 WebP 파일입니다.")
self.display_static_webp(img)
else:
tk.messagebox.showerror("오류", "선택한 파일은 WebP 형식이 아닙니다.")
except Exception as e:
tk.messagebox.showerror("오류", f"WebP 파일을 불러오는 중 오류가 발생했습니다: {e}")
def display_static_webp(self, img):
# 이미지 크기 조정 (200x200)
img = img.resize((200, 200), Image.LANCZOS)
# ImageTk 객체 생성
photo = ImageTk.PhotoImage(img)
# 미리보기 레이블에 표시
self.preview_label.config(image=photo)
self.preview_label.image = photo # Keep a reference! (중요: 이미지 객체를 유지해야 함)
def display_animated_webp(self, img):
try:
# 애니메이션 프레임 추출 및 표시
frames = []
for i in range(img.n_frames):
img.seek(i)
frame = img.copy()
# 이미지 크기 조정 (200x200)
frame = frame.resize((200, 200), Image.LANCZOS)
photo = ImageTk.PhotoImage(frame)
frames.append(photo)
self.photo_images = frames # 프레임 저장
self.animate(0) # 애니메이션 시작
except Exception as e:
tk.messagebox.showerror("오류", f"애니메이션 WebP 처리 중 오류 발생: {e}")
def animate(self, frame_index):
if self.photo_images:
try:
# 미리보기 레이블에 프레임 표시
self.preview_label.config(image=self.photo_images[frame_index])
self.preview_label.image = self.photo_images[frame_index] # Keep a reference!
# 다음 프레임으로 이동 (순환)
next_index = (frame_index + 1) % len(self.photo_images)
self.master.after(50, self.animate, next_index) # 50ms 간격으로 업데이트
except Exception as e:
print(f"Animation error: {e}")
root = tk.Tk()
viewer = WebpViewer(root)
root.mainloop()
코드 설명:
필요한 라이브러리 임포트:
tkinter: GUI 생성filedialog: 파일 선택 대화 상자PIL (Pillow): 이미지 처리 (WebP 지원)webp: WebP 파일 처리
WebpViewer클래스:__init__(self, master): 생성자. GUI 요소를 초기화합니다.open_button: "열기" 버튼을 생성하고open_webp메서드에 연결합니다.preview_label: 미리보기 이미지를 표시할 레이블을 생성합니다. 초기에는 비어 있습니다.webp_image: 로드된 WebP 이미지 객체를 저장하는 변수입니다.photo_images: 애니메이션 WebP의 프레임들을 저장하는 리스트입니다.
open_webp(self): "열기" 버튼을 클릭했을 때 실행되는 메서드입니다.filedialog.askopenfilename()을 사용하여 WebP 파일을 선택합니다.- 선택한 파일 경로가 유효하면
load_webp메서드를 호출하여 파일을 로드하고 처리합니다.
load_webp(self, file_path): WebP 파일을 로드하고 정적 이미지인지 애니메이션 이미지인지 확인합니다.Image.open()을 사용하여 WebP 이미지를 엽니다.img.format == 'WEBP'를 통해 파일이 WebP 형식인지 확인합니다.len(img.info.get('loop', 0)) > 0를 통해 애니메이션 여부를 판단합니다.loop정보가 있으면 애니메이션입니다.- 정적 이미지인 경우
display_static_webp()를 호출하고, 애니메이션 이미지인 경우display_animated_webp()를 호출합니다.
display_static_webp(self, img): 정적 WebP 이미지를 미리보기 레이블에 표시합니다.img.resize((200, 200), Image.LANCZOS)를 사용하여 이미지 크기를 200x200으로 조정합니다.Image.LANCZOS는 고품질 리샘플링 필터입니다.ImageTk.PhotoImage(img)를 사용하여 PIL 이미지를 Tkinter에서 사용할 수 있는PhotoImage객체로 변환합니다.self.preview_label.config(image=photo)를 사용하여 미리보기 레이블에 이미지를 설정합니다.- 중요:
self.preview_label.image = photo를 통해PhotoImage객체에 대한 참조를 유지해야 합니다. 그렇지 않으면 가비지 컬렉션에 의해 이미지 객체가 삭제되어 화면에 표시되지 않을 수 있습니다.
display_animated_webp(self, img): 애니메이션 WebP 이미지를 처리하고 미리보기 레이블에 표시합니다.img.n_frames를 사용하여 이미지의 프레임 수를 가져옵니다.- 각 프레임을 추출하여 크기를 조정하고
PhotoImage객체로 변환하여self.photo_images리스트에 저장합니다. self.animate(0)을 호출하여 애니메이션을 시작합니다.
animate(self, frame_index): 애니메이션 프레임을 순차적으로 표시하는 메서드입니다.self.photo_images리스트에서frame_index에 해당하는 프레임을 가져와 미리보기 레이블에 설정합니다.next_index = (frame_index + 1) % len(self.photo_images)를 사용하여 다음 프레임 인덱스를 계산합니다 (순환).self.master.after(50, self.animate, next_index)를 사용하여 50ms 후에animate메서드를 다시 호출하여 애니메이션을 계속합니다.
GUI 생성 및 실행:
root = tk.Tk(): Tkinter 루트 창을 생성합니다.viewer = WebpViewer(root):WebpViewer클래스의 인스턴스를 생성하고 루트 창에 연결합니다.root.mainloop(): Tkinter 이벤트 루프를 시작하여 GUI를 표시하고 사용자 입력을 처리합니다.
사용 방법:
- 위 코드를 파이썬 파일로 저장합니다 (예:
webp_viewer.py). - 터미널 또는 명령 프롬프트에서 파일을 실행합니다:
python webp_viewer.py - "열기" 버튼을 클릭하고 WebP 파일을 선택합니다.
- 선택한 WebP 파일이 미리보기 레이블에 표시됩니다 (정적 이미지 또는 애니메이션).
주의 사항:
- PIL 설치:Pillow 라이브러리가 설치되어 있어야 합니다. 설치하려면 다음 명령어를 사용하세요:
pip install pillow - WebP 지원:PIL이 WebP를 지원하는지 확인하십시오. 최신 버전의 Pillow는 일반적으로 WebP를 기본적으로 지원합니다.
- 이미지 참조 유지:Tkinter에서 이미지를 표시할 때
PhotoImage객체에 대한 참조를 유지해야 합니다 (예:self.preview_label.image = photo). 그렇지 않으면 가비지 컬렉션에 의해 이미지 객체가 삭제되어 화면에 표시되지 않을 수 있습니다. - 애니메이션 속도:
self.master.after(50, self.animate, next_index)의 50ms 값은 애니메이션 속도를 제어합니다. 값을 변경하여 속도를 조정할 수 있습니다. - 오류 처리:코드에 오류 처리를 추가하여 파일 로드 또는 이미지 처리 중에 발생할 수 있는 예외를 처리합니다.
try...except블록을 사용하여 오류를 포착하고 사용자에게 적절한 메시지를 표시하는 것이 좋습니다. - WebP 라이브러리:일부 시스템에서는 WebP 지원을 위해 추가적인 라이브러리가 필요할 수 있습니다. 문제가 발생하면 운영 체제 및 Python 버전에 맞는 WebP 라이브러리를 설치해야 할 수도 있습니다.
o1 이 아닌 이상은 몇번 되물어가며 수정해줘야 하는데..
첫시도에서 얼만큼 구현하는지만 확인해보겠습니다.
ChatGPT o3-mini

Gemma 3

둘다 첫 시도는 실패했습니다.
그러면 각각 문제점을 말해주고 수정해보겠습니다.
ChatGPT o3-mini

2트, 성공했습니다. 애니메이션도 잘 작동합니다.
이전에 실패한 원인은 리샘플링 코드를 잘못짰다고 하는군요.
다시 Gemma 3!

WebP는 불러왔으나 애니메이션이 작동하지 않는군요.
다시한번 문제를 해결해 달라고 시도해봅니다.
3트...
하지만.. 여전히 2트와 같은 상태입니다.
이로써 우리가 알수 있는 것은...
ChatGPT o1이나 클로드를 사용해야 한방에 원하는 걸 얻을 확율이 높다! 입니다.

감사합니다.
댓글 (3)
- L
Layne
25.03.18 · 223.♡.85.21
감사합니다. 덕분에 시간을 아꼈습니다 -
DDINKIssTyle
→ Layne 작성자
25.03.18 · 61.♡.73.102
- 샤
샤이닝
25.03.18 · 175.♡.173.229
코딩은 qwq 가 잘한다고 들었습니다
댓글을 작성하려면 이 필요합니다.