PyTorch预处理图像后调用OpenCV HOGDescriptor遇类型错误求助
解决OpenCV HOGDescriptor.compute()的图像类型不匹配错误
这个错误本质是OpenCV的HOG计算函数对输入图像的数据类型和维度格式有严格要求,咱们一步步拆解问题并解决:
错误原因解析
报错里的img.type() == 0 || img.type() == ...其实是OpenCV在检查输入图像是否为以下两种合法类型:
CV_8U:8位无符号单通道图像(0-255像素值)CV_32F:32位浮点单通道图像
而你的代码里存在两个核心问题:
- 维度格式不匹配:PyTorch的
ToTensor()输出的是(通道数, 高度, 宽度)(CHW)格式的Tensor,转成numpy后还是这个顺序,但OpenCV需要的是(高度, 宽度, 通道数)(HWC)格式。 - 数值范围与类型问题:
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
相关产品推荐
相关产品推荐

