本文探讨了不同特征提取和融合技术在图像分类任务中的效果。实验基于1000张图片,覆盖10个类别,应用SVM、决策树、KNN和朴素贝叶斯算法,对比了直方图、HOG、LBP和颜色矩特征。发现直方图特征在SVM中表现最佳,准确率达0.8600。实验有局限性,仅供参考。

目录

 第一步:准备数据

第二步:图像特征提取函数解析

第三步:特征增强与组合

第四步:模型训练与评估

 运行结果


 第一步:准备数据

for i in range(10):
    for f in os.listdir(f"photo2/{i}"):
        X.append(os.path.join(f"photo2/{i}", f))
        Y.append(i)

X = np.array(X)
Y = np.array(Y)
X_train, X_test, Y_train, Y_test = train_test_split(X, Y, test_size=0.2, random_state=1)

第二步:图像特征提取函数解析

在图像处理与模式识别领域,特征提取是识别和分类图像的关键步骤。以下是四个常用的特征提取函数,它们分别提取图像的直方图特征、HOG特征、LBP特征和颜色矩特征。

1. 直方图特征提取 (extract_histogram_features)

该函数用于提取图像的颜色直方图特征,它捕捉了图像的颜色分布信息。

def extract_histogram_features(image_path):
    image = cv2.imdecode(np.fromfile(image_path, dtype=np.uint8), cv2.IMREAD_COLOR)
    img = cv2.resize(image, (256, 256), interpolation=cv2.INTER_CUBIC)
    hist = cv2.calcHist([img], [0, 1], None, [256, 256], [0.0, 255.0, 0.0, 255.0])
    return (hist / 255).flatten()
  • cv2.imdecode 和 np.fromfile 用于从文件路径加载图像。
  • cv2.resize 将图像调整为统一的大小(256x256),以便于处理。
  • cv2.calcHist 计算图像的直方图,其中 [0, 1] 表示对蓝色和绿色通道进行直方图计算,[256, 256] 表示直方图的bin数量,[0.0, 255.0, 0.0, 255.0] 为直方图的值域。
  • 直方图的值被归一化并展平,以便于后续处理。

2. HOG特征提取 (extract_hog_features)

HOG(Histogram of Oriented Gradients)特征提取函数用于提取图像中的梯度方向信息,这有助于描述图像中物体的形状和轮廓。

def extract_hog_features(image_path):
    image = cv2.imread(image_path, cv2.IMREAD_COLOR)
    if len(image.shape) > 2 and image.shape[2] == 3:
        image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
    features = hog(image, orientations=8, pixels_per_cell=(16, 16), cells_per_block=(1, 1), block_norm='L2')
    return features
  • cv2.imread 用于读取图像。
  • 如果图像是彩色的,cv2.cvtColor 将其转换为灰度图像。
  • hog 函数计算HOG特征,orientations=8 表示梯度的方向数量,pixels_per_cell 和 cells_per_block 控制单元的大小和块的划分,block_norm='L2' 是块的归一化方法。

3. LBP特征提取 (extract_lbp_features)

局部二值模式(LBP)是一种纹理描述符,它捕捉图像中的局部纹理信息,对光照变化具有较好的鲁棒性。

def extract_lbp_features(image_path):
    image = cv2.imread(image_path, cv2.IMREAD_GRAYSCALE)
    lbp = local_binary_pattern(image, P=8, R=1, method='uniform')
    lbp_8u = cv2.convertScaleAbs(lbp)
    hist = cv2.calcHist([lbp_8u], [0], None, [256], [0, 256])
    return hist.flatten()
  • cv2.imread 以灰度模式读取图像。
  • local_binary_pattern 计算LBP特征。
  • cv2.convertScaleAbs 将LBP图像转换为8位无符号整数。
  • cv2.calcHist 计算LBP图像的直方图,并展平结果。

4. 颜色矩特征提取 (extract_color_moments_features)

颜色矩特征基于图像颜色分布的统计特征,包括均值、标准差等。

