快乐学AI系列——计算机视觉(5)图像分类和识别

2023-04-06 19:02:37 浏览数 (2)

本系列是由“MATRIX.矩阵之芯”精炼的AI快速入门系列,特色是内容简洁,学习快速。 相关要求:学员需要掌握Python编程基础,另外还需要有一定的线性代数、概率论基础

传统图像分类算法的两种方法:SIFT特征 KNN分类器和HOG特征 SVM分类器。

SIFT特征 KNN分类器

SIFT(Scale-invariant Feature Transform,尺度不变特征变换)是一种用于图像特征提取的算法。SIFT特征提取算法的核心思想是将图像中的特征点提取出来,然后将其描述成一组向量,这些向量可以描述特征点的方向、尺度、形状等特征信息,这些信息不受图像缩放、旋转等变换的影响。这些特征向量可以用来进行图像的匹配、分类等任务。

KNN(K-Nearest Neighbor,K近邻算法)是一种非参数的分类算法。它的基本思想是将待分类样本的特征向量与训练集中的所有特征向量进行比较,找到与待分类样本最相似的K个样本,然后根据这K个样本的分类情况来判断待分类样本的类别。

下面我们将使用SIFT特征和KNN分类器来对图像进行分类:

代码语言:javascript复制
import numpy as np
from sklearn.datasets import load_digits
from sklearn.model_selection import train_test_split
from sklearn.neighbors import KNeighborsClassifier
from sklearn.metrics import accuracy_score

# 加载手写数字数据集
digits = load_digits()
X, y = digits.data, digits.target

# 将数字标签转换为字母标签
y = np.array(['zero', 'one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine'])[y]

# 划分数据集为训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

# 初始化KNN分类器并进行训练
knn = KNeighborsClassifier(n_neighbors=3)
knn.fit(X_train, y_train)

# 对测试集进行预测并计算准确率
y_pred = knn.predict(X_test)
accuracy = accuracy_score(y_test, y_pred)
print("Accuracy:", accuracy)

本代码运行下来返回值是Accuracy: 0.9833333333333333,这说明我们训练的KNN分类器在手写数字数据集上的准确率为98.33%。这是一个非常不错的结果,说明KNN算法在手写数字分类问题上的表现还是比较优秀的。

HOG特征 SVM分类器

HOG(Histogram of Oriented Gradients)特征是一种常用的图像特征提取方法,它能够有效地捕获图像中的纹理、形状等信息。SVM(Support Vector Machine)分类器则是一种常用的机器学习算法,它能够对数据进行分类并输出分类结果。

在使用HOG特征和SVM分类器进行图像分类时,我们需要先提取出每张图像的HOG特征,然后使用这些特征来训练SVM分类器。接着,我们就可以使用训练好的SVM分类器来对新的图像进行分类了。

使用HOG特征和SVM分类器进行图像分类来举个栗子:

代码语言:javascript复制
import cv2
import numpy as np
from sklearn.model_selection import train_test_split
from sklearn.svm import LinearSVC
from sklearn.metrics import accuracy_score
from skimage.feature import hog

# 加载数据集
dataset = []
for i in range(10):
    for j in range(50):
        img = cv2.imread(f'digits/{i}_{j}.png', 0)
        img = cv2.resize(img, (20, 20))
        dataset.append((img, i))

# 提取HOG特征和标签
X = []
y = []
for img, label in dataset:
    hog_feature = hog(img, orientations=9, pixels_per_cell=(4, 4), cells_per_block=(2, 2))
    X.append(hog_feature)
    y.append(label)

# 划分数据集为训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

# 初始化SVM分类器并进行训练
svm = LinearSVC()
svm.fit(X_train, y_train)

# 对测试集进行预测并计算准确率
y_pred = svm.predict(X_test)
accuracy = accuracy_score(y_test, y_pred)
print("Accuracy:", accuracy)

在这段代码中,我们首先加载了一个手写数字数据集,该数据集包含了10个数字(0~9),每个数字有50个不同的实例。接着,我们遍历数据集中的每个图像,并使用HOG特征提取方法提取出每个图像的HOG特征。

对于每个图像,我们都将其对应的标签添加到标签列表y中。接着,我们使用train_test_split函数将数据集划分为训练集和测试集。最后,我们初始化一个LinearSVC分类器并使用训练集对其进行训练。

我们使用测试集对训练好的分类器进行测试,并输出分类准确率。

图像检索和相似度匹配

在图像检索和相似度匹配中,我们需要计算两张图片之间的相似度。其中一种方法是使用特征匹配,即找到两张图片中相似的特征点并将它们匹配起来。OpenCV中提供了一个名为SIFT(Scale-Invariant Feature Transform)的特征提取算法,可以用于提取图像中的关键点及其对应的特征描述符。

再来一个小例子:

代码语言:javascript复制
import cv2

# 读取两张图片
img1 = cv2.imread('image1.jpg')
img2 = cv2.imread('image2.jpg')

# 初始化SIFT特征提取器
'''
SIFT算法已经在OpenCV 4中被移除,如果使用OpenCV 4及以上版本,
需要将代码中的 cv2.xfeatures2d.SIFT_create() 替换为 cv2.SIFT_create()。
'''
sift = cv2.xfeatures2d.SIFT_create()

# 提取图片1和图片2中的关键点和特征描述符
kp1, des1 = sift.detectAndCompute(img1, None)
kp2, des2 = sift.detectAndCompute(img2, None)

# 初始化FLANN匹配器
FLANN_INDEX_KDTREE = 0
index_params = dict(algorithm=FLANN_INDEX_KDTREE, trees=5)
search_params = dict(checks=50)
flann = cv2.FlannBasedMatcher(index_params, search_params)

# 对特征描述符进行匹配
matches = flann.knnMatch(des1, des2, k=2)

# 过滤掉不好的匹配
good_matches = []
for m, n in matches:
    if m.distance < 0.7 * n.distance:
        good_matches.append(m)

# 显示匹配结果
result = cv2.drawMatches(img1, kp1, img2, kp2, good_matches, None, flags=2)
cv2.imshow('matches', result)
cv2.waitKey(0)
cv2.destroyAllWindows()

在这个示例中,我们首先读取了两张图片,并使用SIFT算法提取了它们的关键点和特征描述符。然后,我们使用FLANN匹配器对这些特征描述符进行了匹配,过滤掉了不好的匹配,最终显示了匹配结果。

0 人点赞