File size: 4,845 Bytes
3e961ec |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 |
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()
|