# Depth Anything

Оценивайте глубину по одиночным изображениям с помощью Depth Anything.

{% hint style="success" %}
Все примеры можно запускать на GPU-серверах, арендуемых через [CLORE.AI Marketplace](https://clore.ai/marketplace).
{% endhint %}

## Аренда на CLORE.AI

1. Посетите [CLORE.AI Marketplace](https://clore.ai/marketplace)
2. Отфильтруйте по типу GPU, объему VRAM и цене
3. Выберите **On-Demand** (фиксированная ставка) или **Spot** (цена по ставке)
4. Настройте ваш заказ:
   * Выберите Docker-образ
   * Установите порты (TCP для SSH, HTTP для веб-интерфейсов)
   * Добавьте переменные окружения при необходимости
   * Введите команду запуска
5. Выберите способ оплаты: **CLORE**, **BTC**, или **USDT/USDC**
6. Создайте заказ и дождитесь развертывания

### Доступ к вашему серверу

* Найдите данные для подключения в **Моих заказах**
* Веб-интерфейсы: используйте URL HTTP-порта
* SSH: `ssh -p <port> root@<proxy-address>`

## Что такое Depth Anything?

Depth Anything предоставляет:

* Современное (state-of-the-art) оценивание глубины
* Работает с любым изображением
* Не требуется стереокамера
* Быстрая инференция

## Варианты моделей

| Модель               | Размер    | VRAM  | Скорость        |
| -------------------- | --------- | ----- | --------------- |
| Depth-Anything-Small | 25M       | 2GB   | Самая быстрая   |
| Depth-Anything-Base  | 98M       | 4 ГБ  | Быстро          |
| Depth-Anything-Large | 335M      | 8GB   | Лучшее качество |
| Depth-Anything-V2    | Различные | 4-8GB | Последняя       |

## Быстрое развертывание

**Docker-образ:**

```
pytorch/pytorch:2.5.1-cuda12.4-cudnn9-runtime
```

**Порты:**

```
22/tcp
7860/http
```

**Команда:**

```bash
pip install transformers torch gradio && \
python depth_anything_app.py
```

## Доступ к вашему сервису

После развертывания найдите ваш `http_pub` URL в **Моих заказах**:

1. Перейдите на **Моих заказах** страницу
2. Нажмите на ваш заказ
3. Найдите `http_pub` URL (например, `abc123.clorecloud.net`)

Используйте `https://YOUR_HTTP_PUB_URL` вместо `localhost` в примерах ниже.

## Установка

```bash
pip install transformers torch
pip install opencv-python pillow
```

## Базовое использование

```python
from transformers import pipeline
from PIL import Image

# Загрузить конвейер оценки глубины
pipe = pipeline(
    task="depth-estimation",
    model="LiheYoung/depth-anything-large-hf",
    device="cuda"
)

# Оценить глубину
image = Image.open("photo.jpg")
depth = pipe(image)

# Сохранить карту глубины
depth["depth"].save("depth_map.png")
```

## Depth Anything V2

```python
from transformers import AutoImageProcessor, AutoModelForDepthEstimation
import torch
from PIL import Image
import numpy as np

# Загрузить модель
processor = AutoImageProcessor.from_pretrained("depth-anything/Depth-Anything-V2-Large-hf")
model = AutoModelForDepthEstimation.from_pretrained("depth-anything/Depth-Anything-V2-Large-hf")
model.to("cuda")

# Обработать изображение
image = Image.open("photo.jpg")
inputs = processor(images=image, return_tensors="pt").to("cuda")

with torch.no_grad():
    outputs = model(**inputs)
    predicted_depth = outputs.predicted_depth

# Интерполировать до исходного размера
prediction = torch.nn.functional.interpolate(
    predicted_depth.unsqueeze(1),
    size=image.size[::-1],
    mode="bicubic",
    align_corners=False,
)

# Конвертировать в numpy
depth = prediction.squeeze().cpu().numpy()
depth = (depth - depth.min()) / (depth.max() - depth.min()) * 255
depth = depth.astype(np.uint8)

# Сохранить
Image.fromarray(depth).save("depth.png")
```

## Цветная карта глубины

```python
import cv2
import numpy as np
from PIL import Image

def colorize_depth(depth_array, colormap=cv2.COLORMAP_INFERNO):
    # Нормализовать в диапазон 0-255
    depth_normalized = cv2.normalize(depth_array, None, 0, 255, cv2.NORM_MINMAX)
    depth_uint8 = depth_normalized.astype(np.uint8)

    # Применить цветовую карту
    colored = cv2.applyColorMap(depth_uint8, colormap)

    return Image.fromarray(cv2.cvtColor(colored, cv2.COLOR_BGR2RGB))

# Пример использования
depth_colored = colorize_depth(depth)
depth_colored.save("depth_colored.png")
```

## Пакетная обработка

```python
from transformers import pipeline
from PIL import Image
import os

pipe = pipeline(
    task="depth-estimation",
    model="LiheYoung/depth-anything-large-hf",
    device="cuda"
)

input_dir = "./images"
output_dir = "./depth_maps"
os.makedirs(output_dir, exist_ok=True)

for filename in os.listdir(input_dir):
    if filename.endswith(('.jpg', '.png', '.jpeg')):
        image_path = os.path.join(input_dir, filename)
        image = Image.open(image_path)

        # Получить глубину
        depth = pipe(image)

        # Сохранить
        output_path = os.path.join(output_dir, f"depth_{filename}")
        depth["depth"].save(output_path)
        print(f"Обработано: {filename}")
```

## Интерфейс Gradio

```python
import gradio as gr
from transformers import pipeline
import cv2
import numpy as np

pipe = pipeline(
    task="depth-estimation",
    model="LiheYoung/depth-anything-large-hf",
    device="cuda"
)

def estimate_depth(image, colormap):
    # Получить глубину
    result = pipe(image)
    depth = np.array(result["depth"])

    # Оцветить
    depth_normalized = cv2.normalize(depth, None, 0, 255, cv2.NORM_MINMAX).astype(np.uint8)

    colormaps = {
        "Inferno": cv2.COLORMAP_INFERNO,
        "Viridis": cv2.COLORMAP_VIRIDIS,
        "Plasma": cv2.COLORMAP_PLASMA,
        "Magma": cv2.COLORMAP_MAGMA,
        "Jet": cv2.COLORMAP_JET
    }

    colored = cv2.applyColorMap(depth_normalized, colormaps[colormap])
    colored = cv2.cvtColor(colored, cv2.COLOR_BGR2RGB)

    return result["depth"], colored

demo = gr.Interface(
    fn=estimate_depth,
    inputs=[
        gr.Image(type="pil", label="Входное изображение"),
        gr.Dropdown(
            ["Inferno", "Viridis", "Plasma", "Magma", "Jet"],
            value="Inferno",
            label="Colormap"
        )
    ],
    outputs=[
        gr.Image(label="Depth Map (Grayscale)"),
        gr.Image(label="Depth Map (Colored)")
    ],
    title="Depth Anything - Depth Estimation"
)

demo.launch(server_name="0.0.0.0", server_port=7860)
```

## API-сервер

```python
from fastapi import FastAPI, UploadFile, File
from fastapi.responses import Response
from transformers import pipeline
from PIL import Image
import io
import numpy as np
import cv2

app = FastAPI()

pipe = pipeline(
    task="depth-estimation",
    model="LiheYoung/depth-anything-large-hf",
    device="cuda"
)

@app.post("/depth")
async def estimate_depth(image: UploadFile = File(...), colored: bool = True):
    # Загрузить изображение
    img = Image.open(io.BytesIO(await image.read()))

    # Оценить глубину
    result = pipe(img)
    depth = np.array(result["depth"])

    if colored:
        depth_normalized = cv2.normalize(depth, None, 0, 255, cv2.NORM_MINMAX).astype(np.uint8)
        depth_img = cv2.applyColorMap(depth_normalized, cv2.COLORMAP_INFERNO)
        depth_img = cv2.cvtColor(depth_img, cv2.COLOR_BGR2RGB)
    else:
        depth_img = depth

    # Конвертировать в байты
    output = Image.fromarray(depth_img)
    buffer = io.BytesIO()
    output.save(buffer, format="PNG")

    return Response(content=buffer.getvalue(), media_type="image/png")

# Запуск: uvicorn server:app --host 0.0.0.0 --port 8000
```

## Генерация 3D облака точек

```python
import numpy as np
import open3d as o3d
from PIL import Image

def depth_to_pointcloud(rgb_image, depth_map, focal_length=500):
    """Преобразовать RGB-изображение и карту глубины в 3D облако точек"""
    rgb = np.array(rgb_image)
    depth = np.array(depth_map)

    # Получить размеры изображения
    height, width = depth.shape

    # Создать сетку (mesh grid)
    u = np.arange(width)
    v = np.arange(height)
    u, v = np.meshgrid(u, v)

    # Преобразовать в 3D-координаты
    z = depth.astype(float)
    x = (u - width / 2) * z / focal_length
    y = (v - height / 2) * z / focal_length

    # Сложить координаты
    points = np.stack([x, y, z], axis=-1).reshape(-1, 3)
    colors = rgb.reshape(-1, 3) / 255.0

    # Создать облако точек
    pcd = o3d.geometry.PointCloud()
    pcd.points = o3d.utility.Vector3dVector(points)
    pcd.colors = o3d.utility.Vector3dVector(colors)

    return pcd

# Пример использования
rgb = Image.open("photo.jpg")
depth = pipe(rgb)["depth"]

pcd = depth_to_pointcloud(rgb, depth)
o3d.io.write_point_cloud("output.ply", pcd)
```

## Сценарии использования

### 3D фотоэффект

```python
def create_3d_photo(image, depth, shift=20):
    """Создать параллаксный эффект для 3D-фотографий"""
    import cv2
    import numpy as np

    img = np.array(image)
    depth_arr = np.array(depth)

    # Нормализовать глубину
    depth_norm = (depth_arr - depth_arr.min()) / (depth_arr.max() - depth_arr.min())

    # Создать смещённую версию
    shifted = np.zeros_like(img)
    for y in range(img.shape[0]):
        for x in range(img.shape[1]):
            offset = int(shift * depth_norm[y, x])
            new_x = min(x + offset, img.shape[1] - 1)
            shifted[y, new_x] = img[y, x]

    return Image.fromarray(shifted)
```

### Размытие фона (портретный режим)

```python
def portrait_mode(image, depth, blur_strength=25):
    import cv2
    import numpy as np

    img = np.array(image)
    depth_arr = np.array(depth)

    # Нормализовать глубину
    depth_norm = (depth_arr - depth_arr.min()) / (depth_arr.max() - depth_arr.min())

    # Создать маску размытия (фон = большая глубина = больше размытия)
    blur_mask = depth_norm

    # Применить размытие
    blurred = cv2.GaussianBlur(img, (blur_strength, blur_strength), 0)

    # Смешивание на основе глубины
    mask_3d = np.stack([blur_mask] * 3, axis=-1)
    result = (img * (1 - mask_3d) + blurred * mask_3d).astype(np.uint8)

    return Image.fromarray(result)
```

## Производительность

| Модель    | GPU      | Время на изображение |
| --------- | -------- | -------------------- |
| Небольшая | RTX 3060 | \~50ms               |
| Базовый   | RTX 3060 | \~100ms              |
| Large     | RTX 3090 | \~150ms              |
| Large     | RTX 4090 | \~80ms               |
| V2-Large  | RTX 4090 | \~100ms              |

## Устранение неполадок

### Плохое качество глубины

* Используйте вариант модели большего размера
* Убедитесь в хорошем качестве изображения
* Проверьте наличие отражающих поверхностей

### Проблемы с памятью

* Используйте вариант модели меньшего размера
* Уменьшите разрешение изображения
* Включите вывод fp16

### Медленная обработка

* Используйте меньшую модель
* Обрабатывайте пакетами, если возможно
* Используйте вывод на GPU

## Оценка стоимости

Типичные ставки на маркетплейсе CLORE.AI (по состоянию на 2024):

| GPU       | Почасовая ставка | Дневная ставка | Сессия 4 часа |
| --------- | ---------------- | -------------- | ------------- |
| RTX 3060  | \~$0.03          | \~$0.70        | \~$0.12       |
| RTX 3090  | \~$0.06          | \~$1.50        | \~$0.25       |
| RTX 4090  | \~$0.10          | \~$2.30        | \~$0.40       |
| A100 40GB | \~$0.17          | \~$4.00        | \~$0.70       |
| A100 80GB | \~$0.25          | \~$6.00        | \~$1.00       |

*Цены варьируются в зависимости от провайдера и спроса. Проверьте* [*CLORE.AI Marketplace*](https://clore.ai/marketplace) *для текущих тарифов.*

**Экономьте деньги:**

* Используйте **Spot** рынок для гибких рабочих нагрузок (часто на 30–50% дешевле)
* Платите с помощью **CLORE** токенов
* Сравнивайте цены у разных провайдеров

## Дальнейшие шаги

* [ControlNet](https://docs.clore.ai/guides/guides_v2-ru/obrabotka-izobrazhenii/controlnet-advanced) - Используйте глубину для управления
* [Segment Anything](https://docs.clore.ai/guides/guides_v2-ru/obrabotka-izobrazhenii/segment-anything) - Сегментация объектов
* [3D-генерация](https://docs.clore.ai/guides/guides_v2-ru/3d-generaciya/triposr) - Глубина для видео