def extract_color_moments_features(image_path):
    image = cv2.imread(image_path, cv2.IMREAD_COLOR)
    img = cv2.resize(image, (256, 256), interpolation=cv2.INTER_CUBIC)
    lab = cv2.cvtColor(img, cv2.COLOR_BGR2LAB)
    l, a, b = cv2.split(lab)
    mean_l = np.mean(l)
    std_l = np.std(l)
    mean_a = np.mean(a)
    std_a = np.std(a)
    mean_b = np.mean(b)
    std_b = np.std(b)
    return np.array([mean_l, std_l, mean_a, std_a, mean_b, std_b])
  • cv2.imread 读取图像。
  • cv2.resize 调整图像大小。
  • cv2.cvtColor 将图像从BGR颜色空间转换到LAB颜色空间。
  • cv2.split 分离LAB颜色空间的三个通道。
  • 计算每个通道的均值和标准差,并将结果组合成一个特征数组。

第三步:特征增强与组合

在图像分类任务中,特征增强是一种提升特征表达能力的技术,它可以帮助改善模型的性能。

# 初始化PowerTransformer
pt = PowerTransformer(method='box-cox')
  • PowerTransformer 是 scikit-learn 库中的一个类,用于执行幂变换,这里特别使用的是 Box-Cox 变换,这是一种用于稳定数据方差和使数据更接近正态分布的变换方法。
# 定义特征增强变换函数
def feature_enhancement(features, level):
    if level == 1:
        return features
    elif level == 2:
        return features * 1.2  # 特征放大
    elif level == 3:
        return np.log1p(features)  # 对数变换
    elif level == 4:
        return np.sqrt(features)  # 平方根变换
    elif level == 5:
        features_positive = features - np.min(features) + 1  # 平移并加1以确保所有值都是正数
        return pt.fit_transform(features_positive.reshape(-1, 1)).flatten()  # Box-Cox变换
  • feature_enhancement 函数根据传入的 level 参数对特征进行不同的增强操作。
  • level == 1 时,特征不做变换。
  • level == 2 时,特征进行放大,乘以1.2。
  • level == 3 时,特征进行对数变换,使用 np.log1p 来避免对0取对数。
  • level == 4 时,特征进行平方根变换。
  • level == 5 时,特征进行 Box-Cox 变换,首先确保所有值都是正数,然后应用变换。
# 定义特征提取函数列表
feature_funcs = [
    extract_histogram_features,
    extract_hog_features,
    extract_lbp_features,
    extract_color_moments_features
]
  • feature_funcs 是一个包含四个特征提取函数的列表,每个函数对应于一种特征提取方法。
def combine_features(image_path, feature_funcs):
    features = np.hstack([func(image_path) for func in feature_funcs])
    return features
  • combine_features 函数接受一个图像路径和特征提取函数列表作为参数。
  • 它通过列表推导式调用每个特征提取函数,并将结果水平堆叠(np.hstack)成一个统一的特征向量。
  • 这个特征向量包含了从同一图像中提取的所有特征,可以用于后续的模型训练和测试。

这一步骤通过特征增强和特征组合,为模型提供了更丰富、更具表达力的特征集。特征增强可以帮助模型捕捉到数据中的更多信息,而特征组合则允许模型从多个角度理解图像内容,从而提高分类的准确性。这种方法在处理高维数据和复杂问题时尤为重要,能够显著提升模型的性能。

第四步:模型训练与评估

在完成了特征提取和增强之后,下一步是对分类模型进行训练和评估。

def evaluate_accuracy(clf, XX_train, Y_train, XX_test, Y_test):
    clf.fit(XX_train, Y_train)
    Y_pred = clf.predict(XX_test)
    return accuracy_score(Y_test, Y_pred)
  • evaluate_accuracy 函数接受一个分类器 clf 和训练、测试数据集作为参数。
  • 使用 clf.fit 对训练数据进行拟合(训练)。
  • 使用 clf.predict 对测试数据进行预测。
  • 使用 accuracy_score 计算预测结果的准确率。
