Content
# qwen-groundingdino-visual-mcp
> **LM Studio + Qwen VL + GroundingDINO** — üretim kalitesinde açık-kelime dağarcıklı nesne tespiti ve zekice yerleştirme öneri motoru, MCP protokolü üzerinden.
---
## Mimari Özet
```
┌──────────────────────┐ stdio ┌──────────────────────────────────────┐
│ LM Studio │◄───────────►│ annotator_mcp.py │
│ Qwen VL (orkestratör)│ │ GroundingDINO (tespit motoru) │
│ function-calling UI │ │ Kural motoru (yerleştirme) │
└──────────────────────┘ │ Oturum belleği (session_memory.json) │
└──────────────────────────────────────┘
```
| Bileşen | Teknoloji | Notlar |
|---|---|---|
| Orkestratör LLM | Qwen VL (LM Studio'da) | Multimodal; ne zaman hangi tool'u çağıracağına kendisi karar verir |
| Tespit motoru | `IDEA-Research/grounding-dino-base` | `transformers` üzerinden, **trust_remote_code=False** |
| Transport | stdio | HTTP/ağ bağlantısı **yoktur** |
| Model format | safetensors | GGUF/llama.cpp ile **hiçbir ilgisi yoktur** |
---
## Kurulum
### 1. Python sanal ortamı oluştur
```bash
python -m venv .venv
# Windows
.venv\Scripts\activate
# Linux/macOS
source .venv/bin/activate
```
### 2. Bağımlılıkları yükle
**CPU-only (varsayılan):**
```bash
pip install -r requirements.txt
```
**CUDA 12.1 (GPU hızlandırma):**
```bash
pip install torch==2.4.1+cu121 torchvision==0.19.1+cu121 \
--index-url https://download.pytorch.org/whl/cu121
# Geri kalanı (torch'u tekrar yüklememek için --no-deps kullanma, sadece requirements'i yükle)
pip install transformers==4.44.2 accelerate==0.34.2 huggingface_hub==0.25.1 \
Pillow==10.4.0 numpy==1.26.4 mcp==1.3.0 tokenizers==0.19.1
```
**CUDA 11.8:**
```bash
pip install torch==2.4.1+cu118 torchvision==0.19.1+cu118 \
--index-url https://download.pytorch.org/whl/cu118
# ardından yukarıdaki diğer paketleri yükle
```
### 3. Sözdizimi doğrulaması
```bash
python -m py_compile annotator_mcp.py && echo "OK — sözdizimi hatası yok"
```
### 4. Model ön-indirme (isteğe bağlı)
İlk tool çağrısında model otomatik indirilir. İnternetsiz ortamlar için önden indirebilirsiniz:
```bash
python -c "
from transformers import AutoProcessor, AutoModelForZeroShotObjectDetection
AutoProcessor.from_pretrained('IDEA-Research/grounding-dino-base')
AutoModelForZeroShotObjectDetection.from_pretrained('IDEA-Research/grounding-dino-base')
print('Model önbelleğe alındı.')
"
```
---
## LM Studio Yapılandırması — `mcp.json`
LM Studio'nun MCP ayarlar dosyasına aşağıdaki bloğu ekleyin:
```json
{
"mcpServers": {
"groundingdino-annotator": {
"command": "python",
"args": [
"C:/Users/ASUS/Projects/qwen-groundingdino-visual-mcp/annotator_mcp.py"
],
"env": {
"GROUNDING_DINO_MODEL_ID": "IDEA-Research/grounding-dino-base",
"BOX_THRESHOLD": "0.35",
"TEXT_THRESHOLD": "0.25"
}
}
}
}
```
> **Not:** `command` için sanal ortamdaki Python yolunu kullanmak daha güvenlidir:
> `"C:/Users/ASUS/Projects/qwen-groundingdino-visual-mcp/.venv/Scripts/python.exe"`
### Hafif model (daha az bellek):
```json
"GROUNDING_DINO_MODEL_ID": "IDEA-Research/grounding-dino-tiny"
```
---
## Örnek Sohbet Akışı
### Senaryo: "Masadaki vazoyu bul, ardından yanına bir kupa öner"
```
Kullanıcı:
C:/sahne/mutfak.jpg görüntüsündeki masayı ve vazoyu bul.
Qwen → detect_objects({
"image_path": "C:/sahne/mutfak.jpg",
"query": "masa, vazo",
"session_id": "mutfak_sahnesi"
})
Sunucu yanıtı:
{
"session_id": "mutfak_sahnesi",
"count": 2,
"detections": [
{ "label": "masa", "score": 0.82, "bbox": [120, 450, 880, 950] },
{ "label": "vazo", "score": 0.74, "bbox": [400, 200, 600, 450] }
]
}
---
Kullanıcı:
Vazonun sağına ideal kupa yerleştirme noktasını öner.
Qwen → suggest_ideal_placements({
"session_id": "mutfak_sahnesi",
"target_object": "kupa",
"reference_object": "vazo",
"relation": "right_of"
})
Sunucu yanıtı:
{
"suggested_bbox": [610, 250, 760, 440],
"score": 0.8712,
"rule_breakdown": {
"overlap_penalty": 1.0,
"edge_margin": 0.82,
"spacing_from_objects": 0.61,
"prefer_center": 0.73
}
}
---
Kullanıcı:
Bu koordinatları görüntüye çiz ve kaydet.
Qwen → annotate_image({
"image_path": "C:/sahne/mutfak.jpg",
"output_path": "C:/sahne/mutfak_annotated.jpg",
"session_id": "mutfak_sahnesi",
"annotations": [
{ "label": "masa", "bbox": [120, 450, 880, 950] },
{ "label": "vazo", "bbox": [400, 200, 600, 450] },
{ "label": "kupa", "bbox": [610, 250, 760, 440] }
]
})
Sonuç: 3 nesne kırmızı çerçeve + etiketle işaretlenmiş görüntü kaydedildi.
```
---
## Koordinat Sistemi
Tüm bbox koordinatları **0-1000 normalize skalasında** `[x1, y1, x2, y2]` formatındadır:
```
(0,0) ─────────────── (1000,0)
│ │
│ görüntü alanı │
│ │
(0,1000) ───────────(1000,1000)
```
Bu skala Qwen VL'nin koordinat çıktısıyla tutarlıdır.
---
## Tool Referansı
| Tool | Amaç | Zorunlu Parametreler |
|------|-------|----------------------|
| `detect_objects` | GroundingDINO tespiti | `image_path`, `query` |
| `register_detected_objects` | Manuel nesne kaydı | `session_id`, `objects` |
| `annotate_image` | Görüntü üzerine çizim | `image_path`, `output_path`, `annotations` |
| `suggest_ideal_placements` | Yerleştirme önerisi | `session_id`, `target_object` |
| `list_session_objects` | Oturum durumu | `session_id` |
| `reset_session` | Bellek temizleme | `session_id` |
---
## Doğrulama Testi
Aşağıdaki Python betiği, MCP olmadan doğrudan sunucunun tespit fonksiyonunu test eder:
```python
# test_detect.py
import sys
sys.path.insert(0, ".")
from annotator_mcp import format_groundingdino_query, _run_detection_sync
# 1. Sorgu formatlama testi
q = format_groundingdino_query("Masa, VAZO, Kapı")
assert q == "masa . vazo . kapı .", f"Beklenen 'masa . vazo . kapı .' ama '{q}' geldi"
print(f"✓ format_groundingdino_query: '{q}'")
# 2. Gerçek tespit testi (bir görüntü gerektirir)
TEST_IMAGE = "test.jpg" # Var olan bir .jpg yolu girin
import os
if os.path.isfile(TEST_IMAGE):
results = _run_detection_sync(
image_path=TEST_IMAGE,
query="insan, masa, sandalye",
box_threshold=0.35,
text_threshold=0.25,
session_id="test_session",
)
print(f"✓ Tespit tamamlandı: {len(results)} nesne bulundu")
for r in results:
print(f" [{r['label']:15s}] skor={r['score']:.3f} bbox={r['bbox']}")
else:
print(f"⚠ {TEST_IMAGE} bulunamadı — tespit adımı atlandı")
print("\n✓ Tüm birim testler geçti.")
```
Çalıştırma:
```bash
python test_detect.py
```
Beklenen çıktı formatı:
```json
{
"session_id": "test_session",
"count": 2,
"detections": [
{ "label": "masa", "score": 0.7812, "bbox": [45, 380, 955, 920] },
{ "label": "sandalye","score": 0.6531, "bbox": [20, 420, 300, 890] }
]
}
```
---
## ⚠️ Bilinen Tuzaklar
> Bu bölüm, proje geliştirme sırasında gerçekten yaşanan sorunları belgeler.
> Gelecekteki geliştiriciler ve AI sistemleri için rehber niteliğindedir.
### 1. GGUF vs safetensors karışıklığı
**Sorun:** GroundingDINO'yu LM Studio'nun GGUF/llama.cpp arayüzüyle yüklemeye çalışmak.
**Belirti:** `gguf_init_from_reader: tensor name too long` veya benzeri anlamsız hatalar.
**Neden:** GroundingDINO (ve genel olarak tüm `trust_remote_code`/özel mimari modeller) llama.cpp ekosistemiyle **uyumlu değildir**. Bu model safetensors formatındadır ve GGUF'a dönüştürülemez.
**Çözüm:** Model **yalnızca** bu Python süreci içinde `transformers.from_pretrained()` ile, orijinal safetensors formatında yönetilmelidir. LM Studio'nun model arayüzüne **hiç dokunmayın**.
---
### 2. transformers sürüm uyumsuzluğu
**Sorun:** `requirements.txt`'te `transformers` sürümü pinlenmemişse en güncel sürüm kurulabilir ve API kırılabilir.
**Belirti:** `TypeError: post_process_grounded_object_detection() got unexpected keyword argument 'input_ids'` veya tam tersi.
**Neden:** `post_process_grounded_object_detection`'ın fonksiyon imzası transformers sürümleri arasında değişmiştir.
**Çözüm (bu projede uygulanmıştır):** `requirements.txt`'te `transformers==4.44.2` olarak pinlendi. Ek olarak kod, yeni imzayı dener; `TypeError` alırsa eski imzaya otomatik düşer (try/except cascade). Yine de sürümü değiştirmeden önce mutlaka test edin.
---
### 3. Event loop bloklanması
**Sorun:** `_run_detection_sync()` veya `_find_best_placement_sync()` async `call_tool` handler'ından `asyncio.to_thread` olmadan doğrudan çağrılırsa.
**Belirti:** Inference süresince (1-5 saniye) MCP sunucusu tüm diğer isteklere (ping, iptal) kilitlenir.
**Çözüm (bu projede uygulanmıştır):** Tüm CPU/GPU-bound fonksiyonlar `await asyncio.to_thread(...)` ile sarılmıştır. Hiçbir zaman bu sarımı kaldırmayın.
---
### 4. Hayali dosya yolu (Hallucinated image_path)
**Sorun:** LLM, sohbete sürükle-bırak yapılan bir görseli "gördüğü" için (base64 olarak) bazen bu görselin disk yolunu uydurabilir.
**Belirti:** `FileNotFoundError: 'C:/imagined/path.jpg'`
**Neden:** Model görseli base64 olarak görüyor; gerçek disk yolunu bilmiyor.
**Çözüm:**
- Tool description'larında açıkça belirtilmiştir: `image_path` gerçek bir disk yolu olmalıdır.
- Kod, `Image.open()` başarısız olursa net hata döndürür: *"Dosya bulunamadı: ... Lütfen diskte gerçekten var olan bir dosya yolu belirtin."*
- Kullanıcıların her zaman gerçek dosya yolunu metin olarak yazması gerekir.
---
### 5. MCP handshake timeout
**Sorun:** Model `import` anında veya `annotator_mcp.py` başlangıcında yüklenirse.
**Belirti:** LM Studio, MCP sunucusunu başlatır ama ~3 saniye içinde handshake yanıtı alamaz ve bağlantıyı düşürür. Log: `MCP server connection timed out` veya benzeri.
**Neden:** Model yükleme (1-2 GB safetensors, birkaç saniye) handshake penceresini aşıyor.
**Çözüm (bu projede uygulanmıştır):** Lazy loading zorunludur. `_model = None` ile başlar; `load_model()` yalnızca **ilk tool çağrısında** tetiklenir. `torch` ve `transformers` import'ları da `load_model()` içinde yapılır (yavaş import'ları geciktirmek için).
---
### 6. Florence-2 ile karıştırma
**Sorun:** Florence-2 gibi `trust_remote_code=True` gerektiren modellerin kurulum mantığını GroundingDINO'ya uygulamak.
**Fark:** GroundingDINO, transformers 4.38+ sürümünde resmi olarak entegre edilmiştir ve `trust_remote_code` gerektirmez. Bu, Florence-2'ye göre önemli bir **kararlılık avantajıdır** — remote code her güncellemede kırılabilir, resmi entegre kod kırılmaz.
**Çözüm:** `from_pretrained()` çağrılarında `trust_remote_code` parametresi hiç kullanmayın.
---
## Proje Yapısı
```
qwen-groundingdino-visual-mcp/
├── annotator_mcp.py # Ana MCP sunucusu (tek dosya, tüm mantık burada)
├── requirements.txt # Sabit sürümlü bağımlılıklar
├── README.md # Bu dosya
└── session_memory.json # Çalışma zamanında oluşturulur (otomatik)
```
---
## Lisans
MIT — Dilediğiniz gibi kullanın, değiştirin ve dağıtın.
MCP Config
Below is the configuration for this MCP Server. You can copy it directly to Cursor or other MCP clients.
mcp.json
Connection Info
You Might Also Like
No recommendations available