aafa

import cv2

import numpy as np

import pytesseract

import time

import pyautogui

import threading

import tkinter as tk

import re

from deep_translator import GoogleTranslator

from PIL import Image, ImageTk

from difflib import SequenceMatcher


 

# OCR motoru ayarı

pytesseract.pytesseract.tesseract_cmd = r'C:\Program Files\Tesseract-OCR\tesseract.exe'


 

class RegionSelector:

   def __init__(self, callback):

       self.callback = callback

       self.root = tk.Tk()

       self.root.attributes('-fullscreen', True)

       self.root.attributes('-alpha', 0.3)

       self.root.configure(bg='grey')

       

       self.canvas = tk.Canvas(self.root, cursor="cross", bg="grey")

       self.canvas.pack(fill=tk.BOTH, expand=True)

       

       self.start_x = None

       self.start_y = None

       self.current_rect = None

       

       self.canvas.bind("<ButtonPress-1>", self.on_press)

       self.canvas.bind("<B1-Motion>", self.on_drag)

       self.canvas.bind("<ButtonRelease-1>", self.on_release)

       

       self.instruction = tk.Label(self.root,

                                  text="Çevirmek istediğiniz bölgeyi seçin\nİptal için ESC tuşuna basın",

                                  font=("Arial", 14), bg="black", fg="white", bd=2)

       self.instruction.place(relx=0.5, rely=0.1, anchor=tk.CENTER)

       

       self.root.bind("<Escape>", self.cancel)

       

       self.root.mainloop()

       

   def on_press(self, event):

       self.start_x = self.canvas.canvasx(event.x)

       self.start_y = self.canvas.canvasy(event.y)

       

       if self.current_rect:

           self.canvas.delete(self.current_rect)

           

       self.current_rect = self.canvas.create_rectangle(

           self.start_x, self.start_y, self.start_x, self.start_y,

           outline='red', width=2

       )

   

   def on_drag(self, event):

       cur_x = self.canvas.canvasx(event.x)

       cur_y = self.canvas.canvasy(event.y)

       

       self.canvas.coords(self.current_rect, self.start_x, self.start_y, cur_x, cur_y)

   

   def on_release(self, event):

       end_x = self.canvas.canvasx(event.x)

       end_y = self.canvas.canvasy(event.y)

       

       x1 = min(self.start_x, end_x)

       y1 = min(self.start_y, end_y)

       x2 = max(self.start_x, end_x)

       y2 = max(self.start_y, end_y)

       

       if (x2 - x1 > 20) and (y2 - y1 > 20):

           self.root.destroy()

           self.callback((int(x1), int(y1), int(x2-x1), int(y2-y1)))

       else:

           messagebox.showwarning("Uyarı", "Lütfen daha büyük bir alan seçin!")

   

   def cancel(self, event):

       self.root.destroy()

       self.callback(None)


 

