Python Code 2
Python Code 2
class AIGalleryApp:
def __init__(self):
# Initialize the main window
ctk.set_appearance_mode("system")
ctk.set_default_color_theme("blue")
self.root = ctk.CTk()
self.root.title("AI Gallery Pro")
self.root.geometry("1400x900")
self.root.minsize(1000, 700)
# Initialize variables
self.current_images = []
self.current_index = 0
self.albums = {}
self.settings = self.load_settings()
self.face_encodings = {}
# Initialize database
self.init_database()
def init_database(self):
"""Initialize SQLite database for storing image metadata"""
self.conn = sqlite3.connect('gallery.db')
cursor = self.conn.cursor()
cursor.execute('''
CREATE TABLE IF NOT EXISTS images (
id INTEGER PRIMARY KEY,
path TEXT UNIQUE,
filename TEXT,
album TEXT,
tags TEXT,
date_added TEXT,
file_hash TEXT,
ai_description TEXT,
face_count INTEGER,
dominant_colors TEXT
)
''')
cursor.execute('''
CREATE TABLE IF NOT EXISTS albums (
id INTEGER PRIMARY KEY,
name TEXT UNIQUE,
color TEXT,
created_date TEXT,
description TEXT
)
''')
self.conn.commit()
def create_gui(self):
"""Create the main GUI interface"""
# Main container
self.main_frame = ctk.CTkFrame(self.root)
self.main_frame.pack(fill="both", expand=True, padx=10,
pady=10)
# Title
self.title_label = ctk.CTkLabel(
self.top_frame,
text="AI Gallery Pro",
font=ctk.CTkFont(size=24, weight="bold")
)
self.title_label.pack(side="left", padx=20)
# Search bar
self.search_var = tk.StringVar()
self.search_entry = ctk.CTkEntry(
self.top_frame,
placeholder_text="Search images...",
textvariable=self.search_var,
width=300
)
self.search_entry.pack(side="right", padx=5)
self.search_entry.bind('<KeyRelease>', self.search_images)
# AI Features button
self.ai_button = ctk.CTkButton(
self.top_frame,
text="AI Features",
command=self.show_ai_features
)
self.ai_button.pack(side="right", padx=5)
# Albums section
self.albums_label = ctk.CTkLabel(
self.sidebar,
text="Albums",
font=ctk.CTkFont(size=18, weight="bold")
)
self.albums_label.pack(pady=10)
# Album list
self.album_frame = ctk.CTkScrollableFrame(self.sidebar,
height=200)
self.album_frame.pack(fill="x", padx=10, pady=5)
# Folders section
self.folders_label = ctk.CTkLabel(
self.sidebar,
text="Folders",
font=ctk.CTkFont(size=18, weight="bold")
)
self.folders_label.pack(pady=(20, 10))
# Image grid/viewer
self.create_image_viewer()
def create_image_viewer(self):
"""Create the main image viewing area"""
# View mode buttons
self.view_frame = ctk.CTkFrame(self.image_area)
self.view_frame.pack(fill="x", padx=10, pady=5)
self.grid_btn = ctk.CTkButton(
self.view_frame,
text="Grid View",
command=self.switch_to_grid
)
self.grid_btn.pack(side="left", padx=5)
self.single_btn = ctk.CTkButton(
self.view_frame,
text="Single View",
command=self.switch_to_single
)
self.single_btn.pack(side="left", padx=5)
self.current_view = "grid"
def create_dropdown_menu(self):
"""Create the dropdown menu"""
self.dropdown = ctk.CTkToplevel(self.root)
self.dropdown.withdraw() # Hide initially
self.dropdown.overrideredirect(True)
self.dropdown.configure(fg_color=("gray90", "gray20"))
# Menu items
menu_items = [
("Settings", self.open_settings),
("AI Features", self.show_ai_features),
("Import Images", self.import_folder),
("Export Album", self.export_album),
("Backup Data", self.backup_data),
("About", self.show_about)
]
def toggle_menu(self):
"""Toggle the dropdown menu"""
if self.dropdown.winfo_viewable():
self.dropdown.withdraw()
else:
# Position dropdown below menu button
x = self.root.winfo_x() + 20
y = self.root.winfo_y() + 80
self.dropdown.geometry(f"200x250+{x}+{y}")
self.dropdown.deiconify()
def open_settings(self):
"""Open settings dialog"""
settings_window = ctk.CTkToplevel(self.root)
settings_window.title("Settings")
settings_window.geometry("600x500")
settings_window.transient(self.root)
# Appearance settings
appearance_frame = ctk.CTkFrame(notebook)
notebook.add(appearance_frame, text="Appearance")
# Theme selection
theme_label = ctk.CTkLabel(appearance_frame, text="Theme:")
theme_label.pack(pady=10)
theme_var = tk.StringVar(value=self.settings.get('theme',
'system'))
theme_menu = ctk.CTkOptionMenu(
appearance_frame,
values=["light", "dark", "system"],
variable=theme_var,
command=self.change_theme
)
theme_menu.pack(pady=5)
# Color theme
color_label = ctk.CTkLabel(appearance_frame, text="Color
Theme:")
color_label.pack(pady=10)
color_var =
tk.StringVar(value=self.settings.get('color_theme', 'blue'))
color_menu = ctk.CTkOptionMenu(
appearance_frame,
values=["blue", "green", "dark-blue"],
variable=color_var,
command=self.change_color_theme
)
color_menu.pack(pady=5)
# AI Settings
ai_frame = ctk.CTkFrame(notebook)
notebook.add(ai_frame, text="AI Settings")
self.api_entry = ctk.CTkEntry(
ai_frame,
placeholder_text="Enter your Gemini API key",
width=400,
show="*"
)
self.api_entry.pack(pady=5)
self.api_entry.insert(0, self.settings.get('gemini_api_key',
''))
# General Settings
general_frame = ctk.CTkFrame(notebook)
notebook.add(general_frame, text="General")
# Auto-backup
backup_var =
tk.BooleanVar(value=self.settings.get('auto_backup', False))
backup_check = ctk.CTkCheckBox(
general_frame,
text="Enable automatic backup",
variable=backup_var
)
backup_check.pack(pady=10)
# Thumbnail size
thumb_label = ctk.CTkLabel(general_frame, text="Thumbnail
Size:")
thumb_label.pack(pady=10)
thumb_var =
tk.StringVar(value=str(self.settings.get('thumbnail_size', 200)))
thumb_slider = ctk.CTkSlider(
general_frame,
from_=100,
to=400,
variable=thumb_var
)
thumb_slider.pack(pady=5)
def show_ai_features(self):
"""Show AI features dialog"""
ai_window = ctk.CTkToplevel(self.root)
ai_window.title("AI Features")
ai_window.geometry("800x600")
ai_window.transient(self.root)
# AI Features list
ai_features = [
("Generate Image", "Create new images using AI",
self.ai_generate_image),
("Auto Tag Images", "Automatically tag images with AI",
self.ai_auto_tag),
("Face Recognition", "Detect and group faces",
self.ai_face_recognition),
("Object Detection", "Identify objects in images",
self.ai_object_detection),
("Color Analysis", "Analyze dominant colors",
self.ai_color_analysis),
("Duplicate Detection", "Find duplicate images",
self.ai_duplicate_detection),
("Image Enhancement", "Enhance image quality",
self.ai_enhance_image),
("Style Transfer", "Apply artistic styles",
self.ai_style_transfer),
("Background Removal", "Remove image backgrounds",
self.ai_remove_background),
("Image Upscaling", "Increase image resolution",
self.ai_upscale_image),
("Scene Classification", "Classify image scenes",
self.ai_scene_classification),
("Text Extraction", "Extract text from images",
self.ai_text_extraction),
("Emotion Detection", "Detect emotions in faces",
self.ai_emotion_detection),
("Image Similarity", "Find similar images",
self.ai_image_similarity),
("Auto Cropping", "Intelligently crop images",
self.ai_auto_crop),
("Noise Reduction", "Remove image noise",
self.ai_noise_reduction),
("Image Colorization", "Colorize black & white images",
self.ai_colorize),
("Content Moderation", "Detect inappropriate content",
self.ai_content_moderation),
("Image Captioning", "Generate image descriptions",
self.ai_image_captioning),
("Smart Albums", "Create AI-powered albums",
self.ai_smart_albums)
]
title_label = ctk.CTkLabel(
feature_frame,
text=title,
font=ctk.CTkFont(size=16, weight="bold")
)
title_label.pack(anchor="w", padx=10, pady=(10, 0))
desc_label = ctk.CTkLabel(
feature_frame,
text=description,
font=ctk.CTkFont(size=12)
)
desc_label.pack(anchor="w", padx=10)
action_btn = ctk.CTkButton(
feature_frame,
text="Run",
command=command,
width=80
)
action_btn.pack(anchor="e", padx=10, pady=10)
# AI Feature implementations
def ai_generate_image(self):
"""Generate image using Gemini API"""
dialog = ctk.CTkInputDialog(
text="Enter image description:",
title="AI Image Generation"
)
prompt = dialog.get_input()
if prompt:
self.show_loading("Generating image...")
threading.Thread(
target=self._generate_image_thread,
args=(prompt,)
).start()
os.makedirs("generated_images", exist_ok=True)
def ai_auto_tag(self):
"""Automatically tag images using AI"""
if not self.current_images:
messagebox.showwarning("Warning", "No images loaded")
return
self.show_loading("Analyzing images...")
threading.Thread(target=self._auto_tag_thread).start()
def _auto_tag_thread(self):
"""Auto-tag images in separate thread"""
try:
for img_path in self.current_images:
# Simulate AI tagging
tags = self._analyze_image_content(img_path)
self._save_image_tags(img_path, tags)
except Exception as e:
self.root.after(0, lambda: self.hide_loading())
self.root.after(0, lambda: messagebox.showerror(
"Error",
f"Failed to tag images: {str(e)}"
))
def ai_face_recognition(self):
"""Perform face recognition on images"""
if not self.current_images:
messagebox.showwarning("Warning", "No images loaded")
return
self.show_loading("Detecting faces...")
threading.Thread(target=self._face_recognition_thread).start()
def _face_recognition_thread(self):
"""Face recognition in separate thread"""
try:
face_groups = {}
if not matched:
# Create new group
group_id = len(face_groups)
face_groups[group_id] = [encoding]
except Exception as e:
self.root.after(0, lambda: self.hide_loading())
self.root.after(0, lambda: messagebox.showerror(
"Error",
f"Face recognition failed: {str(e)}"
))
# Offline Features
def ai_object_detection(self):
"""Detect objects in images (offline)"""
if not self.current_images:
messagebox.showwarning("Warning", "No images loaded")
return
self.show_loading("Detecting objects...")
threading.Thread(target=self._object_detection_thread).start()
def _object_detection_thread(self):
"""Object detection using OpenCV (offline)"""
try:
# Load YOLO or use OpenCV's DNN module
# For demo, we'll simulate object detection
detected_objects = {}
except Exception as e:
self.root.after(0, lambda: self.hide_loading())
self.root.after(0, lambda: messagebox.showerror(
"Error",
f"Object detection failed: {str(e)}"
))
def ai_color_analysis(self):
"""Analyze dominant colors in images (offline)"""
if not self.current_images:
messagebox.showwarning("Warning", "No images loaded")
return
self.show_loading("Analyzing colors...")
threading.Thread(target=self._color_analysis_thread).start()
def _color_analysis_thread(self):
"""Color analysis in separate thread"""
try:
from sklearn.cluster import KMeans
for img_path in self.current_images:
# Load and process image
image = cv2.imread(img_path)
image = cv2.cvtColor(image, cv2.COLOR_BGR_RGB)
except Exception as e:
self.root.after(0, lambda: self.hide_loading())
self.root.after(0, lambda: messagebox.showerror(
"Error",
f"Color analysis failed: {str(e)}"
))
def ai_duplicate_detection(self):
"""Detect duplicate images (offline)"""
if not self.current_images:
messagebox.showwarning("Warning", "No images loaded")
return
self.show_loading("Detecting duplicates...")
threading.Thread(target=self._duplicate_detection_thread).start()
def _duplicate_detection_thread(self):
"""Duplicate detection using image hashing"""
try:
import imagehash
hashes = {}
duplicates = []
for img_path in self.current_images:
try:
# Calculate perceptual hash
with Image.open(img_path) as img:
img_hash = str(imagehash.phash(img))
if img_hash in hashes:
duplicates.append((img_path,
hashes[img_hash]))
else:
hashes[img_hash] = img_path
except Exception:
continue
if duplicates:
self.root.after(0, lambda:
self._show_duplicates_dialog(duplicates))
else:
self.root.after(0, lambda: messagebox.showinfo(
"Result",
"No duplicate images found"
))
except Exception as e:
self.root.after(0, lambda: self.hide_loading())
self.root.after(0, lambda: messagebox.showerror(
"Error",
f"Duplicate detection failed: {str(e)}"
))
def ai_enhance_image(self):
"""Enhance image quality (offline)"""
if not self.current_images:
messagebox.showwarning("Warning", "No images loaded")
return
self.show_loading("Enhancing image...")
threading.Thread(
target=self._enhance_image_thread,
args=(current_img,)
).start()
# Enhance contrast
enhancer = ImageEnhance.Contrast(enhanced)
enhanced = enhancer.enhance(1.2)
# Enhance sharpness
enhancer = ImageEnhance.Sharpness(enhanced)
enhanced = enhancer.enhance(1.1)
# Enhance color
enhancer = ImageEnhance.Color(enhanced)
enhanced = enhancer.enhance(1.1)
except Exception as e:
self.root.after(0, lambda: self.hide_loading())
self.root.after(0, lambda: messagebox.showerror(
"Error",
f"Image enhancement failed: {str(e)}"
))
def ai_remove_background(self):
messagebox.showinfo("Info", "Background removal feature coming
soon!")
def ai_upscale_image(self):
messagebox.showinfo("Info", "Image upscaling feature coming
soon!")
def ai_scene_classification(self):
messagebox.showinfo("Info", "Scene classification feature
coming soon!")
def ai_text_extraction(self):
messagebox.showinfo("Info", "Text extraction feature coming
soon!")
def ai_emotion_detection(self):
messagebox.showinfo("Info", "Emotion detection feature coming
soon!")
def ai_image_similarity(self):
messagebox.showinfo("Info", "Image similarity feature coming
soon!")
def ai_auto_crop(self):
messagebox.showinfo("Info", "Auto cropping feature coming
soon!")
def ai_noise_reduction(self):
messagebox.showinfo("Info", "Noise reduction feature coming
soon!")
def ai_colorize(self):
messagebox.showinfo("Info", "Image colorization feature coming
soon!")
def ai_content_moderation(self):
messagebox.showinfo("Info", "Content moderation feature coming
soon!")
def ai_image_captioning(self):
messagebox.showinfo("Info", "Image captioning feature coming
soon!")
def ai_smart_albums(self):
messagebox.showinfo("Info", "Smart albums feature coming
soon!")
# Helper methods
def show_loading(self, message="Loading..."):
"""Show loading dialog"""
self.loading_window = ctk.CTkToplevel(self.root)
self.loading_window.title("Processing")
self.loading_window.geometry("300x100")
self.loading_window.transient(self.root)
self.loading_window.grab_set()
# Progress bar
progress = ctk.CTkProgressBar(self.loading_window)
progress.pack(pady=10)
progress.configure(mode="indeterminate")
progress.start()
def hide_loading(self):
"""Hide loading dialog"""
if hasattr(self, 'loading_window'):
self.loading_window.destroy()
# Color analysis
colors = img.getcolors(maxcolors=256*256*256)
if colors:
dominant_color = max(colors, key=lambda x: x[0])[1]
if isinstance(dominant_color, tuple) and
len(dominant_color) >= 3:
r, g, b = dominant_color[:3]
if r > 200 and g > 200 and b > 200:
tags.append("bright")
elif r < 50 and g < 50 and b < 50:
tags.append("dark")
return