Spaces:
Paused
Paused
Upload 3 files
Browse files- README.md +9 -1
- app.py +46 -30
- requirements.txt +12 -3
README.md
CHANGED
|
@@ -4,7 +4,7 @@ emoji: 🔍
|
|
| 4 |
colorFrom: blue
|
| 5 |
colorTo: green
|
| 6 |
sdk: gradio
|
| 7 |
-
sdk_version:
|
| 8 |
app_file: app.py
|
| 9 |
pinned: false
|
| 10 |
license: gpl-3.0
|
|
@@ -72,6 +72,14 @@ tags:
|
|
| 72 |
- **Unknown Words**: If a word isn't in the dictionary, it will be passed through unchanged. Check the Chinese preview to verify translations.
|
| 73 |
- **GPU Required**: This demo requires GPU acceleration. If you encounter memory errors, try using a smaller model.
|
| 74 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 75 |
## 📖 Citation
|
| 76 |
|
| 77 |
If you use WeDetect in your research, please cite:
|
|
|
|
| 4 |
colorFrom: blue
|
| 5 |
colorTo: green
|
| 6 |
sdk: gradio
|
| 7 |
+
sdk_version: 5.50.0
|
| 8 |
app_file: app.py
|
| 9 |
pinned: false
|
| 10 |
license: gpl-3.0
|
|
|
|
| 72 |
- **Unknown Words**: If a word isn't in the dictionary, it will be passed through unchanged. Check the Chinese preview to verify translations.
|
| 73 |
- **GPU Required**: This demo requires GPU acceleration. If you encounter memory errors, try using a smaller model.
|
| 74 |
|
| 75 |
+
## 🔧 Technical Details
|
| 76 |
+
|
| 77 |
+
This Space uses:
|
| 78 |
+
- **Gradio 5.50.0+** - Compatible with huggingface_hub 1.x
|
| 79 |
+
- **huggingface_hub 1.x** - Latest HF Hub API
|
| 80 |
+
- **MMDetection 3.3.0** - Object detection framework
|
| 81 |
+
- **@spaces.GPU** decorator for GPU acceleration
|
| 82 |
+
|
| 83 |
## 📖 Citation
|
| 84 |
|
| 85 |
If you use WeDetect in your research, please cite:
|
app.py
CHANGED
|
@@ -11,12 +11,17 @@ Features:
|
|
| 11 |
- Automatic English→Chinese translation with editable preview
|
| 12 |
- Adjustable confidence threshold
|
| 13 |
- Visual results with bounding boxes
|
|
|
|
|
|
|
|
|
|
|
|
|
| 14 |
"""
|
| 15 |
|
| 16 |
import os
|
| 17 |
import sys
|
| 18 |
import tempfile
|
| 19 |
import colorsys
|
|
|
|
| 20 |
from typing import List, Tuple, Optional
|
| 21 |
|
| 22 |
import gradio as gr
|
|
@@ -134,6 +139,7 @@ ENGLISH_TO_CHINESE = {
|
|
| 134 |
"kite": "风筝", "balloon": "气球", "flag": "旗帜",
|
| 135 |
}
|
| 136 |
|
|
|
|
| 137 |
# ============================================================================
|
| 138 |
# TRANSLATION FUNCTIONS
|
| 139 |
# ============================================================================
|
|
@@ -175,10 +181,10 @@ def translate_class_list(classes_text: str, input_mode: str) -> str:
|
|
| 175 |
|
| 176 |
if input_mode == "English":
|
| 177 |
translated = [translate_to_chinese(c) for c in classes]
|
| 178 |
-
return ','.join(translated)
|
| 179 |
else:
|
| 180 |
# Already Chinese, return as-is
|
| 181 |
-
return ','.join(classes)
|
| 182 |
|
| 183 |
|
| 184 |
# ============================================================================
|
|
@@ -188,6 +194,7 @@ def translate_class_list(classes_text: str, input_mode: str) -> str:
|
|
| 188 |
_model_cache = {}
|
| 189 |
_repo_path = None
|
| 190 |
|
|
|
|
| 191 |
def setup_repo():
|
| 192 |
"""Clone the WeDetect repository if not already present."""
|
| 193 |
global _repo_path
|
|
@@ -195,18 +202,21 @@ def setup_repo():
|
|
| 195 |
if _repo_path is not None and os.path.exists(_repo_path):
|
| 196 |
return _repo_path
|
| 197 |
|
| 198 |
-
import subprocess
|
| 199 |
-
|
| 200 |
repo_dir = "/tmp/WeDetect"
|
| 201 |
|
| 202 |
if not os.path.exists(repo_dir):
|
| 203 |
print("📥 Cloning WeDetect repository...")
|
| 204 |
-
|
| 205 |
-
|
| 206 |
-
|
| 207 |
-
|
| 208 |
-
|
| 209 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 210 |
|
| 211 |
# Add to Python path for imports
|
| 212 |
if repo_dir not in sys.path:
|
|
@@ -279,7 +289,7 @@ def draw_detections(
|
|
| 279 |
labels: np.ndarray,
|
| 280 |
class_names: List[str],
|
| 281 |
threshold: float
|
| 282 |
-
) -> Image.Image:
|
| 283 |
"""Draw bounding boxes and labels on an image."""
|
| 284 |
|
| 285 |
img_draw = image.copy()
|
|
@@ -291,8 +301,8 @@ def draw_detections(
|
|
| 291 |
"/usr/share/fonts/truetype/wqy/wqy-zenhei.ttc",
|
| 292 |
"/usr/share/fonts/truetype/wqy/wqy-microhei.ttc",
|
| 293 |
"/usr/share/fonts/opentype/noto/NotoSansCJK-Regular.ttc",
|
| 294 |
-
"simsun.ttc",
|
| 295 |
"/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf",
|
|
|
|
| 296 |
]
|
| 297 |
|
| 298 |
for font_path in font_paths:
|
|
@@ -303,7 +313,11 @@ def draw_detections(
|
|
| 303 |
continue
|
| 304 |
|
| 305 |
if font is None:
|
| 306 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 307 |
|
| 308 |
colors = generate_colors(len(class_names))
|
| 309 |
detection_count = 0
|
|
@@ -409,9 +423,13 @@ def detect_objects(
|
|
| 409 |
|
| 410 |
finally:
|
| 411 |
# Cleanup
|
| 412 |
-
os.
|
|
|
|
| 413 |
|
| 414 |
except Exception as e:
|
|
|
|
|
|
|
|
|
|
| 415 |
return image, f"❌ Error: {str(e)}"
|
| 416 |
|
| 417 |
|
|
@@ -470,22 +488,20 @@ def create_demo():
|
|
| 470 |
lines=2
|
| 471 |
)
|
| 472 |
|
| 473 |
-
|
| 474 |
-
|
| 475 |
-
|
| 476 |
-
|
| 477 |
-
|
| 478 |
-
|
| 479 |
-
|
| 480 |
-
)
|
| 481 |
|
| 482 |
-
|
| 483 |
-
|
| 484 |
-
|
| 485 |
-
|
| 486 |
-
|
| 487 |
-
|
| 488 |
-
)
|
| 489 |
|
| 490 |
detect_btn = gr.Button(
|
| 491 |
"🔍 Detect Objects",
|
|
@@ -507,7 +523,7 @@ def create_demo():
|
|
| 507 |
lines=2
|
| 508 |
)
|
| 509 |
|
| 510 |
-
# Examples
|
| 511 |
gr.Markdown("### 📸 Examples")
|
| 512 |
gr.Examples(
|
| 513 |
examples=[
|
|
|
|
| 11 |
- Automatic English→Chinese translation with editable preview
|
| 12 |
- Adjustable confidence threshold
|
| 13 |
- Visual results with bounding boxes
|
| 14 |
+
|
| 15 |
+
Compatible with:
|
| 16 |
+
- Gradio 5.50.0+ / 6.x
|
| 17 |
+
- huggingface_hub 1.x
|
| 18 |
"""
|
| 19 |
|
| 20 |
import os
|
| 21 |
import sys
|
| 22 |
import tempfile
|
| 23 |
import colorsys
|
| 24 |
+
import subprocess
|
| 25 |
from typing import List, Tuple, Optional
|
| 26 |
|
| 27 |
import gradio as gr
|
|
|
|
| 139 |
"kite": "风筝", "balloon": "气球", "flag": "旗帜",
|
| 140 |
}
|
| 141 |
|
| 142 |
+
|
| 143 |
# ============================================================================
|
| 144 |
# TRANSLATION FUNCTIONS
|
| 145 |
# ============================================================================
|
|
|
|
| 181 |
|
| 182 |
if input_mode == "English":
|
| 183 |
translated = [translate_to_chinese(c) for c in classes]
|
| 184 |
+
return ', '.join(translated)
|
| 185 |
else:
|
| 186 |
# Already Chinese, return as-is
|
| 187 |
+
return ', '.join(classes)
|
| 188 |
|
| 189 |
|
| 190 |
# ============================================================================
|
|
|
|
| 194 |
_model_cache = {}
|
| 195 |
_repo_path = None
|
| 196 |
|
| 197 |
+
|
| 198 |
def setup_repo():
|
| 199 |
"""Clone the WeDetect repository if not already present."""
|
| 200 |
global _repo_path
|
|
|
|
| 202 |
if _repo_path is not None and os.path.exists(_repo_path):
|
| 203 |
return _repo_path
|
| 204 |
|
|
|
|
|
|
|
| 205 |
repo_dir = "/tmp/WeDetect"
|
| 206 |
|
| 207 |
if not os.path.exists(repo_dir):
|
| 208 |
print("📥 Cloning WeDetect repository...")
|
| 209 |
+
try:
|
| 210 |
+
subprocess.run(
|
| 211 |
+
["git", "clone", "--depth", "1", "https://github.com/WeChatCV/WeDetect.git", repo_dir],
|
| 212 |
+
check=True,
|
| 213 |
+
capture_output=True,
|
| 214 |
+
text=True
|
| 215 |
+
)
|
| 216 |
+
print("✅ Repository cloned!")
|
| 217 |
+
except subprocess.CalledProcessError as e:
|
| 218 |
+
print(f"❌ Failed to clone repository: {e.stderr}")
|
| 219 |
+
raise
|
| 220 |
|
| 221 |
# Add to Python path for imports
|
| 222 |
if repo_dir not in sys.path:
|
|
|
|
| 289 |
labels: np.ndarray,
|
| 290 |
class_names: List[str],
|
| 291 |
threshold: float
|
| 292 |
+
) -> Tuple[Image.Image, int]:
|
| 293 |
"""Draw bounding boxes and labels on an image."""
|
| 294 |
|
| 295 |
img_draw = image.copy()
|
|
|
|
| 301 |
"/usr/share/fonts/truetype/wqy/wqy-zenhei.ttc",
|
| 302 |
"/usr/share/fonts/truetype/wqy/wqy-microhei.ttc",
|
| 303 |
"/usr/share/fonts/opentype/noto/NotoSansCJK-Regular.ttc",
|
|
|
|
| 304 |
"/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf",
|
| 305 |
+
"simsun.ttc",
|
| 306 |
]
|
| 307 |
|
| 308 |
for font_path in font_paths:
|
|
|
|
| 313 |
continue
|
| 314 |
|
| 315 |
if font is None:
|
| 316 |
+
try:
|
| 317 |
+
font = ImageFont.load_default(size=16)
|
| 318 |
+
except TypeError:
|
| 319 |
+
# Older Pillow versions don't support size argument
|
| 320 |
+
font = ImageFont.load_default()
|
| 321 |
|
| 322 |
colors = generate_colors(len(class_names))
|
| 323 |
detection_count = 0
|
|
|
|
| 423 |
|
| 424 |
finally:
|
| 425 |
# Cleanup
|
| 426 |
+
if os.path.exists(temp_path):
|
| 427 |
+
os.unlink(temp_path)
|
| 428 |
|
| 429 |
except Exception as e:
|
| 430 |
+
import traceback
|
| 431 |
+
error_msg = f"❌ Error: {str(e)}\n{traceback.format_exc()}"
|
| 432 |
+
print(error_msg)
|
| 433 |
return image, f"❌ Error: {str(e)}"
|
| 434 |
|
| 435 |
|
|
|
|
| 488 |
lines=2
|
| 489 |
)
|
| 490 |
|
| 491 |
+
threshold_slider = gr.Slider(
|
| 492 |
+
minimum=0.0,
|
| 493 |
+
maximum=1.0,
|
| 494 |
+
value=0.3,
|
| 495 |
+
step=0.05,
|
| 496 |
+
label="📊 Confidence Threshold"
|
| 497 |
+
)
|
|
|
|
| 498 |
|
| 499 |
+
model_dropdown = gr.Dropdown(
|
| 500 |
+
choices=["large", "base", "tiny"],
|
| 501 |
+
value=DEFAULT_MODEL,
|
| 502 |
+
label="🧠 Model Size",
|
| 503 |
+
info="Large=best quality, Tiny=fastest"
|
| 504 |
+
)
|
|
|
|
| 505 |
|
| 506 |
detect_btn = gr.Button(
|
| 507 |
"🔍 Detect Objects",
|
|
|
|
| 523 |
lines=2
|
| 524 |
)
|
| 525 |
|
| 526 |
+
# Examples section
|
| 527 |
gr.Markdown("### 📸 Examples")
|
| 528 |
gr.Examples(
|
| 529 |
examples=[
|
requirements.txt
CHANGED
|
@@ -1,11 +1,20 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
# Core ML frameworks
|
| 2 |
torch>=2.0.0
|
| 3 |
torchvision>=0.15.0
|
| 4 |
|
| 5 |
# Gradio and HF integration
|
| 6 |
-
|
|
|
|
|
|
|
| 7 |
spaces
|
| 8 |
-
huggingface_hub
|
| 9 |
|
| 10 |
# Image processing
|
| 11 |
Pillow>=9.0.0
|
|
@@ -26,4 +35,4 @@ terminaltables
|
|
| 26 |
jsonlines
|
| 27 |
tabulate
|
| 28 |
|
| 29 |
-
# Note: git is
|
|
|
|
| 1 |
+
# =============================================================================
|
| 2 |
+
# WeDetect HuggingFace Spaces - Requirements
|
| 3 |
+
# =============================================================================
|
| 4 |
+
# Compatible with Gradio 5.50.0+ and huggingface_hub 1.x
|
| 5 |
+
# The HfFolder class was removed in huggingface_hub 1.0, and Gradio 5.50.0+
|
| 6 |
+
# updated to use get_token() instead.
|
| 7 |
+
# =============================================================================
|
| 8 |
+
|
| 9 |
# Core ML frameworks
|
| 10 |
torch>=2.0.0
|
| 11 |
torchvision>=0.15.0
|
| 12 |
|
| 13 |
# Gradio and HF integration
|
| 14 |
+
# Gradio 5.50.0+ is compatible with huggingface_hub 1.x (uses get_token() not HfFolder)
|
| 15 |
+
gradio>=5.50.0
|
| 16 |
+
huggingface_hub>=1.0.0
|
| 17 |
spaces
|
|
|
|
| 18 |
|
| 19 |
# Image processing
|
| 20 |
Pillow>=9.0.0
|
|
|
|
| 35 |
jsonlines
|
| 36 |
tabulate
|
| 37 |
|
| 38 |
+
# Note: git is pre-installed in HF Spaces (required for cloning config files)
|