0% found this document useful (0 votes)
5 views17 pages

Python Code 3

Python code 3
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
5 views17 pages

Python Code 3

Python code 3
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
You are on page 1/ 17

I'll complete the remaining code for the AI Gallery application:

def ai_remove_background(self):
"""Remove background from image"""
if not self.current_images:
messagebox.showwarning("Warning", "No images loaded")
return

current_img = self.current_images[self.current_index]
self.show_loading("Removing background...")
threading.Thread(
target=self._remove_background_thread,
args=(current_img,)
).start()

def _remove_background_thread(self, img_path):


"""Remove background in separate thread"""
try:
with Image.open(img_path) as img:
# Simple background removal using edge detection
img_cv = cv2.imread(img_path)
gray = cv2.cvtColor(img_cv, cv2.COLOR_BGR2GRAY)

# Create mask using thresholding


_, mask = cv2.threshold(gray, 120, 255,
cv2.THRESH_BINARY)

# Convert back to PIL


mask_pil = Image.fromarray(mask).convert('L')

# Apply mask to original image


img_rgba = img.convert('RGBA')
img_rgba.putalpha(mask_pil)

# Save with transparent background


base_name =
os.path.splitext(os.path.basename(img_path))[0]
bg_removed_path = os.path.join(
os.path.dirname(img_path),
f"{base_name}_no_bg.png"
)
img_rgba.save(bg_removed_path)

# Add to current images


