Opera8 commited on
Commit
bc72ac7
·
verified ·
1 Parent(s): 56fa104

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +81 -40
app.py CHANGED
@@ -29,23 +29,82 @@ colors.steel_blue = colors.Color(
29
 
30
  device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
31
 
32
- # --- بارگذاری مدل تشخیص محتوای نامناسب (NSFW) ---
33
- print("Loading Safety Checker...")
34
- safety_classifier = pipeline("image-classification", model="Falconsai/nsfw_image_detection", device=-1)
 
 
 
 
 
35
 
36
  def is_image_nsfw(image):
37
  if image is None: return False
38
  try:
39
- results = safety_classifier(image)
40
- for result in results:
41
- if result['label'] == 'nsfw' and result['score'] > 0.75:
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
42
  return True
 
43
  return False
44
  except Exception as e:
45
  print(f"Safety check error: {e}")
46
- return False
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
47
 
48
- # --- بارگذاری مدل اصلی ---
49
  from diffusers import FlowMatchEulerDiscreteScheduler
50
  from qwenimage.pipeline_qwenimage_edit_plus import QwenImageEditPlusPipeline
51
  from qwenimage.transformer_qwenimage import QwenImageTransformer2DModel
@@ -54,7 +113,7 @@ from qwenimage.qwen_fa3_processor import QwenDoubleStreamAttnProcessorFA3
54
  dtype = torch.bfloat16
55
  device = "cuda" if torch.cuda.is_available() else "cpu"
56
 
57
- print("Loading pipeline...")
58
  pipe = QwenImageEditPlusPipeline.from_pretrained(
59
  "Qwen/Qwen-Image-Edit-2509",
60
  transformer=QwenImageTransformer2DModel.from_pretrained(
@@ -106,30 +165,6 @@ ASPECT_RATIOS_MAP = {
106
  "شخصی‌سازی (Custom)": "Custom"
107
  }
108
 
109
- BANNED_WORDS = [
110
- "nude", "naked", "sex", "porn", "undressed", "nsfw", "erotic", "xxx",
111
- "breast", "nipple", "genital", "vagina", "penis", "ass", "butt", "sexual",
112
- "lingerie", "bikini", "swimwear", "underwear", "fetish", "topless",
113
- "exhibitionism", "hentai", "ecchi", "18+"
114
- ]
115
-
116
- def check_text_safety(text):
117
- text_lower = text.lower()
118
- for word in BANNED_WORDS:
119
- if f" {word} " in f" {text_lower} ":
120
- return False
121
- return True
122
-
123
- def translate_prompt(text):
124
- if not text:
125
- return ""
126
- try:
127
- translated = GoogleTranslator(source='auto', target='en').translate(text)
128
- return translated
129
- except Exception as e:
130
- print(f"Translation Error: {e}")
131
- return text
132
-
133
  def update_dimensions_on_upload(image):
134
  if image is None:
135
  return 1024, 1024
@@ -146,12 +181,6 @@ def update_dimensions_on_upload(image):
146
  new_height = (new_height // 8) * 8
147
  return new_width, new_height
148
 
149
- def update_sliders_visibility(choice):
150
- if choice == "شخصی‌سازی (Custom)":
151
- return gr.update(visible=True), gr.update(visible=True)
152
- else:
153
- return gr.update(visible=False), gr.update(visible=False)
154
-
155
  def get_error_html(message):
156
  return f"""
157
  <div style="background-color: #fee2e2; border: 1px solid #ef4444; color: #b91c1c; padding: 12px; border-radius: 8px; text-align: center; margin-bottom: 10px; font-weight: bold; display: flex; align-items: center; justify-content: center; gap: 8px;">
@@ -182,12 +211,15 @@ def infer(
182
  custom_height,
183
  progress=gr.Progress(track_tqdm=True)
184
  ):
 
185
  if input_image is None:
186
  return None, seed, get_error_html("لطفاً ابتدا یک تصویر بارگذاری کنید.")
187
 
 
188
  if is_image_nsfw(input_image):
189
  return None, seed, get_error_html("تصویر ورودی دارای محتوای نامناسب است و پردازش نمی‌شود.")
190
 
 
191
  english_prompt = translate_prompt(prompt)
192
  if not check_text_safety(english_prompt):
193
  return None, seed, get_error_html("متن درخواست شامل کلمات غیرمجاز یا غیراخلاقی است.")
@@ -201,7 +233,15 @@ def infer(
201
 
202
  generator = torch.Generator(device=device).manual_seed(seed)
203
 
204
- safety_negative = "nsfw, nude, naked, porn, sexual, xxx, breast, nipple, genital, vagina, penis, ass, lingerie, bikini, swimwear, underwear, fetish, topless, gore, violence, blood"
 
 
 
 
 
 
 
 
205
  base_negative = "worst quality, low quality, bad anatomy, bad hands, text, error, missing fingers, extra digit, fewer digits, cropped, jpeg artifacts, signature, watermark, username, blurry"
206
  final_negative_prompt = f"{safety_negative}, {base_negative}"
207
 
@@ -229,6 +269,7 @@ def infer(
229
  true_cfg_scale=guidance_scale,
230
  ).images[0]
231
 
 
232
  if is_image_nsfw(result):
233
  return None, seed, get_error_html("تصویر تولید شده حاوی محتوای نامناسب بود و حذف شد.")
234
 
 
29
 
30
  device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
31
 
32
+ # --- بارگذاری سیستم امنیتی دوگانه (Dual Safety System) ---
33
+ print("Loading Safety Checkers...")
34
+
35
+ # مدل اول: سریع و استاندارد
36
+ safety_classifier_1 = pipeline("image-classification", model="Falconsai/nsfw_image_detection", device=-1)
37
+
38
+ # مدل دوم: بسیار دقیق و سخت‌گیر (ViT)
39
+ safety_classifier_2 = pipeline("image-classification", model="AdamCodd/vit-base-nsfw-detector", device=-1)
40
 
41
  def is_image_nsfw(image):
42
  if image is None: return False
43
  try:
44
+ # بررسی با مدل اول
45
+ results1 = safety_classifier_1(image)
46
+ for result in results1:
47
+ if result['label'] == 'nsfw' and result['score'] > 0.5: # حساسیت متوسط
48
+ print(f"Safety Check 1 Failed: {result['score']}")
49
+ return True
50
+
51
+ # بررسی با مدل دوم (سخت‌گیرانه برای موارد نیمه برهنه)
52
+ results2 = safety_classifier_2(image)
53
+ for result in results2:
54
+ label = result['label'].lower()
55
+ score = result['score']
56
+
57
+ # اگر مدل تشخیص دهد nsfw است (حتی با احتمال ۳۰ درصد)
58
+ if label == 'nsfw' and score > 0.3:
59
+ print(f"Safety Check 2 (NSFW) Failed: {score}")
60
+ return True
61
+
62
+ # اگر مدل تشخیص دهد تصویر سکسی یا نیمه برهنه است
63
+ if label in ['sexy', 'porn', 'hentai'] and score > 0.4:
64
+ print(f"Safety Check 2 (Partial) Failed: {label} - {score}")
65
  return True
66
+
67
  return False
68
  except Exception as e:
69
  print(f"Safety check error: {e}")
70
+ # در صورت خطا در سیستم امنیتی، جانب احتیاط رعایت شود
71
+ return True
72
+
73
+ # --- لیست کلمات ممنوعه (انگلیسی) ---
74
+ # این لیست بعد از ترجمه متن کاربر چک می‌شود
75
+ BANNED_WORDS = [
76
+ "nsfw", "nude", "naked", "sex", "porn", "erotic", "xxx", "18+", "uncensored",
77
+ "breast", "nipple", "areola", "cleavage", "topless", "open chest",
78
+ "genital", "vagina", "penis", "dick", "cock", "pussy", "ass", "butt", "anus",
79
+ "lingerie", "bikini", "swimwear", "underwear", "panties", "bra",
80
+ "fetish", "bdsm", "bondage", "exhibitionism", "voyeur",
81
+ "hentai", "ecchi", "ahegao", "paizuri",
82
+ "undressed", "stripping", "naked body", "exposed skin", "sheer", "see-through",
83
+ "rape", "violence", "blood", "gore", "sexual"
84
+ ]
85
+
86
+ def check_text_safety(text):
87
+ """بررسی متن انگلیسی برای کلمات ممنوعه"""
88
+ if not text: return True
89
+ text_lower = text.lower()
90
+ for word in BANNED_WORDS:
91
+ # بررسی کلمه به صورت مستقل یا چسبیده
92
+ if word in text_lower:
93
+ print(f"Banned word found: {word}")
94
+ return False
95
+ return True
96
+
97
+ def translate_prompt(text):
98
+ if not text:
99
+ return ""
100
+ try:
101
+ translated = GoogleTranslator(source='auto', target='en').translate(text)
102
+ return translated
103
+ except Exception as e:
104
+ print(f"Translation Error: {e}")
105
+ return text
106
 
107
+ # --- بارگذاری مدل اصلی ویرایش تصویر ---
108
  from diffusers import FlowMatchEulerDiscreteScheduler
109
  from qwenimage.pipeline_qwenimage_edit_plus import QwenImageEditPlusPipeline
110
  from qwenimage.transformer_qwenimage import QwenImageTransformer2DModel
 
113
  dtype = torch.bfloat16
114
  device = "cuda" if torch.cuda.is_available() else "cpu"
115
 
116
+ print("Loading Generation Pipeline...")
117
  pipe = QwenImageEditPlusPipeline.from_pretrained(
118
  "Qwen/Qwen-Image-Edit-2509",
119
  transformer=QwenImageTransformer2DModel.from_pretrained(
 
165
  "شخصی‌سازی (Custom)": "Custom"
166
  }
167
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
168
  def update_dimensions_on_upload(image):
169
  if image is None:
170
  return 1024, 1024
 
181
  new_height = (new_height // 8) * 8
182
  return new_width, new_height
183
 
 
 
 
 
 
 
184
  def get_error_html(message):
185
  return f"""
186
  <div style="background-color: #fee2e2; border: 1px solid #ef4444; color: #b91c1c; padding: 12px; border-radius: 8px; text-align: center; margin-bottom: 10px; font-weight: bold; display: flex; align-items: center; justify-content: center; gap: 8px;">
 
211
  custom_height,
212
  progress=gr.Progress(track_tqdm=True)
213
  ):
214
+ # 1. بررسی وجود تصویر
215
  if input_image is None:
216
  return None, seed, get_error_html("لطفاً ابتدا یک تصویر بارگذاری کنید.")
217
 
218
+ # 2. بررسی امنیتی تصویر ورودی (با دو مدل)
219
  if is_image_nsfw(input_image):
220
  return None, seed, get_error_html("تصویر ورودی دارای محتوای نامناسب است و پردازش نمی‌شود.")
221
 
222
+ # 3. ترجمه و بررسی متن
223
  english_prompt = translate_prompt(prompt)
224
  if not check_text_safety(english_prompt):
225
  return None, seed, get_error_html("متن درخواست شامل کلمات غیرمجاز یا غیراخلاقی است.")
 
233
 
234
  generator = torch.Generator(device=device).manual_seed(seed)
235
 
236
+ # 4. تنظیم دستورات منفی (Negative Prompt) سخت‌گیرانه
237
+ # این کلمات به هوش مصنوعی می‌گویند که چه چیزهایی نسازد
238
+ safety_negative = (
239
+ "nsfw, nude, naked, porn, sexual, xxx, breast, nipple, areola, genital, "
240
+ "vagina, penis, ass, lingerie, bikini, swimwear, underwear, fetish, "
241
+ "topless, open chest, revealing clothes, cleavage, see-through, sheer, "
242
+ "gore, violence, blood, navel, midriff, exposed skin, erotic, ecchi, hentai, "
243
+ "uncensored, stripping"
244
+ )
245
  base_negative = "worst quality, low quality, bad anatomy, bad hands, text, error, missing fingers, extra digit, fewer digits, cropped, jpeg artifacts, signature, watermark, username, blurry"
246
  final_negative_prompt = f"{safety_negative}, {base_negative}"
247
 
 
269
  true_cfg_scale=guidance_scale,
270
  ).images[0]
271
 
272
+ # 5. بررسی امنیتی تصویر خروجی (با دو مدل)
273
  if is_image_nsfw(result):
274
  return None, seed, get_error_html("تصویر تولید شده حاوی محتوای نامناسب بود و حذف شد.")
275