🈯 Paddle OCR ile Görüntü İşleme / Çeviri: Adım Adım Rehber
Bu yazıda, kullanıcıların resimlerden metin çıkarıp, bu metni seçilen bir dile çevirebileceği bir OCR (Optical Character Recognition) ve çeviri uygulaması geliştireceğiz. Bu uygulama, görsellerden metin tanıyacak, ardından bu metni çevirecek ve kullanıcılara çevrilmiş metni gösterecek. Uygulamanın özellikleri arasında resim yükleme (Sürükle - Bırak), dil seçme ve metin kopyalama gibi işlevler yer alacak.
1. Gereksinimler ve Kurulum
Bu uygulamayı çalıştırmak için aşağıdaki Python kütüphanelerine ihtiyacınız olacak:
Tkinter: GUI oluşturma
Pillow: Resimleri işleme
PaddleOCR: OCR işlemi yapma
deep_translator: Çeviri yapma
tkinterdnd2: Resim sürükleyip bırakma işlevselliği
pyperclip: Çevrilen metni kopyalama
Tüm gereksinimleri kurmak için aşağıdaki gibi bir bat dosyası oluşturup çalıştırabilirsiniz:
@echo off
python --version >nul 2>&1
if %errorlevel% neq 0 (
echo Python bulunamadi, kurulum baslatiliyor...
echo Python 3.11.5 indiriliyor...
curl -o python-installer.exe https://www.python.org/ftp/python/3.11.5/python-3.11.5-amd64.exe
start /wait python-installer.exe /quiet InstallAllUsers=1 PrependPath=1
del python-installer.exe
echo Python kuruldu.
)
echo Pip guncelleniyor...
python -m pip install --upgrade pip
set "requirements=tkinter pillow paddleocr deep-translator tkinterdnd2 pyperclip"
for %%k in (%requirements%) do (
python -c "import %%k" >nul 2>&1
if %errorlevel% neq 0 (
echo %%k kutuphanesi bulunamadi, kurulum baslatiliyor...
python -m pip install %%k
)
)
echo Tum kutuphaneler kurulu. Uygulamayi calistirabilirsiniz.
pause
2.Uygulama Tasarımı
Uygulamamızda bir kullanıcı arayüzü (GUI) olacak ve bu arayüzde aşağıdaki bileşenler bulunacak:
Görsel Yükleme: Kullanıcılar, desteklenen dosya formatlarında (JPG, PNG, BMP, vb.) bir görsel sürükleyip bırakabilecekler.
Dil Seçimi: Tanınan metnin hangi dilden çevrileceği ayarlanabilecek.
Metin Görüntüleme: Çıkarılan metin ve çevirisi ekranda gösterilecek.
Metin Kopyalama: Kullanıcılar, çevrilen metni kolayca kopyalayabilecekler.
3.Kaynak Kod
Aşağıda, uygulamanın tüm kodunu bulabilirsiniz. Kodda detaylı açıklamalar yer almakta, böylece her adımı detaylıca inceleyebilirsiniz.
# Gerekli kütüphanelerin içe aktarılması
import tkinter as tk
from tkinter import ttk, messagebox
from PIL import Image, ImageTk
from paddleocr import PaddleOCR
from deep_translator import GoogleTranslator
import threading
from tkinterdnd2 import DND_FILES, TkinterDnD
import pyperclip
class FuturisticOCRTranslator:
"""
Fütüristik görünümlü OCR ve çeviri uygulaması.
Görüntülerden metin çıkarımı yapıp farklı dillere çeviri yapar.
"""
def __init__(self):
# Ana pencere ayarları
self.root = TkinterDnD.Tk()
self.root.title("OCR Çeviri")
self.root.geometry("1200x450")
self.root.configure(bg='#0a0a1f')
# Combobox stil ayarları
self.root.option_add('*TCombobox*Listbox.background', '#0a0a1f')
self.root.option_add('*TCombobox*Listbox.foreground', '#00ff8c')
self.root.option_add('*TCombobox*Listbox.selectBackground', '#1a1a3f')
self.root.option_add('*TCombobox*Listbox.selectForeground', '#00ff8c')
# Animasyon ve görüntü değişkenleri
self.border_color_index = 0
self.current_image = None
self.MAX_IMAGE_SIZE = (250, 200) # Maksimum görüntü boyutları
# Uygulama renk paleti
self.colors = {
'bg': '#0a0a1f', # Arka plan rengi
'accent': '#00FF00', # Vurgu rengi
'secondary': '#0066ff', # İkincil renk
'text': '#00ff8c', # Metin rengi
'border': '#00ccff', # Kenarlık rengi
'box_bg': '#0f0f2f', # Kutu arka plan rengi
'button_bg': '#1a1a3f' # Buton arka plan rengi
}
# Ttk stil yapılandırması
self.style = ttk.Style()
self.style.theme_use('default')
self.configure_styles()
# Desteklenen diller sözlüğü
self.languages = {
'Türkçe': 'tr',
'İngilizce': 'en',
'Almanca': 'de',
'Fransızca': 'fr',
'İspanyolca': 'es',
'İtalyanca': 'it',
'Rusça': 'ru',
'Japonca': 'ja',
'Korece': 'ko',
'Çince': 'zh-CN'
}
# Kullanıcı arayüzü ve OCR motorunun kurulumu
self.setup_ui()
self.ocr = PaddleOCR(use_angle_cls=True, lang='en')
self.animate_borders()
def configure_styles(self):
"""Ttk bileşenleri için özel stillerin yapılandırılması"""
# Frame stili
self.style.configure('Cyber.TFrame',
background=self.colors['bg'])
# Etiket stilleri
self.style.configure('Cyber.TLabel',
background=self.colors['bg'],
foreground=self.colors['text'],
font=('Consolas', 11))
self.style.configure('CyberTitle.TLabel',
background=self.colors['bg'],
foreground=self.colors['accent'],
font=('Consolas', 24, 'bold'))
self.style.configure('CyberSubTitle.TLabel',
background=self.colors['bg'],
foreground='#888888',
font=('Consolas', 12))
# Combobox stilleri
self.style.map('TCombobox',
fieldbackground=[('readonly', self.colors['bg'])],
selectbackground=[('readonly', self.colors['bg'])],
selectforeground=[('readonly', self.colors['text'])],
background=[('readonly', self.colors['bg'])],
foreground=[('readonly', self.colors['text'])])
self.style.configure('TCombobox',
background=self.colors['bg'],
fieldbackground=self.colors['bg'],
foreground=self.colors['text'],
arrowcolor=self.colors['accent'],
selectbackground=self.colors['bg'],
selectforeground=self.colors['text'])
# Buton stili
self.style.configure('Cyber.TButton',
background=self.colors['button_bg'],
foreground=self.colors['text'],
borderwidth=2,
font=('Consolas', 10))
def setup_ui(self):
"""Kullanıcı arayüzünün oluşturulması"""
# Ana frame yapısı
self.main_frame = ttk.Frame(self.root, style='Cyber.TFrame')
self.main_frame.pack(fill=tk.BOTH, expand=True, padx=20, pady=10)
# Başlık bölümü
title_frame = ttk.Frame(self.main_frame, style='Cyber.TFrame')
title_frame.pack(fill=tk.X, pady=(0, 10))
title = ttk.Label(title_frame,
text="LEIDENFROST OCR ÇEVİRİ 🈯",
style='CyberTitle.TLabel')
title.pack()
subtitle = ttk.Label(title_frame,
text="Gelişmiş Görüntü Tanıma ve Çeviri Sistemi",
style='CyberSubTitle.TLabel')
subtitle.pack()
# Kontrol paneli
self.control_frame = ttk.Frame(self.main_frame, style='Cyber.TFrame')
self.control_frame.pack(fill=tk.X, pady=(0, 10))
# Dil seçimi bölümü
lang_frame = ttk.Frame(self.control_frame, style='Cyber.TFrame')
lang_frame.pack(pady=5)
# Kaynak dil seçimi
ttk.Label(lang_frame,
text="KAYNAK ⟶",
style='Cyber.TLabel').pack(side=tk.LEFT, padx=(0, 10))
self.source_lang = ttk.Combobox(lang_frame,
values=['Otomatik'],
state='readonly',
style='TCombobox',
width=15)
self.source_lang.pack(side=tk.LEFT, padx=(0, 20))
self.source_lang.set('Otomatik')
# Hedef dil seçimi
ttk.Label(lang_frame,
text="HEDEF ⟶",
style='Cyber.TLabel').pack(side=tk.LEFT, padx=(0, 10))
self.target_lang = ttk.Combobox(lang_frame,
values=list(self.languages.keys()),
state='readonly',
style='TCombobox',
width=15)
self.target_lang.pack(side=tk.LEFT)
self.target_lang.set('Türkçe')
# Combobox olay bağlayıcıları
self.source_lang.bind('<>', lambda e: self.update_combobox_colors(self.source_lang))
self.target_lang.bind('<>', lambda e: self.update_combobox_colors(self.target_lang))
self.root.after(10, lambda: self.update_combobox_colors(self.source_lang))
self.root.after(10, lambda: self.update_combobox_colors(self.target_lang))
# İçerik bölümü
content_frame = ttk.Frame(self.main_frame, style='Cyber.TFrame')
content_frame.pack(fill=tk.BOTH, expand=True)
content_frame.grid_columnconfigure(0, weight=1)
content_frame.grid_columnconfigure(1, weight=1)
# Görüntü bölümü
self.image_frame = tk.Frame(content_frame, bg=self.colors['bg'])
self.image_frame.grid(row=0, column=0, sticky='nsew', padx=(0, 10))
# Animasyonlu kenarlıklar
self.border_frames = []
current_frame = self.image_frame
for i in range(3):
frame = tk.Frame(current_frame, bg=self.colors['border'])
frame.pack(fill=tk.BOTH, expand=True, padx=2, pady=2)
self.border_frames.append(frame)
current_frame = frame
# İç frame
self.inner_frame = tk.Frame(self.border_frames[-1], bg=self.colors['bg'])
self.inner_frame.pack(fill=tk.BOTH, expand=True, padx=2, pady=2)
# Görüntü konteynırı
self.image_container = ttk.Frame(self.inner_frame, style='Cyber.TFrame')
self.image_container.pack(fill=tk.BOTH, expand=True)
# Sürükle-bırak etiketi
self.drop_label = ttk.Label(self.image_container,
text="⤓ RESİM SÜRÜKLE BIRAK ⤓\n\nDesteklenen formatlar: PNG, JPG, JPEG, BMP, GIF\n WEBP, TIFF, TIF, HEIF, HEIC, RAW \n\n Resme tıklayarak tam ekran görüntüle",
style='Cyber.TLabel')
self.drop_label.pack(fill=tk.BOTH, expand=True)
# Görüntü etiketi
self.image_label = ttk.Label(self.image_container, style='Cyber.TLabel')
# Temizle butonu
self.clear_button = tk.Button(self.inner_frame,
text="🗑 RESMİ TEMİZLE",
command=self.clear_image,
bg=self.colors['button_bg'],
fg=self.colors['text'],
activebackground=self.colors['accent'],
activeforeground=self.colors['bg'],
font=('Consolas', 10),
bd=0,
padx=10,
cursor='hand2')
# Sonuç bölümü
result_outer_frame = tk.Frame(content_frame, bg=self.colors['border'])
result_outer_frame.grid(row=0, column=1, sticky='nsew', padx=(10, 0))
self.result_frame = tk.Frame(result_outer_frame, bg=self.colors['box_bg'])
self.result_frame.pack(fill=tk.BOTH, expand=True, padx=2, pady=2)
# Sonuç başlık bölümü
text_header = tk.Frame(self.result_frame, bg=self.colors['box_bg'])
text_header.pack(fill=tk.X, padx=10, pady=5)
ttk.Label(text_header,
text="Çeviri Sonucu:",
style='Cyber.TLabel').pack(side=tk.LEFT)
# Kopyala butonu
copy_button = tk.Button(text_header,
text="📋 KOPYALA",
command=self.copy_text,
bg=self.colors['button_bg'],
fg=self.colors['text'],
activebackground=self.colors['accent'],
activeforeground=self.colors['bg'],
font=('Consolas', 10),
bd=0,
padx=10,
cursor='hand2')
copy_button.pack(side=tk.RIGHT)
# Sonuç metin alanı
self.text_label = tk.Text(self.result_frame,
wrap=tk.WORD,
font=('Consolas', 11),
bg=self.colors['box_bg'],
fg=self.colors['text'],
insertbackground=self.colors['text'],
selectbackground=self.colors['accent'],
selectforeground=self.colors['bg'],
bd=0,
height=10,
padx=10,
pady=10)
self.text_label.pack(fill=tk.BOTH, expand=True)
# Kaydırma çubuğu
scrollbar = tk.Scrollbar(self.result_frame,
orient='vertical',
command=self.text_label.yview,
bg=self.colors['button_bg'],
troughcolor=self.colors['box_bg'],
activebackground=self.colors['accent'])
scrollbar.pack(side=tk.RIGHT, fill=tk.Y)
self.text_label.configure(yscrollcommand=scrollbar.set)
# Sürükle-bırak ve fare olayları
self.drop_label.drop_target_register(DND_FILES)
self.drop_label.dnd_bind('<>', self.handle_drop)
self.inner_frame.bind('', self.on_hover_enter)
self.inner_frame.bind('', self.on_hover_leave)
def update_combobox_colors(self, combobox):
"""Combobox renklerinin güncellenmesi"""
combobox.configure(
foreground=self.colors['text'],
background=self.colors['bg']
)
combobox.event_generate('')
combobox.event_generate('')
def clear_image(self):
"""Görüntüyü ve sonuçları temizleme"""
self.current_image = None
self.image_label.pack_forget()
self.drop_label.pack(fill=tk.BOTH, expand=True)
self.clear_button.pack_forget()
self.text_label.delete(1.0, tk.END)
def copy_text(self):
"""Çeviri sonucunu panoya kopyalama"""
text = self.text_label.get(1.0, tk.END).strip()
pyperclip.copy(text)
# Kopyalama bildirimi
temp_label = tk.Label(self.result_frame,
text="✓ Kopyalandı!",
fg=self.colors['accent'],
bg=self.colors['box_bg'],
font=('Consolas', 10))
temp_label.place(relx=1, rely=0, anchor='ne')
self.root.after(1000, temp_label.destroy)
def animate_borders(self):
"""Kenarlık animasyonunu gerçekleştirme"""
colors = ['#00ccff', '#00ff8c', '#0066ff', '#ff00ff']
for i, frame in enumerate(self.border_frames):
new_color = colors[(i + self.border_color_index) % len(colors)]
frame.configure(bg=new_color)
self.border_color_index = (self.border_color_index + 1) % len(colors)
# Her 1000ms'de bir animasyonu güncelle
self.root.after(1000, self.animate_borders)
def on_hover_enter(self, event):
"""Fare üzerine geldiğinde etiket rengini değiştirme"""
self.drop_label.configure(foreground=self.colors['accent'])
def on_hover_leave(self, event):
"""Fare ayrıldığında etiket rengini eski haline getirme"""
self.drop_label.configure(foreground=self.colors['text'])
def handle_drop(self, event):
"""Sürükle-bırak olayını işleme"""
file_paths = event.data.split()
# Birden fazla dosya kontrolü
if len(file_paths) > 1:
messagebox.showerror("Hata", "Lütfen aynı anda sadece bir resim sürükleyin!")
return
file_path = file_paths[0]
if file_path.startswith('{'):
file_path = file_path[1:-1]
# Desteklenen dosya formatları kontrolü
if not file_path.lower().endswith((
'.png', '.jpg', '.jpeg', '.bmp', '.gif', '.webp',
'.tiff', '.tif','.heif', '.heic', '.raw'
)):
messagebox.showerror("Hata", "Lütfen geçerli bir resim dosyası seçin!")
return
# Geçerli resim dosyası kontrolü
try:
Image.open(file_path)
except:
messagebox.showerror("Hata", "Seçilen dosya geçerli bir resim değil!")
return
self.display_image(file_path)
self.process_image(file_path)
def display_image(self, file_path):
"""Seçilen görüntüyü ekranda gösterme"""
self.drop_label.pack_forget()
self.current_image = Image.open(file_path)
# Görüntü boyutunu hesapla ve yeniden boyutlandır
display_size = self.calculate_display_size(self.current_image)
image = self.current_image.resize(display_size, Image.Resampling.LANCZOS)
photo = ImageTk.PhotoImage(image)
self.image_label.configure(image=photo)
self.image_label.image = photo
self.image_label.pack(expand=True)
self.image_label.bind('', self.show_fullscreen)
self.clear_button.pack(pady=5)
def calculate_display_size(self, image):
"""Görüntünün gösterim boyutunu hesaplama"""
max_width, max_height = self.MAX_IMAGE_SIZE
width, height = image.size
aspect_ratio = width / height
# En-boy oranını koruyarak yeniden boyutlandırma
if width > max_width or height > max_height:
if aspect_ratio > max_width/max_height:
new_width = max_width
new_height = int(max_width / aspect_ratio)
else:
new_height = max_height
new_width = int(max_height * aspect_ratio)
else:
new_width, new_height = width, height
return (new_width, new_height)
def show_fullscreen(self, event=None):
"""Görüntüyü tam ekran gösterme"""
if not self.current_image:
return
# Tam ekran penceresi oluşturma
self.fullscreen_window = tk.Toplevel(self.root)
self.fullscreen_window.attributes('-fullscreen', True)
self.fullscreen_window.configure(bg='black')
self.fullscreen_window.protocol("WM_DELETE_WINDOW", self.close_fullscreen)
self.fullscreen_window.bind('', self.check_escape)
self.fullscreen_window.focus_force()
# Ekran boyutlarına göre görüntüyü ölçeklendirme
screen_width = self.fullscreen_window.winfo_screenwidth()
screen_height = self.fullscreen_window.winfo_screenheight()
aspect_ratio = self.current_image.width / self.current_image.height
if aspect_ratio > screen_width/screen_height:
new_width = screen_width
new_height = int(screen_width / aspect_ratio)
else:
new_height = screen_height
new_width = int(screen_height * aspect_ratio)
# Tam ekran görüntüyü oluşturma ve gösterme
image = self.current_image.resize((new_width, new_height), Image.Resampling.LANCZOS)
photo = ImageTk.PhotoImage(image)
label = tk.Label(self.fullscreen_window, image=photo, bg='black')
label.image = photo
label.pack(expand=True)
label.bind('', lambda e: self.close_fullscreen())
# Bilgi etiketi
info_label = tk.Label(self.fullscreen_window,
text="ESC veya tıklama ile çıkış yapabilirsiniz",
fg='white',
bg='black',
font=('Consolas', 12))
info_label.place(relx=0.5, rely=0.95, anchor='center')
def check_escape(self, event):
"""ESC tuşu kontrolü"""
if event.keysym == 'Escape':
self.close_fullscreen()
def close_fullscreen(self):
"""Tam ekran görüntülemeyi kapatma"""
if hasattr(self, 'fullscreen_window'):
self.fullscreen_window.destroy()
del self.fullscreen_window
def process_image(self, file_path):
"""OCR ve çeviri işlemini gerçekleştirme"""
def process():
try:
# İşlem başlangıç bildirimi
self.text_label.delete(1.0, tk.END)
self.text_label.insert(tk.END, "İşleniyor...\n")
# OCR işlemi
result = self.ocr.ocr(file_path, cls=True)
extracted_text = '\n'.join([line[1][0] for line in result[0]])
# Çeviri işlemi
target = self.languages[self.target_lang.get()]
translator = GoogleTranslator(source='auto', target=target)
translated_text = translator.translate(extracted_text)
# Sonucu gösterme
self.text_label.delete(1.0, tk.END)
self.text_label.insert(tk.END, translated_text)
except Exception as e:
# Hata durumunda kullanıcıyı bilgilendirme
messagebox.showerror("Hata", f"İşlem sırasında bir hata oluştu: {str(e)}")
self.text_label.delete(1.0, tk.END)
self.text_label.insert(tk.END, "İşlem sırasında hata oluştu.")
# İşlemi arka planda başlatma
threading.Thread(target=process, daemon=True).start()
def run(self):
"""Uygulamayı başlatma"""
self.root.mainloop()
# Ana program başlangıcı
if __name__ == "__main__":
app = FuturisticOCRTranslator()
app.run()
4.Uygulama Ekran Görüntüsü
5.Sonuç
PaddleOCR ve DeepTranslator kütüphanesinin gücünü kullanan bu uygulama, özellikle çok dilli belge işleme, yabancı dildeki metinleri hızlıca anlama ve dijital içerik çevirisi gibi ihtiyaçlar için kullanışlı bir araç sunuyor. Açık kaynak kodlu bu projeyi kendi ihtiyaçlarınıza göre özelleştirebilir, geliştirebilir ve farklı projelerinize entegre edebilirsiniz.