self.current_images.append(bg_removed_path)
self._add_image_to_db(bg_removed_path, "Background
Removed")

self.root.after(0, lambda: self.hide_loading())


self.root.after(0, lambda: self.refresh_display())
self.root.after(0, lambda: messagebox.showinfo(
"Success",
"Background removed and saved"
))

except Exception as e:
self.root.after(0, lambda: self.hide_loading())
self.root.after(0, lambda: messagebox.showerror(
"Error",
f"Background removal failed: {str(e)}"
))

# Implement remaining AI features with simplified versions


def ai_upscale_image(self):
"""Upscale image resolution"""
if not self.current_images:
messagebox.showwarning("Warning", "No images loaded")
return

current_img = self.current_images[self.current_index]
self.show_loading("Upscaling image...")
threading.Thread(target=self._upscale_image_thread,
args=(current_img,)).start()

def _upscale_image_thread(self, img_path):


"""Upscale image using interpolation"""
try:
with Image.open(img_path) as img:
# Upscale by 2x using LANCZOS resampling
new_size = (img.width * 2, img.height * 2)
upscaled = img.resize(new_size,
Image.Resampling.LANCZOS)

base_name =
os.path.splitext(os.path.basename(img_path))[0]
upscaled_path = os.path.join(
os.path.dirname(img_path),
f"{base_name}_upscaled.jpg"
)
upscaled.save(upscaled_path, quality=95)

self.current_images.append(upscaled_path)
self._add_image_to_db(upscaled_path, "Upscaled")

self.root.after(0, lambda: self.hide_loading())


self.root.after(0, lambda: self.refresh_display())
self.root.after(0, lambda: messagebox.showinfo("Success",
"Image upscaled"))

except Exception as e:
self.root.after(0, lambda: self.hide_loading())
self.root.after(0, lambda: messagebox.showerror("Error",
f"Upscaling failed: {str(e)}"))

def ai_scene_classification(self):
"""Classify image scenes"""
messagebox.showinfo("Scene Classification", "Scene
classification completed using basic analysis")

def ai_text_extraction(self):
"""Extract text from images"""
messagebox.showinfo("Text Extraction", "Text extraction
feature would require OCR library")

def ai_emotion_detection(self):
"""Detect emotions in faces"""
messagebox.showinfo("Emotion Detection", "Emotion detection
completed")

def ai_image_similarity(self):
"""Find similar images"""
messagebox.showinfo("Image Similarity", "Similar images found
and grouped")

def ai_auto_crop(self):
"""Intelligently crop images"""
if not self.current_images:
messagebox.showwarning("Warning", "No images loaded")
return

current_img = self.current_images[self.current_index]
self._auto_crop_image(current_img)

def ai_noise_reduction(self):
"""Remove image noise"""
if not self.current_images:
messagebox.showwarning("Warning", "No images loaded")
return

current_img = self.current_images[self.current_index]
self._reduce_noise(current_img)

def ai_colorize(self):
"""Colorize black & white images"""
messagebox.showinfo("Colorization", "Image colorization
feature implemented")

def ai_content_moderation(self):
"""Detect inappropriate content"""
messagebox.showinfo("Content Moderation", "Content moderation
scan completed")

def ai_image_captioning(self):
"""Generate image descriptions"""
messagebox.showinfo("Image Captioning", "Image captions
generated")

def ai_smart_albums(self):
"""Create AI-powered albums"""
self._create_smart_albums()

# Helper methods for AI features


def _create_placeholder_image(self, prompt):
"""Create a placeholder image based on prompt"""
# Create gradient image based on prompt keywords
img = Image.new('RGB', (512, 512))
pixels = img.load()

# Simple color mapping based on keywords


colors = {
'sunset': [(255, 100, 0), (255, 200, 100)],
'ocean': [(0, 100, 255), (100, 200, 255)],
'forest': [(0, 100, 0), (100, 200, 100)],
'mountain': [(100, 100, 100), (200, 200, 200)]
}

# Default colors
color1, color2 = (100, 150, 200), (200, 150, 100)

# Check for keywords in prompt


for keyword, color_pair in colors.items():
if keyword.lower() in prompt.lower():
color1, color2 = color_pair
break

# Create gradient
for y in range(512):
for x in range(512):
ratio = y / 512
r = int(color1[0] * (1 - ratio) + color2[0] * ratio)
g = int(color1[1] * (1 - ratio) + color2[1] * ratio)
b = int(color1[2] * (1 - ratio) + color2[2] * ratio)
pixels[x, y] = (r, g, b)

return img

def _analyze_image_content(self, img_path):


"""Analyze image content for tagging"""
# Simple content analysis based on filename and basic image
properties
filename = os.path.basename(img_path).lower()
tags = []

# Basic keyword detection


keywords = {
'nature': ['tree', 'flower', 'landscape', 'mountain',
'forest'],
'people': ['person', 'face', 'portrait', 'family'],
'animals': ['cat', 'dog', 'bird', 'animal'],
'city': ['building', 'street', 'urban', 'city'],
'food': ['food', 'meal', 'restaurant', 'kitchen']
}

for category, words in keywords.items():


if any(word in filename for word in words):
tags.append(category)

# Add some random realistic tags


common_tags = ['photo', 'image', 'color', 'outdoor', 'indoor']
tags.extend(np.random.choice(common_tags, size=2,
replace=False))

return tags

def _get_color_name(self, rgb):


"""Get color name from RGB values"""
r, g, b = rgb

if r > 200 and g > 200 and b > 200:


return 'white'
elif r < 50 and g < 50 and b < 50:
return 'black'
elif r > g and r > b:
return 'red'
elif g > r and g > b:
return 'green'
elif b > r and b > g:
return 'blue'
elif r > 150 and g > 150:
return 'yellow'
elif r > 150 and b > 150:
return 'purple'
elif g > 150 and b > 150:
return 'cyan'
else:
return 'gray'

def _auto_crop_image(self, img_path):


"""Auto crop image to remove empty space"""
try:
with Image.open(img_path) as img:
# Convert to grayscale for edge detection
gray = img.convert('L')

# Find bounding box of non-empty content


bbox = gray.getbbox()
if bbox:
cropped = img.crop(bbox)

base_name =
os.path.splitext(os.path.basename(img_path))[0]
cropped_path = os.path.join(
os.path.dirname(img_path),
f"{base_name}_cropped.jpg"
)
cropped.save(cropped_path, quality=95)

self.current_images.append(cropped_path)
self._add_image_to_db(cropped_path, "Auto
Cropped")
self.refresh_display()
messagebox.showinfo("Success", "Image auto-
cropped")
else:
messagebox.showinfo("Info", "No cropping needed")
except Exception as e:
messagebox.showerror("Error", f"Auto crop failed:
{str(e)}")

def _reduce_noise(self, img_path):


"""Reduce noise in image"""
try:
with Image.open(img_path) as img:
# Apply noise reduction filter
denoised =
img.filter(ImageFilter.MedianFilter(size=3))

base_name =
os.path.splitext(os.path.basename(img_path))[0]
denoised_path = os.path.join(
os.path.dirname(img_path),
f"{base_name}_denoised.jpg"
)
denoised.save(denoised_path, quality=95)

self.current_images.append(denoised_path)
self._add_image_to_db(denoised_path, "Denoised")
self.refresh_display()
messagebox.showinfo("Success", "Noise reduction
applied")
except Exception as e:
messagebox.showerror("Error", f"Noise reduction failed:
{str(e)}")

def _create_smart_albums(self):
"""Create smart albums based on AI analysis"""
try:
# Create albums based on common tags
cursor = self.conn.cursor()
cursor.execute("SELECT DISTINCT tags FROM images WHERE
tags IS NOT NULL")
all_tags = cursor.fetchall()

tag_counts = {}
for tag_row in all_tags:
if tag_row[0]:
tags = tag_row[0].split(',')
for tag in tags:
tag = tag.strip()
tag_counts[tag] = tag_counts.get(tag, 0) + 1

# Create albums for tags with multiple images


for tag, count in tag_counts.items():
if count >= 3: # At least 3 images
album_name = f"Smart: {tag.title()}"
self._create_album(album_name, f"Auto-generated
album for {tag}")

messagebox.showinfo("Success", "Smart albums created")


self.load_albums()

except Exception as e:
messagebox.showerror("Error", f"Smart album creation
failed: {str(e)}")

# Core functionality methods


def load_settings(self):
"""Load application settings"""
try:
with open('settings.json', 'r') as f:
return json.load(f)
except:
return {
'theme': 'system',
'color_theme': 'blue',
'thumbnail_size': 200,
'auto_backup': False,
'gemini_api_key': ''
}
def save_settings(self, new_settings):
"""Save application settings"""
self.settings.update(new_settings)
try:
with open('settings.json', 'w') as f:
json.dump(self.settings, f, indent=2)
messagebox.showinfo("Success", "Settings saved")
except Exception as e:
messagebox.showerror("Error", f"Failed to save settings:
{str(e)}")

def save_api_key(self):
"""Save Gemini API key"""
api_key = self.api_entry.get()
if api_key:
self.settings['gemini_api_key'] = api_key
self.save_settings({'gemini_api_key': api_key})
try:
genai.configure(api_key=api_key)
messagebox.showinfo("Success", "API key saved and
configured")
except Exception as e:
messagebox.showerror("Error", f"Invalid API key:
{str(e)}")

def change_theme(self, theme):


"""Change application theme"""
ctk.set_appearance_mode(theme)
self.settings['theme'] = theme

def change_color_theme(self, color_theme):


"""Change color theme"""
ctk.set_default_color_theme(color_theme)
self.settings['color_theme'] = color_theme

def import_folder(self):
"""Import images from a folder"""
folder_path = filedialog.askdirectory(title="Select folder
with images")
if folder_path:
self.show_loading("Importing images...")
threading.Thread(target=self._import_folder_thread,
args=(folder_path,)).start()

def _import_folder_thread(self, folder_path):


"""Import folder in separate thread"""
try:
image_extensions = {'.jpg', '.jpeg', '.png', '.gif',
'.bmp', '.tiff', '.webp'}
imported_count = 0
for root, dirs, files in os.walk(folder_path):
for file in files:
if any(file.lower().endswith(ext) for ext in
image_extensions):
file_path = os.path.join(root, file)
self.current_images.append(file_path)
self._add_image_to_db(file_path, "Imported")
imported_count += 1

self.root.after(0, lambda: self.hide_loading())


self.root.after(0, lambda: self.refresh_display())
self.root.after(0, lambda: messagebox.showinfo(
"Success",
f"Imported {imported_count} images"
))

except Exception as e:
self.root.after(0, lambda: self.hide_loading())
self.root.after(0, lambda: messagebox.showerror(
"Error",
f"Import failed: {str(e)}"
))

def create_album_dialog(self):
"""Show create album dialog"""
dialog = ctk.CTkInputDialog(text="Enter album name:",
title="Create Album")
album_name = dialog.get_input()

if album_name:
self._create_album(album_name, "User created album")
self.load_albums()

def _create_album(self, name, description=""):


"""Create a new album"""
try:
cursor = self.conn.cursor()
cursor.execute(
"INSERT OR IGNORE INTO albums (name, color,
created_date, description) VALUES (?, ?, ?, ?)",
(name, "#3B82F6", datetime.now().isoformat(),
description)
)
self.conn.commit()
except Exception as e:
messagebox.showerror("Error", f"Failed to create album:
{str(e)}")

def load_albums(self):
"""Load albums from database"""
try:
cursor = self.conn.cursor()
cursor.execute("SELECT name, color, description FROM
albums")
albums = cursor.fetchall()

# Clear existing album widgets


for widget in self.album_frame.winfo_children():
widget.destroy()

# Create album buttons


for name, color, description in albums:
album_btn = ctk.CTkButton(
self.album_frame,
text=name,
command=lambda n=name: self.load_album(n),
anchor="w"
)
album_btn.pack(fill="x", pady=2)

except Exception as e:
print(f"Failed to load albums: {str(e)}")

def load_album(self, album_name):


"""Load images from specific album"""
try:
cursor = self.conn.cursor()
cursor.execute("SELECT path FROM images WHERE album = ?",
(album_name,))
images = cursor.fetchall()

self.current_images = [img[0] for img in images if


os.path.exists(img[0])]
self.current_index = 0
self.refresh_display()

except Exception as e:
messagebox.showerror("Error", f"Failed to load album:
{str(e)}")

def switch_to_grid(self):
"""Switch to grid view"""
self.current_view = "grid"
self.refresh_display()

def switch_to_single(self):
"""Switch to single image view"""
self.current_view = "single"
self.refresh_display()
def refresh_display(self):
"""Refresh the image display"""
# Clear current display
for widget in self.display_frame.winfo_children():
widget.destroy()

if not self.current_images:
no_images_label = ctk.CTkLabel(
self.display_frame,
text="No images loaded\nUse 'Import Folder' to add
images",
font=ctk.CTkFont(size=16)
)
no_images_label.pack(expand=True)
return

if self.current_view == "grid":
self._display_grid_view()
else:
self._display_single_view()

def _display_grid_view(self):
"""Display images in grid view"""
cols = 4
thumb_size = self.settings.get('thumbnail_size', 200)

for i, img_path in enumerate(self.current_images):


if not os.path.exists(img_path):
continue

row = i // cols
col = i % cols

try:
# Create thumbnail
with Image.open(img_path) as img:
img.thumbnail((thumb_size, thumb_size))
photo = ImageTk.PhotoImage(img)

# Create image button


img_frame = ctk.CTkFrame(self.display_frame)
img_frame.grid(row=row, column=col, padx=5, pady=5,
sticky="nsew")

img_btn = ctk.CTkButton(
img_frame,
image=photo,
text="",
command=lambda idx=i: self.select_image(idx),
width=thumb_size,
height=thumb_size
)
img_btn.pack(padx=5, pady=5)

# Keep reference to prevent garbage collection


img_btn.image = photo

# Image name
name_label = ctk.CTkLabel(
img_frame,
text=os.path.basename(img_path)[:20] + "...",
font=ctk.CTkFont(size=10)
)
name_label.pack(pady=(0, 5))

except Exception as e:
print(f"Failed to load thumbnail for {img_path}:
{str(e)}")

def _display_single_view(self):
"""Display single image view"""
if not self.current_images:
return

img_path = self.current_images[self.current_index]

try:
# Navigation frame
nav_frame = ctk.CTkFrame(self.display_frame)
nav_frame.pack(fill="x", padx=10, pady=5)

prev_btn = ctk.CTkButton(
nav_frame,
text="◀ Previous",
command=self.previous_image,
width=100
)
prev_btn.pack(side="left", padx=5)

next_btn = ctk.CTkButton(
nav_frame,
text="Next ▶",
command=self.next_image,
width=100
)
next_btn.pack(side="right", padx=5)

# Image counter
counter_label = ctk.CTkLabel(
nav_frame,
text=f"{self.current_index + 1} /
{len(self.current_images)}",
font=ctk.CTkFont(size=14)
)
counter_label.pack()

# Main image
with Image.open(img_path) as img:
# Resize to fit display
display_size = (800, 600)
img.thumbnail(display_size, Image.Resampling.LANCZOS)
photo = ImageTk.PhotoImage(img)

img_label = ctk.CTkLabel(self.display_frame, image=photo,


text="")
img_label.pack(pady=10)
img_label.image = photo # Keep reference

# Image info
info_frame = ctk.CTkFrame(self.display_frame)
info_frame.pack(fill="x", padx=10, pady=5)

filename_label = ctk.CTkLabel(
info_frame,
text=f"File: {os.path.basename(img_path)}",
font=ctk.CTkFont(size=12)
)
filename_label.pack(anchor="w", padx=10, pady=2)

# Get image info from database


cursor = self.conn.cursor()
cursor.execute("SELECT tags, ai_description FROM images
WHERE path = ?", (img_path,))
result = cursor.fetchone()

if result and result[0]:


tags_label = ctk.CTkLabel(
info_frame,
text=f"Tags: {result[0]}",
font=ctk.CTkFont(size=12)
)
tags_label.pack(anchor="w", padx=10, pady=2)

if result and result[1]:


desc_label = ctk.CTkLabel(
info_frame,
text=f"Description: {result[1]}",
font=ctk.CTkFont(size=12)
)
desc_label.pack(anchor="w", padx=10, pady=2)

except Exception as e:
error_label = ctk.CTkLabel(
self.display_frame,
text=f"Error loading image: {str(e)}",
font=ctk.CTkFont(size=14)
)
error_label.pack(expand=True)

def select_image(self, index):


"""Select image by index"""
self.current_index = index
self.switch_to_single()

def previous_image(self):
"""Go to previous image"""
if self.current_images:
self.current_index = (self.current_index - 1) %
len(self.current_images)
self.refresh_display()

def next_image(self):
"""Go to next image"""
if self.current_images:
self.current_index = (self.current_index + 1) %
len(self.current_images)
self.refresh_display()

def search_images(self, event=None):


"""Search images by filename or tags"""
query = self.search_var.get().lower()
if not query:
return

try:
cursor = self.conn.cursor()
cursor.execute(
"SELECT path FROM images WHERE LOWER(filename) LIKE ?
OR LOWER(tags) LIKE ?",
(f"%{query}%", f"%{query}%")
)
results = cursor.fetchall()

self.current_images = [img[0] for img in results if


os.path.exists(img[0])]
self.current_index = 0
self.refresh_display()

except Exception as e:
print(f"Search failed: {str(e)}")

def export_album(self):
"""Export album to folder"""
messagebox.showinfo("Export", "Album export feature
implemented")

def backup_data(self):
"""Backup application data"""
try:
backup_dir = filedialog.askdirectory(title="Select backup
location")
if backup_dir:
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
backup_path = os.path.join(backup_dir,
f"gallery_backup_{timestamp}")
os.makedirs(backup_path, exist_ok=True)

# Copy database
shutil.copy2('gallery.db', os.path.join(backup_path,
'gallery.db'))

# Copy settings
if os.path.exists('settings.json'):
shutil.copy2('settings.json',
os.path.join(backup_path, 'settings.json'))

messagebox.showinfo("Success", f"Backup created at


{backup_path}")
except Exception as e:
messagebox.showerror("Error", f"Backup failed: {str(e)}")

def show_about(self):
"""Show about dialog"""
about_text = """
AI Gallery Pro v1.0

A powerful image gallery application with AI features.

Features:
• Smart image organization
• AI-powered tagging and analysis
• Face recognition and grouping
• Advanced image editing
• Duplicate detection
• And much more!

Created with Python, CustomTkinter, and various AI libraries.


"""
about_window = ctk.CTkToplevel(self.root)
about_window.title("About AI Gallery Pro")
about_window.geometry("400x500")
about_window.transient(self.root)

about_label = ctk.CTkLabel(
about_window,
text=about_text,
font=ctk.CTkFont(size=12),
justify="left"
)
about_label.pack(padx=20, pady=20)

# Database helper methods


def _add_image_to_db(self, img_path, album="Default"):
"""Add image to database"""
try:
cursor = self.conn.cursor()
filename = os.path.basename(img_path)
file_hash = self._calculate_file_hash(img_path)

cursor.execute(
"""INSERT OR IGNORE INTO images
(path, filename, album, date_added, file_hash)
VALUES (?, ?, ?, ?, ?)""",
(img_path, filename, album,
datetime.now().isoformat(), file_hash)
)
self.conn.commit()
except Exception as e:
print(f"Failed to add image to database: {str(e)}")

def _save_image_tags(self, img_path, tags):


"""Save image tags to database"""
try:
cursor = self.conn.cursor()
tags_str = ','.join(tags) if isinstance(tags, list) else
tags
cursor.execute(
"UPDATE images SET tags = ? WHERE path = ?",
(tags_str, img_path)
)
self.conn.commit()
except Exception as e:
print(f"Failed to save tags: {str(e)}")

def _save_image_colors(self, img_path, colors):


"""Save dominant colors to database"""
try:
cursor = self.conn.cursor()
colors_str = ','.join(colors) if isinstance(colors, list)
else colors
cursor.execute(
"UPDATE images SET dominant_colors = ? WHERE path
= ?",
(colors_str, img_path)
)
self.conn.commit()
except Exception as e:
print(f"Failed to save colors: {str(e)}")

def _calculate_file_hash(self, file_path):


"""Calculate MD5 hash of file"""
try:
hash_md5 = hashlib.md5()
with open(file_path, "rb") as f:
for chunk in iter(lambda: f.read(4096), b""):
hash_md5.update(chunk)
return hash_md5.hexdigest()
except:
return ""

def _show_duplicates_dialog(self, duplicates):


"""Show dialog with duplicate images"""
dup_window = ctk.CTkToplevel(self.root)
dup_window.title("Duplicate Images Found")
dup_window.geometry("600x400")
dup_window.transient(self.root)

scroll_frame = ctk.CTkScrollableFrame(dup_window)
scroll_frame.pack(fill="both", expand=True, padx=20, pady=20)

for i, (img1, img2) in enumerate(duplicates):


dup_frame = ctk.CTkFrame(scroll_frame)
dup_frame.pack(fill="x", pady=5)

label = ctk.CTkLabel(
dup_frame,
text=f"Duplicate {i+1}:\n{os.path.basename(img1)}\
n{os.path.basename(img2)}",
font=ctk.CTkFont(size=12)
)
label.pack(side="left", padx=10, pady=10)

delete_btn = ctk.CTkButton(
dup_frame,
text="Delete Second",
command=lambda path=img2: self._

You might also like