当前位置:   article > 正文

(11-2)图像分类:基于特征提取和机器学习的图像分类_基于直方图特征提取和knn的颜色分类器

基于直方图特征提取和knn的颜色分类器

11.2  基于特征提取和机器学习的图像分类

统的图像分类方法通常涉及手工设计的特征提取步骤,例如边缘检测、纹理特征提取、颜色直方图等。然后,这些提取的特征被输入到机器学习算法中,如支持向量机(SVM)、随机森林(Random Forest)和k最近邻(k-Nearest Neighbors)等进行分类。

11.2.1  基本流程

使用特征提取和机器学习方法实现图像分类的基本流程如下:

(1)数据准备:首先,需要收集并准备好带有标注的图像数据集。确保数据集中包含各个类别的典型样本,并确保标注准确和完整。

2特征提取:特征提取是将图像转换为机器学习算法能够理解和处理的特征向量的过程。常见的特征提取方法包括:

  1. 边缘检测:使用边缘检测算法(如Sobel、Canny等)提取图像的边缘信息。
  2. 颜色直方图:将图像中各个颜色通道的像素值统计为直方图,用于表示颜色分布。
  3. 纹理特征:提取图像中的纹理信息,如灰度共生矩阵(GLCM)和局部二值模式(LBP)等。
  4. 尺度不变特征变换(SIFT):提取具有尺度和旋转不变性的局部特征描述子。
  5. 主成分分析(PCA):将高维的图像特征降维到低维空间中,以减少特征的维度和冗余信息。

(3)特征表示:将提取得到的特征转换为机器学习算法所需的向量形式。可以将特征向量简单地按照一定的规则进行拼接或者使用降维方法(如PCA)将其转换为较低维度的特征表示。

4数据划分:将准备好的特征向量以及对应的标签划分为训练集和测试集,通常采用交叉验证等方法进行划分。

5机器学习模型训练和分类:选择适当的机器学习算法,如支持向量机(SVM)、随机森林(Random Forest)或k最近邻(k-Nearest Neighbors)等。使用训练集的特征向量和标签进行模型训练,通过优化算法调整模型参数。训练完成后,使用测试集的特征向量进行分类预测,并评估分类准确率、精确率、召回率等指标。

6模型评估和调优:根据评估结果,可以调整机器学习模型的超参数、特征选择、模型选择等来提高分类性能。常用的方法包括网格搜索、交叉验证等。

需要注意的是,特征提取和机器学习方法在处理大规模图像数据集时可能存在一些限制,例如手工设计特征可能无法捕捉到复杂的语义信息。然而,在小规模数据集或资源受限的环境中,特征提取和机器学习方法仍然是一个有效的选择。随着深度学习技术的发展,深度学习方法在图像分类任务上取得了更好的性能,但传统方法仍然具有一定的实用性和应用场景。

11.2.2  基于Scikit-Learn机器学习的图像分类

机器学习从开始到建模的基本流程是:获取数据、数据预处理、训练模型、模型评估、预测、分类。本次我们将根据传统机器学习的流程,看看在每一步流程中都有哪些常用的函数以及他们的用法是怎么样的。例如下面是一个使用库Scikit-learn实现图像分类的例子,其中采用了特征提取和机器学习方法。

实例11-1:使用库Scikit-learn实现图像分类

