import os import tempfile import gradio as gr from PIL import Image # Import Tagger Processors from modules.taggers.joint import JointTaggerProcessor, run_joint_classifier from modules.taggers.cl import CLTaggerProcessor from modules.taggers.pixai import PixaiTaggerProcessor from modules.taggers.anime import AnimeTaggerProcessor from modules.taggers.gemini import GeminiTaggerProcessor # Import Managers and Utils from modules.managers.category_manager import kategori_sozlugu_yukle, kategorizelendir_ileri from modules.tagger_refinement import rafine_etiketler from modules.utils.tag_utils import unique_and_sort_tags from modules.managers.rule_manager import apply_additions # --- CL Tagger Modülünü İçe Aktarma --- try: from modules.cl_tagger_module import CLTagger except ImportError: try: from .cl_tagger_module import CLTagger # Fallback for relative import except ImportError: print("cl_tagger_module.py bulunamadı.") CLTagger = None # Global Instance Variables cl_tagger_instance = None try: if CLTagger: cl_tagger_instance = CLTagger() print("CL Tagger (ONNX) başarıyla yüklendi.") except Exception as e: print(f"CL Tagger (ONNX) yüklenirken hata: {e}") cl_tagger_instance = None # --- Ortak İşleme Fonksiyonu --- def _process_single_image( image, joint_thresh, use_joint, cl_gen_thresh, cl_char_thresh, use_cl_tagger, pixai_general_thresh, pixai_char_thresh, use_pixai_tagger, animetagger_model, animetagger_thresh, use_animetagger, use_gemini, gemini_api_key, gemini_mode, gemini_model_id, gemini_prompt_vision, gemini_prompt_tags, gemini_prompt_hybrid, gemini_system_instruction, replacement_file_path, synonym_file_path, addition_file_path, sort_order="Alfabetik", device: str = "Auto", context_weight: float = 0.0, enable_cat_for_gemini=False, selected_cats_for_gemini=None ): if image is None: return "", "", "", "⚠️ Resim yüklenmedi.", [] alert_messages = [] all_tags = set() all_raw_tags_for_original_sort = [] gemini_result_text = "" current_joint_processor = JointTaggerProcessor(replacement_file_path, synonym_file_path, addition_file_path) current_cl_tagger_processor = CLTaggerProcessor(cl_tagger_instance, replacement_file_path, synonym_file_path, addition_file_path) current_pixai_processor = PixaiTaggerProcessor(replacement_file_path, synonym_file_path, addition_file_path) current_animetagger_processor = AnimeTaggerProcessor(replacement_file_path, synonym_file_path, addition_file_path) current_gemini_processor = GeminiTaggerProcessor() if use_joint: j_raw, j_alert, j_order = current_joint_processor.predict(image, joint_thresh, replacement_file_path, synonym_file_path, addition_file_path, sort_order, device) if "Hata" not in j_raw and "❌" not in j_alert: all_tags.update(t.strip() for t in j_raw.split(',') if t.strip()) all_raw_tags_for_original_sort.extend(j_order) else: alert_messages.append(f"Joint: {j_alert}") if use_cl_tagger: cl_raw, cl_alert, cl_order = current_cl_tagger_processor.predict(image, cl_gen_thresh, cl_char_thresh, replacement_file_path, synonym_file_path, addition_file_path, sort_order) if "Hata" not in cl_raw and "❌" not in cl_alert: all_tags.update(t.strip() for t in cl_raw.split(',') if t.strip()) all_raw_tags_for_original_sort.extend(cl_order) else: alert_messages.append(f"CL: {cl_alert}") if use_pixai_tagger: p_raw, p_alert, p_order = current_pixai_processor.predict(image, pixai_general_thresh, pixai_char_thresh, replacement_file_path, synonym_file_path, addition_file_path, "Orijinal", device) if "Hata" not in p_raw and "❌" not in p_alert: all_tags.update(t.strip() for t in p_raw.split(',') if t.strip()) all_raw_tags_for_original_sort.extend(p_order) else: alert_messages.append(f"PixAI: {p_alert}") if use_animetagger: a_raw, a_alert, a_order = current_animetagger_processor.predict(image, animetagger_model, animetagger_thresh, replacement_file_path, synonym_file_path, addition_file_path, "Orijinal", device) if "Hata" not in a_raw and "❌" not in a_alert: all_tags.update(t.strip() for t in a_raw.split(',') if t.strip()) all_raw_tags_for_original_sort.extend(a_order) else: alert_messages.append(f"AnimeTagger: {a_alert}") combined_final_tags_string = unique_and_sort_tags(", ".join(list(all_tags)), sort_order, original_order_ref=all_raw_tags_for_original_sort) refined_final_tags_string = rafine_etiketler(combined_final_tags_string, context_weight) refined_final_tags_string = apply_additions(refined_final_tags_string, addition_file_path) if use_gemini: active_prompt = gemini_prompt_vision if gemini_mode == "Tags": active_prompt = gemini_prompt_tags elif gemini_mode == "Vision + Tags": active_prompt = gemini_prompt_hybrid tags_content_for_gemini = "" if gemini_mode in ["Tags", "Vision + Tags"]: source_tags = refined_final_tags_string if refined_final_tags_string else combined_final_tags_string if enable_cat_for_gemini and selected_cats_for_gemini: tags_content_for_gemini = kategorizelendir_ileri(source_tags, selected_cats_for_gemini, kategori_sozlugu_yukle()) else: tags_content_for_gemini = source_tags g_text, g_alert = current_gemini_processor.predict( image, gemini_api_key, active_prompt, gemini_mode, tags_content_for_gemini, gemini_model_id, gemini_system_instruction ) if "❌" in g_alert or "⚠️" in g_alert: alert_messages.append(f"Gemini: {g_alert}") else: gemini_result_text = g_text final_alert = "✅ İşlem tamamlandı!" if not alert_messages else "❌ Hatalar: " + "; ".join(alert_messages) return combined_final_tags_string, refined_final_tags_string, gemini_result_text, final_alert, all_raw_tags_for_original_sort # --- Ana Etiketleme Fonksiyonları --- def toplu_islem( image, joint_thresh, use_joint, cl_gen_thresh, cl_char_thresh, use_cl_tagger, pixai_general_thresh, pixai_char_thresh, use_pixai_tagger, animetagger_model, animetagger_thresh, use_animetagger, use_gemini, gemini_api_key, gemini_mode, gemini_model_id, gemini_prompt_vision, gemini_prompt_tags, gemini_prompt_hybrid, gemini_system_instruction, replacement_file_path, synonym_file_path, addition_file_path, enable_categorization, selected_categories, sort_order="Alfabetik", device: str = "Auto", context_weight: float = 0.0 ): final_tags_string, refined_tags_string, gemini_out, alert_message, _ = _process_single_image( image, joint_thresh, use_joint, cl_gen_thresh, cl_char_thresh, use_cl_tagger, pixai_general_thresh, pixai_char_thresh, use_pixai_tagger, animetagger_model, animetagger_thresh, use_animetagger, use_gemini, gemini_api_key, gemini_mode, gemini_model_id, gemini_prompt_vision, gemini_prompt_tags, gemini_prompt_hybrid, gemini_system_instruction, replacement_file_path, synonym_file_path, addition_file_path, sort_order, device, context_weight, enable_cat_for_gemini=enable_categorization, selected_cats_for_gemini=selected_categories ) source_for_cat = refined_tags_string if refined_tags_string else final_tags_string categorized_tags_output = kategorizelendir_ileri(source_for_cat, selected_categories, kategori_sozlugu_yukle()) if (enable_categorization and selected_categories) else "" parts = [] if categorized_tags_output: parts.append(categorized_tags_output) if gemini_out: parts.append(gemini_out) combined_cat_gem = ", ".join(parts) return alert_message, final_tags_string, refined_tags_string, categorized_tags_output, gemini_out, combined_cat_gem def toplu_islem_batch( progress=gr.Progress(), images=None, joint_thresh=0.25, use_joint=True, cl_gen_thresh=0.55, cl_char_thresh=0.60, use_cl_tagger=True, pixai_general_thresh=0.30, pixai_char_thresh=0.85, use_pixai_tagger=False, animetagger_model="MobileNet V4 (Hızlı)", animetagger_thresh=0.35, use_animetagger=False, use_gemini=False, gemini_api_key="", gemini_mode="Vision", gemini_model_id="gemini-2.5-flash", gemini_prompt_vision="", gemini_prompt_tags="", gemini_prompt_hybrid="", gemini_system_instruction="", replacement_file_path="", synonym_file_path="", addition_file_path="", enable_categorization=False, selected_categories=None, sort_order="Alfabetik", device: str = "Auto", context_weight: float = 0.0 ): if not images: return "⚠️ Resim yüklenmedi.", "", None, "", "", "", "" all_final, all_refined, all_cat, all_orig, all_gemini, results_html, alerts = [], [], [], [], [], [], [] total = len(images) for i, img_obj in enumerate(images): progress(i / total, desc=f"İşleniyor: {os.path.basename(img_obj.name)} ({i+1}/{total})") try: image = Image.open(img_obj.name) except Exception as e: alerts.append(f"{img_obj.name}: Okuma hatası: {e}"); continue comb, ref, gem_out, alert, orig = _process_single_image( image, joint_thresh, use_joint, cl_gen_thresh, cl_char_thresh, use_cl_tagger, pixai_general_thresh, pixai_char_thresh, use_pixai_tagger, animetagger_model, animetagger_thresh, use_animetagger, use_gemini, gemini_api_key, gemini_mode, gemini_model_id, gemini_prompt_vision, gemini_prompt_tags, gemini_prompt_hybrid, gemini_system_instruction, replacement_file_path, synonym_file_path, addition_file_path, sort_order, device, context_weight, enable_cat_for_gemini=enable_categorization, selected_cats_for_gemini=selected_categories ) if "❌" in alert or "⚠️" in alert: alerts.append(f"{img_obj.name}: {alert}") else: all_final.append(comb); all_refined.append(ref); all_orig.extend(orig) if gem_out: all_gemini.append(f"--- {os.path.basename(img_obj.name)} ---\n{gem_out}") source = ref if ref else comb cat_out = kategorizelendir_ileri(source, selected_categories, kategori_sozlugu_yukle()) if (enable_categorization and selected_categories) else "" if cat_out: all_cat.append(cat_out) html_part = f"
{os.path.basename(img_obj.name)}
Tags: {ref}" if gem_out: html_part += f"
Gemini: {gem_out}" html_part += "
" results_html.append(html_part) progress(1.0, desc="✅ Bitti.") final_alert = "✅ Başarılı!" if not alerts else "⚠️ Hatalar:\n" + "\n".join(alerts) out_file = None if all_final: with tempfile.NamedTemporaryFile(mode='w+', encoding='utf-8', delete=False, suffix=".txt") as tf: tf.write("\n".join(all_final)); out_file = tf.name gemini_combined_str = "\n\n".join(all_gemini) return final_alert, "
".join(results_html), out_file, "\n".join(all_cat), unique_and_sort_tags(", ".join(list(set(all_orig))), "Alfabetik"), unique_and_sort_tags(", ".join(all_refined), "Alfabetik"), gemini_combined_str def process_dual_images(image1, image2, joint_thresh1, use_joint1, joint_thresh2, use_joint2, cl_gen_thresh1, cl_char_thresh1, use_cl_tagger1, cl_gen_thresh2, cl_char_thresh2, use_cl_tagger2, pixai_general_thresh1, pixai_char_thresh1, use_pixai_tagger1, pixai_general_thresh2, pixai_char_thresh2, use_pixai_tagger2, animetagger_model1, animetagger_thresh1, use_animetagger1, animetagger_model2, animetagger_thresh2, use_animetagger2, use_gemini, gemini_api_key, gemini_mode, gemini_model_id, gemini_prompt_vision, gemini_prompt_tags, gemini_prompt_hybrid, gemini_system_instruction, replacement_file_path, synonym_file_path, addition_file_path, enable_categorization_img1, selected_categories_img1, enable_categorization_img2, selected_categories_img2, sort_order="Alfabetik", device: str = "Auto", context_weight: float = 0.0): images_settings = [ (image1, use_joint1, joint_thresh1, cl_gen_thresh1, cl_char_thresh1, use_cl_tagger1, pixai_general_thresh1, pixai_char_thresh1, use_pixai_tagger1, animetagger_model1, animetagger_thresh1, use_animetagger1, enable_categorization_img1, selected_categories_img1), (image2, use_joint2, joint_thresh2, cl_gen_thresh2, cl_char_thresh2, use_cl_tagger2, pixai_general_thresh2, pixai_char_thresh2, use_pixai_tagger2, animetagger_model2, animetagger_thresh2, use_animetagger2, enable_categorization_img2, selected_categories_img2) ] alerts, cats, all_tags_sets, refined_sets, orig_tags, gemini_results = [], [], [], [], [], [] for img, uj, jt, cg, cc, uc, pg, pc, up, am, at, ua, enc, selc in images_settings: comb, ref, gem_out, alert, orig = _process_single_image( img, jt, uj, cg, cc, uc, pg, pc, up, am, at, ua, use_gemini, gemini_api_key, gemini_mode, gemini_model_id, gemini_prompt_vision, gemini_prompt_tags, gemini_prompt_hybrid, gemini_system_instruction, replacement_file_path, synonym_file_path, addition_file_path, sort_order, device, context_weight, enable_cat_for_gemini=enc, selected_cats_for_gemini=selc ) if "❌" in alert: alerts.append(alert) all_tags_sets.append(set(comb.split(', '))); refined_sets.append(set(ref.split(', '))); orig_tags.extend(orig) gemini_results.append(gem_out) src = ref if ref else comb cats.append(kategorizelendir_ileri(src, selc, kategori_sozlugu_yukle()) if (enc and selc) else "") combined_all = unique_and_sort_tags(", ".join(list(set().union(*all_tags_sets))), sort_order, orig_tags) combined_ref = unique_and_sort_tags(", ".join(list(set().union(*refined_sets))), sort_order, orig_tags) combined_all = apply_additions(combined_all, addition_file_path) combined_ref = apply_additions(combined_ref, addition_file_path) combined_cat = unique_and_sort_tags(", ".join([c for c in cats if c]), sort_order, orig_tags) valid_captions = [g.strip() for g in gemini_results if g and g.strip()] gemini_combined_text = " ".join(valid_captions) parts = [] if combined_cat: parts.append(combined_cat) if gemini_combined_text: parts.append(gemini_combined_text) combined_cat_plus_gem = ", ".join(parts) return alerts, combined_all, combined_ref, combined_cat, gemini_combined_text, combined_cat_plus_gem