🈯 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ü

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.

×
    Original text
    Rate this translation
    Your feedback will be used to help improve Google Translate