源码路径:daima\9\catdog.py

  1. import os
  2. import cv2
  3. import numpy as np
  4. from sklearn.model_selection import train_test_split
  5. from sklearn.svm import SVC
  6. from sklearn.metrics import accuracy_score
  7. # 数据集路径和类别标签
  8. dataset_path = "path_to_dataset"
  9. categories = ["cat", "dog"]
  10. # 提取特征的函数(示例中使用颜色直方图作为特征)
  11. def extract_features(image_path):
  12. image = cv2.imread(image_path)
  13. image = cv2.resize(image, (100, 100)) # 调整图像大小
  14. hist = cv2.calcHist([image], [0, 1, 2], None, [8, 8, 8], [0, 256, 0, 256, 0, 256]) # 计算颜色直方图
  15. hist = cv2.normalize(hist, hist).flatten() # 归一化并展平
  16. return hist
  17. # 加载图像数据和标签
  18. data = []
  19. labels = []
  20. for category in categories:
  21. category_path = os.path.join(dataset_path, category)
  22. for image_name in os.listdir(category_path):
  23. image_path = os.path.join(category_path, image_name)
  24. features = extract_features(image_path)
  25. data.append(features)
  26. labels.append(category)
  27. # 将数据集划分为训练集和测试集
  28. X_train, X_test, y_train, y_test = train_test_split(data, labels, test_size=0.2, random_state=42)
  29. # 使用支持向量机(SVM)作为分类器
  30. classifier = SVC()
  31. classifier.fit(X_train, y_train)
  32. # 在测试集上进行预测
  33. y_pred = classifier.predict(X_test)
  34. # 计算分类准确率
  35. accuracy = accuracy_score(y_test, y_pred)
  36. print("Accuracy:", accuracy)

上述代码中,首先定义了数据集路径和类别标签。然后,通过函数extract_features()提取图像的特征,这里使用的是颜色直方图。接下来,遍历数据集中的图像,提取特征并将其添加到数据列表中,同时记录对应的类别标签。然后,使用函数train_test_split()将数据集划分为训练集和测试集。在训练阶段,使用SVC类作为分类器,通过调用fit方法对训练数据进行训练。最后,使用训练好的分类器在测试集上进行预测,并计算分类准确率。执行后会输出:

Accuracy: 0.7857142857142857'
运行

