songMix / Image_Artifact_Visualizer.py
yyy1026's picture
Upload Image_Artifact_Visualizer.py
3e961ec
raw
history blame
4.85 kB
import cv2
import numpy as np
import tkinter as tk
from tkinter import filedialog
from tkinterdnd2 import DND_FILES, TkinterDnD
from PIL import Image, ImageTk
import os
class ImageViewer(TkinterDnD.Tk):
def __init__(self):
super().__init__()
self.title("Image Artifact Visualizer")
self.geometry("800x600")
# キャンバスを作成
self.canvas = tk.Canvas(self, bg="black")
self.canvas.pack(fill=tk.BOTH, expand=True)
# 画像データ
self.image = None
self.tk_image = None
self.zoom_factor = 1.0
self.offset_x = 0
self.offset_y = 0
# マウスドラッグ用
self.start_x = 0
self.start_y = 0
self.is_dragging = False
# イベント設定
self.canvas.bind("<MouseWheel>", self.zoom_image)
self.canvas.bind("<ButtonPress-1>", self.start_drag)
self.canvas.bind("<B1-Motion>", self.do_drag)
self.canvas.bind("<ButtonRelease-1>", self.end_drag)
# ドラッグ&ドロップの設定
self.drop_target_register(DND_FILES)
self.dnd_bind("<<Drop>>", self.on_drop)
# ファイル選択ボタン
btn = tk.Button(self, text="Select Image", command=self.select_file, font=("Arial", 12))
btn.pack(side=tk.BOTTOM, pady=10)
def select_file(self):
file_path = filedialog.askopenfilename(filetypes=[("Image Files", "*.jpg;*.jpeg;*.png;*.webp")])
if file_path:
self.load_image(file_path)
def on_drop(self, event):
file_path = event.data.strip("{}") # パスの前後の{}を削除
if os.path.isfile(file_path):
self.load_image(file_path)
def load_image(self, file_path):
try:
file_path = os.path.normpath(file_path) # 日本語や特殊文字対応
# Pillowで画像を読み込む(OpenCVのimreadの代わり)
img_pil = Image.open(file_path).convert("L") # モノクロ化
img_cv = np.array(img_pil) # OpenCV用に変換
# **アーティファクト強調処理**
img_cv = self.enhance_artifacts(img_cv)
self.image = Image.fromarray(img_cv) # OpenCV → PIL
self.zoom_factor = 1.0
self.offset_x = 0
self.offset_y = 0
self.update_image()
except Exception as e:
print(f"Error loading image: {e}")
def enhance_artifacts(self, img_cv):
"""JPEGノイズやブロックアーティファクトを強調"""
img_blur = cv2.GaussianBlur(img_cv, (3, 3), 0) # ぼかし
img_sharp = cv2.addWeighted(img_cv, 2.5, img_blur, -1.5, 0) # シャープ化
# ヒストグラム平坦化でコントラスト強調
img_eq = cv2.equalizeHist(img_sharp)
return img_eq
def update_image(self):
if self.image:
# 画像のサイズ調整
img_resized = self.image.resize(
(int(self.image.width * self.zoom_factor), int(self.image.height * self.zoom_factor)),
Image.Resampling.LANCZOS
)
self.tk_image = ImageTk.PhotoImage(img_resized)
# キャンバス更新
self.canvas.delete("all")
self.canvas.create_image(
self.offset_x + self.canvas.winfo_width() // 2,
self.offset_y + self.canvas.winfo_height() // 2,
image=self.tk_image,
anchor=tk.CENTER
)
def zoom_image(self, event):
"""マウスホイールでズーム"""
old_zoom = self.zoom_factor
if event.delta > 0:
self.zoom_factor *= 1.1 # ズームイン
else:
self.zoom_factor /= 1.1 # ズームアウト
# ズーム位置の補正
scale_factor = self.zoom_factor / old_zoom
self.offset_x = int(self.offset_x * scale_factor)
self.offset_y = int(self.offset_y * scale_factor)
self.update_image()
def start_drag(self, event):
"""マウスドラッグ開始"""
self.start_x = event.x
self.start_y = event.y
self.is_dragging = True
def do_drag(self, event):
"""マウスドラッグ処理"""
if self.is_dragging:
self.offset_x += event.x - self.start_x
self.offset_y += event.y - self.start_y
self.start_x = event.x
self.start_y = event.y
self.update_image()
def end_drag(self, event):
"""マウスドラッグ終了"""
self.is_dragging = False
if __name__ == "__main__":
app = ImageViewer()
app.mainloop()