| """ |
| Omni Image Editor - Redesigned |
| A modern, mobile-first Gradio 6 interface for image editing and generation. |
| """ |
|
|
| import gradio as gr |
| from pipeline import OmniMMDitV2Pipeline |
| from nfsw_filter import NSFWDetector |
|
|
| |
| |
| try: |
| pipeline = OmniMMDitV2Pipeline( |
| model=None, |
| vae=None, |
| text_encoder=None, |
| tokenizer=None, |
| scheduler=None, |
| ) |
| safety_checker = NSFWDetector() |
| except Exception as e: |
| print(f"Warning: Models could not be initialized: {e}") |
| |
| pipeline = None |
| safety_checker = None |
|
|
| def check_safety(image): |
| """Run NSFW check on the image.""" |
| if safety_checker is None: |
| return image, "Safety check unavailable." |
| |
| try: |
| |
| label, _ = safety_checker.predict_from_pil(image) |
| if label == "nsfw": |
| return None, "⚠️ NSFW content detected. Image blocked." |
| return image, "✅ Image is safe." |
| except Exception as e: |
| return image, f"Error checking safety: {e}" |
|
|
| def edit_image(input_image, prompt, negative_prompt, guidance_scale, num_steps): |
| """Process image editing request.""" |
| if input_image is None: |
| return None, "Please upload an image first." |
| |
| if pipeline is None: |
| return None, "Model not loaded. Check server logs." |
|
|
| |
| safe_image, safety_msg = check_safety(input_image) |
| if safe_image is None: |
| return None, safety_msg |
|
|
| |
| try: |
| |
| |
| result = pipeline( |
| prompt=prompt, |
| input_images=[input_image], |
| negative_prompt=negative_prompt, |
| guidance_scale=guidance_scale, |
| num_inference_steps=int(num_steps), |
| height=1024, |
| width=1024 |
| ) |
| |
| |
| if hasattr(result, 'images'): |
| output_image = result.images[0] |
| else: |
| output_image = result[0] |
| |
| return output_image, f"Success! {safety_msg}" |
| |
| except Exception as e: |
| return None, f"Error during generation: {str(e)}" |
|
|
| |
|
|
| |
| custom_theme = gr.themes.Soft( |
| primary_hue="indigo", |
| secondary_hue="cyan", |
| neutral_hue="slate", |
| font=gr.themes.GoogleFont("Inter"), |
| text_size="lg", |
| spacing_size="lg", |
| radius_size="lg" |
| ).set( |
| |
| button_primary_background_fill="*primary_500", |
| button_primary_background_fill_hover="*primary_600", |
| button_primary_text_color="white", |
| button_secondary_background_fill="*neutral_100", |
| button_secondary_background_fill_hover="*neutral_200", |
| |
| block_background_fill="*background_fill_primary", |
| block_border_width="0px", |
| block_shadow="*shadow_drop_lg", |
| |
| block_title_text_weight="600", |
| block_title_text_size="*text_xl", |
| ) |
|
|
| with gr.Blocks() as demo: |
| |
| |
| gr.HTML(""" |
| <div style="display: flex; align-items: center; justify-content: space-between; padding: 1rem 0;"> |
| <div> |
| <h1 style="margin: 0; font-size: 1.5rem; font-weight: 700; color: #4F46E5;">Omni Editor</h1> |
| <p style="margin: 0; color: #64748B;">Next-Gen Image Editing</p> |
| </div> |
| <a href="https://huggingface.co/spaces/akhaliq/anycoder" target="_blank" style="text-decoration: none; color: #4F46E5; font-weight: 500; font-size: 0.9rem;"> |
| Built with anycoder ↗ |
| </a> |
| </div> |
| """) |
|
|
| with gr.Row(equal_height=True): |
| |
| with gr.Column(scale=1, min_width=300): |
| gr.Markdown("### 🎨 Controls") |
| |
| with gr.Accordion("⚙️ Generation Settings", open=True): |
| prompt = gr.Textbox( |
| label="Prompt", |
| placeholder="Describe the changes you want...", |
| lines=3, |
| show_label=False |
| ) |
| negative_prompt = gr.Textbox( |
| label="Negative Prompt", |
| placeholder="Things to avoid...", |
| lines=2, |
| show_label=False |
| ) |
| |
| with gr.Row(): |
| guidance = gr.Slider( |
| minimum=1.0, |
| maximum=20.0, |
| value=7.5, |
| step=0.5, |
| label="Guidance Scale" |
| ) |
| steps = gr.Slider( |
| minimum=10, |
| maximum=50, |
| value=25, |
| step=1, |
| label="Steps" |
| ) |
| |
| generate_btn = gr.Button("✨ Generate Edit", variant="primary", size="lg") |
| status_msg = gr.Textbox(label="Status", interactive=False, visible=False) |
|
|
| gr.Markdown(""" |
| --- |
| ### 💡 Tips |
| - Upload a clear image for best results. |
| - Be descriptive in your prompt. |
| - Use negative prompts to remove artifacts. |
| """) |
|
|
| |
| with gr.Column(scale=2): |
| gr.Markdown("### 🖼️ Workspace") |
| |
| with gr.Row(): |
| input_image = gr.Image( |
| label="Input", |
| type="pil", |
| sources=["upload", "clipboard", "webcam"], |
| interactive=True |
| ) |
| output_image = gr.Image( |
| label="Result", |
| type="pil", |
| interactive=False |
| ) |
|
|
| |
| generate_btn.click( |
| fn=edit_image, |
| inputs=[input_image, prompt, negative_prompt, guidance, steps], |
| outputs=[output_image, status_msg], |
| api_visibility="public" |
| ).then( |
| |
| lambda: gr.Textbox(visible=True), |
| outputs=[status_msg] |
| ) |
|
|
| |
| demo.launch( |
| theme=custom_theme, |
| footer_links=[{"label": "Built with anycoder", "url": "https://huggingface.co/spaces/akhaliq/anycoder"}] |
| ) |