aiqtech commited on
Commit
b33ef2d
ยท
verified ยท
1 Parent(s): e63eda8

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +212 -83
app.py CHANGED
@@ -588,112 +588,196 @@ def update_box_button(img, box_input):
588
 
589
 
590
  css = """
591
- footer {display: none}
 
 
 
 
592
  .main-title {
593
  text-align: center;
594
- margin: 1em 0;
595
- padding: 1.5em;
596
  background: linear-gradient(135deg, #f5f7fa 0%, #c3cfe2 100%);
597
  border-radius: 15px;
598
- box-shadow: 0 4px 6px rgba(0,0,0,0.1);
 
599
  }
 
600
  .main-title h1 {
601
  color: #2196F3;
602
- font-size: 2.8em;
603
- margin-bottom: 0.3em;
604
  font-weight: 700;
 
605
  }
 
606
  .main-title p {
607
  color: #555;
608
- font-size: 1.3em;
609
- line-height: 1.4;
610
- }
611
- .container {
612
- max-width: 1200px;
613
- margin: auto;
614
- padding: 20px;
615
  }
 
 
616
  .input-panel, .output-panel {
617
  background: white;
618
- padding: 1.5em;
619
- border-radius: 12px;
620
- box-shadow: 0 2px 8px rgba(0,0,0,0.08);
621
- margin-bottom: 1em;
 
 
 
 
 
622
  }
 
 
623
  .controls-panel {
624
  background: #f8f9fa;
625
- padding: 1em;
626
- border-radius: 8px;
627
- margin: 1em 0;
 
628
  }
 
 
629
  .image-display {
630
  min-height: 512px;
631
  display: flex;
632
  align-items: center;
633
  justify-content: center;
634
  background: #fafafa;
635
- border-radius: 8px;
636
- margin: 1em 0;
637
- }
638
- .example-section {
639
- text-align: center;
640
- padding: 2em;
641
- background: #f5f5f5;
642
  border-radius: 12px;
643
- margin-top: 2em;
644
- }
645
- .example-section img {
646
- max-width: 100%;
647
- border-radius: 8px;
648
- box-shadow: 0 4px 8px rgba(0,0,0,0.1);
649
- }
650
- .accordion {
651
- border: 1px solid #e0e0e0;
652
- border-radius: 8px;
653
- margin: 1em 0;
654
- }
655
- .accordion-header {
656
- padding: 1em;
657
- background: #f5f5f5;
658
- cursor: pointer;
659
- }
660
- .accordion-content {
661
- padding: 1em;
662
- display: none;
663
- }
664
- .accordion.open .accordion-content {
665
- display: block;
666
- }
667
- .position-grid {
668
- display: grid;
669
- grid-template-columns: repeat(3, 1fr);
670
- gap: 8px;
671
- margin: 1em 0;
672
  }
673
 
674
-
675
  .position-btn {
676
- padding: 10px;
677
- border: 1px solid #ddd;
678
- border-radius: 4px;
679
  background: white;
680
  cursor: pointer;
681
- transition: all 0.3s ease;
682
- width: 40px;
683
- height: 40px;
684
  display: flex;
685
  align-items: center;
686
  justify-content: center;
 
 
687
  }
688
 
689
  .position-btn:hover {
690
  background: #e3f2fd;
 
 
691
  }
692
 
693
  .position-btn.selected {
694
  background-color: #2196F3;
695
  color: white;
696
  border-color: #1976D2;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
697
  }
698
  """
699
 
@@ -862,14 +946,21 @@ def update_controls(bg_prompt):
862
 
863
  with gr.Blocks(theme=gr.themes.Soft(), css=css) as demo:
864
  position = gr.State(value="bottom-center")
865
-
 
866
  gr.HTML("""
867
  <div class="main-title">
868
  <h1>๐ŸŽจ GiniGen Canvas-o3</h1>
869
  <p>Remove background of specified objects, generate new backgrounds, and insert text over or behind images with prompts.</p>
870
  </div>
871
  """)
 
 
 
 
 
872
 
 
873
  with gr.Row(equal_height=True):
874
  # ์™ผ์ชฝ ํŒจ๋„ (์ž…๋ ฅ)
875
  with gr.Column(scale=1):
@@ -881,8 +972,10 @@ with gr.Blocks(theme=gr.themes.Soft(), css=css) as demo:
881
  type="pil",
882
  label="Upload Image",
