lingbot-depth-pretrain-vitl-14实战教程:Linux服务器无GUI环境下纯CLI调用流程

1. 引言:为什么需要纯命令行调用?

想象一下这个场景:你正在一台远程的Linux服务器上工作,这台服务器没有图形界面,只有黑底白字的终端。你部署了一个强大的深度估计模型,但发现官方文档只介绍了网页界面的使用方法。这时候,你该怎么办?

这就是我们今天要解决的问题。lingbot-depth-pretrain-vitl-14是一个基于DINOv2 ViT-L/14编码器的深度估计模型,它确实提供了方便的WebUI界面。但在实际的工程部署、自动化处理或者资源受限的环境中,我们往往需要通过纯命令行(CLI)的方式来调用它。

学习目标:通过这篇教程,你将学会如何在没有任何图形界面的Linux服务器上,通过纯命令行方式调用lingbot-depth模型,完成深度估计和补全任务。

前置知识:你只需要对Linux命令行有基本了解,知道怎么用cdlscurl这些命令就行。不需要你是深度学习专家,也不需要你懂Python高级编程。

教程价值:无论你是做机器人导航、3D重建,还是工业检测,掌握CLI调用都能让你的工作流程更加自动化、更加高效。更重要的是,当服务器资源紧张或者需要批量处理时,命令行方式往往是最可靠的选择。

2. 环境准备:确认你的部署状态

在开始之前,我们需要先确认几件事情。别担心,这些检查都很简单,就像开车前检查油表一样。

2.1 检查模型服务是否正常运行

首先,登录到你的Linux服务器。如果你用的是云服务商提供的实例,通常可以通过SSH连接:

ssh username@your-server-ip

