LPX commited on
Commit
6909ab7
·
1 Parent(s): 5aa075b

refactor: reorganize Gradio interface layout for improved user experience and accessibility

Browse files
Files changed (1) hide show
  1. app_mcp.py +104 -113
app_mcp.py CHANGED
@@ -3,9 +3,6 @@ import time
3
  from typing import Literal
4
  import spaces
5
  import gradio as gr
6
- import modelscope_studio.components.antd as antd
7
- import modelscope_studio.components.antdx as antdx
8
- import modelscope_studio.components.base as ms
9
  from transformers import pipeline, AutoImageProcessor, SwinForImageClassification, Swinv2ForImageClassification, AutoFeatureExtractor, AutoModelForImageClassification
10
  from torchvision import transforms
11
  import torch
@@ -485,118 +482,112 @@ def predict_image_with_json(img, confidence_threshold, augment_methods, rotate_d
485
  return img_pil, cleaned_forensics_images, table_rows, json_results, consensus_html
486
 
487
  with gr.Blocks(css="#post-gallery { overflow: hidden !important;} .grid-wrap{ overflow-y: hidden !important;} .ms-gr-ant-welcome-icon{ height:unset !important;} .tabs{margin-top:10px;}") as demo:
488
- with ms.Application() as app:
489
- with antd.ConfigProvider():
490
- antdx.Welcome(
491
- icon="https://cdn-avatars.huggingface.co/v1/production/uploads/639daf827270667011153fbc/WpeSFhuB81DY-1TjNUmV_.png",
492
- title="Welcome to Project OpenSight",
493
- description="The OpenSight aims to be an open-source SOTA generated image detection model. This HF Space is not only an introduction but a educational playground for the public to evaluate and challenge current open source models. **Space will be upgraded shortly; inference on all 6 models should take about 1.2~ seconds.** "
494
- )
495
- with gr.Tab("👀 Detection Models Eval / Playground"):
496
- gr.Markdown("# Open Source Detection Models Found on the Hub\n\n - **Space will be upgraded shortly;** inference on all 6 models should take about 1.2~ seconds once we're back on CUDA.\n - The **Community Forensics** mother of all detection models is now available for inference, head to the middle tab above this.\n - Lots of exciting things coming up, stay tuned!")
497
-
498
- with gr.Row():
499
- with gr.Column(scale=1):
500
- image_input = gr.Image(label="Upload Image to Analyze", sources=['upload', 'webcam'], type='pil')
501
- with gr.Accordion("Settings (Optional)", open=False, elem_id="settings_accordion"):
502
- augment_checkboxgroup = gr.CheckboxGroup(["rotate", "add_noise", "sharpen"], label="Augmentation Methods")
503
- rotate_slider = gr.Slider(0, 45, value=2, step=1, label="Rotate Degrees", visible=False)
504
- noise_slider = gr.Slider(0, 50, value=4, step=1, label="Noise Level", visible=False)
505
- sharpen_slider = gr.Slider(0, 50, value=11, step=1, label="Sharpen Strength", visible=False)
506
- confidence_slider = gr.Slider(0.0, 1.0, value=0.75, step=0.05, label="Confidence Threshold")
507
- inputs = [image_input, confidence_slider, augment_checkboxgroup, rotate_slider, noise_slider, sharpen_slider]
508
- predict_button = gr.Button("Predict")
509
- augment_button = gr.Button("Augment & Predict")
510
- image_output = gr.Image(label="Processed Image", visible=False)
511
-
512
-
513
- with gr.Column(scale=2):
514
- # Use Gradio-native Dataframe to display results with headers
515
- results_table = gr.Dataframe(
516
- label="Model Predictions",
517
- headers=["Model", "Contributor", "AI Score", "Real Score", "Label"],
518
- datatype=["str", "str", "number", "number", "str"]
519
- )
520
- forensics_gallery = gr.Gallery(label="Post Processed Images", visible=True, columns=[4], rows=[2], container=False, height="auto", object_fit="contain", elem_id="post-gallery")
521
- with gr.Accordion("Debug Output (Raw JSON)", open=False):
522
- debug_json = gr.JSON(label="Raw Model Results")
523
- consensus_md = gr.Markdown(label="Consensus", value="")
524
-
525
- outputs = [image_output, forensics_gallery, results_table, debug_json, consensus_md]
526
-
527
- # Show/hide rotate slider based on selected augmentation method
528
- augment_checkboxgroup.change(lambda methods: gr.update(visible="rotate" in methods), inputs=[augment_checkboxgroup], outputs=[rotate_slider])
529
- augment_checkboxgroup.change(lambda methods: gr.update(visible="add_noise" in methods), inputs=[augment_checkboxgroup], outputs=[noise_slider])
530
- augment_checkboxgroup.change(lambda methods: gr.update(visible="sharpen" in methods), inputs=[augment_checkboxgroup], outputs=[sharpen_slider])
531
-
532
- predict_button.click(
533
- fn=predict_image_with_json,
534
- inputs=inputs,
535
- outputs=outputs,
536
- api_name="predict"
537
- )
538
- augment_button.click( # Connect Augment button to the function
539
- fn=predict_image_with_json,
540
- inputs=[
541
- image_input,
542
- confidence_slider,
543
- gr.CheckboxGroup(["rotate", "add_noise", "sharpen"], value=["rotate", "add_noise", "sharpen"], visible=False), # Default values
544
- rotate_slider,
545
- noise_slider,
546
- sharpen_slider
547
- ],
548
- outputs=outputs,
549
- api_name="augment_then_predict"
550
- )
551
- with gr.Tab("🙈 Project Introduction"):
552
- gr.Markdown(QUICK_INTRO)
553
-
554
- with gr.Tab("👑 Community Forensics Preview"):
555
- # temp_space = gr.load("aiwithoutborders-xyz/OpenSight-Community-Forensics-Preview", src="spaces")
556
- gr.Markdown("Community Forensics Preview coming soon!") # Placeholder for now
557
- with gr.Tab("🥇 Leaderboard"):
558
- gr.Markdown("# AI Generated / Deepfake Detection Models Leaderboard: Soon™")
559
-
560
- with gr.Tab("Wavelet Blocking Noise Estimation", visible=False):
561
- gr.Interface(
562
- fn=wavelet_blocking_noise_estimation,
563
- inputs=[gr.Image(type="pil"), gr.Slider(1, 32, value=8, step=1, label="Block Size")],
564
- outputs=gr.Image(type="pil"),
565
- title="Wavelet-Based Noise Analysis",
566
- description="Analyzes image noise patterns using wavelet decomposition. This tool helps detect compression artifacts and artificial noise patterns that may indicate image manipulation. Higher noise levels in specific regions can reveal areas of potential tampering.",
567
- api_name="tool_waveletnoise"
568
- )
569
 
570
- """Forensics Tool: Bit Plane Extractor
571
-
572
- Args:
573
- image: PIL Image to analyze
574
- channel: Color channel to extract bit plane from ("Luminance", "Red", "Green", "Blue", "RGB Norm")
575
- bit_plane: Bit plane index to extract (0-7)
576
- filter_type: Filter to apply ("Disabled", "Median", "Gaussian")
577
- """
578
- with gr.Tab("Bit Plane Values", visible=False):
579
- gr.Interface(
580
-
581
- fn=bit_plane_extractor,
582
- inputs=[
583
- gr.Image(type="pil"),
584
- gr.Dropdown(["Luminance", "Red", "Green", "Blue", "RGB Norm"], label="Channel", value="Luminance"),
585
- gr.Slider(0, 7, value=0, step=1, label="Bit Plane"),
586
- gr.Dropdown(["Disabled", "Median", "Gaussian"], label="Filter", value="Disabled")
587
- ],
588
- outputs=gr.Image(type="pil"),
589
- title="Bit Plane Analysis",
590
- description="Extracts and visualizes individual bit planes from different color channels. This forensic tool helps identify hidden patterns and artifacts in image data that may indicate manipulation. Different bit planes can reveal inconsistencies in image processing or editing.",
591
- api_name="tool_bitplane"
 
 
592
  )
593
- # with gr.Tab("EXIF Full Dump"):
594
- # gr.Interface(
595
- # fn=exif_full_dump,
596
- # inputs=gr.Image(type="pil"),
597
- # outputs=gr.JSON(),
598
- # description="Extract all EXIF metadata from the uploaded image."
599
- # )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
600
 
601
  # --- MCP-Ready Launch ---
602
  if __name__ == "__main__":
 
3
  from typing import Literal
4
  import spaces
5
  import gradio as gr
 
 
 
6
  from transformers import pipeline, AutoImageProcessor, SwinForImageClassification, Swinv2ForImageClassification, AutoFeatureExtractor, AutoModelForImageClassification
7
  from torchvision import transforms
8
  import torch
 
482
  return img_pil, cleaned_forensics_images, table_rows, json_results, consensus_html
483
 
484
  with gr.Blocks(css="#post-gallery { overflow: hidden !important;} .grid-wrap{ overflow-y: hidden !important;} .ms-gr-ant-welcome-icon{ height:unset !important;} .tabs{margin-top:10px;}") as demo:
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
485
 
486
+ with gr.Tab("👀 Detection Models Eval / Playground"):
487
+ gr.Markdown("# Open Source Detection Models Found on the Hub\n\n - **Space will be upgraded shortly;** inference on all 6 models should take about 1.2~ seconds once we're back on CUDA.\n - The **Community Forensics** mother of all detection models is now available for inference, head to the middle tab above this.\n - Lots of exciting things coming up, stay tuned!")
488
+
489
+ with gr.Row():
490
+ with gr.Column(scale=1):
491
+ image_input = gr.Image(label="Upload Image to Analyze", sources=['upload', 'webcam'], type='pil')
492
+ with gr.Accordion("Settings (Optional)", open=False, elem_id="settings_accordion"):
493
+ augment_checkboxgroup = gr.CheckboxGroup(["rotate", "add_noise", "sharpen"], label="Augmentation Methods")
494
+ rotate_slider = gr.Slider(0, 45, value=2, step=1, label="Rotate Degrees", visible=False)
495
+ noise_slider = gr.Slider(0, 50, value=4, step=1, label="Noise Level", visible=False)
496
+ sharpen_slider = gr.Slider(0, 50, value=11, step=1, label="Sharpen Strength", visible=False)
497
+ confidence_slider = gr.Slider(0.0, 1.0, value=0.75, step=0.05, label="Confidence Threshold")
498
+ inputs = [image_input, confidence_slider, augment_checkboxgroup, rotate_slider, noise_slider, sharpen_slider]
499
+ predict_button = gr.Button("Predict")
500
+ augment_button = gr.Button("Augment & Predict")
501
+ image_output = gr.Image(label="Processed Image", visible=False)
502
+
503
+
504
+ with gr.Column(scale=2):
505
+ # Use Gradio-native Dataframe to display results with headers
506
+ results_table = gr.Dataframe(
507
+ label="Model Predictions",
508
+ headers=["Model", "Contributor", "AI Score", "Real Score", "Label"],
509
+ datatype=["str", "str", "number", "number", "str"]
510
  )
511
+ forensics_gallery = gr.Gallery(label="Post Processed Images", visible=True, columns=[4], rows=[2], container=False, height="auto", object_fit="contain", elem_id="post-gallery")
512
+ with gr.Accordion("Debug Output (Raw JSON)", open=False):
513
+ debug_json = gr.JSON(label="Raw Model Results")
514
+ consensus_md = gr.Markdown(label="Consensus", value="")
515
+
516
+ outputs = [image_output, forensics_gallery, results_table, debug_json, consensus_md]
517
+
518
+ # Show/hide rotate slider based on selected augmentation method
519
+ augment_checkboxgroup.change(lambda methods: gr.update(visible="rotate" in methods), inputs=[augment_checkboxgroup], outputs=[rotate_slider])
520
+ augment_checkboxgroup.change(lambda methods: gr.update(visible="add_noise" in methods), inputs=[augment_checkboxgroup], outputs=[noise_slider])
521
+ augment_checkboxgroup.change(lambda methods: gr.update(visible="sharpen" in methods), inputs=[augment_checkboxgroup], outputs=[sharpen_slider])
522
+
523
+ predict_button.click(
524
+ fn=predict_image_with_json,
525
+ inputs=inputs,
526
+ outputs=outputs,
527
+ api_name="predict"
528
+ )
529
+ augment_button.click( # Connect Augment button to the function
530
+ fn=predict_image_with_json,
531
+ inputs=[
532
+ image_input,
533
+ confidence_slider,
534
+ gr.CheckboxGroup(["rotate", "add_noise", "sharpen"], value=["rotate", "add_noise", "sharpen"], visible=False), # Default values
535
+ rotate_slider,
536
+ noise_slider,
537
+ sharpen_slider
538
+ ],
539
+ outputs=outputs,
540
+ api_name="augment_then_predict"
541
+ )
542
+ with gr.Tab("🙈 Project Introduction"):
543
+ gr.Markdown(QUICK_INTRO)
544
+
545
+ with gr.Tab("👑 Community Forensics Preview"):
546
+ # temp_space = gr.load("aiwithoutborders-xyz/OpenSight-Community-Forensics-Preview", src="spaces")
547
+ gr.Markdown("Community Forensics Preview coming soon!") # Placeholder for now
548
+ with gr.Tab("🥇 Leaderboard"):
549
+ gr.Markdown("# AI Generated / Deepfake Detection Models Leaderboard: Soon™")
550
+
551
+ with gr.Tab("Wavelet Blocking Noise Estimation", visible=False):
552
+ gr.Interface(
553
+ fn=wavelet_blocking_noise_estimation,
554
+ inputs=[gr.Image(type="pil"), gr.Slider(1, 32, value=8, step=1, label="Block Size")],
555
+ outputs=gr.Image(type="pil"),
556
+ title="Wavelet-Based Noise Analysis",
557
+ description="Analyzes image noise patterns using wavelet decomposition. This tool helps detect compression artifacts and artificial noise patterns that may indicate image manipulation. Higher noise levels in specific regions can reveal areas of potential tampering.",
558
+ api_name="tool_waveletnoise"
559
+ )
560
+
561
+ """Forensics Tool: Bit Plane Extractor
562
+
563
+ Args:
564
+ image: PIL Image to analyze
565
+ channel: Color channel to extract bit plane from ("Luminance", "Red", "Green", "Blue", "RGB Norm")
566
+ bit_plane: Bit plane index to extract (0-7)
567
+ filter_type: Filter to apply ("Disabled", "Median", "Gaussian")
568
+ """
569
+ with gr.Tab("Bit Plane Values", visible=False):
570
+ gr.Interface(
571
+
572
+ fn=bit_plane_extractor,
573
+ inputs=[
574
+ gr.Image(type="pil"),
575
+ gr.Dropdown(["Luminance", "Red", "Green", "Blue", "RGB Norm"], label="Channel", value="Luminance"),
576
+ gr.Slider(0, 7, value=0, step=1, label="Bit Plane"),
577
+ gr.Dropdown(["Disabled", "Median", "Gaussian"], label="Filter", value="Disabled")
578
+ ],
579
+ outputs=gr.Image(type="pil"),
580
+ title="Bit Plane Analysis",
581
+ description="Extracts and visualizes individual bit planes from different color channels. This forensic tool helps identify hidden patterns and artifacts in image data that may indicate manipulation. Different bit planes can reveal inconsistencies in image processing or editing.",
582
+ api_name="tool_bitplane"
583
+ )
584
+ # with gr.Tab("EXIF Full Dump"):
585
+ # gr.Interface(
586
+ # fn=exif_full_dump,
587
+ # inputs=gr.Image(type="pil"),
588
+ # outputs=gr.JSON(),
589
+ # description="Extract all EXIF metadata from the uploaded image."
590
+ # )
591
 
592
  # --- MCP-Ready Launch ---
593
  if __name__ == "__main__":