在Pandas中为未知列数动态定义列名:HOG图像特征存入DataFrame的实现问题
解决HOG特征自动存入DataFrame(无需手动指定列数)的问题
看起来你碰到的核心问题是HOG特征维度太高,没法手动定义列名,而且原代码里的DataFrame初始化和数据追加逻辑也有问题,导致运行报错。我来帮你修正这个问题,同时优化整个流程:
先分析原代码的几个关键问题:
- 手动指定列数完全不匹配HOG特征维度:你创建的
image_hog2只有8列,但HOG特征(不管是fd特征向量还是hog_image的扁平化结果)的维度都远超8,直接赋值必然报错。 - 数据追加逻辑混乱:每次循环都把
image_hog2追加到image_hog,会导致数据重复堆积,而且索引也会乱。 - 混淆了HOG的特征向量和可视化图像:
fd才是我们通常用来做机器学习的HOG特征向量,而hog_image是用来可视化梯度分布的图像,如果你是为了后续分类/建模,应该用fd而不是hog_image.flatten()(当然如果确实需要图像像素当特征,也可以调整)。
修正后的代码方案
我们可以先把所有图像的HOG特征收集到一个列表里,最后一次性转换成DataFrame,这样列数会自动匹配特征维度,完全不需要手动指定。同时还可以顺便收集标签,方便后续任务:
import numpy as np import cv2 import os from skimage.transform import resize from skimage.feature import hog import pandas as pd data_path = "/content/drive/My Drive/ADIP/seperate_ricepests8/seperate_ricepests8/" # 初始化两个列表,分别存HOG特征和对应的标签 hog_features = [] labels_list = [] # 遍历每个类别文件夹 labels = os.listdir(data_path) for dirname in labels: filepath = os.path.join(data_path, dirname) print(f"Extracting {dirname} ... ") # 遍历文件夹下的每张图像 for file in os.listdir(filepath): filename = os.path.join(filepath, file) # 读取图像并预处理 image = cv2.imread(filename) # 转灰度图(skimage的hog也支持单通道输入) image_gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) # 调整到HOG常用的输入尺寸(128x64是经典尺寸) resized_img = resize(image_gray, (128, 64)) # 提取HOG特征向量(fd是特征,hog_image是可视化图) fd, _ = hog( resized_img, orientations=9, pixels_per_cell=(8, 8), cells_per_block=(2, 2), visualize=True, channel_axis=None # 单通道图像用这个参数,skimage版本不同可能用multichannel=False ) # 将特征和标签加入列表 hog_features.append(fd) labels_list.append(dirname) print(f"{dirname} ok!") # 将特征列表转换成DataFrame,列会自动按特征维度生成(0,1,2,...) hog_df = pd.DataFrame(hog_features) # 如果需要给列名加上前缀,比如hog_0, hog_1...,可以用下面的代码 # hog_df.columns = [f"hog_{i}" for i in range(hog_df.shape[1])] # 把标签列加入DataFrame(可选,方便后续建模) hog_df["label"] = labels_list # 查看结果 print(hog_df.shape) print(hog_df.head())
关键改进点说明:
- 动态适配列数:通过先收集所有特征到列表,再转DataFrame,pandas会自动根据特征向量的长度生成对应数量的列,完全不需要手动指定。
- 清晰的数据流程:用列表收集特征和标签,避免原代码中重复追加DataFrame的混乱逻辑,运行效率也更高。
- 明确HOG特征的选择:这里用的是
fd(方向梯度直方图的特征向量),这是HOG算法输出的核心特征,适合后续的机器学习任务。如果你确实需要用可视化的hog_image的像素作为特征,只需要把fd换成hog_image.flatten()即可,代码同样能自动适配列数。 - 兼容skimage版本:注意
channel_axis=None是skimage较新版本的参数,如果你的版本比较旧,可以换成multichannel=False。
这样处理后,每张图像的HOG特征就会作为一行存入DataFrame,后续的图像依次追加,完全解决了列数未知的问题。
内容的提问来源于stack exchange,提问作者Qasim0787
相关产品推荐
相关产品推荐

