[AI学习:SPIN -win-安装SPIN-工具过程 SPIN win 电脑安装=accoda 环境-第四篇:代码修复]

[AI学习:SPIN -win-安装SPIN-工具过程 SPIN win 电脑安装=accoda 环境-第四篇:代码修复])

  • 1-概述
    • (1)概述
    • (2)操作流程-解决问题
      • [1-重新进入环境:问题1:ImportError: cannot import name 'rotation_matrix_to_angle_axis' from 'utils.geometry'](#1-重新进入环境:问题1:ImportError: cannot import name 'rotation_matrix_to_angle_axis' from 'utils.geometry')
      • [2-问题:_pickle.UnpicklingError: Weights only load failed. 。。。。error: Unsupported operand 73](#2-问题:_pickle.UnpicklingError: Weights only load failed. 。。。。error: Unsupported operand 73)
      • [3-问题:TypeError: crop() missing 2 required positional arguments: 'scale' and 'res'](#3-问题:TypeError: crop() missing 2 required positional arguments: 'scale' and 'res')
      • [4-问题:TypeError: 'int' object is not subscriptable](#4-问题:TypeError: 'int' object is not subscriptable)
      • [5-问题:AttributeError: scipy.misc is deprecated and has no attribute imresize](#5-问题:AttributeError: scipy.misc is deprecated and has no attribute imresize)
      • [6-问题:ValueError: too many values to unpack (expected 4)](#6-问题:ValueError: too many values to unpack (expected 4))
      • [7-问题:RuntimeError: Input type (torch.cuda.DoubleTensor) and weight type (torch.cuda.FloatTensor) should be the same](#7-问题:RuntimeError: Input type (torch.cuda.DoubleTensor) and weight type (torch.cuda.FloatTensor) should be the same)
      • [8-问题: RuntimeError: einsum(): subscript i has size 300 for operand](#8-问题: RuntimeError: einsum(): subscript i has size 300 for operand)
    • (3)总结

1-概述

(1)概述

上篇已经说了,最近学习AI,看到了SPIN这个工具,可以将图片转换位3D模型,我们继续来尝试,并且将问题记录。

前篇文章:[AI学习:SPIN -win-安装SPIN-工具过程 SPIN win 电脑安装=accoda 环境-第三篇:解决报错]

我们之前布置了环境,之后往后遇到很多问题,今天来继续操作。

(2)操作流程-解决问题

1-重新进入环境:问题1:ImportError: cannot import name 'rotation_matrix_to_angle_axis' from 'utils.geometry'

bash 复制代码
ImportError: cannot import name 'rotation_matrix_to_angle_axis' from 'utils.geometry'

在 SPIN 的 utils/geometry.py 里并没有这个函数;你打印出来的可用函数只有:

bash 复制代码
['quat_to_rotmat', 'rot6d_to_rotmat']

也就是说,你在 demo_norender.py 的这行:

bash 复制代码
from utils.geometry import rotation_matrix_to_angle_axis
2)-解决方式

尝试解决:

bash 复制代码
# from utils.geometry import rotation_matrix_to_angle_axis   # ❌ 删除这行

在文件顶部加一个小工具函数(放在 imports 下面即可):

bash 复制代码
import torch
import torch.nn.functional as F

def rotmat_to_axis_angle(R: torch.Tensor) -> torch.Tensor:
    """
    R: (..., 3, 3) rotation matrices
    return: (..., 3) axis-angle (Rodrigues) vectors
    """
    # clamp trace -> acos domain
    trace = R[..., 0, 0] + R[..., 1, 1] + R[..., 2, 2]
    cos_theta = (trace - 1.0) * 0.5
    cos_theta = torch.clamp(cos_theta, -1.0 + 1e-6, 1.0 - 1e-6)
    theta = torch.acos(cos_theta)

    rx = R[..., 2, 1] - R[..., 1, 2]
    ry = R[..., 0, 2] - R[..., 2, 0]
    rz = R[..., 1, 0] - R[..., 0, 1]
    axis = torch.stack([rx, ry, rz], dim=-1)
    axis = F.normalize(axis, dim=-1)

    aa = axis * theta.unsqueeze(-1)  # (...,3)
    # 角度极小时设为 0,避免数值噪声
    aa = torch.where(theta.unsqueeze(-1) < 1e-8, torch.zeros_like(aa), aa)
    return aa

2-问题:_pickle.UnpicklingError: Weights only load failed. 。。。。error: Unsupported operand 73

bash 复制代码
_pickle.UnpicklingError: Weights only load failed.
In PyTorch 2.6, the default value of the `weights_only` arg in `torch.load`
changed to True. Re-running `torch.load` with `weights_only=False` will likely succeed.
pickle error: Unsupported operand 73

当前用的是 PyTorch 2.6,torch.load() 的默认参数 weights_only=True 会阻止用 pickle 反序列化老版本保存的 .pt 文件(SPIN 的 model_checkpoint.pt 就是老格式)。

按提示把 weights_only=False 传进去即可。

1)-修复方案

打开 demo_norender.py,找到加载 checkpoint 的那行(你日志里是第 44 行左右):

bash 复制代码
ckpt_dict = torch.load(ckpt, map_location=DEVICE)

改成:

bash 复制代码
import pickle  # 文件顶部确保有
ckpt_dict = torch.load(ckpt, map_location=DEVICE, weights_only=False, pickle_module=pickle)

3-问题:TypeError: crop() missing 2 required positional arguments: 'scale' and 'res'

1)-修复方案

修改demo_norender.py

找到这一行(大约第 28 行):

bash 复制代码
_, rgb_img, _, = crop(img, bbox)  # 裁到 224

改成

bash 复制代码
# bbox.json 通常包含中心坐标 (center_x, center_y) 和缩放比例 scale
# 从 JSON 中读取这些值
center = bbox['center']
scale = bbox['scale']
res = 224  # 输出分辨率

_, rgb_img, _, = crop(img, center, scale, res)

4-问题:TypeError: 'int' object is not subscriptable

bash 复制代码
TypeError: 'int' object is not subscriptable
... in get_transform
t[0, 0] = float(res[1]) / ...

说明 utils/imutils.py:get_transform(center, scale, res, ...) 里面把 res 当作二维 (w, h) 使用,而在 demo_norender.py 里把 res 传成了单个整数 224,所以索引 res[1] 报错。

1)-修复方案

读取 bbox、裁剪那段改成下面这个版本(确保 res 是 (224, 224),center/scale 是 float):

bash 复制代码
import json, numpy as np
import cv2
from torchvision import transforms
from utils.imutils import crop

DEVICE = 'cuda' if torch.cuda.is_available() else 'cpu'

def load_image_with_bbox(img_path, bbox_json):
    # 读图并转为 RGB
    img = cv2.imread(img_path)[:, :, ::-1]

    with open(bbox_json, 'r', encoding='utf-8') as f:
        box = json.load(f)

    # 兼容两种格式:1) {center:[x,y], scale:s};2) {x,y,w,h}
    if 'center' in box and 'scale' in box:
        center = np.array(box['center'], dtype=np.float32)
        scale = float(box['scale'])
    else:
        x = float(box['x']); y = float(box['y'])
        w = float(box['w']); h = float(box['h'])
        center = np.array([x + w / 2.0, y + h / 2.0], dtype=np.float32)
        # SPIN 里 scale 是相对 200 的缩放
        scale = max(w, h) / 200.0

    # 注意:res 必须是 (w, h) 二元数组/元组,不能是单个 int
    res = np.array([224, 224], dtype=np.float32)

    # 按 SPIN 的接口:crop(img, center, scale, res)
    _, rgb_img, _, = crop(img, center, scale, res)

    normalize = transforms.Normalize(mean=[0.485, 0.456, 0.406],
                                     std=[0.229, 0.224, 0.225])
    to_t = transforms.Compose([transforms.ToTensor(), normalize])
    return to_t(rgb_img).unsqueeze(0).to(DEVICE)

执行指令

bash 复制代码
python demo_norender.py --checkpoint data\model_checkpoint.pt --img examples\front.jpg --json examples\front_bbox.json

5-问题:AttributeError: scipy.misc is deprecated and has no attribute imresize

bash 复制代码
AttributeError: scipy.misc is deprecated and has no attribute imresize

这说明 imutils.py 里在用老旧的 scipy.misc.imresize()(在 scipy>=1.3 中被删除了)。

环境中是新版 SciPy,所以这一行彻底失效。

1)-修复方案
bash 复制代码
new_img = scipy.misc.imresize(new_img, res)

替换方案

注意:OpenCV 的 resize() 参数是 (width, height),所以顺序不能反。

如果之前定义了 res = [224, 224],这里 (res[0], res[1]) 就正好匹配。

bash 复制代码
import cv2

new_img = cv2.resize(new_img, (int(res[0]), int(res[1])), interpolation=cv2.INTER_LINEAR)

6-问题:ValueError: too many values to unpack (expected 4)

bash 复制代码
ValueError: too many values to unpack (expected 4)
... in load_image_with_bbox
_, rgb_img, _, = crop(img, center, scale, (224, 224))

意思是:utils/imutils.py 里的 crop() 返回的值个数比 4 个还多,而这行代码只准备了解包成 4 个变量,所以报 "too many values"。

不同版本的 SPIN / 自改过的 imutils.crop 返回值个数不一致:有的返回 (ul, br, rgb_img, trans),有的还会多返回 rot、trans_inv 等。因此最稳妥的写法是只取你真正需要的那个 裁剪后的 RGB 图,其余用"星号收集"。

1)-修复方案

用星号接收多余返回值

bash 复制代码
# 原来:
# _, rgb_img, _, = crop(img, center, scale, (224, 224))

# 改成:
_, rgb_img, *rest = crop(img, center, scale, (224, 224))

7-问题:RuntimeError: Input type (torch.cuda.DoubleTensor) and weight type (torch.cuda.FloatTensor) should be the same

bash 复制代码
RuntimeError: Input type (torch.cuda.DoubleTensor) and weight type (torch.cuda.FloatTensor) should be the same

喂给模型的张量是 double(float64),而模型权重是 float32。卷积要求两者 dtype 一致。

1)-修复方案
bash 复制代码
# x 是你 load_image_with_bbox 返回的输入
x = load_image_with_bbox(img, bbox_json)

# 关键:统一 dtype 和 device
x = x.to(device=DEVICE, dtype=torch.float32)

# (可选)确保模型也在 fp32
model = model.to(torch.float32)

with torch.no_grad():
    pred_rotmat, pred_betas, pred_camera = model(x)

8-问题: RuntimeError: einsum(): subscript i has size 300 for operand

bash 复制代码
RuntimeError: einsum(): subscript i has size 300 for operand 1 which does not broadcast with previously seen size 10
... in smplx/lbs.py -> blend_shapes
... v_shaped = v_template + blend_shapes(betas, shapedirs)

这说明 传给 SMPL 的 betas 向量长度是 300,而 当前 SMPL 模型只带 10 个 shape 基(shapedirs[..., 10])。二者不匹配,于是 einsum 广播失败。

在 SPIN 中,正确的 betas 维度应该是 10(形如 [B, 10])。现在的 pred_betas 是 [B, 300](多半是用了 smplx 的实现或模型输出头和目标不一致)。

1)-修复方案

