10-具身智能视觉特征库匹配:让机器人“认识“它看到的世界
具身智能视觉特征库匹配:让机器人"认识"它看到的世界
黑漂技术佬的第10篇实战笔记 —— 当向量检索遇上机械臂,机器人终于知道该抓什么了
一、具身智能中的视觉检索需求
具身智能(Embodied AI)是当下AI领域最火的方向之一。简单说,就是给AI一个"身体"(机器人),让它不仅能"看"能"想",还能"动"。传统AI是"脑子在罐子里"——只能处理数据,具身智能是"脑子装在身体里"——能感知环境、做决策、执行动作。
在这个体系里,视觉特征库匹配扮演什么角色?是机器人的"记忆"。
举个具体场景:一个补货机器人站在货架前,它需要:
- 看到环境中有哪些物体(YOLO检测)
- 认识这些物体是什么(向量检索匹配特征库)
- 决定怎么操作(根据匹配结果选择抓取策略)
- 执行动作(机械臂运动控制)
第2步就是本文的重点——视觉特征库匹配。没有这一步,机器人看到了物体但不知道是什么,后面的一切都是空中楼阁。
1.1 机械臂抓取:识别目标 → 匹配特征库 → 确定抓取策略
不同物体需要不同的抓取方式。可乐瓶要捏瓶身,鸡蛋要轻托底部,纸巾盒要夹两侧。机器人怎么知道面前这个东西该用什么方式抓?靠特征库匹配——识别出物体类别后,从预设的策略库里取出对应的抓取方案。
1.2 场景理解:检测环境物体 → 特征匹配 → 理解场景
机器人不仅要认识单个物体,还要理解整个场景。比如看到"货架+缺货格子+散落商品",推断出"需要补货"。这种场景理解也建立在物体识别的基础上。
二、视觉特征库匹配完整流程
摄像头输入 → YOLO检测 → 框出物体位置
↓
裁剪目标区域
↓
ResNet/MobileNet提取特征
↓
FAISS/Milvus向量检索匹配特征库
↓
返回匹配结果+置信度
↓
根据匹配结果选择动作策略
2.1 YOLO检测:框出物体位置
from ultralytics import YOLO
import cv2
import numpy as np
class SceneDetector:
"""场景物体检测器"""
def __init__(self, model_path='yolov8n.pt', conf_threshold=0.5):
self.model = YOLO(model_path)
self.conf_threshold = conf_threshold
def detect(self, image):
"""
检测场景中的所有物体
:param image: 图片路径或numpy数组(BGR)
:return: 检测结果列表
"""
results = self.model(image, conf=self.conf_threshold)
detections = []
for result in results:
boxes = result.boxes
for box in boxes:
x1, y1, x2, y2 = box.xyxy[0].cpu().numpy().astype(int)
confidence = float(box.conf[0].cpu().numpy())
class_id = int(box.cls[0].cpu().numpy())
class_name = result.names[class_id]
detections.append({
'bbox': (x1, y1, x2, y2),
'confidence': confidence,
'class_name': class_name,
'class_id': class_id
})
return detections
def visualize(self, image, detections):
"""可视化检测结果"""
img = image.copy()
for det in detections:
x1, y1, x2, y2 = det['bbox']
label = f"{det['class_name']} {det['confidence']:.2f}"
cv2.rectangle(img, (x1, y1), (x2, y2), (0, 255, 0), 2)
cv2.putText(img, label, (x1, y1 - 10),
cv2.FONT_HERSHEY_SIMPLEX, 0.6, (0, 255, 0), 2)
return img
2.2 特征提取:裁剪目标 → 提取特征
import torch
import torchvision.models as models
import torchvision.transforms as transforms
from PIL import Image
class FeatureExtractor:
"""物体特征提取器"""
def __init__(self, model_name='resnet18'):
if model_name == 'resnet18':
base = models.resnet18(pretrained=True)
self.dim = 512
elif model_name == 'mobilenet_v3_small':
base = models.mobilenet_v3_small(pretrained=True)
self.dim = 576
else:
raise ValueError(f"不支持: {model_name}")
self.model = torch.nn.Sequential(*list(base.children())[:-1])
self.model.eval()
self.transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406],
std=[0.229, 0.224, 0.225])
])
def extract_from_crop(self, crop_image):
"""从裁剪的图像区域提取特征"""
if isinstance(crop_image, np.ndarray):
# BGR → RGB → PIL
crop_rgb = cv2.cvtColor(crop_image, cv2.COLOR_BGR2RGB)
pil_img = Image.fromarray(crop_rgb)
else:
pil_img = crop_image
tensor = self.transform(pil_img).unsqueeze(0)
with torch.no_grad():
feature = self.model(tensor)
feature = feature.squeeze().numpy().astype('float32')
norm = np.linalg.norm(feature)
if norm > 0:
feature = feature / norm
return feature
def extract_batch(self, crop_images):
"""批量提取特征(多个目标同时处理)"""
tensors = []
for crop in crop_images:
if isinstance(crop, np.ndarray):
crop_rgb = cv2.cvtColor(crop, cv2.COLOR_BGR2RGB)
pil_img = Image.fromarray(crop_rgb)
else:
pil_img = crop
tensors.append(self.transform(pil_img))
batch = torch.stack(tensors)
with torch.no_grad():
features = self.model(batch)
features = features.squeeze(-1).squeeze(-1).numpy().astype('float32')
# L2归一化
norms = np.linalg.norm(features, axis=1, keepdims=True)
features = features / np.maximum(norms, 1e-8)
return features
2.3 向量检索:匹配特征库
import faiss
import json
class FeatureLibrary:
"""视觉特征库管理"""
def __init__(self, index_path, metadata_path):
self.index = faiss.read_index(index_path)
with open(metadata_path, 'r', encoding='utf-8') as f:
self.metadata = json.load(f)
print(f"特征库加载完成: {self.index.ntotal} 条记录")
def search(self, query_feature, top_k=5):
"""检索单个特征"""
query = np.array([query_feature]).astype('float32')
scores, indices = self.index.search(query, top_k)
results = []
for i in range(top_k):
idx = indices[0][i]
if idx >= 0:
match = self.metadata[idx].copy()
match['score'] = float(scores[0][i])
results.append(match)
return results
def search_batch(self, query_features, top_k=5):
"""批量检索多个特征"""
queries = np.array(query_features).astype('float32')
scores, indices = self.index.search(queries, top_k)
all_results = []
for q_idx in range(len(query_features)):
results = []
for i in range(top_k):
idx = indices[q_idx][i]
if idx >= 0:
match = self.metadata[idx].copy()
match['score'] = float(scores[q_idx][i])
results.append(match)
all_results.append(results)
return all_results
2.4 结果决策:根据匹配结果选择动作
class ActionDecisionEngine:
"""动作决策引擎:根据识别结果选择操作策略"""
# 物体类别 → 抓取策略映射
GRASP_STRATEGIES = {
'bottle': {'method': 'lateral_grip', 'force': 0.5, 'approach': 'side'},
'can': {'method': 'lateral_grip', 'force': 0.7, 'approach': 'side'},
'box': {'method': 'parallel_grip', 'force': 0.8, 'approach': 'top'},
'fruit': {'method': 'soft_cup', 'force': 0.3, 'approach': 'top'},
'egg': {'method': 'soft_cup', 'force': 0.2, 'approach': 'top'},
'snack_bag': {'method': 'pinch_grip', 'force': 0.4, 'approach': 'top'},
}
def decide(self, match_result):
"""
根据匹配结果生成动作策略
:param match_result: 特征库检索返回的最佳匹配
:return: 动作策略字典
"""
if not match_result:
return {'action': 'skip', 'reason': '未匹配到已知物体'}
best_match = match_result[0]
object_category = best_match.get('category', 'unknown')
confidence = best_match.get('score', 0)
# 置信度太低,不执行操作
if confidence < 0.6:
return {
'action': 'skip',
'reason': f'置信度过低({confidence:.2f})',
'best_guess': best_match.get('name', 'unknown')
}
# 获取抓取策略
strategy = self.GRASP_STRATEGIES.get(
object_category,
{'method': 'default_grip', 'force': 0.5, 'approach': 'top'}
)
return {
'action': 'grasp',
'object_name': best_match.get('name'),
'object_category': object_category,
'confidence': confidence,
'grasp_strategy': strategy,
'bbox': best_match.get('bbox')
}
三、完整Pipeline整合
class EmbodiedVisionPipeline:
"""具身智能视觉Pipeline:检测→提特征→检索→决策"""
def __init__(self, index_path, metadata_path,
yolo_model='yolov8n.pt', feature_model='resnet18'):
self.detector = SceneDetector(yolo_model)
self.extractor = FeatureExtractor(feature_model)
self.library = FeatureLibrary(index_path, metadata_path)
self.decision_engine = ActionDecisionEngine()
def process(self, image):
"""
处理一帧图像,完成从检测到决策的全流程
:param image: 输入图片(BGR numpy数组或路径)
:return: 处理结果列表
"""
# 第1步:YOLO检测
detections = self.detector.detect(image)
print(f"[1] 检测到 {len(detections)} 个目标")
if not detections:
return []
# 读取图片用于裁剪
if isinstance(image, str):
frame = cv2.imread(image)
else:
frame = image
# 第2步:裁剪所有目标区域
crops = []
for det in detections:
x1, y1, x2, y2 = det['bbox']
crop = frame[y1:y2, x1:x2]
crops.append(crop)
# 第3步:批量提取特征
features = self.extractor.extract_batch(crops)
print(f"[2] 特征提取完成: {features.shape}")
# 第4步:批量向量检索
search_results = self.library.search_batch(features, top_k=3)
print(f"[3] 向量检索完成")
# 第5步:动作决策
decisions = []
for i, (det, results) in enumerate(zip(detections, search_results)):
# 把检测位置信息加入匹配结果
for r in results:
r['bbox'] = det['bbox']
decision = self.decision_engine.decide(results)
decisions.append({
'detection': det,
'search_results': results,
'decision': decision
})
obj_name = decision.get('object_name', 'unknown')
conf = decision.get('confidence', 0)
action = decision.get('action', 'skip')
print(f" 目标{i+1}: {det['class_name']} → {obj_name} "
f"(置信度:{conf:.2f}) → 动作:{action}")
return decisions
# 使用示例
pipeline = EmbodiedVisionPipeline(
index_path="object_library.faiss",
metadata_path="object_metadata.json"
)
# 处理一帧货架图片
results = pipeline.process("shelf_photo.jpg")
# 输出示例:
# [1] 检测到 5 个目标
# [2] 特征提取完成: (5, 512)
# [3] 向量检索完成
# 目标1: bottle → 可口可乐330ml (置信度:0.95) → 动作:grasp
# 目标2: bottle → 雪碧330ml (置信度:0.91) → 动作:grasp
# 目标3: box → 纸巾盒 (置信度:0.88) → 动作:grasp
四、特征库管理
特征库不是一成不变的,需要支持动态增删改:
class FeatureLibraryManager:
"""特征库管理器:支持增删改查"""
def __init__(self, index_path, metadata_path, dimension=512):
self.index_path = index_path
self.metadata_path = metadata_path
self.dimension = dimension
# 加载已有库
self.index = faiss.read_index(index_path)
with open(metadata_path, 'r', encoding='utf-8') as f:
self.metadata = json.load(f)
self.extractor = FeatureExtractor('resnet18')
def add_object(self, object_id, name, category, images, **extra_info):
"""
新增物体到特征库
:param object_id: 物体唯一ID
:param name: 物体名称
:param category: 物体类别
:param images: 物体图片路径列表(多角度)
:param extra_info: 额外元数据(如抓取策略)
"""
# 提取多角度特征
features = []
for img_path in images:
feat = self.extractor.extract_from_crop(img_path)
features.append(feat)
# 多角度特征取平均,生成原型向量
centroid = np.mean(features, axis=0).astype('float32')
centroid = centroid / np.linalg.norm(centroid)
# 添加到索引
self.index.add(np.array([centroid]))
# 添加元数据
meta = {
'object_id': object_id,
'name': name,
'category': category,
'num_images': len(images),
**extra_info
}
self.metadata.append(meta)
# 保存
self._save()
print(f"物体 '{name}' 已添加到特征库")
def update_object(self, object_id, new_images=None, **updated_info):
"""
更新物体特征(替换特征向量)
FAISS不支持直接删除单条记录,需要重建索引
"""
# 找到要更新的记录
target_idx = None
for i, meta in enumerate(self.metadata):
if meta['object_id'] == object_id:
target_idx = i
break
if target_idx is None:
print(f"未找到物体: {object_id}")
return
# 更新元数据
self.metadata[target_idx].update(updated_info)
# 如果提供了新图片,重新提取特征
if new_images:
features = []
for img_path in new_images:
feat = self.extractor.extract_from_crop(img_path)
features.append(feat)
new_centroid = np.mean(features, axis=0).astype('float32')
new_centroid = new_centroid / np.linalg.norm(new_centroid)
# 重建索引(小规模库可以接受)
self._rebuild_index_with_update(target_idx, new_centroid)
self._save()
print(f"物体 '{object_id}' 已更新")
def remove_object(self, object_id):
"""删除物体(标记删除,定期重建索引)"""
target_idx = None
for i, meta in enumerate(self.metadata):
if meta['object_id'] == object_id:
target_idx = i
break
if target_idx is None:
print(f"未找到物体: {object_id}")
return
# 从元数据中移除
removed = self.metadata.pop(target_idx)
# 重建索引(去掉对应向量)
all_vectors = []
for i in range(self.index.ntotal):
if i == target_idx:
continue
vec = self.index.reconstruct(i)
all_vectors.append(vec)
# 重建
quantizer = faiss.IndexFlatIP(self.dimension)
new_index = faiss.IndexIVFFlat(quantizer, self.dimension,
min(100, len(all_vectors)//10),
faiss.METRIC_INNER_PRODUCT)
if len(all_vectors) > 0:
vectors_array = np.array(all_vectors).astype('float32')
new_index.train(vectors_array)
new_index.add(vectors_array)
self.index = new_index
self._save()
print(f"物体 '{removed['name']}' 已从特征库删除")
def _save(self):
faiss.write_index(self.index, self.index_path)
with open(self.metadata_path, 'w', encoding='utf-8') as f:
json.dump(self.metadata, f, ensure_ascii=False, indent=2)
def _rebuild_index_with_update(self, target_idx, new_vector):
"""重建索引(更新单条向量)"""
all_vectors = []
for i in range(self.index.ntotal):
if i == target_idx:
all_vectors.append(new_vector)
else:
all_vectors.append(self.index.reconstruct(i))
vectors_array = np.array(all_vectors).astype('float32')
quantizer = faiss.IndexFlatIP(self.dimension)
new_index = faiss.IndexIVFFlat(quantizer, self.dimension,
min(100, len(all_vectors)//10),
faiss.METRIC_INNER_PRODUCT)
new_index.train(vectors_array)
new_index.add(vectors_array)
self.index = new_index
五、多模态融合:视觉特征 + 文本描述(CLIP)
纯视觉特征有个问题:长得像的东西分不清。比如红富士苹果和花牛苹果,视觉特征几乎一样。怎么办?引入文本描述,做多模态融合。
CLIP模型能同时理解图像和文本,把两者映射到同一个向量空间。这样就可以用文字描述来辅助识别。
from transformers import CLIPModel, CLIPProcessor
class MultiModalMatcher:
"""多模态匹配器:视觉+文本融合"""
def __init__(self, model_name='openai/clip-vit-base-patch32'):
self.model = CLIPModel.from_pretrained(model_name)
self.processor = CLIPProcessor.from_pretrained(model_name)
self.model.eval()
self.dimension = 512 # CLIP输出维度
def extract_image_feature(self, image):
"""提取图像特征"""
if isinstance(image, np.ndarray):
image = Image.fromarray(cv2.cvtColor(image, cv2.COLOR_BGR2RGB))
inputs = self.processor(images=image, return_tensors="pt")
with torch.no_grad():
features = self.model.get_image_features(**inputs)
features = features.squeeze().numpy().astype('float32')
features = features / np.linalg.norm(features)
return features
def extract_text_feature(self, text):
"""提取文本特征"""
inputs = self.processor(text=[text], return_tensors="pt",
padding=True, truncation=True)
with torch.no_grad():
features = self.model.get_text_features(**inputs)
features = features.squeeze().numpy().astype('float32')
features = features / np.linalg.norm(features)
return features
def build_multimodal_index(self, items):
"""
构建多模态特征库
:param items: [{"image": path, "description": "红色成熟番茄", ...}, ...]
"""
image_features = []
text_features = []
metadata = []
for item in items:
# 图像特征
img_feat = self.extract_image_feature(item['image'])
image_features.append(img_feat)
# 文本特征
text_feat = self.extract_text_feature(item['description'])
text_features.append(text_feat)
metadata.append(item)
# 融合策略:加权平均(图像权重0.7,文本权重0.3)
image_features = np.array(image_features)
text_features = np.array(text_features)
fused_features = 0.7 * image_features + 0.3 * text_features
# 重新归一化
norms = np.linalg.norm(fused_features, axis=1, keepdims=True)
fused_features = fused_features / np.maximum(norms, 1e-8)
fused_features = fused_features.astype('float32')
# 构建FAISS索引
index = faiss.IndexFlatIP(self.dimension)
index.add(fused_features)
return index, metadata
def search_with_description(self, query_image, query_text, index,
metadata, top_k=5, image_weight=0.7):
"""
用图像+文本描述联合检索
"""
img_feat = self.extract_image_feature(query_image)
text_feat = self.extract_text_feature(query_text)
# 融合查询特征
query_fused = image_weight * img_feat + (1 - image_weight) * text_feat
query_fused = query_fused / np.linalg.norm(query_fused)
# 检索
query = np.array([query_fused]).astype('float32')
scores, indices = index.search(query, top_k)
results = []
for i in range(top_k):
idx = indices[0][i]
if idx >= 0:
match = metadata[idx].copy()
match['score'] = float(scores[0][i])
results.append(match)
return results
六、实际落地案例
6.1 无人售货柜补货机器人
场景:仓库里有一堆商品,售货柜里缺了几个格子,补货机器人需要从仓库中找到对应商品并放到货架上。
class RestockingRobot:
"""无人售货柜补货机器人"""
def __init__(self, feature_library):
self.pipeline = EmbodiedVisionPipeline(
index_path="warehouse_objects.faiss",
metadata_path="warehouse_objects.json"
)
self.library = feature_library
def scan_warehouse(self, camera_image):
"""
扫描仓库,建立可用商品清单
"""
results = self.pipeline.process(camera_image)
available_items = []
for r in results:
if r['decision']['action'] == 'grasp':
available_items.append({
'name': r['decision']['object_name'],
'category': r['decision']['object_category'],
'bbox': r['decision']['bbox'],
'confidence': r['decision']['confidence']
})
return available_items
def find_target_item(self, camera_image, target_product_id):
"""
在画面中找到目标商品的位置
"""
results = self.pipeline.process(camera_image)
for r in results:
best = r['search_results'][0] if r['search_results'] else None
if best and best.get('object_id') == target_product_id:
return {
'found': True,
'bbox': r['detection']['bbox'],
'confidence': r['decision']['confidence'],
'grasp_strategy': r['decision'].get('grasp_strategy')
}
return {'found': False}
def execute_restock(self, target_product_id, max_attempts=3):
"""执行补货流程"""
for attempt in range(max_attempts):
print(f"\n=== 补货尝试 {attempt + 1} ===")
# 1. 拍照
frame = self.capture_frame()
# 2. 找目标商品
target = self.find_target_item(frame, target_product_id)
if not target['found']:
print("未找到目标商品,调整位置...")
self.robot_move("adjust_position")
continue
# 3. 执行抓取
print(f"找到目标商品,置信度: {target['confidence']:.2f}")
strategy = target['grasp_strategy']
grasp_success = self.execute_grasp(
target['bbox'],
strategy['method'],
strategy['force'],
strategy['approach']
)
if grasp_success:
# 4. 放到目标位置
self.place_to_shelf(target_product_id)
print("补货成功!")
return True
else:
print("抓取失败,重试...")
return False
def capture_frame(self):
"""从相机捕获一帧"""
# 实际实现调用相机SDK
pass
def execute_grasp(self, bbox, method, force, approach):
"""执行机械臂抓取"""
# 实际实现调用机械臂SDK
print(f" 抓取方式: {method}, 力度: {force}, 接近方向: {approach}")
return True # 模拟成功
def place_to_shelf(self, product_id):
"""放到货架"""
print(f" 将商品 {product_id} 放到货架")
def robot_move(self, action):
"""机器人移动"""
pass
6.2 智慧农业采摘机器人
场景:果园里,机器人需要识别成熟的果实,判断成熟度,然后采摘。特征库里存的是不同成熟度果实的特征模板。
class HarvestingRobot:
"""智慧农业采摘机器人"""
def __init__(self):
# 特征库包含不同成熟度的果实特征
# metadata中包含ripeness字段: "unripe" / "semi_ripe" / "ripe" / "overripe"
self.pipeline = EmbodiedVisionPipeline(
index_path="fruit_library.faiss",
metadata_path="fruit_metadata.json"
)
def scan_orchard(self, camera_image):
"""扫描果树,识别成熟果实"""
results = self.pipeline.process(camera_image)
harvestable = []
for r in results:
if not r['search_results']:
continue
best = r['search_results'][0]
ripeness = best.get('ripeness', 'unknown')
confidence = best.get('score', 0)
# 只采摘成熟果实
if ripeness == 'ripe' and confidence > 0.7:
harvestable.append({
'fruit_type': best.get('name'),
'ripeness': ripeness,
'bbox': r['detection']['bbox'],
'confidence': confidence
})
print(f" 发现成熟果实: {best['name']} "
f"(成熟度:{ripeness}, 置信度:{confidence:.2f})")
elif ripeness in ['semi_ripe', 'unripe']:
print(f" 果实未成熟: {best['name']} ({ripeness}), 跳过")
return harvestable
def harvest(self, camera_image):
"""执行采摘流程"""
# 1. 扫描识别
targets = self.scan_orchard(camera_image)
if not targets:
print("未发现可采摘的成熟果实")
return 0
print(f"\n发现 {len(targets)} 个可采摘果实,开始采摘...")
harvested = 0
for target in targets:
# 2. 定位果实三维位置(结合深度相机)
fruit_3d_pos = self.locate_3d(target['bbox'])
# 3. 机械臂移动到果实位置
self.move_arm_to(fruit_3d_pos)
# 4. 执行采摘动作(剪切/夹取/吸取,取决于果实类型)
if self.pick_fruit(target['fruit_type']):
harvested += 1
print(f" 采摘成功: {target['fruit_type']}")
else:
print(f" 采摘失败: {target['fruit_type']}")
print(f"\n采摘完成: {harvested}/{len(targets)}")
return harvested
def locate_3d(self, bbox):
"""结合深度相机获取三维坐标"""
# 实际实现使用RGB-D相机
x1, y1, x2, y2 = bbox
cx = (x1 + x2) / 2
cy = (y1 + y2) / 2
return (cx, cy, 0.5) # 模拟深度0.5米
def move_arm_to(self, position):
"""机械臂移动"""
print(f" 机械臂移动到: {position}")
def pick_fruit(self, fruit_type):
"""执行采摘"""
print(f" 采摘 {fruit_type}")
return True
七、项目架构总结
一个完整的具身智能视觉检索系统,架构如下:
┌─────────────────────────────────────────────────────────┐
│ 感知层 (Perception) │
│ ┌──────────┐ ┌──────────────┐ ┌───────────────────┐ │
│ │ RGB相机 │ │ RGB-D深度相机 │ │ 其他传感器(触觉等) │ │
│ └────┬─────┘ └──────┬───────┘ └────────┬──────────┘ │
│ └───────────────┼────────────────────┘ │
│ ↓ │
│ ┌────────────────────────────────────────────────────┐ │
│ │ YOLO物体检测 → 目标区域裁剪 │ │
│ └────────────────────────┬───────────────────────────┘ │
└───────────────────────────┼─────────────────────────────┘
↓
┌─────────────────────────────────────────────────────────┐
│ 认知层 (Cognition) │
│ ┌──────────────┐ ┌──────────────────┐ │
│ │ 特征提取模型 │ │ 多模态融合(CLIP) │ │
│ │ ResNet/Mobile │ │ 视觉+文本融合 │ │
│ └──────┬───────┘ └────────┬─────────┘ │
│ └──────────┬────────┘ │
│ ↓ │
│ ┌────────────────────────────────────────────────────┐ │
│ │ 向量检索 (FAISS/Milvus) → 匹配特征库 │ │
│ │ 返回: 物体名称 + 类别 + 置信度 │ │
│ └────────────────────────┬───────────────────────────┘ │
│ ↓ │
│ ┌────────────────────────────────────────────────────┐ │
│ │ 动作决策引擎 → 选择抓取策略/操作方案 │ │
│ └────────────────────────┬───────────────────────────┘ │
└───────────────────────────┼─────────────────────────────┘
↓
┌─────────────────────────────────────────────────────────┐
│ 执行层 (Action) │
│ ┌──────────┐ ┌──────────┐ ┌──────────────────────┐ │
│ │ 机械臂控制 │ │ 移动底盘 │ │ 末端执行器(夹爪/吸盘) │ │
│ └──────────┘ └──────────┘ └──────────────────────┘ │
└─────────────────────────────────────────────────────────┘
整个闭环就是六个字:感知→认知→执行。感知层负责"看见",认知层负责"认识",执行层负责"动手"。向量检索在认知层扮演核心角色——它是连接"看见"和"认识"的桥梁,把像素转化成语义。
具身智能的视觉检索和普通视觉检索最大的区别在于:检索结果直接驱动物理动作。普通检索错了最多返回错误结果,具身智能检索错了可能导致机械臂抓坏东西。所以这里对置信度阈值的要求更严格,对特征库的维护更精细,对实时性的要求也更高——一个闭环控制系统,检索延迟太高会导致机械臂动作卡顿甚至失控。
DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。
更多推荐

所有评论(0)