# 测试不同的特征提取方法
features_methods = {
    'histogram': extract_histogram_features,
    'hog': extract_hog_features,
    'lbp': extract_lbp_features,
    'color_moments': extract_color_moments_features,
}
  • features_methods 字典包含了四种不同的特征提取方法,每个方法对应一个函数。
# 存储准确率结果
accuracy_results = {}
  • accuracy_results 字典用于存储每种特征提取方法和增强级别下的准确率结果。
# 进度条
total_iterations = len(features_methods)*5   # 5 levels
pbar = tqdm(total=total_iterations, desc="Processing", unit="method")
  • 初始化一个进度条,用于显示处理进度。总共需要处理 features_methods 中的每个方法在5个增强级别下的情况。
# 定义一个函数来训练和评估模型
def train_and_evaluate(feature_name, feature_func, level):
    XX_train_features = np.array([feature_enhancement(feature_func(i), level) for i in X_train])
    XX_test_features = np.array([feature_enhancement(feature_func(i), level) for i in X_test])

    classifiers = {
        'SVM': SVC(kernel="linear", probability=True),
        'Decision Tree': DecisionTreeClassifier(),
        'KNN': KNeighborsClassifier(n_neighbors=11),
        'Naive Bayes': BernoulliNB()
    }

    for classifier_name, clf in classifiers.items():
        accuracy = evaluate_accuracy(clf, XX_train_features, Y_train, XX_test_features, Y_test)
        print(f"Feature: {feature_name}, Level: {level}, {classifier_name}: {accuracy:.4f}")
        accuracy_results[(feature_name, level, classifier_name)] = accuracy
    pbar.update(1)  # 更新进度条
  • train_and_evaluate 函数接受特征名称、特征提取函数和增强级别作为参数。
  • 对训练和测试数据集中的每个图像路径应用特征提取和增强函数,生成特征矩阵。
  • 遍历所有分类器,对每种分类器使用 evaluate_accuracy 函数评估准确率,并打印结果。
  • 将结果存储在 accuracy_results 字典中,并更新进度条。
# 使用线程池来并行执行训练和评估
with ThreadPoolExecutor(max_workers=4) as executor:
    # 提交任务到线程池
    for feature_name, feature_func in features_methods.items():
        for level in range(1, 6):  # 五档特征处理
            executor.submit(train_and_evaluate, feature_name, feature_func, level)

pbar.close()
  • 使用 ThreadPoolExecutor 并行执行训练和评估任务,以提高效率。
  • 对每种特征提取方法和每个增强级别,提交一个 train_and_evaluate 任务到线程池。
  • 关闭进度条。

 运行结果

特征提取方法 分类器 Level 1 Level 2 Level 3 Level 4 Level 5
histogram SVM 0.7950 0.7950 0.8100 0.8600 0.8350
决策树 0.5650 0.5500 0.5600 0.5650 0.5000
KNN 0.5600 0.5600 0.5750 0.6950 0.6250
朴素贝叶斯 0.6250 0.6250 0.6250 0.6250 0.6250
hog SVM 0.7600 0.7600 0.7600 0.7600 0.7400
决策树 0.3600 0.4000 0.3750 0.3950 0.2800
KNN 0.3300 0.3300 0.3650 0.4000 0.4950
朴素贝叶斯 0.3650 0.3650 0.3650 0.3650 0.7000
lbp SVM 0.7150 0.7200 0.6300 0.7100 0.0650
决策树 0.5800 0.5750 0.5550 0.5700 0.0800
KNN 0.6000 0.6000 0.6500 0.6050 0.0850
朴素贝叶斯 0.0650 0.0650 0.0650 0.0650 0.0650
color_moments SVM 0.6850 0.6900 0.6200 0.7000 0.5450
决策树 0.6900 0.6650 0.6550 0.6600 0.5550
KNN 0.6650 0.6650 0.6600 0.6900 0.5850
朴素贝叶斯 0.0650 0.0650 0.0650 0.0650 0.1600

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