class HitmanTranslator:

   def __init__(self):

       self.running = False

       self.last_text = ""

       self.target_language = "tr"

       self.setup_overlay()

       self.translation_history = {}

       

       # Varsayılan yakalama bölgesi

       self.capture_region = (150, 850, 1620, 130)

       self.custom_region_set = False

       

       # Metin stabilizasyonu için

       self.text_buffer = []

       self.buffer_size = 3

       self.min_confidence_threshold = 50  # OCR güven eşiği (0-100)

       self.min_text_length = 5  # Minimum anlamlı metin uzunluğu

       self.similar_text_threshold = 0.7  # Benzerlik oranı (0-1)

       

       # OCR algılama kararlılığı

       self.consecutive_matches = 0

       self.required_consecutive = 2  # Kaç kez aynı metin algılanmalı

       

       # Saçma karakter filtreleme

       self.gibberish_pattern = re.compile(r'^[a-zA-Z\s]{1,2}$|^[^a-zA-Z0-9\s]{1,3}$|^[a-zA-Z]{1,2}$|^\s*[a-zA-Z]\s*$')

       

   def setup_overlay(self):

       self.overlay = tk.Tk()

       self.overlay.attributes('-topmost', True)

       self.overlay.attributes('-alpha', 0.8)

       self.overlay.geometry('600x250+50+50')

       self.overlay.configure(bg='black')

       self.overlay.overrideredirect(True)

       

       # Kontrol paneli

       control_frame = tk.Frame(self.overlay, bg="black")

       control_frame.pack(side=tk.TOP, fill=tk.X)

       

       # Bölge seçim butonu

       select_region_button = tk.Button(control_frame, text="Bölge Seç",

                                      command=self.select_region, bg="blue", fg="white")

       select_region_button.pack(side=tk.LEFT, padx=5, pady=5)

       

       # Varsayılan bölgeye dönme butonu

       default_region_button = tk.Button(control_frame, text="Varsayılan Bölge",

                                      command=self.reset_to_default_region, bg="green", fg="white")

       default_region_button.pack(side=tk.LEFT, padx=5, pady=5)

       

       # Çeviriyi temizleme butonu

       clear_button = tk.Button(control_frame, text="Temizle",

                              command=self.clear_translation, bg="orange", fg="white")

       clear_button.pack(side=tk.LEFT, padx=5, pady=5)

       

       # Pencereyi taşımak için düğme

       move_button = tk.Button(control_frame, text="Taşı", bg="gray", fg="white")

       move_button.pack(side=tk.LEFT, padx=5, pady=5)

       move_button.bind("<ButtonPress-1>", self.start_move)

       move_button.bind("<ButtonRelease-1>", self.stop_move)

       move_button.bind("<B1-Motion>", self.on_motion)

       

       # Çıkış butonu

       exit_button = tk.Button(control_frame, text="X", command=self.stop,

                              bg="red", fg="white", width=2)

       exit_button.pack(side=tk.RIGHT, padx=5, pady=5)

       

       # Bölge bilgisi

       self.region_label = tk.Label(self.overlay,

                                   text="Varsayılan bölge kullanılıyor",

                                   bg="black", fg="yellow", font=("Arial", 10))

       self.region_label.pack(pady=2)

       

       # Algılanan metin bilgisi

       self.detected_text_label = tk.Label(self.overlay,

                                         text="Algılanan: -",

                                         bg="black", fg="cyan", font=("Arial", 10))

       self.detected_text_label.pack(pady=2)

       

       # Çeviri metni için etiket

       self.label = tk.Label(self.overlay, text="Çeviri bekleniyor...",

                            fg="white", bg="black", wraplength=580,

                            font=("Arial", 14), justify=tk.LEFT)

       self.label.pack(pady=10, padx=10, fill=tk.BOTH, expand=True)

       

       # Görüntü önizleme için frame

       self.preview_frame = tk.Frame(self.overlay, bg="black", height=50)

       self.preview_frame.pack(side=tk.BOTTOM, fill=tk.X)

       self.preview_label = tk.Label(self.preview_frame, bg="black")

       self.preview_label.pack(pady=5)

       

   def clear_translation(self):

       self.label.config(text="Çeviri bekleniyor...")

       self.detected_text_label.config(text="Algılanan: -")

       self.text_buffer = []

       self.last_text = ""

       self.consecutive_matches = 0

       

   def select_region(self):

       self.overlay.withdraw()

       time.sleep(0.5)

       RegionSelector(self.region_callback)

   

   def region_callback(self, region):

       self.overlay.deiconify()

       

       if region:

           self.capture_region = region

           self.custom_region_set = True

           self.region_label.config(text=f"Özel bölge: {region}")

           print(f"Yeni bölge seçildi: {region}")

           # Bölge değiştiğinde tamponları temizle

           self.clear_translation()

       

   def reset_to_default_region(self):

       self.capture_region = (150, 850, 1620, 130)

       self.custom_region_set = False

       self.region_label.config(text="Varsayılan bölge kullanılıyor")

       # Bölge değiştiğinde tamponları temizle

       self.clear_translation()

       

   def start_move(self, event):

       self.x = event.x

       self.y = event.y


 

   def stop_move(self, event):

       self.x = None

       self.y = None


 

   def on_motion(self, event):

       deltax = event.x - self.x

       deltay = event.y - self.y

       x = self.overlay.winfo_x() + deltax

       y = self.overlay.winfo_y() + deltay

       self.overlay.geometry(f"+{x}+{y}")

       

   def start(self):

       self.running = True

       self.overlay.deiconify()

       threading.Thread(target=self.translation_loop, daemon=True).start()

       

   def stop(self):

       self.running = False

       self.overlay.destroy()

       

   def is_gibberish(self, text):

       # Anlamsız kısa metinleri veya tekrarlayan harfleri filtrele

       if len(text.strip()) < self.min_text_length:

           return True

           

       # Tekrarlayan karakterleri kontrol et

       char_counts = {}

       for char in text:

           if char in char_counts:

               char_counts[char] += 1

           else:

               char_counts[char] = 1

               

       # Bir karakter toplam metnin %60'ından fazlasını oluşturuyorsa gibberish olarak işaretle

       for char, count in char_counts.items():

           if count > len(text) * 0.6 and len(text) > 3:

               return True

               

       # Anlamsız kısa karakter dizileri için düzenli ifade kontrolü

       if self.gibberish_pattern.match(text):

           return True

           

       # Harf ve boşluk dışında pek bir şey yoksa anlamsız kabul et

       if len(re.sub(r'[a-zA-Z\s]', '', text)) < 2 and len(text) < 10:

           return True

           

       return False

       

   def similar_text_exists(self, text):

       # Son algılanan metinlerde benzer bir metin var mı?

       for old_text in self.text_buffer:

           similarity = SequenceMatcher(None, text, old_text).ratio()

           if similarity > self.similar_text_threshold:

               return True

       return False

       

   def capture_subtitles(self):

       # Görüntüyü yakala

       screenshot = pyautogui.screenshot(region=self.capture_region)

       img = np.array(screenshot)

       img = cv2.cvtColor(img, cv2.COLOR_RGB2BGR)

       

       # Önizleme için görüntüyü küçült

       h, w = img.shape[:2]

       aspect = w / h

       preview_width = 300

       preview_height = int(preview_width / aspect)

       preview_img = cv2.resize(img, (preview_width, preview_height))

       self.update_preview(preview_img)

       

       # Geliştirilmiş görüntü işleme

       gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

       

       # Filtreleme ve kontrast iyileştirme

       blurred = cv2.GaussianBlur(gray, (5, 5), 0)

       clahe = cv2.createCLAHE(clipLimit=2.0, tileGridSize=(8, 8))

       enhanced = clahe.apply(blurred)

       

       # Binarizasyon (ikili görüntüye dönüştürme)

       _, thresh = cv2.threshold(enhanced, 150, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)

       

       # Gürültü azaltma

       kernel = np.ones((2, 2), np.uint8)

       thresh = cv2.morphologyEx(thresh, cv2.MORPH_CLOSE, kernel)

       

       # OCR ayarları - daha sıkı parametreler

       config = '--psm 6 --oem 3 -c tessedit_char_whitelist="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.,:;\'\"!?-() "'

       

       # Sadece güven derecesi yüksek metinleri al

       data = pytesseract.image_to_data(thresh, lang='eng', config=config, output_type=pytesseract.Output.DICT)

       

       # Güven değeri yüksek metinleri birleştir

       text_parts = []

       for i in range(len(data['text'])):

           # Güven değeri eşiğimizden yüksek olan kelimeler

           if int(data['conf'][i]) > self.min_confidence_threshold:

               text_parts.append(data['text'][i])

               

       text = ' '.join(text_parts)

       

       # Temizleme

       text = self.clean_text(text)

       

       # Algılanan metni göster

       max_display_len = 30

       display_text = text if len(text) <= max_display_len else text[:max_display_len] + "..."

       self.detected_text_label.config(text=f"Algılanan: {display_text}")

       

       return text

   

   def update_preview(self, img):

       img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)

       img = Image.fromarray(img)

       img = ImageTk.PhotoImage(image=img)

       

       self.preview_label.configure(image=img)

       self.preview_label.image = img

   

   def clean_text(self, text):

       if not text:

           return ""

           

       # Temel temizlik

       text = text.strip()

       

       # Fazla boşlukları temizle

       text = re.sub(r'\s+', ' ', text)

       

       # Tek harfleri temizle

       text = re.sub(r'\b[a-zA-Z]\b', '', text)

       

       # Rakam olmayan sayıları kaldır

       text = re.sub(r'[^\w\s\.,;:\-\?\!\'\"]+', '', text)

       

       return text.strip()

   

   def translate_text(self, text):

       if not text or len(text) < self.min_text_length:

           return None

           

       # Saçma metin kontrolü

       if self.is_gibberish(text):

           print(f"Saçma metin algılandı ve filtrelendi: '{text}'")

           return None

           

       # Çok kısa metinleri engelle

       if len(text.split()) < 2 and len(text) < 10:

           print(f"Çok kısa metin filtrelendi: '{text}'")

           return None

           

       # Son metinle aynıysa yeniden çevirme

       if text == self.last_text:

           return self.translation_history.get(text, None)

           

       # Daha önce çevrilmişse cache'den al

       if text in self.translation_history:

           self.last_text = text

           return self.translation_history[text]

       

       try:

           # Çeviri yap

           result = GoogleTranslator(source='auto', target=self.target_language).translate(text)

           

           if result:

               self.last_text = text

               self.translation_history[text] = result

               return result

           return None

           

       except Exception as e:

           print(f"Çeviri hatası: {e}")

           return None

   

   def translation_loop(self):

       consecutive_empty = 0

       

       while self.running:

           try:

               # Metni yakala

               game_text = self.capture_subtitles()

               

               # Metin yoksa veya anlamsızsa

               if not game_text or self.is_gibberish(game_text):

                   consecutive_empty += 1

                   time.sleep(0.5)

                   continue

               

               # Benzer metin daha önce algılanmış mı kontrol et

               if game_text == self.last_text:

                   self.consecutive_matches += 1

               else:

                   self.consecutive_matches = 1

               

               # Aynı metin belirli sayıda kez algılanırsa çevir

               if self.consecutive_matches >= self.required_consecutive:

                   print(f"Kararlı metin algılandı: {game_text}")

                   translated = self.translate_text(game_text)

                   if translated:

                       consecutive_empty = 0

                       self.label.config(text=translated)

                       print(f"Çeviri: {translated}")

                       

                       # Tampon belleğe ekle

                       self.text_buffer.append(game_text)

                       if len(self.text_buffer) > self.buffer_size:

                           self.text_buffer.pop(0)

               

               # Metin bulunamadıysa

               if consecutive_empty > 10:  # 5 saniye

                   if self.label['text'] != "Çeviri bekleniyor...":

                       self.label.config(text="Çeviri bekleniyor...")

                       self.detected_text_label.config(text="Algılanan: -")

                   consecutive_empty = 0

               

               time.sleep(0.5)

               

           except Exception as e:

               print(f"Döngü hatası: {e}")

               time.sleep(1)

   

   def run(self):

       try:

           self.start()

           self.overlay.mainloop()

       except KeyboardInterrupt:

           self.stop()


 

if __name__ == "__main__":

   translator = HitmanTranslator()

   translator.run()