登录成功后,第一件事就是检查模型服务是否已经启动。lingbot-depth镜像默认会启动两个服务:FastAPI REST服务(端口8000)和Gradio WebUI服务(端口7860。

我们可以用curl命令来快速检查:

# 检查FastAPI服务是否正常
curl -s http://localhost:8000/docs | grep -q "FastAPI" && echo "FastAPI服务正常" || echo "FastAPI服务异常"

# 检查Gradio服务是否正常(虽然我们用CLI,但检查一下也无妨)
curl -s http://localhost:7860 | grep -q "Gradio" && echo "Gradio服务正常" || echo "Gradio服务异常"

如果两个服务都正常,你会看到相应的提示。如果服务没有启动,你需要先启动它:

# 进入模型目录并启动服务
cd /root
bash start.sh

启动过程大概需要5-8秒来加载模型到GPU显存。你可以用nvidia-smi命令查看GPU使用情况,确认模型是否加载成功。

2.2 准备测试数据

模型服务正常后,我们需要准备一些测试图片。幸运的是,镜像已经自带了一些示例图片,我们直接使用就行:

# 查看示例图片目录
ls -la /root/assets/lingbot-depth-main/examples/

# 通常会有多个示例目录,比如0、1、2等
# 每个目录包含rgb.png(彩色图)和raw_depth.png(原始深度图)

让我们看看第一个示例的内容:

# 查看图片信息
file /root/assets/lingbot-depth-main/examples/0/rgb.png
file /root/assets/lingbot-depth-main/examples/0/raw_depth.png

# 如果需要查看图片尺寸(虽然看不到图片内容,但可以看元数据)
identify /root/assets/lingbot-depth-main/examples/0/rgb.png 2>/dev/null || echo "需要安装imagemagick"

如果identify命令不可用,别担心,我们后面会用Python代码来获取图片信息。

3. 基础概念:理解模型的工作模式

在开始调用之前,我们先花几分钟理解一下这个模型能做什么。这样你在使用的时候就知道该选择哪种模式,参数该怎么设置。

3.1 两种核心模式

lingbot-depth模型主要支持两种工作模式:

  1. 单目深度估计(Monocular Depth)

    • 输入:只需要一张RGB彩色图片
    • 输出:估计出的深度图
    • 原理:模型从纯视觉外观推断场景的深度信息
    • 适用场景:当你只有普通相机拍摄的图片时
  2. 深度补全(Depth Completion)

    • 输入:RGB图片 + 稀疏深度图
    • 输出:补全后的完整深度图
    • 原理:结合视觉信息和已有的深度测量值,填补缺失的深度区域
    • 适用场景:当你使用RGB-D相机(如Kinect)或LiDAR,但深度数据不完整时

3.2 理解输入输出格式

为了正确调用API,我们需要知道数据该怎么传:

  • 图片格式:支持PNG、JPEG等常见格式
  • 颜色空间:RGB格式,像素值范围0-255
  • 深度图单位:输入深度图如果是毫米(mm),需要转换为米(m)
  • 输出深度:单位是米(m),浮点数

4. 纯CLI调用:三种实战方法

现在进入正题。我将介绍三种不同的命令行调用方法,从最简单到最灵活,你可以根据需求选择。

4.1 方法一:使用curl直接调用REST API(最简单)

这是最直接的方法,适合快速测试和简单集成。模型提供了FastAPI服务,我们可以用curl命令直接调用。

4.1.1 单目深度估计示例

让我们从最简单的单目深度估计开始:

#!/bin/bash
# 保存为 test_monocular.sh

# 定义API地址
API_URL="http://localhost:8000/predict"

# 准备图片数据(base64编码)
IMAGE_PATH="/root/assets/lingbot-depth-main/examples/0/rgb.png"
IMAGE_BASE64=$(base64 -w 0 "$IMAGE_PATH")

# 构建JSON请求
JSON_DATA=$(cat <<EOF
{
  "image": "$IMAGE_BASE64",
  "mode": "monocular",
  "return_npy": false
}
EOF
)

# 发送请求
echo "正在发送请求到模型..."
RESPONSE=$(curl -s -X POST "$API_URL" \
  -H "Content-Type: application/json" \
  -d "$JSON_DATA")

# 检查响应
if echo "$RESPONSE" | grep -q "status.*success"; then
    echo "✓ 深度估计成功!"
    
    # 提取深度图并保存
    DEPTH_BASE64=$(echo "$RESPONSE" | python3 -c "import sys, json; data=json.load(sys.stdin); print(data.get('depth_image', ''))")
    if [ -n "$DEPTH_BASE64" ]; then
        echo "$DEPTH_BASE64" | base64 -d > depth_result.png
        echo "✓ 深度图已保存为 depth_result.png"
    fi
    
    # 显示统计信息
    echo "响应信息:"
    echo "$RESPONSE" | python3 -c "import sys, json; data=json.load(sys.stdin); info=data.get('info', {}); print(f'深度范围: {info.get(\"depth_range\", \"N/A\")}'); print(f'输入尺寸: {info.get(\"input_size\", \"N/A\")}'); print(f'模式: {info.get(\"mode\", \"N/A\")}')"
else
    echo "✗ 请求失败"
    echo "响应内容:$RESPONSE"
fi

运行这个脚本:

chmod +x test_monocular.sh
./test_monocular.sh

如果一切正常,你会看到深度估计成功的提示,并且生成一个depth_result.png文件。虽然你在命令行看不到图片内容,但可以用file命令确认文件已生成:

file depth_result.png
4.1.2 深度补全示例

深度补全需要同时提供RGB图片和稀疏深度图:

#!/bin/bash
# 保存为 test_completion.sh

API_URL="http://localhost:8000/predict"

# 准备两张图片
RGB_PATH="/root/assets/lingbot-depth-main/examples/0/rgb.png"
DEPTH_PATH="/root/assets/lingbot-depth-main/examples/0/raw_depth.png"

RGB_BASE64=$(base64 -w 0 "$RGB_PATH")
DEPTH_BASE64=$(base64 -w 0 "$DEPTH_PATH")

# 注意:这里需要相机内参
JSON_DATA=$(cat <<EOF
{
  "image": "$RGB_BASE64",
  "depth": "$DEPTH_BASE64",
  "mode": "completion",
  "fx": 460.14,
  "fy": 460.20,
  "cx": 319.66,
  "cy": 237.40,
  "return_npy": false
}
EOF
)

echo "正在发送深度补全请求..."
RESPONSE=$(curl -s -X POST "$API_URL" \
  -H "Content-Type: application/json" \
  -d "$JSON_DATA")

if echo "$RESPONSE" | grep -q "status.*success"; then
    echo "✓ 深度补全成功!"
    
    # 保存结果
    DEPTH_BASE64=$(echo "$RESPONSE" | python3 -c "import sys, json; data=json.load(sys.stdin); print(data.get('depth_image', ''))")
    if [ -n "$DEPTH_BASE64" ]; then
        echo "$DEPTH_BASE64" | base64 -d > depth_completion_result.png
        echo "✓ 补全深度图已保存为 depth_completion_result.png"
    fi
else
    echo "✗ 请求失败"
    echo "响应内容:$RESPONSE"
fi

4.2 方法二:使用Python脚本调用(最灵活)

如果你需要更复杂的处理逻辑,或者想要批量处理多张图片,使用Python脚本是更好的选择。

4.2.1 安装必要的Python库

首先确保你有必要的Python库:

pip install requests pillow numpy opencv-python

如果已经部署了lingbot-depth镜像,这些库应该都已经安装好了。

4.2.2 完整的Python调用示例

创建一个Python脚本call_lingbot.py

#!/usr/bin/env python3
"""
lingbot-depth模型命令行调用示例
支持单目深度估计和深度补全两种模式
"""

import requests
import base64
import json
import argparse
from pathlib import Path
import cv2
import numpy as np
from PIL import Image
import time

class LingBotDepthClient:
    """lingbot-depth模型客户端"""
    
    def __init__(self, base_url="http://localhost:8000"):
        self.base_url = base_url
        self.predict_url = f"{base_url}/predict"
        
    def image_to_base64(self, image_path):
        """将图片转换为base64字符串"""
        with open(image_path, "rb") as f:
            return base64.b64encode(f.read()).decode('utf-8')
    
    def save_depth_image(self, depth_base64, output_path):
        """保存base64编码的深度图"""
        if not depth_base64:
            print("警告:没有深度图数据")
            return False
        
        try:
            depth_data = base64.b64decode(depth_base64)
            with open(output_path, "wb") as f:
                f.write(depth_data)
            print(f"深度图已保存: {output_path}")
            return True
        except Exception as e:
            print(f"保存深度图失败: {e}")
            return False
    
    def predict_monocular(self, image_path, output_path="depth_output.png", 
                         return_npy=False):
        """
        单目深度估计
        
        参数:
            image_path: RGB图片路径
            output_path: 输出深度图路径
            return_npy: 是否返回npy格式的原始数据
        """
        print(f"开始单目深度估计: {image_path}")
        
        # 准备请求数据
        image_base64 = self.image_to_base64(image_path)
        
        payload = {
            "image": image_base64,
            "mode": "monocular",
            "return_npy": return_npy
        }
        
        # 发送请求
        start_time = time.time()
        try:
            response = requests.post(self.predict_url, json=payload, timeout=30)
            response.raise_for_status()
            result = response.json()
        except requests.exceptions.RequestException as e:
            print(f"请求失败: {e}")
            return None
        
        elapsed = time.time() - start_time
        print(f"推理完成,耗时: {elapsed:.2f}秒")
        
        # 检查结果
        if result.get("status") != "success":
            print(f"模型推理失败: {result.get('message', '未知错误')}")
            return None
        
        # 保存深度图
        depth_image = result.get("depth_image")
        if depth_image:
            self.save_depth_image(depth_image, output_path)
        
        # 显示信息
        info = result.get("info", {})
        print(f"模式: {info.get('mode', 'N/A')}")
        print(f"深度范围: {info.get('depth_range', 'N/A')}")
        print(f"输入尺寸: {info.get('input_size', 'N/A')}")
        print(f"设备: {info.get('device', 'N/A')}")
        
        return result
    
    def predict_completion(self, rgb_path, depth_path, output_path="completion_output.png",
                          fx=460.14, fy=460.20, cx=319.66, cy=237.40,
                          return_npy=False):
        """
        深度补全
        
        参数:
            rgb_path: RGB图片路径
            depth_path: 稀疏深度图路径
            output_path: 输出深度图路径
            fx, fy, cx, cy: 相机内参
            return_npy: 是否返回npy格式的原始数据
        """
        print(f"开始深度补全")
        print(f"  RGB图像: {rgb_path}")
        print(f"  深度图: {depth_path}")
        print(f"  相机内参: fx={fx}, fy={fy}, cx={cx}, cy={cy}")
        
        # 准备请求数据
        rgb_base64 = self.image_to_base64(rgb_path)
        depth_base64 = self.image_to_base64(depth_path)
        
        payload = {
            "image": rgb_base64,
            "depth": depth_base64,
            "mode": "completion",
            "fx": fx,
            "fy": fy,
            "cx": cx,
            "cy": cy,
            "return_npy": return_npy
        }
        
        # 发送请求
        start_time = time.time()
        try:
            response = requests.post(self.predict_url, json=payload, timeout=30)
            response.raise_for_status()
            result = response.json()
        except requests.exceptions.RequestException as e:
            print(f"请求失败: {e}")
            return None
        
        elapsed = time.time() - start_time
        print(f"推理完成,耗时: {elapsed:.2f}秒")
        
        # 检查结果
        if result.get("status") != "success":
            print(f"模型推理失败: {result.get('message', '未知错误')}")
            return None
        
        # 保存深度图
        depth_image = result.get("depth_image")
        if depth_image:
            self.save_depth_image(depth_image, output_path)
        
        # 显示信息
        info = result.get("info", {})
        print(f"模式: {info.get('mode', 'N/A')}")
        print(f"深度范围: {info.get('depth_range', 'N/A')}")
        print(f"输入尺寸: {info.get('input_size', 'N/A')}")
        
        return result

def main():
    parser = argparse.ArgumentParser(description="lingbot-depth模型命令行客户端")
    parser.add_argument("--mode", choices=["monocular", "completion"], 
                       required=True, help="运行模式")
    parser.add_argument("--image", required=True, help="RGB图像路径")
    parser.add_argument("--depth", help="深度图路径(仅completion模式需要)")
    parser.add_argument("--output", default="output.png", help="输出文件路径")
    parser.add_argument("--fx", type=float, default=460.14, help="相机内参fx")
    parser.add_argument("--fy", type=float, default=460.20, help="相机内参fy")
    parser.add_argument("--cx", type=float, default=319.66, help="相机内参cx")
    parser.add_argument("--cy", type=float, default=237.40, help="相机内参cy")
    parser.add_argument("--return-npy", action="store_true", 
                       help="是否返回npy格式数据")
    
    args = parser.parse_args()
    
    # 创建客户端
    client = LingBotDepthClient()
    
    # 根据模式调用
    if args.mode == "monocular":
        if args.depth:
            print("警告:单目模式不需要深度图参数,忽略--depth")
        
        result = client.predict_monocular(
            args.image, 
            args.output,
            args.return_npy
        )
        
    elif args.mode == "completion":
        if not args.depth:
            print("错误:深度补全模式需要--depth参数")
            return
        
        result = client.predict_completion(
            args.image,
            args.depth,
            args.output,
            args.fx, args.fy, args.cx, args.cy,
            args.return_npy
        )
    
    if result:
        print("✓ 处理完成")
    else:
        print("✗ 处理失败")

if __name__ == "__main__":
    main()

使用这个脚本非常简单:

# 单目深度估计
python3 call_lingbot.py --mode monocular \
  --image /root/assets/lingbot-depth-main/examples/0/rgb.png \
  --output monocular_depth.png

# 深度补全
python3 call_lingbot.py --mode completion \
  --image /root/assets/lingbot-depth-main/examples/0/rgb.png \
  --depth /root/assets/lingbot-depth-main/examples/0/raw_depth.png \
  --output completion_depth.png \
  --fx 460.14 --fy 460.20 --cx 319.66 --cy 237.40

4.3 方法三:批量处理脚本(最实用)

在实际工作中,我们经常需要处理大量图片。下面是一个批量处理的示例:

#!/usr/bin/env python3
"""
批量处理脚本:处理整个目录的图片
"""

import os
import glob
from pathlib import Path
from call_lingbot import LingBotDepthClient  # 假设上面的类在call_lingbot.py中

def batch_process_monocular(input_dir, output_dir, pattern="*.png"):
    """
    批量单目深度估计
    
    参数:
        input_dir: 输入图片目录
        output_dir: 输出目录
        pattern: 文件匹配模式
    """
    # 创建输出目录
    os.makedirs(output_dir, exist_ok=True)
    
    # 获取所有图片文件
    image_files = glob.glob(os.path.join(input_dir, pattern))
    print(f"找到 {len(image_files)} 张图片")
    
    # 创建客户端
    client = LingBotDepthClient()
    
    # 批量处理
    success_count = 0
    for i, image_path in enumerate(image_files):
        print(f"\n处理第 {i+1}/{len(image_files)} 张: {os.path.basename(image_path)}")
        
        # 生成输出路径
        output_path = os.path.join(
            output_dir, 
            f"depth_{Path(image_path).stem}.png"
        )
        
        try:
            result = client.predict_monocular(image_path, output_path)
            if result:
                success_count += 1
                print(f"  ✓ 成功")
            else:
                print(f"  ✗ 失败")
        except Exception as e:
            print(f"  ✗ 异常: {e}")
    
    print(f"\n批量处理完成,成功: {success_count}/{len(image_files)}")

def main():
    # 示例:处理示例目录中的所有rgb图片
    input_dir = "/root/assets/lingbot-depth-main/examples"
    output_dir = "/root/batch_results"
    
    # 先收集所有rgb.png文件
    rgb_files = []
    for example_dir in sorted(glob.glob(os.path.join(input_dir, "*"))):
        rgb_path = os.path.join(example_dir, "rgb.png")
        if os.path.exists(rgb_path):
            rgb_files.append(rgb_path)
    
    print(f"找到 {len(rgb_files)} 个示例")
    
    # 创建客户端
    client = LingBotDepthClient()
    
    # 逐个处理
    for i, rgb_path in enumerate(rgb_files):
        example_name = Path(rgb_path).parent.name
        print(f"\n处理示例 {example_name} ({i+1}/{len(rgb_files)})")
        
        output_path = os.path.join(output_dir, f"{example_name}_depth.png")
        client.predict_monocular(rgb_path, output_path)

if __name__ == "__main__":
    main()

5. 实用技巧与常见问题

掌握了基本调用方法后,我们来看看一些实用技巧和可能遇到的问题。

5.1 性能优化建议

在命令行环境下,性能优化很重要:

# 1. 使用合适的图片尺寸
# 模型对14的倍数尺寸处理最好,如448x448、336x336
# 可以在调用前先调整图片尺寸

# 2. 批量处理时控制并发
# 虽然可以并行调用,但要注意GPU显存限制
# 建议使用队列控制同时处理的数量

# 3. 缓存模型结果
# 如果多次处理相同图片,可以考虑缓存结果

5.2 常见问题解决

问题1:服务没有响应

# 检查服务状态
curl -I http://localhost:8000/docs

# 查看服务日志
tail -f /root/lingbot-depth.log  # 如果有日志文件的话

# 重启服务
cd /root
pkill -f "python.*fastapi"  # 谨慎使用
bash start.sh

问题2:显存不足

# 查看GPU显存使用
nvidia-smi

# 如果显存不足,可以尝试:
# 1. 减小图片尺寸
# 2. 降低并发数量
# 3. 使用CPU模式(不推荐,速度慢)

问题3:图片格式问题

# 在Python中检查图片格式
from PIL import Image
img = Image.open("your_image.jpg")
print(f"格式: {img.format}, 尺寸: {img.size}, 模式: {img.mode}")

# 如果不是RGB,需要转换
if img.mode != "RGB":
    img = img.convert("RGB")
    img.save("converted.jpg")

5.3 自动化脚本示例

最后,分享一个完整的自动化处理脚本,你可以根据自己的需求修改:

#!/bin/bash
# 自动化处理脚本:monitor_and_process.sh
# 监控目录,自动处理新图片

INPUT_DIR="/data/images/input"
OUTPUT_DIR="/data/images/output"
PROCESSED_DIR="/data/images/processed"
LOG_FILE="/var/log/lingbot_processor.log"

# 创建目录
mkdir -p "$INPUT_DIR" "$OUTPUT_DIR" "$PROCESSED_DIR"

echo "$(date): 开始监控目录 $INPUT_DIR" >> "$LOG_FILE"

# 无限循环监控
while true; do
    # 查找新图片
    NEW_IMAGES=$(find "$INPUT_DIR" -name "*.jpg" -o -name "*.png" | head -10)
    
    if [ -n "$NEW_IMAGES" ]; then
        echo "$(date): 发现新图片,开始处理..." >> "$LOG_FILE"
        
        for IMAGE in $NEW_IMAGES; do
            FILENAME=$(basename "$IMAGE")
            echo "处理: $FILENAME" >> "$LOG_FILE"
            
            # 调用Python脚本处理
            python3 /root/call_lingbot.py --mode monocular \
                --image "$IMAGE" \
                --output "$OUTPUT_DIR/depth_$FILENAME" \
                2>&1 >> "$LOG_FILE"
            
            # 移动已处理图片
            mv "$IMAGE" "$PROCESSED_DIR/"
            
            echo "完成: $FILENAME" >> "$LOG_FILE"
        done
    fi
    
    # 等待10秒再次检查
    sleep 10
done

6. 总结

通过这篇教程,我们学习了在Linux服务器无GUI环境下调用lingbot-depth模型的三种方法:

  1. curl直接调用:最简单快捷,适合快速测试和简单集成
  2. Python脚本调用:最灵活强大,适合复杂逻辑和自定义处理
  3. 批量处理脚本:最实用高效,适合处理大量数据

关键要点回顾

  • 模型提供了REST API接口,端口是8000
  • 支持单目深度估计和深度补全两种模式
  • 深度补全需要提供相机内参
  • 图片需要转换为base64编码传输
  • 输出可以是PNG图片或npy原始数据

下一步建议

如果你需要将深度估计集成到更大的系统中,可以考虑:

  • 将API调用封装成服务
  • 添加错误重试机制
  • 实现结果缓存提高性能
  • 添加监控和报警

最后的小提示:虽然命令行看起来不如图形界面直观,但它给了你最大的灵活性和控制力。一旦掌握了这些方法,你就能在各种环境下自如地使用lingbot-depth模型,无论是本地开发、远程服务器,还是自动化流水线。


获取更多AI镜像

想探索更多AI镜像和应用场景?访问 CSDN星图镜像广场,提供丰富的预置镜像,覆盖大模型推理、图像生成、视频生成、模型微调等多个领域,支持一键部署。

Logo

腾讯云面向开发者汇聚海量精品云计算使用和开发经验,营造开放的云计算技术生态圈。

更多推荐