883
  interactive=True,
884
- height=400
 
885
  )
 
886
  with gr.Group():
887
  inpaint_prompt = gr.Textbox(
888
  label="Inpainting Prompt",
@@ -899,8 +992,10 @@ with gr.Blocks(theme=gr.themes.Soft(), css=css) as demo:
899
  text_prompt = gr.Textbox(
900
  label="Object to Extract",
901
  placeholder="Enter what you want to extract...",
902
- interactive=True
 
903
  )
 
904
  with gr.Row():
905
  bg_prompt = gr.Textbox(
906
  label="Background Prompt (optional)",
@@ -1052,18 +1147,64 @@ with gr.Blocks(theme=gr.themes.Soft(), css=css) as demo:
1052
  btn_bottom_right: "bottom-right"
1053
  }
1054
 
 
 
 
 
 
 
 
 
 
1055
  for btn, pos in position_mapping.items():
1056
  btn.click(
1057
- fn=lambda pos=pos: update_position(pos),
1058
- outputs=position
 
 
 
 
 
1059
  )
1060
 
 
1061
  inpaint_btn.click(
1062
- fn=process_inpainting,
 
 
 
 
1063
  inputs=[input_image, mask_input, inpaint_prompt],
1064
- outputs=input_image
1065
  )
1066
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1067
  bg_prompt.change(
1068
  fn=update_controls,
1069
  inputs=bg_prompt,
@@ -1085,19 +1226,7 @@ with gr.Blocks(theme=gr.themes.Soft(), css=css) as demo:
1085
  queue=False
1086
  )
1087
 
1088
- process_btn.click(
1089
- fn=process_prompt,
1090
- inputs=[
1091
- input_image,
1092
- text_prompt,
1093
- bg_prompt,
1094
- aspect_ratio,
1095
- position,
1096
- scale_slider
1097
- ],
1098
- outputs=[combined_image, extracted_image],
1099
- queue=True
1100
- )
1101
 
1102
  add_text_btn.click(
1103
  fn=add_text_to_image,
 
588
 
589
 
590
  css = """
591
+ /* ๊ธฐ๋ณธ ๋ ˆ์ด์•„์›ƒ */
592
+ footer {display: none !important}
593
+ body {background: #f5f7fa !important}
594
+
595
+ /* ๋ฉ”์ธ ํƒ€์ดํ‹€ */
596
  .main-title {
597
  text-align: center;
598
+ margin: 1.5em auto;
599
+ padding: 2em;
600
  background: linear-gradient(135deg, #f5f7fa 0%, #c3cfe2 100%);
601
  border-radius: 15px;
602
+ box-shadow: 0 8px 16px rgba(0,0,0,0.1);
603
+ max-width: 1200px;
604
  }
605
+
606
  .main-title h1 {
607
  color: #2196F3;
608
+ font-size: 3em;
609
+ margin-bottom: 0.5em;
610
  font-weight: 700;
611
+ text-shadow: 2px 2px 4px rgba(0,0,0,0.1);
612
  }
613
+
614
  .main-title p {
615
  color: #555;
616
+ font-size: 1.4em;
617
+ line-height: 1.6;
618
+ max-width: 800px;
619
+ margin: 0 auto;
 
 
 
620
  }
621
+
622
+ /* ํŒจ๋„ ์Šคํƒ€์ผ๋ง */
623
  .input-panel, .output-panel {
624
  background: white;
625
+ padding: 2em;
626
+ border-radius: 15px;
627
+ box-shadow: 0 4px 12px rgba(0,0,0,0.05);
628
+ margin-bottom: 1.5em;
629
+ transition: all 0.3s ease;
630
+ }
631
+
632
+ .input-panel:hover, .output-panel:hover {
633
+ box-shadow: 0 6px 16px rgba(0,0,0,0.1);
634
  }
635
+
636
+ /* ์ปจํŠธ๋กค ํŒจ๋„ */
637
  .controls-panel {
638
  background: #f8f9fa;
639
+ padding: 1.5em;
640
+ border-radius: 12px;
641
+ margin: 1.5em 0;
642
+ border: 1px solid #e9ecef;
643
  }
644
+
645
+ /* ์ด๋ฏธ์ง€ ๋””์Šคํ”Œ๋ ˆ์ด */
646
  .image-display {
647
  min-height: 512px;
648
  display: flex;
649
  align-items: center;
650
  justify-content: center;
651
  background: #fafafa;
 
 
 
 
 
 
 
652
  border-radius: 12px;
653
+ margin: 1.5em 0;
654
+ border: 2px dashed #e0e0e0;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
655
  }
656
 
657
+ /* ๋ฒ„ํŠผ ์Šคํƒ€์ผ๋ง */
658
  .position-btn {
659
+ padding: 12px;
660
+ border: 2px solid #ddd;
661
+ border-radius: 8px;
662
  background: white;
663
  cursor: pointer;
664
+ transition: all 0.2s ease;
665
+ width: 48px;
666
+ height: 48px;
667
  display: flex;
668
  align-items: center;
669
  justify-content: center;
670
+ font-size: 1.2em;
671
+ margin: 4px;
672
  }
673
 
674
  .position-btn:hover {
675
  background: #e3f2fd;
676
+ transform: translateY(-2px);
677
+ box-shadow: 0 4px 8px rgba(0,0,0,0.1);
678
  }
679
 
680
  .position-btn.selected {
681
  background-color: #2196F3;
682
  color: white;
683
  border-color: #1976D2;
684
+ box-shadow: 0 4px 12px rgba(33,150,243,0.3);
685
+ }
686
+
687
+ /* ๊ทธ๋ฆฌ๋“œ ๋ ˆ์ด์•„์›ƒ */
688
+ .position-grid {
689
+ display: grid;
690
+ grid-template-columns: repeat(3, 1fr);
691
+ gap: 10px;
692
+ margin: 1.5em 0;
693
+ padding: 10px;
694
+ background: #f5f5f5;
695
+ border-radius: 12px;
696
+ }
697
+
698
+ /* ์ž…๋ ฅ ํ•„๋“œ ์Šคํƒ€์ผ๋ง */
699
+ input[type="text"], textarea {
700
+ border: 2px solid #e0e0e0;
701
+ border-radius: 8px;
702
+ padding: 12px;
703
+ font-size: 1.1em;
704
+ transition: all 0.3s ease;
705
+ }
706
+
707
+ input[type="text"]:focus, textarea:focus {
708
+ border-color: #2196F3;
709
+ box-shadow: 0 0 0 3px rgba(33,150,243,0.2);
710
+ }
711
+
712
+ /* ์Šฌ๋ผ์ด๋” ์Šคํƒ€์ผ๋ง */
713
+ .slider-container {
714
+ margin: 1.5em 0;
715
+ }
716
+
717
+ .slider {
718
+ height: 6px;
719
+ background: #e0e0e0;
720
+ border-radius: 3px;
721
+ }
722
+
723
+ .slider-handle {
724
+ width: 20px;
725
+ height: 20px;
726
+ background: #2196F3;
727
+ border: 2px solid white;
728
+ box-shadow: 0 2px 4px rgba(0,0,0,0.2);
729
+ }
730
+
731
+ /* ์ƒํƒœ ๋ฉ”์‹œ์ง€ */
732
+ .status-message {
733
+ padding: 10px;
734
+ border-radius: 8px;
735
+ margin: 10px 0;
736
+ font-size: 0.9em;
737
+ transition: all 0.3s ease;
738
+ }
739
+
740
+ .status-success {
741
+ background: #e8f5e9;
742
+ color: #2e7d32;
743
+ border: 1px solid #a5d6a7;
744
+ }
745
+
746
+ .status-error {
747
+ background: #ffebee;
748
+ color: #c62828;
749
+ border: 1px solid #ef9a9a;
750
+ }
751
+
752
+ /* ๋ฐ˜์‘ํ˜• ๋””์ž์ธ */
753
+ @media (max-width: 768px) {
754
+ .main-title h1 {
755
+ font-size: 2em;
756
+ }
757
+
758
+ .main-title p {
759
+ font-size: 1.1em;
760
+ }
761
+
762
+ .input-panel, .output-panel {
763
+ padding: 1em;
764
+ }
765
+
766
+ .position-btn {
767
+ width: 40px;
768
+ height: 40px;
769
+ font-size: 1em;
770
+ }
771
+ }
772
+
773
+ /* ์• ๋‹ˆ๋ฉ”์ด์…˜ ํšจ๊ณผ */
774
+ @keyframes fadeIn {
775
+ from {opacity: 0; transform: translateY(10px);}
776
+ to {opacity: 1; transform: translateY(0);}
777
+ }
778
+
779
+ .fade-in {
780
+ animation: fadeIn 0.3s ease-out;
781
  }
782
  """
783
 
 
946
 
947
  with gr.Blocks(theme=gr.themes.Soft(), css=css) as demo:
948
  position = gr.State(value="bottom-center")
949
+ processing_status = gr.State(value="idle")
950
+
951
  gr.HTML("""
952
  <div class="main-title">
953
  <h1>๐ŸŽจ GiniGen Canvas-o3</h1>
954
  <p>Remove background of specified objects, generate new backgrounds, and insert text over or behind images with prompts.</p>
955
  </div>
956
  """)
957
+
958
+ status_message = gr.HTML(
959
+ value='<div class="status-message"></div>',
960
+ visible=False
961
+ )
962
 
963
+
964
  with gr.Row(equal_height=True):
965
  # ์™ผ์ชฝ ํŒจ๋„ (์ž…๋ ฅ)
966
  with gr.Column(scale=1):
 
972
  type="pil",
973
  label="Upload Image",
974
  interactive=True,
975
+ height=400,
976
+ elem_classes="fade-in"
977
  )
978
+
979
  with gr.Group():
980
  inpaint_prompt = gr.Textbox(
981
  label="Inpainting Prompt",
 
992
  text_prompt = gr.Textbox(
993
  label="Object to Extract",
994
  placeholder="Enter what you want to extract...",
995
+ interactive=True,
996
+ elem_classes="fade-in"
997
  )
998
+
999
  with gr.Row():
1000
  bg_prompt = gr.Textbox(
1001
  label="Background Prompt (optional)",
 
1147
  btn_bottom_right: "bottom-right"
1148
  }
1149
 
1150
+ def update_ui_state(component_id, value, is_error=False):
1151
+ """UI ์ƒํƒœ ์—…๋ฐ์ดํŠธ ์œ ํ‹ธ๋ฆฌํ‹ฐ"""
1152
+ class_name = "status-error" if is_error else "status-success"
1153
+ return gr.update(
1154
+ value=f'<div class="status-message {class_name}">{value}</div>',
1155
+ visible=True
1156
+ )
1157
+
1158
+ # ๋ฒ„ํŠผ ์ด๋ฒคํŠธ ๋ฐ”์ธ๋”ฉ
1159
  for btn, pos in position_mapping.items():
1160
  btn.click(
1161
+ fn=lambda p=pos: debug_event("position_update", p),
1162
+ inputs=[],
1163
+ outputs=[status_message]
1164
+ ).then(
1165
+ fn=update_position_and_ui,
1166
+ inputs=[gr.State(pos)],
1167
+ outputs=[position] + list(position_mapping.keys())
1168
  )
1169
 
1170
+ # ์ธํŽ˜์ธํŒ… ํ”„๋กœ์„ธ์Šค
1171
  inpaint_btn.click(
1172
+ fn=lambda: debug_event("inpainting_start"),
1173
+ inputs=[],
1174
+ outputs=[status_message]
1175
+ ).then(
1176
+ fn=process_inpainting_with_feedback,
1177
  inputs=[input_image, mask_input, inpaint_prompt],
1178
+ outputs=[input_image, status_message]
1179
  )
1180
 
1181
+ # ํ”„๋กœ์„ธ์Šค ๋ฒ„ํŠผ
1182
+ process_btn.click(
1183
+ fn=lambda: debug_event("process_start"),
1184
+ inputs=[],
1185
+ outputs=[status_message]
1186
+ ).then(
1187
+ fn=process_prompt,
1188
+ inputs=[
1189
+ input_image,
1190
+ text_prompt,
1191
+ bg_prompt,
1192
+ aspect_ratio,
1193
+ position,
1194
+ scale_slider
1195
+ ],
1196
+ outputs=[combined_image, extracted_image, status_message]
1197
+ )
1198
+
1199
+
1200
+
1201
+ for btn, pos in position_mapping.items():
1202
+ btn.click(
1203
+ fn=lambda pos=pos: update_position(pos),
1204
+ outputs=position
1205
+ )
1206
+
1207
+
1208
  bg_prompt.change(
1209
  fn=update_controls,
1210
  inputs=bg_prompt,
 
1226
  queue=False
1227
  )
1228
 
1229
+
 
 
 
 
 
 
 
 
 
 
 
 
1230
 
1231
  add_text_btn.click(
1232
  fn=add_text_to_image,