You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PyTorch预处理图像后调用OpenCV HOGDescriptor遇类型错误求助

解决OpenCV HOGDescriptor.compute()的图像类型不匹配错误

这个错误本质是OpenCV的HOG计算函数对输入图像的数据类型和维度格式有严格要求,咱们一步步拆解问题并解决:

错误原因解析

报错里的img.type() == 0 || img.type() == ...其实是OpenCV在检查输入图像是否为以下两种合法类型:

  • CV_8U:8位无符号单通道图像(0-255像素值)
  • CV_32F:32位浮点单通道图像

而你的代码里存在两个核心问题:

  1. 维度格式不匹配:PyTorch的ToTensor()输出的是(通道数, 高度, 宽度)(CHW)格式的Tensor,转成numpy后还是这个顺序,但OpenCV需要的是(高度, 宽度, 通道数)(HWC)格式。
  2. 数值范围与类型问题:ToTensor()会把图像像素从0-255缩放到0-1,转成numpy后是float32类型,但维度不对的情况下,OpenCV无法识别这是单通道图像,导致类型检查失败。

修复后的代码

直接修改你循环内的处理逻辑即可:

import numpy as np
import cv2
from torchvision import transforms, datasets

# 你的原始变换代码不变
train_transforms = transforms.Compose([
    transforms.Resize([32,32]), 
    transforms.Grayscale(), 
    transforms.ToTensor(),
])
train_data = datasets.ImageFolder(datadir, transform=train_transforms)

nbins = 9
cell_size = (2, 2)
block_size = (2, 2)

for im, l in train_data:
    # 1. 将Tensor转为numpy,并调整维度为OpenCV要求的HWC格式
    im_np = im.numpy().transpose((1, 2, 0))  # 从(C,H,W) -> (H,W,C)
    # 2. 灰度图可以去掉多余的通道维度,变成2D数组(可选,但更规范)
    im_np = im_np.squeeze()
    
    # 3. 转换为OpenCV支持的类型:这里选CV_8U(最常用的8位单通道)
    im_np = (im_np * 255).astype(np.uint8)
    # 如果你需要浮点精度,也可以用CV_32F:
    # im_np = im_np.astype(np.float32)
    
    # 初始化HOGDescriptor(注意这里用调整后的im_np.shape)
    hog = cv2.HOGDescriptor(
        _winSize=(im_np.shape[1] // cell_size[1] * cell_size[1], 
                  im_np.shape[0] // cell_size[0] * cell_size[0]),
        _blockSize=(block_size[1] * cell_size[1], 
                    block_size[0] * cell_size[0]),
        _blockStride=(cell_size[1], cell_size[0]),
        _cellSize=(cell_size[1], cell_size[0]),
        _nbins=nbins
    )
    # 计算HOG特征
    hog_features = hog.compute(im_np)

额外优化建议

如果你的数据集很大,这种循环处理效率很低,推荐把HOG计算封装成PyTorch的自定义Transform,这样可以和数据加载器无缝结合,利用多进程加速:

import torch

class HOGTransform:
    def __init__(self, nbins=9, cell_size=(2,2), block_size=(2,2)):
        self.nbins = nbins
        self.cell_size = cell_size
        self.block_size = block_size
    
    def __call__(self, img):
        # img是PIL图像,先转成numpy的HWC格式
        im_np = np.array(img)
        # 灰度图处理(如果输入已经是灰度图可以省略)
        if len(im_np.shape) == 3:
            im_np = cv2.cvtColor(im_np, cv2.COLOR_RGB2GRAY)
        # 初始化HOG并计算特征
        hog = cv2.HOGDescriptor(
            _winSize=(im_np.shape[1] // self.cell_size[1] * self.cell_size[1], 
                      im_np.shape[0] // self.cell_size[0] * self.cell_size[0]),
            _blockSize=(self.block_size[1] * self.cell_size[1], 
                        self.block_size[0] * self.cell_size[0]),
            _blockStride=(self.cell_size[1], self.cell_size[0]),
            _cellSize=(self.cell_size[1], self.cell_size[0]),
            _nbins=self.nbins
        )
        features = hog.compute(im_np)
        # 转成Tensor返回
        return torch.from_numpy(features).float()

# 然后修改transforms
train_transforms = transforms.Compose([
    transforms.Resize([32,32]), 
    transforms.Grayscale(),
    HOGTransform(nbins=9, cell_size=(2,2), block_size=(2,2))
])

这样数据加载时会自动处理HOG特征,不需要手动循环,更符合PyTorch的使用习惯。

内容的提问来源于stack exchange,提问作者huehue

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.13 09:04:19