注意:上面输出的准确率只有0.78的原因是作者在运行时使用的数据集过小导致的,机器学习算法通常需要足够的数据来学习和泛化。在源码中提供了kaggle dog VS.cat 数据集(下载地址是:https://aistudio.baidu.com/aistudio/datasetdetail/11544),在这个训练集中共有25000张图片,猫狗各一半。格式为dog.xxx.jpg/cat.xxx.jpg(xxx为编号) 测试集12500张,没标定是猫还是狗,格式为xxx.jpg。大家可以使用这个数据集进行训练识别,准确率会大大提高。这只是一个简单的示例,实际应用中可能需要根据具体情况进行更多的数据预处理、特征选择、模型调优等步骤。另外,可以尝试使用其他特征提取方法和机器学习算法,以及结合交叉验证等技术来提高分类性能。

再看下面的实例文件hua.py实现了鸢尾花识别的功能。这是一个经典的机器学习分类问题,它的数据样本中包括了4个特征变量,1个类别变量,样本总数为150。本实例的目标是根据花萼长度(sepal length)、花萼宽度(sepal width)、花瓣长度(petal length)、花瓣宽度(petal width)这四个特征来识别出鸢尾花属于山鸢尾(iris-setosa)、变色鸢尾(iris-versicolor)和维吉尼亚鸢尾(iris-virginica)中的哪一种。

实例11-2实现鸢尾花的识别功能

源码路径:daima\9\hua.py

  1. # 引入数据集,sklearn包含众多数据集
  2. from sklearn import datasets
  3. # 将数据分为测试集和训练集
  4. from sklearn.model_selection import train_test_split
  5. # 利用邻近点方式训练数据
  6. from sklearn.neighbors import KNeighborsClassifier
  7. # 引入数据,本次导入鸢尾花数据,iris数据包含4个特征变量
  8. iris = datasets.load_iris()
  9. # 特征变量
  10. iris_X = iris.data
  11. # print(iris_X)
  12. print('特征变量的长度', len(iris_X))
  13. # 目标值
  14. iris_y = iris.target
  15. print('鸢尾花的目标值', iris_y)
  16. # 利用train_test_split进行训练集和测试机进行分开,test_size占30%
  17. X_train, X_test, y_train, y_test = train_test_split(iris_X, iris_y, test_size=0.3)
  18. # 我们看到训练数据的特征值分为3类
  19. print(y_train)
  20. # 训练数据
  21. # 引入训练方法
  22. knn = KNeighborsClassifier()
  23. # 进行填充测试数据进行训练
  24. knn.fit(X_train, y_train)
  25. params = knn.get_params()
  26. print(params)
  27. score = knn.score(X_test, y_test)
  28. print("预测得分为:%s" % score)
  29. # 预测数据,预测特征值
  30. print(knn.predict(X_test))
  31. # 打印真实特征值
  32. print(y_test)

执行后会输出训练和预测结果:

  1. 特征变量的长度 150
  2. 鸢尾花的目标值 [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
  3. 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
  4. 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 2
  5. 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
  6. 2 2]
  7. [2 1 2 1 0 2 0 1 0 1 0 1 1 2 1 0 0 0 1 2 2 2 2 1 1 2 1 0 2 0 2 0 0 2 2 2 0
  8. 1 1 2 0 2 1 1 1 2 0 0 1 1 1 1 1 0 1 0 2 2 2 1 1 0 0 2 0 2 1 0 2 1 1 0 2 2
  9. 2 0 1 1 0 2 0 1 2 2 1 1 1 0 1 1 2 0 0 2 0 0 1 2 0 0 0 0 1 2 2]
  10. {'algorithm': 'auto', 'leaf_size': 30, 'metric': 'minkowski', 'metric_params': None, 'n_jobs': None, 'n_neighbors': 5, 'p': 2, 'weights': 'uniform'}
  11. 预测得分为:1.0
  12. [0 2 0 0 1 0 1 1 0 0 2 2 1 0 2 2 1 0 0 2 0 2 1 0 2 1 2 2 2 2 0 2 0 0 1 2 2
  13. 0 1 2 1 1 1 0 1]
  14. [0 2 0 0 1 0 1 1 0 0 2 2 1 0 2 2 1 0 0 2 0 2 1 0 2 1 2 2 2 2 0 2 0 0 1 2 2
  15. 0 1 2 1 1 1 0 1]

11.2.3  分类算法

请看下面的实例文件fen.py,功能是绘制不同分类器的分类概率。我们使用一个3类的数据集,并使用支持向量分类器、带L1和L2惩罚项的Logistic回归, 使用One-Vs-Rest或多项设置以及高斯过程分类对其进行分类。在默认情况下,线性SVC不是概率分类器,但在本例中它有一个内建校准选项(probability=True)。箱外的One-Vs-Rest的逻辑回归不是一个多分类的分类器,因此,与其他分类器相比,它在分离第2类和第3类时有更大的困难。

实例11-3:绘制不同分类器对于一个数据集的分类概率

源码路径:daima\9\fen.py

  1. import matplotlib.pyplot as plt
  2. import numpy as np
  3. from sklearn.metrics import accuracy_score
  4. from sklearn.linear_model import LogisticRegression
  5. from sklearn.svm import SVC
  6. from sklearn.gaussian_process import GaussianProcessClassifier
  7. from sklearn.gaussian_process.kernels import RBF
  8. from sklearn import datasets
  9. iris = datasets.load_iris()
  10. X = iris.data[:, 0:2] # we only take the first two features for visualization
  11. y = iris.target
  12. n_features = X.shape[1]
  13. C = 10
  14. kernel = 1.0 * RBF([1.0, 1.0]) # for GPC
  15. # Create different classifiers.
  16. classifiers = {
  17. 'L1 logistic': LogisticRegression(C=C, penalty='l1',
  18. solver='saga',
  19. multi_class='multinomial',
  20. max_iter=10000),
  21. 'L2 logistic (Multinomial)': LogisticRegression(C=C, penalty='l2',
  22. solver='saga',
  23. multi_class='multinomial',
  24. max_iter=10000),
  25. 'L2 logistic (OvR)': LogisticRegression(C=C, penalty='l2',
  26. solver='saga',
  27. multi_class='ovr',
  28. max_iter=10000),
  29. 'Linear SVC': SVC(kernel='linear', C=C, probability=True,
  30. random_state=0),
  31. 'GPC': GaussianProcessClassifier(kernel)
  32. }
  33. n_classifiers = len(classifiers)
  34. plt.figure(figsize=(3 * 2, n_classifiers * 2))
  35. plt.subplots_adjust(bottom=.2, top=.95)
  36. xx = np.linspace(3, 9, 100)
  37. yy = np.linspace(1, 5, 100).T
  38. xx, yy = np.meshgrid(xx, yy)
  39. Xfull = np.c_[xx.ravel(), yy.ravel()]
  40. for index, (name, classifier) in enumerate(classifiers.items()):
  41. classifier.fit(X, y)
  42. y_pred = classifier.predict(X)
  43. accuracy = accuracy_score(y, y_pred)
  44. print("Accuracy (train) for %s: %0.1f%% " % (name, accuracy * 100))
  45. # View probabilities:
  46. probas = classifier.predict_proba(Xfull)
  47. n_classes = np.unique(y_pred).size
  48. for k in range(n_classes):
  49. plt.subplot(n_classifiers, n_classes, index * n_classes + k + 1)
  50. plt.title("Class %d" % k)
  51. if k == 0:
  52. plt.ylabel(name)
  53. imshow_handle = plt.imshow(probas[:, k].reshape((100, 100)),
  54. extent=(3, 9, 1, 5), origin='lower')
  55. plt.xticks(())
  56. plt.yticks(())
  57. idx = (y_pred == k)
  58. if idx.any():
  59. plt.scatter(X[idx, 0], X[idx, 1], marker='o', c='w', edgecolor='k')
  60. ax = plt.axes([0.15, 0.04, 0.7, 0.05])
  61. plt.title("Probability")
  62. plt.colorbar(imshow_handle, cax=ax, orientation='horizontal')
  63. plt.show()

上述代码实现了在一个二维特征空间中可视化多个分类器的决策边界和分类概率。这段代码主要用于演示不同分类器在二维特征空间中的分类效果和概率分布情况。通过观察决策边界和概率图像,可以了解不同分类器在鸢尾花数据集上的性能和特点。具体实现流程如下:

  1. 首先,加载了鸢尾花(Iris)数据集,其中X是特征矩阵,包含了鸢尾花的萼片长度和宽度两个特征;y是目标变量,包含了鸢尾花的类别标签。
  2. 然后,定义了一个正态核函数(RBF)作为高斯过程分类器(GPC)的核函数,并设置了惩罚参数C。
  3. 创建不同的分类器,包括L1正则化的逻辑回归(L1 logistic)、L2正则化的逻辑回归(L2 logistic)、线性支持向量机(Linear SVC)和高斯过程分类器(GPC)。这些分类器使用不同的参数和算法来进行训练和分类。
  4. 使用plt.subplots_adjust调整子图的位置和间距,创建一个绘图窗口,并设置图像的大小。
  5. 生成了一个网格点坐标矩阵(Xfull),用于在整个特征空间中生成预测结果。
  6. 对于每个分类器,依次进行训练和预测,计算训练集上的准确率,并打印出来。
  7. 对于每个分类器,绘制了类别的预测概率图像,显示了每个类别的概率分布情况。
  8. 通过调整颜色条的位置和大小,将颜色条添加到图像中。
  9. 最后使用plt.show()显示绘制的图像。

执行后会输出下面的结果,并在Matplotlib中绘制三种分类的概率如图6-1所示

  1. Accuracy (train) for L1 logistic: 83.3%
  2. Accuracy (train) for L2 logistic (Multinomial): 82.7%
  3. Accuracy (train) for L2 logistic (OvR): 79.3%
  4. Accuracy (train) for Linear SVC: 82.0%
  5. Accuracy (train) for GPC: 82.7%

11-1  执行效果

11.2.4  聚类算法

请看下面的实例文件face.py,功能是使用一个大型的Faces数据集学习一组组成面部的20 *20的图像修补程序。本实例非常有趣,展示了使用Scikit-Learn在线API学习按块处理一个大型数据集的方法。本实例处理的方法是一次加载一个图像,并从这个图像中随机提取50个补丁。一旦积累了500个补丁(使用10个图像),则运行在线KMeans对象 MiniBatchKMeans的partial_fit方法。在连续调用partial-fit期间,某些聚类会被重新分配。这是因为它们所代表的补丁数量太少了,所以最好选择一个随机的新聚类。

实例11-4:使用一个Faces数据集学习一组组成面部的20 *20的图像修补程序

源码路径:daima\9\face.py

  1. import time
  2. import matplotlib.pyplot as plt
  3. import numpy as np
  4. from sklearn import datasets
  5. from sklearn.cluster import MiniBatchKMeans
  6. from sklearn.feature_extraction.image import extract_patches_2d
  7. faces = datasets.fetch_olivetti_faces()
  8. # #############################################################################
  9. # Learn the dictionary of images
  10. print('Learning the dictionary... ')
  11. rng = np.random.RandomState(0)
  12. kmeans = MiniBatchKMeans(n_clusters=81, random_state=rng, verbose=True)
  13. patch_size = (20, 20)
  14. buffer = []
  15. t0 = time.time()
  16. # 在整个数据集上循环6次
  17. index = 0
  18. for _ in range(6):
  19. for img in faces.images:
  20. data = extract_patches_2d(img, patch_size, max_patches=50,
  21. random_state=rng)
  22. data = np.reshape(data, (len(data), -1))
  23. buffer.append(data)
  24. index += 1
  25. if index % 10 == 0:
  26. data = np.concatenate(buffer, axis=0)
  27. data -= np.mean(data, axis=0)
  28. data /= np.std(data, axis=0)
  29. kmeans.partial_fit(data)
  30. buffer = []
  31. if index % 100 == 0:
  32. print('Partial fit of %4i out of %i'
  33. % (index, 6 * len(faces.images)))
  34. dt = time.time() - t0
  35. print('done in %.2fs.' % dt)
  36. # #############################################################################
  37. # Plot the results
  38. plt.figure(figsize=(4.2, 4))
  39. for i, patch in enumerate(kmeans.cluster_centers_):
  40. plt.subplot(9, 9, i + 1)
  41. plt.imshow(patch.reshape(patch_size), cmap=plt.cm.gray,
  42. interpolation='nearest')
  43. plt.xticks(())
  44. plt.yticks(())
  45. plt.suptitle('Patches of faces\nTrain time %.1fs on %d patches' %
  46. (dt, 8 * len(faces.images)), fontsize=16)
  47. plt.subplots_adjust(0.08, 0.02, 0.92, 0.85, 0.08, 0.23)
  48. plt.show()

上述代码主要用于学习和展示图像字典中的图像块。通过将图像块提取为数据,然后使用MiniBatchKMeans算法对数据进行聚类,可以学习到一组具有代表性的图像块,用于后续的图像处理和特征表示。本实例实现了使用MiniBatchKMeans算法学习图像字典,并展示学习到的图像字典中的图像块。具体实现流程如下所示:

  1. 首先,导入了需要的库和模块,包括time、matplotlib.pyplot和numpy。
  2. 通过datasets.fetch_olivetti_faces()加载了奥利维蒂人脸数据集(Olivetti Faces),该数据集包含了一组人脸图像。
  3. 接下来,定义了一个MiniBatchKMeans聚类器,并设置了聚类的数量n_clusters为81,以及随机数生成器的种子random_state。
  4. 定义了一个图像块的大小patch_size,它在本例中是一个20x20的矩形。
  5. 创建了一个空列表buffer,用于存储图像块的数据。
  6. 通过循环遍历整个数据集6次,对每张人脸图像进行处理。
  7. 在每次循环中,使用extract_patches_2d函数从图像中提取图像块,设置最大提取数量为50,然后将图像块的数据进行重塑和规范化处理,将其添加到buffer列表中。
  8. 每当buffer列表中的图像块数量达到10个时,将它们连接成一个数据矩阵,并进行均值归一化处理。
  9. 然后,使用kmeans.partial_fit对数据进行部分拟合(partial fit)来更新聚类器的参数。
  10. 每当处理了100个图像块时,打印出部分拟合的进度。
  11. 通过计算总共花费的时间来评估学习过程的耗时。
  12. 最后,使用matplotlib.pyplot绘制了学习到的图像字典中的图像块。循环遍历聚类器的聚类中心,并使用plt.subplot在子图中显示图像块。设置了合适的标题和调整子图的布局。
  13. 通过plt.show()显示绘制的图像。

执行效果如图11-2所示

图11-2  执行效果

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/空白诗007/article/detail/850293
推荐阅读
相关标签
  

闽ICP备14008679号