拿到模型输出后,把 betas 截到前 10 维 再喂给 SMPL:

bash 复制代码
with torch.no_grad():
    pred_rotmat, pred_betas, pred_cam = model(x.float())

print("pred_betas.shape before:", tuple(pred_betas.shape))
pred_betas = pred_betas[:, :10].contiguous()   # 只保留前 10 维
print("pred_betas.shape after:", tuple(pred_betas.shape))

# 保证 dtype/device 一致
pred_betas = pred_betas.to(dtype=torch.float32, device=DEVICE)

out = smpl(betas=pred_betas)  # 这里就不会再和 shapedirs(10) 冲突了

(3)总结

问题还是太多了,这也是最折磨人地方,准备再分开写吧。

相关推荐
小鸡吃米…4 小时前
机器学习 - K - 中心聚类
人工智能·机器学习·聚类
好奇龙猫5 小时前
【AI学习-comfyUI学习-第三十节-第三十一节-FLUX-SD放大工作流+FLUX图生图工作流-各个部分学习】
人工智能·学习
沈浩(种子思维作者)5 小时前
真的能精准医疗吗?癌症能提前发现吗?
人工智能·python·网络安全·健康医疗·量子计算
saoys5 小时前
Opencv 学习笔记:图像掩膜操作(精准提取指定区域像素)
笔记·opencv·学习
minhuan5 小时前
大模型应用:大模型越大越好?模型参数量与效果的边际效益分析.51
人工智能·大模型参数评估·边际效益分析·大模型参数选择
Cherry的跨界思维5 小时前
28、AI测试环境搭建与全栈工具实战:从本地到云平台的完整指南
java·人工智能·vue3·ai测试·ai全栈·测试全栈·ai测试全栈
MM_MS5 小时前
Halcon变量控制类型、数据类型转换、字符串格式化、元组操作
开发语言·人工智能·深度学习·算法·目标检测·计算机视觉·视觉检测
ASF1231415sd5 小时前
【基于YOLOv10n-CSP-PTB的大豆花朵检测与识别系统详解】
人工智能·yolo·目标跟踪
水如烟6 小时前
孤能子视角:“意识“的阶段性回顾,“感质“假说
人工智能
电子小白1236 小时前
第13期PCB layout工程师初级培训-1-EDA软件的通用设置
笔记·嵌入式硬件·学习·pcb·layout