Yiming-M commited on
Commit
b564f44
·
1 Parent(s): 61ba3dd

2025-08-01 08:54 🐛

Browse files
Files changed (1) hide show
  1. app.py +331 -78
app.py CHANGED
@@ -427,13 +427,13 @@ def predict(image: Image.Image, variant_dataset_metric: str):
427
  complete_zero_map = strucrual_zero_map + sampling_zero_map
428
 
429
  # Normalize maps for display purposes
430
- # def normalize_map(x: np.ndarray) -> np.ndarray:
431
- # """ Normalize the map to [0, 1] range for visualization. """
432
- # x_min = np.min(x)
433
- # x_max = np.max(x)
434
- # if x_max - x_min < EPS:
435
- # return np.zeros_like(x)
436
- # return (x - x_min) / (x_max - x_min + EPS)
437
 
438
  # strucrual_zero_map = normalize_map(strucrual_zero_map)
439
  # sampling_zero_map = normalize_map(sampling_zero_map)
@@ -442,8 +442,8 @@ def predict(image: Image.Image, variant_dataset_metric: str):
442
  # complete_zero_map = normalize_map(complete_zero_map)
443
 
444
  # Apply a colormap for better visualization
445
- # Options: 'viridis' (recommended), 'plasma', 'hot', 'inferno', 'jet'
446
- colormap = cm.get_cmap("viridis")
447
 
448
  # The colormap returns values in [0,1]. Scale to [0,255] and convert to uint8.
449
  den_map = (colormap(den_map) * 255).astype(np.uint8)
@@ -536,9 +536,108 @@ select option[value*="━━━━━━"] {
536
 
537
  /* 整体主题美化 */
538
  .gradio-container {
539
- max-width: 1400px !important;
540
  margin: 0 auto !important;
541
  font-family: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif !important;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
542
  }
543
 
544
  /* 标题样式 */
@@ -546,107 +645,219 @@ select option[value*="━━━━━━"] {
546
  text-align: center !important;
547
  color: #2563eb !important;
548
  font-weight: 700 !important;
549
- font-size: 2.5rem !important;
550
  margin-bottom: 0.5rem !important;
551
  background: linear-gradient(135deg, #667eea 0%, #764ba2 100%) !important;
552
  -webkit-background-clip: text !important;
553
  -webkit-text-fill-color: transparent !important;
 
554
  }
555
 
556
  /* 副标题样式 */
557
  .gr-markdown p {
558
  text-align: center !important;
559
  color: #6b7280 !important;
560
- font-size: 1.1rem !important;
561
  margin-bottom: 2rem !important;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
562
  }
563
 
564
  /* 按钮美化 */
565
  .gr-button {
566
  background: linear-gradient(135deg, #667eea 0%, #764ba2 100%) !important;
567
  border: none !important;
568
- border-radius: 8px !important;
569
  color: white !important;
570
  font-weight: 600 !important;
571
- font-size: 1rem !important;
572
- padding: 12px 24px !important;
573
  transition: all 0.3s ease !important;
574
- box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1) !important;
 
 
575
  }
576
 
577
  .gr-button:hover {
578
- transform: translateY(-2px) !important;
579
- box-shadow: 0 8px 25px -8px rgba(0, 0, 0, 0.3) !important;
 
580
  }
581
 
582
  /* 输入框样式 */
583
  .gr-textbox, .gr-dropdown {
584
- border-radius: 8px !important;
585
  border: 2px solid #e5e7eb !important;
586
- transition: border-color 0.3s ease !important;
 
 
 
587
  }
588
 
589
  .gr-textbox:focus, .gr-dropdown:focus {
590
  border-color: #667eea !important;
591
- box-shadow: 0 0 0 3px rgba(102, 126, 234, 0.1) !important;
 
592
  }
593
 
594
- /* 图像容器美化 */
595
  .gr-image {
596
- border-radius: 12px !important;
597
  overflow: hidden !important;
598
- box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1) !important;
599
  transition: all 0.3s ease !important;
 
 
 
600
  }
601
 
602
  .gr-image:hover {
603
- box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1) !important;
604
  transform: translateY(-2px) !important;
605
  }
606
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
607
  /* 列间距优化 */
608
  .gr-column {
609
  padding: 0 8px !important;
 
 
 
 
 
 
 
 
 
 
610
  }
611
 
612
  /* 标签美化 */
613
  .gr-label {
614
- font-weight: 600 !important;
615
  color: #374151 !important;
616
- margin-bottom: 8px !important;
 
 
 
617
  }
618
 
619
  /* 模型状态框特殊样式 */
620
  .gr-textbox[data-testid*="model-status"] {
621
- background: linear-gradient(135deg, #f3f4f6 0%, #e5e7eb 100%) !important;
622
  font-family: 'Monaco', 'Menlo', monospace !important;
623
- font-size: 0.9rem !important;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
624
  }
625
 
626
  /* 示例区域美化 */
627
  .gr-examples {
628
- background: #f9fafb !important;
629
- border-radius: 12px !important;
630
- padding: 20px !important;
631
- margin-top: 24px !important;
632
- border: 1px solid #e5e7eb !important;
 
 
633
  }
634
 
635
- /* 响应式设计 */
636
- @media (max-width: 768px) {
637
- .gradio-container {
638
- padding: 16px !important;
639
- }
640
-
641
- .gr-column {
642
- margin-bottom: 16px !important;
643
- }
644
-
645
- .gr-markdown h1 {
646
- font-size: 2rem !important;
647
- }
648
  }
649
 
 
 
650
  /* 加载动画 */
651
  @keyframes pulse {
652
  0%, 100% { opacity: 1; }
@@ -691,25 +902,43 @@ with gr.Blocks(css=css, theme=gr.themes.Soft(), title="ZIP Crowd Counting") as d
691
  Choose from different model variants: **ZIP-B** (Base), **ZIP-S** (Small), **ZIP-T** (Tiny), **ZIP-N** (Nano), **ZIP-P** (Pico)
692
  """)
693
 
 
694
  with gr.Row():
695
- with gr.Column(scale=1):
696
- # 模型选择区域
697
  with gr.Group():
698
  gr.Markdown("### 🤖 Model Configuration")
699
- model_dropdown = gr.Dropdown(
700
- choices=pretrained_models,
701
- value="ZIP-B @ NWPU-Crowd @ MAE",
702
- label="🎛️ Select Model & Dataset",
703
- info="Choose model variant, dataset, and evaluation metric"
704
- )
705
- model_status = gr.Textbox(
706
- label="📊 Model Status",
707
- value="🔄 No model loaded",
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
708
  interactive=False,
709
- elem_classes=["status-display"]
 
710
  )
711
-
712
- # 图像输入区域
 
 
713
  with gr.Group():
714
  gr.Markdown("### 📸 Image Input")
715
  input_img = gr.Image(
@@ -723,29 +952,53 @@ with gr.Blocks(css=css, theme=gr.themes.Soft(), title="ZIP Crowd Counting") as d
723
  variant="primary",
724
  size="lg"
725
  )
726
-
727
  with gr.Column(scale=1):
728
  with gr.Group():
729
  gr.Markdown("### 📊 Main Results")
730
- output_den_map = gr.Image(label="🎯 Predicted Density Map", type="pil")
731
- output_text = gr.Textbox(
732
- label="👥 Predicted Count",
733
- info="Total number of people detected"
734
  )
735
-
736
  with gr.Column(scale=1):
737
  with gr.Group():
738
  gr.Markdown("### 🔥 Hotspots")
739
- output_lambda_map = gr.Image(label="📈 Lambda Map", type="pil")
 
 
 
 
740
 
741
- # Zero Analysis section - 横向排列的三个图像
742
- with gr.Row():
743
- with gr.Group():
744
- gr.Markdown("### 🔍 Zero Analysis")
745
- with gr.Row():
746
- output_structural_zero_map = gr.Image(label="🏗️ Structural Zero Map", type="pil")
747
- output_sampling_zero_map = gr.Image(label="📊 Sampling Zero Map", type="pil")
748
- output_complete_zero_map = gr.Image(label="🎯 Complete Zero Map", type="pil")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
749
 
750
  # 当模型变化时,自动更新模型
751
  def on_model_change(variant_dataset_metric):
@@ -806,12 +1059,12 @@ with gr.Blocks(css=css, theme=gr.themes.Soft(), title="ZIP Crowd Counting") as d
806
 
807
  **📊 Main Results:**
808
  - **🎯 Density Map**: Shows where people are located with color intensity, modeled by (1-π) * λ
809
- - **� Predicted Count**: Total number of people detected in the image
810
 
811
  **🔍 Zero Analysis:**
812
  - **🏗️ Structural Zero Map**: Indicates regions that structurally cannot contain head annotations (e.g., walls, sky, torso, or background). These are governed by the π head, which estimates the probability that a region never contains people.
813
  - **📊 Sampling Zero Map**: Shows areas where people could be present but happen not to appear in the current image. These zeros are modeled by (1-π) * exp(-λ), where the expected count λ is near zero.
814
- - **🎯 Complete Zero Map**: A combined visualization of zero probabilities, capturing both structural and sampling zeros. This map reflects overall non-crowd likelihood per region.
815
 
816
  **🔥 Hotspots:**
817
  - **📈 Lambda Map**: Highlights areas with high expected crowd density. Each value represents the expected number of people in that region, modeled by the Poisson intensity (λ). This map focuses on *how many* people are likely to be present, **WITHOUT** assuming people could appear there. ⚠️ Lambda Map **NEEDS** to be combined with Structural Zero Map by (1-π) * λ to produce the final density map.
 
427
  complete_zero_map = strucrual_zero_map + sampling_zero_map
428
 
429
  # Normalize maps for display purposes
430
+ def normalize_map(x: np.ndarray) -> np.ndarray:
431
+ """ Normalize the map to [0, 1] range for visualization. """
432
+ x_min = np.min(x)
433
+ x_max = np.max(x)
434
+ if x_max - x_min < EPS:
435
+ return np.zeros_like(x)
436
+ return (x - x_min) / (x_max - x_min + EPS)
437
 
438
  # strucrual_zero_map = normalize_map(strucrual_zero_map)
439
  # sampling_zero_map = normalize_map(sampling_zero_map)
 
442
  # complete_zero_map = normalize_map(complete_zero_map)
443
 
444
  # Apply a colormap for better visualization
445
+ # Options: 'viridis', 'plasma', 'hot', 'inferno', 'jet' (recommended)
446
+ colormap = cm.get_cmap("jet")
447
 
448
  # The colormap returns values in [0,1]. Scale to [0,255] and convert to uint8.
449
  den_map = (colormap(den_map) * 255).astype(np.uint8)
 
536
 
537
  /* 整体主题美化 */
538
  .gradio-container {
539
+ max-width: 1600px !important;
540
  margin: 0 auto !important;
541
  font-family: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif !important;
542
+ background: linear-gradient(135deg, #f5f7fa 0%, #c3cfe2 100%) !important;
543
+ min-height: 100vh !important;
544
+ padding: 20px !important;
545
+ }
546
+
547
+ /* 响应式布局 - 自动调整列宽 */
548
+ @media (max-width: 1400px) {
549
+ .gradio-container {
550
+ max-width: 1200px !important;
551
+ padding: 18px !important;
552
+ }
553
+ }
554
+
555
+ @media (max-width: 1200px) {
556
+ .gradio-container {
557
+ max-width: 100% !important;
558
+ padding: 16px !important;
559
+ }
560
+
561
+ /* 在中等屏幕上,将第二行改为垂直布局 */
562
+ .gr-row:nth-of-type(2) {
563
+ flex-direction: column !important;
564
+ }
565
+
566
+ .gr-row:nth-of-type(2) .gr-column {
567
+ width: 100% !important;
568
+ margin-bottom: 20px !important;
569
+ }
570
+ }
571
+
572
+ @media (max-width: 900px) {
573
+ /* 在小屏幕上,将第三行也改为垂直布局 */
574
+ .gr-row:nth-of-type(3) {
575
+ flex-direction: column !important;
576
+ }
577
+
578
+ .gr-row:nth-of-type(3) .gr-column {
579
+ width: 100% !important;
580
+ margin-bottom: 20px !important;
581
+ }
582
+
583
+ /* Zero Analysis 在小屏幕上也改为垂直布局 */
584
+ .gr-group .gr-row {
585
+ flex-direction: column !important;
586
+ }
587
+
588
+ .gr-group .gr-row .gr-column {
589
+ width: 100% !important;
590
+ margin-bottom: 16px !important;
591
+ }
592
+ }
593
+
594
+ @media (max-width: 768px) {
595
+ .gradio-container {
596
+ padding: 12px !important;
597
+ }
598
+
599
+ .gr-column {
600
+ margin-bottom: 16px !important;
601
+ padding: 0 4px !important;
602
+ }
603
+
604
+ .gr-markdown h1 {
605
+ font-size: 2rem !important;
606
+ }
607
+
608
+ .gr-group {
609
+ padding: 16px !important;
610
+ }
611
+
612
+ .gr-button {
613
+ padding: 12px 24px !important;
614
+ font-size: 1rem !important;
615
+ }
616
+
617
+ /* 图像高度在小屏幕上调整 */
618
+ .gr-image {
619
+ height: 300px !important;
620
+ }
621
+
622
+ .zero-analysis-image {
623
+ height: 300px !important;
624
+ }
625
+ }
626
+
627
+ /* 超宽屏幕优化 */
628
+ @media (min-width: 1600px) {
629
+ .gradio-container {
630
+ max-width: 1800px !important;
631
+ padding: 24px !important;
632
+ }
633
+
634
+ .gr-image {
635
+ height: 450px !important;
636
+ }
637
+
638
+ .zero-analysis-image {
639
+ height: 450px !important;
640
+ }
641
  }
642
 
643
  /* 标题样式 */
 
645
  text-align: center !important;
646
  color: #2563eb !important;
647
  font-weight: 700 !important;
648
+ font-size: 3rem !important;
649
  margin-bottom: 0.5rem !important;
650
  background: linear-gradient(135deg, #667eea 0%, #764ba2 100%) !important;
651
  -webkit-background-clip: text !important;
652
  -webkit-text-fill-color: transparent !important;
653
+ text-shadow: 0 4px 8px rgba(0,0,0,0.1) !important;
654
  }
655
 
656
  /* 副标题样式 */
657
  .gr-markdown p {
658
  text-align: center !important;
659
  color: #6b7280 !important;
660
+ font-size: 1.2rem !important;
661
  margin-bottom: 2rem !important;
662
+ font-weight: 500 !important;
663
+ }
664
+
665
+ /* 主要布局组美化 */
666
+ .gr-group {
667
+ background: rgba(255, 255, 255, 0.9) !important;
668
+ backdrop-filter: blur(10px) !important;
669
+ border-radius: 20px !important;
670
+ padding: 24px !important;
671
+ margin: 16px 0 !important;
672
+ box-shadow: 0 8px 32px rgba(0, 0, 0, 0.1) !important;
673
+ border: 1px solid rgba(255, 255, 255, 0.2) !important;
674
+ transition: all 0.3s ease !important;
675
+ }
676
+
677
+ .gr-group:hover {
678
+ transform: translateY(-4px) !important;
679
+ box-shadow: 0 12px 40px rgba(0, 0, 0, 0.15) !important;
680
  }
681
 
682
  /* 按钮美化 */
683
  .gr-button {
684
  background: linear-gradient(135deg, #667eea 0%, #764ba2 100%) !important;
685
  border: none !important;
686
+ border-radius: 12px !important;
687
  color: white !important;
688
  font-weight: 600 !important;
689
+ font-size: 1.1rem !important;
690
+ padding: 16px 32px !important;
691
  transition: all 0.3s ease !important;
692
+ box-shadow: 0 6px 20px rgba(102, 126, 234, 0.3) !important;
693
+ text-transform: uppercase !important;
694
+ letter-spacing: 0.5px !important;
695
  }
696
 
697
  .gr-button:hover {
698
+ transform: translateY(-3px) !important;
699
+ box-shadow: 0 10px 30px rgba(102, 126, 234, 0.4) !important;
700
+ background: linear-gradient(135deg, #5a67d8 0%, #6b46c1 100%) !important;
701
  }
702
 
703
  /* 输入框样式 */
704
  .gr-textbox, .gr-dropdown {
705
+ border-radius: 12px !important;
706
  border: 2px solid #e5e7eb !important;
707
+ transition: all 0.3s ease !important;
708
+ background: rgba(255, 255, 255, 0.8) !important;
709
+ font-size: 1rem !important;
710
+ padding: 12px 16px !important;
711
  }
712
 
713
  .gr-textbox:focus, .gr-dropdown:focus {
714
  border-color: #667eea !important;
715
+ box-shadow: 0 0 0 4px rgba(102, 126, 234, 0.1) !important;
716
+ background: rgba(255, 255, 255, 1) !important;
717
  }
718
 
719
+ /* 图像容器美化 - 统一尺寸 */
720
  .gr-image {
721
+ border-radius: 16px !important;
722
  overflow: hidden !important;
723
+ box-shadow: 0 8px 25px rgba(0, 0, 0, 0.15) !important;
724
  transition: all 0.3s ease !important;
725
+ background: white !important;
726
+ height: 400px !important;
727
+ width: 100% !important;
728
  }
729
 
730
  .gr-image:hover {
731
+ box-shadow: 0 15px 35px rgba(0, 0, 0, 0.2) !important;
732
  transform: translateY(-2px) !important;
733
  }
734
 
735
+ /* 确保第二行组件等高 */
736
+ .gr-row:nth-of-type(2) .gr-group {
737
+ height: auto !important;
738
+ min-height: 180px !important;
739
+ display: flex !important;
740
+ flex-direction: column !important;
741
+ }
742
+
743
+ .gr-row:nth-of-type(2) .gr-group > * {
744
+ flex: 1 !important;
745
+ }
746
+
747
+ /* 确保第二行的文本框具有相同的高度 */
748
+ .gr-row:nth-of-type(2) .gr-textbox {
749
+ min-height: 80px !important;
750
+ display: flex !important;
751
+ align-items: center !important;
752
+ }
753
+
754
+ /* 确保第二行下拉菜单区域等高 */
755
+ .gr-row:nth-of-type(2) .gr-dropdown {
756
+ min-height: 60px !important;
757
+ }
758
+
759
  /* 列间距优化 */
760
  .gr-column {
761
  padding: 0 8px !important;
762
+ margin-bottom: 16px !important;
763
+ }
764
+
765
+ /* 第二行特殊布局调整 */
766
+ .gr-row:nth-of-type(2) .gr-column:first-child {
767
+ padding-right: 12px !important;
768
+ }
769
+
770
+ .gr-row:nth-of-type(2) .gr-column:last-child {
771
+ padding-left: 12px !important;
772
  }
773
 
774
  /* 标签美化 */
775
  .gr-label {
776
+ font-weight: 700 !important;
777
  color: #374151 !important;
778
+ margin-bottom: 12px !important;
779
+ font-size: 1.1rem !important;
780
+ text-transform: uppercase !important;
781
+ letter-spacing: 0.5px !important;
782
  }
783
 
784
  /* 模型状态框特殊样式 */
785
  .gr-textbox[data-testid*="model-status"] {
786
+ background: linear-gradient(135deg, #ecfdf5 0%, #d1fae5 100%) !important;
787
  font-family: 'Monaco', 'Menlo', monospace !important;
788
+ font-size: 0.95rem !important;
789
+ font-weight: 600 !important;
790
+ border: 2px solid #10b981 !important;
791
+ }
792
+
793
+ /* Zero Analysis 特殊布局 */
794
+ .gr-row:has(.gr-image[label*="Zero"]) {
795
+ background: linear-gradient(135deg, rgba(255,255,255,0.95) 0%, rgba(248,250,252,0.95) 100%) !important;
796
+ border-radius: 20px !important;
797
+ padding: 24px !important;
798
+ margin: 20px 0 !important;
799
+ box-shadow: 0 10px 30px rgba(0, 0, 0, 0.1) !important;
800
+ }
801
+
802
+ /* Zero Analysis 图像特殊样式 - 统一尺寸 */
803
+ .zero-analysis-image {
804
+ border: 3px solid transparent !important;
805
+ background: linear-gradient(white, white) padding-box,
806
+ linear-gradient(135deg, #667eea, #764ba2) border-box !important;
807
+ border-radius: 16px !important;
808
+ transition: all 0.3s ease !important;
809
+ height: 400px !important;
810
+ width: 100% !important;
811
+ }
812
+
813
+ .zero-analysis-image:hover {
814
+ transform: scale(1.02) !important;
815
+ box-shadow: 0 12px 35px rgba(102, 126, 234, 0.2) !important;
816
+ }
817
+
818
+ /* 确保所有行的组件等高 */
819
+ .gr-row .gr-group {
820
+ min-height: 100% !important;
821
+ display: flex !important;
822
+ flex-direction: column !important;
823
+ }
824
+
825
+ .gr-row .gr-column {
826
+ height: 100% !important;
827
+ }
828
+
829
+ /* 统计信息卡片美化 */
830
+ .gr-textbox[label*="Count"] {
831
+ background: linear-gradient(135deg, #ecfcff 0%, #cffafe 100%) !important;
832
+ border: 2px solid #06b6d4 !important;
833
+ font-size: 1.2rem !important;
834
+ font-weight: 700 !important;
835
+ text-align: center !important;
836
+ color: #0e7490 !important;
837
  }
838
 
839
  /* 示例区域美化 */
840
  .gr-examples {
841
+ background: linear-gradient(135deg, rgba(255,255,255,0.9) 0%, rgba(248,250,252,0.9) 100%) !important;
842
+ backdrop-filter: blur(10px) !important;
843
+ border-radius: 20px !important;
844
+ padding: 30px !important;
845
+ margin-top: 30px !important;
846
+ border: 1px solid rgba(255, 255, 255, 0.2) !important;
847
+ box-shadow: 0 10px 30px rgba(0, 0, 0, 0.1) !important;
848
  }
849
 
850
+ /* Accordion 美化 */
851
+ .gr-accordion {
852
+ background: rgba(255, 255, 255, 0.8) !important;
853
+ border-radius: 16px !important;
854
+ margin: 16px 0 !important;
855
+ border: 1px solid rgba(255, 255, 255, 0.2) !important;
856
+ box-shadow: 0 6px 20px rgba(0, 0, 0, 0.08) !important;
 
 
 
 
 
 
857
  }
858
 
859
+ /* 响应式设计 - 移除旧的媒体查询,已在上方重新定义 */
860
+
861
  /* 加载动画 */
862
  @keyframes pulse {
863
  0%, 100% { opacity: 1; }
 
902
  Choose from different model variants: **ZIP-B** (Base), **ZIP-S** (Small), **ZIP-T** (Tiny), **ZIP-N** (Nano), **ZIP-P** (Pico)
903
  """)
904
 
905
+ # 第二行:模型配置区域(2/3宽度)和预测结果(1/3宽度)
906
  with gr.Row():
907
+ with gr.Column(scale=2):
 
908
  with gr.Group():
909
  gr.Markdown("### 🤖 Model Configuration")
910
+ with gr.Row():
911
+ with gr.Column(scale=1):
912
+ model_dropdown = gr.Dropdown(
913
+ choices=pretrained_models,
914
+ value="ZIP-B @ NWPU-Crowd @ MAE",
915
+ label="🎛️ Select Model & Dataset",
916
+ info="Choose model variant, dataset, and evaluation metric"
917
+ )
918
+
919
+ with gr.Column(scale=1):
920
+ model_status = gr.Textbox(
921
+ label="📊 Model Status",
922
+ value="🔄 No model loaded",
923
+ interactive=False,
924
+ elem_classes=["status-display"],
925
+ lines=3
926
+ )
927
+
928
+ with gr.Column(scale=1):
929
+ with gr.Group():
930
+ gr.Markdown("### 🧙 Predicted Count")
931
+ output_text = gr.Textbox(
932
+ label="Result",
933
+ value="",
934
  interactive=False,
935
+ info="Total number of people detected",
936
+ lines=3
937
  )
938
+
939
+ # 第三行:主要图像(输入图像、密度图、Lambda图)
940
+ with gr.Row():
941
+ with gr.Column(scale=1):
942
  with gr.Group():
943
  gr.Markdown("### 📸 Image Input")
944
  input_img = gr.Image(
 
952
  variant="primary",
953
  size="lg"
954
  )
955
+
956
  with gr.Column(scale=1):
957
  with gr.Group():
958
  gr.Markdown("### 📊 Main Results")
959
+ output_den_map = gr.Image(
960
+ label="🎯 Predicted Density Map",
961
+ type="pil",
962
+ height=400
963
  )
964
+
965
  with gr.Column(scale=1):
966
  with gr.Group():
967
  gr.Markdown("### 🔥 Hotspots")
968
+ output_lambda_map = gr.Image(
969
+ label="📈 Lambda Map",
970
+ type="pil",
971
+ height=400
972
+ )
973
 
974
+ # 第四行:Zero Analysis - 全宽,内部三列等宽
975
+ with gr.Group():
976
+ gr.Markdown("### 🔍 Zero Analysis")
977
+ gr.Markdown("*Explore different types of zero predictions in crowd analysis*")
978
+ with gr.Row():
979
+ with gr.Column(scale=1):
980
+ output_structural_zero_map = gr.Image(
981
+ label="🏗️ Structural Zero Map",
982
+ type="pil",
983
+ height=400,
984
+ elem_classes=["zero-analysis-image"]
985
+ )
986
+
987
+ with gr.Column(scale=1):
988
+ output_sampling_zero_map = gr.Image(
989
+ label="📊 Sampling Zero Map",
990
+ type="pil",
991
+ height=400,
992
+ elem_classes=["zero-analysis-image"]
993
+ )
994
+
995
+ with gr.Column(scale=1):
996
+ output_complete_zero_map = gr.Image(
997
+ label="👺 Complete Zero Map",
998
+ type="pil",
999
+ height=400,
1000
+ elem_classes=["zero-analysis-image"]
1001
+ )
1002
 
1003
  # 当模型变化时,自动更新模型
1004
  def on_model_change(variant_dataset_metric):
 
1059
 
1060
  **📊 Main Results:**
1061
  - **🎯 Density Map**: Shows where people are located with color intensity, modeled by (1-π) * λ
1062
+ - **🧙 Predicted Count**: Total number of people detected in the image
1063
 
1064
  **🔍 Zero Analysis:**
1065
  - **🏗️ Structural Zero Map**: Indicates regions that structurally cannot contain head annotations (e.g., walls, sky, torso, or background). These are governed by the π head, which estimates the probability that a region never contains people.
1066
  - **📊 Sampling Zero Map**: Shows areas where people could be present but happen not to appear in the current image. These zeros are modeled by (1-π) * exp(-λ), where the expected count λ is near zero.
1067
+ - **👺 Complete Zero Map**: A combined visualization of zero probabilities, capturing both structural and sampling zeros. This map reflects overall non-crowd likelihood per region.
1068
 
1069
  **🔥 Hotspots:**
1070
  - **📈 Lambda Map**: Highlights areas with high expected crowd density. Each value represents the expected number of people in that region, modeled by the Poisson intensity (λ). This map focuses on *how many* people are likely to be present, **WITHOUT** assuming people could appear there. ⚠️ Lambda Map **NEEDS** to be combined with Structural Zero Map by (1-π) * λ to produce the final density map.