iis服务器助手广告
返回顶部
首页 > 资讯 > 后端开发 > Python >Python-OpenCV中如何利用 KNN 算法识别手写数字
  • 479
分享到

Python-OpenCV中如何利用 KNN 算法识别手写数字

2023-06-22 03:06:53 479人浏览 泡泡鱼

Python 官方文档:入门教程 => 点击学习

摘要

手写数字数据集 MNIST 介绍为了保证完整性,从算法所用的训练数据讲起,训练数据是由 MNIST 手写数字组成的,MNIST 数据集来自美国国家标准与技术研究所,由来自 250 个不同人手写的数字构成,其中训练集包含 60000 张图片,


手写数字数据集 MNIST 介绍

为了保证完整性,从算法所用的训练数据讲起,训练数据是由 MNIST 手写数字组成的,MNIST 数据集来自美国国家标准与技术研究所,由来自 250 个不同人手写的数字构成,其中训练集包含 60000 张图片,测试集包含 10000 张图片,每个图片都有其标签,图片大小为 28*28。许多机器学习库提供了加载 MNIST 数据集的方法,这里使用 keras 库进行加载:

# 导入 keras 库import keras# 加载数据(train_dataset, train_labels), (test_dataset, test_labels) = keras.datasets.mnist.load_data()train_labels = np.array(train_labels, dtype=np.int32)# 打印数据集形状print(train_dataset.shape, test_dataset.shape)# 图像预览for i in range(40):    plt.subplot(4, 10, i+1)    plt.imshow(train_dataset[i], cmap='gray')    plt.title(train_labels[i], fontsize=10)    plt.axis('off')plt.show()

Python-OpenCV中如何利用 KNN 算法识别手写数字

基准模型——利用 KNN 算法识别手写数字

加载数据集后,我们尝试使用 KNN 分类器识别数字,在原始方法中,我们首先使用原始像素值作为特征,因此图像描述符的大小为 28 × 28 = 784。

首先利用 keras 加载所有数字图像,为了了解数据训练的全部流程,我们将加载的训练数据集划分为 训练数据集 + 测试数据集,每部分占比 50%:

# 加载数据集(train_dataset, train_labels), (test_dataset, test_labels) = keras.datasets.mnist.load_data()train_labels = np.array(train_labels, dtype=np.int32)# 将原始图像作为描述符def raw_pixels(img):    return img.flatten()# 数据打散shuffle = np.random.permutation(len(train_dataset))train_dataset, train_labels = train_dataset[shuffle], train_labels[shuffle]# 计算每个图像的描述符,这里特征描述符是原始像素raw_descriptors = []for img in train_dataset:    raw_descriptors.append(np.float32(raw_pixels(img)))raw_descriptors = np.squeeze(raw_descriptors)# 将数据拆分为训练和测试数据(各占 50%)# 因此,使用 30000 个数字来训练分类器,30000 位数字来测试训练后的分类器partition = int(0.5 * len(raw_descriptors))raw_descriptors_train, raw_descriptors_test = np.split(raw_descriptors, [partition])labels_train, labels_test = np.split(train_labels, [partition])

现在,我们就可以使用 knn.train() 方法训练 KNN 模型并使用 get_accuracy() 函数对其进行测试:

# 训练 KNN 模型knn = cv2.ml.KNearest_create()knn.train(raw_descriptors_train, cv2.ml.ROW_SAMPLE, labels_train)# 测试 kNN 模型k = 5ret, result, neighbours, dist = knn.findNearest(raw_descriptors_test, k)# 根据真实值和预测值计算准确率def get_accuracy(predictions, labels):    acc = (np.squeeze(predictions) == labels).mean()    return acc * 100acc = get_accuracy(result, labels_test)print("Accuracy: {}".fORMat(acc))

我们可以看到当 K = 5 时,KNN 模型可以获得 96.48% 的准确率,但我们仍然可以对其进行改进,以获取更高性能。

改进模型1——参数 K 对识别手写数字精确度的影响

我们已经知道在 KNN 算法中,一个影响算法性能的重要参数就是 K,因此,我们可以首先尝试使用不同的 K 值,查看其对识别手写数字精确度的影响。

为了比较不同 K 值时模型的准确率,我们首先需要创建一个字典来存储测试不同 K 值时的准确率:

from collections import defaultdictresults = defaultdict(list)

接下来,计算 knn.findNearest() 方法,改变 K 参数,并将结果存储在字典中:

# K 取值范围为 (1, 9)for k in range(1, 10):    ret, result, neighbours, dist = knn.findNearest(raw_descriptors_test, k)    acc = get_accuracy(result, labels_test)    print(" {}".format("%.2f" % acc))    results['50'].append(acc)

最后,绘制结果:

ax = plt.subplot(1, 1, 1)ax.set_xlim(0, 10)dim = np.arange(1, 10)for key in results:    ax.plot(dim, results[key], linestyle='--', marker='o', label="50%")    plt.legend(loc='upper left', title="% training")plt.title('Accuracy of the K-NN model varying k')plt.xlabel("number of k")plt.ylabel("accuracy")plt.show()

程序运行结果如下图所示:

Python-OpenCV中如何利用 KNN 算法识别手写数字

如上图所示,改变 K 参数获得的准确率也是不同的,因此,在应用程序用可以通过调整 K 参数来获取最佳性能。

改进模型2——训练数据量对识别手写数字精确度的影响

在机器学习中,使用更多的数据训练分类器通常会提高模型的性能,这是由于分类器可以更好地学习特征的结构。在 KNN 分类器中,增加训练数也会增加在特征空间中找到测试数据正确匹配的概率。

接下来,我们就修改=用于训练和测试模型的图像百分比,来观察训练数据量对识别手写数字精确度的影响:

# 划分训练数据集和测试数据集split_values = np.arange(0.1, 1, 0.1)# 存储结果准确率results = defaultdict(list)# 创建模型knn = cv2.ml.KNearest_create()# 不同训练数据量对识别手写数字精确度的影响for split_value in split_values:    # 将数据集划分为训练和测试数据集    partition = int(split_value * len(raw_descriptors))    raw_descriptors_train, raw_descriptors_test = np.split(raw_descriptors, [partition])    labels_train, labels_test = np.split(train_labels, [partition])    # 训练 KNN 模型    print('Training KNN model - raw pixels as features')    knn.train(raw_descriptors_train, cv2.ml.ROW_SAMPLE, labels_train)    # 同时对于每种划分测试不同 K 值影响    for k in range(1, 10):        ret, result, neighbours, dist = knn.findNearest(raw_descriptors_test, k)        acc = get_accuracy(result, labels_test)        print("{}".format("%.2f" % acc))        results[int(split_value * 100)].append(acc)

训练算法的数字图像的百分比为10%、20%、…、90%,测试算法的数字百分比为90%、80%、…、10%,最后,绘制结果:

ax = plt.subplot(1, 1, 1)ax.set_xlim(0, 10)dim = np.arange(1, 10)for key in results:    ax.plot(dim, results[key], linestyle='--', marker='o', label=str(key) + "%")plt.legend(loc='upper left', title="% training")plt.title('Accuracy of the KNN model varying both k and the percentage of images to train/test')plt.xlabel("number of k")plt.ylabel("accuracy")plt.show()

Python-OpenCV中如何利用 KNN 算法识别手写数字

从上图可以看出,随着训练图像数量的增加,准确率也会增加。因此当条件允许的情况下,可以通过增加训练数据量来提高模型性能。

虽然可以看到准确率虽然已经可以到达97%以上,但是我们不能就此止步。

改进模型3——预处理对识别手写数字精确度的影响

在以上示例中,我们均使用原始像素值作为特征来训练分类器。在机器学习中,训练分类器之前的一个通常可以对输入数据进行某种预处理,用以提高分类器训练性能,因此,接下来我们应用预处理以查看其对识别手写数字精确度的影响。

预处理函数 desew() 如下:

def deskew(img):    m = cv2.moments(img)    if abs(m['mu02']) < 1e-2:        return img.copy()    skew = m['mu11'] / m['mu02']    M = np.float32([[1, skew, -0.5 * SIZE_IMAGE * skew], [0, 1, 0]])    img = cv2.warpAffine(img, M, (SIZE_IMAGE, SIZE_IMAGE), flags=cv2.WARP_INVERSE_MAP | cv2.INTER_LINEAR)    return img

desew() 函数通过使用其二阶矩对数字进行去歪斜。更具体地说,可以通过两个中心矩的比值 (mu11/mu02) 计算偏斜的度量。计算出的偏斜用于计算仿射变换,从而消除数字的偏斜。接下来对比预处理的前后图片效果:

for i in range(10):    plt.subplot(2, 10, i+1)    plt.imshow(train_dataset[i], cmap='gray')    plt.title(train_labels[i], fontsize=10)    plt.axis('off')    plt.subplot(2, 10, i+11)    plt.imshow(deskew(train_dataset[i]), cmap='gray')    plt.axis('off')plt.show()

在下图的第一行显示了原始数字图像,第二行显示了预处理后的数字图像:

Python-OpenCV中如何利用 KNN 算法识别手写数字

通过应用此预处理,识别的准确率得到提高,准确率曲线如下图所示:

Python-OpenCV中如何利用 KNN 算法识别手写数字

可以看到经过预处理的分类器准确率甚至可以接近98%,考虑到我们仅仅是使用了简单的 KNN 模型,效果已经很不错了,但是我们还可以进一步提高模型性能。

改进模型4——使用高级描述符作为图像特征提高 KNN 算法准确率

在以上示例中,我们一直使用原始像素值作为特征描述符。在机器学习中,一种常见的方法是使用更高级的描述符,接下来将使用定向梯度直方图 (Histogram of Oriented Gradients, HOG) 作为图像特征用以提高 KNN 算法准确率。

特征描述符是图像的一种表示,它通过提取描述基本特征(例如形状、颜色或纹理等)的有用信息来简化图像。通常,特征描述符将图像转换为长度为 n 的特征向量,HOG 是一种用于计算机视觉的流行特征描述符。

接下来定义 get_hog() 函数获取 HOG 描述符:

(train_dataset, train_labels), (test_dataset, test_labels) = keras.datasets.mnist.load_data()SIZE_IMAGE = train_dataset.shape[1]train_labels = np.array(train_labels, dtype=np.int32)def get_hog():    hog = cv2.HOGDescriptor((SIZE_IMAGE, SIZE_IMAGE), (8, 8), (4, 4), (8, 8), 9, 1, -1, 0, 0.2, 1, 64, True)    print("hog descriptor size: {}".format(hog.getDescriptorSize()))    return hog

然后使用 HOG 特征训练 KNN 模型

hog = get_hog()hog_descriptors = []for img in train_dataset:    hog_descriptors.append(hog.compute(deskew(img)))hog_descriptors = np.squeeze(hog_descriptors)

训练完成的模型的准确率,如下图所示:

Python-OpenCV中如何利用 KNN 算法识别手写数字

通过上述改进过程,可以看到编写机器学习模型时的一个好方法是从解决问题的基本基线模型开始,然后通过添加更好的预处理、更高级的特征描述符或其他机器学习技术来迭代改进模型。最后,如果条件允许,可以收集更多数据用于训练和测试模型。

完整代码

最终完整代码如下所示,改进过程中的其他代码可以根据上述讲解对以下代码进行简单修改获得:

import cv2import numpy as npimport matplotlib.pyplot as pltfrom collections import defaultdictimport keras(train_dataset, train_labels), (test_dataset, test_labels) = keras.datasets.mnist.load_data()SIZE_IMAGE = train_dataset.shape[1]train_labels = np.array(train_labels, dtype=np.int32)def get_accuracy(predictions, labels):    acc = (np.squeeze(predictions) == labels).mean()    return acc * 100    def raw_pixels(img):    return img.flatten()def deskew(img):    m = cv2.moments(img)    if abs(m['mu02']) < 1e-2:        return img.copy()    skew = m['mu11'] / m['mu02']    M = np.float32([[1, skew, -0.5 * SIZE_IMAGE * skew], [0, 1, 0]])    img = cv2.warpAffine(img, M, (SIZE_IMAGE, SIZE_IMAGE), flags=cv2.WARP_INVERSE_MAP | cv2.INTER_LINEAR)    return imgdef get_hog():    hog = cv2.HOGDescriptor((SIZE_IMAGE, SIZE_IMAGE), (8, 8), (4, 4), (8, 8), 9, 1, -1, 0, 0.2, 1, 64, True)    print("hog descriptor size: {}".format(hog.getDescriptorSize()))    return hogshuffle = np.random.permutation(len(train_dataset))train_dataset, train_labels = train_dataset[shuffle], train_labels[shuffle]# 高级图像描述符hog = get_hog()hog_descriptors = []for img in train_dataset:    hog_descriptors.append(hog.compute(deskew(img)))hog_descriptors = np.squeeze(hog_descriptors)# 数据划分split_values = np.arange(0.1, 1, 0.1)# 创建字典用于存储准确率results = defaultdict(list)# 创建 KNN 模型knn = cv2.ml.KNearest_create()for split_value in split_values:    partition = int(split_value * len(hog_descriptors))    hog_descriptors_train, hog_descriptors_test = np.split(hog_descriptors, [partition])    labels_train, labels_test = np.split(train_labels, [partition])    print('Training KNN model - HOG features')    knn.train(hog_descriptors_train, cv2.ml.ROW_SAMPLE, labels_train)    # 存储准确率    for k in np.arange(1, 10):        ret, result, neighbours, dist = knn.findNearest(hog_descriptors_test, k)        acc = get_accuracy(result, labels_test)        print(" {}".format("%.2f" % acc))        results[int(split_value * 100)].append(acc)fig = plt.figure(figsize=(12, 5))plt.suptitle("k-NN handwritten digits recognition", fontsize=14, fontweight='bold')ax = plt.subplot(1, 1, 1)ax.set_xlim(0, 10)dim = np.arange(1, 10)for key in results:    ax.plot(dim, results[key], linestyle='--', marker='o', label=str(key) + "%")plt.legend(loc='upper left', title="% training")plt.title('Accuracy of the k-NN model varying both k and the percentage of images to train/test with pre-processing '          'and HoG features')plt.xlabel("number of k")plt.ylabel("accuracy")plt.show()


--结束END--

本文标题: Python-OpenCV中如何利用 KNN 算法识别手写数字

本文链接: https://www.lsjlt.com/news/302010.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • Python-OpenCV中如何利用 KNN 算法识别手写数字
    手写数字数据集 MNIST 介绍为了保证完整性,从算法所用的训练数据讲起,训练数据是由 MNIST 手写数字组成的,MNIST 数据集来自美国国家标准与技术研究所,由来自 250 个不同人手写的数字构成,其中训练集包含 60000 张图片,...
    99+
    2023-06-22
  • Python-OpenCV实战:利用KNN算法识别手写数字
    目录前言手写数字数据集 MNIST 介绍基准模型——利用 KNN 算法识别手写数字改进模型1——参数 K 对识别手写数字精确度的影响改进模型2——训练数据量对识别手写数字精确度的影响...
    99+
    2024-04-02
  • Python利用SVM算法实现识别手写数字
    目录前言使用 SVM 进行手写数字识别参数 C 和 γ 对识别手写数字精确度的影响完整代码前言 支持向量机 (Support Vector Machine, SVM) 是一种监督学习...
    99+
    2024-04-02
  • Python如何利用opencv实现手势识别
    目录获取视频(摄像头)肤色检测轮廓处理前言: 网上搜到了一些关于手势处理的实验,我在这儿简单的实现一下,主要运用的知识就是opencv,python基本语法,图像处理基础知识。 获取...
    99+
    2024-04-02
  • pytorch如何利用ResNet18进行手写数字识别
    目录利用ResNet18进行手写数字识别先写resnet18.py再写绘图utils.py最后是主函数mnist_train.py总结利用ResNet18进行手写数字识别 先写res...
    99+
    2023-02-02
    pytorch ResNet18 ResNet18手写数字识别 pytorch手写数字识别
  • Python中如何实现MNIST手写数字识别功能
    这篇文章主要为大家展示了“Python中如何实现MNIST手写数字识别功能”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“Python中如何实现MNIST手写数字识别功能”这篇文章吧。数据集介绍M...
    99+
    2023-06-22
  • Python如何手写KNN算法预测城市空气质量
    本篇内容介绍了“Python如何手写KNN算法预测城市空气质量”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!一、KNN算法简介KNN(K-N...
    99+
    2023-06-25
  • 如何使用Python识别手势数字
    这篇文章主要介绍如何使用Python识别手势数字,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!前言谷歌出了一个开源的、跨平台的、可定制化的机器学习解决方案工具包,给在线流媒体(当然也可以用于普通的视频、图像等)提供了...
    99+
    2023-06-15
  • Python中怎么利用KNN算法处理缺失数据
    这篇文章将为大家详细讲解有关Python中怎么利用KNN算法处理缺失数据,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。KNN代表" K最近邻居",这是一种简单算法,可根据...
    99+
    2023-06-16
  • Python如何实现带GUI界面的手写数字识别
    这篇文章给大家分享的是有关Python如何实现带GUI界面的手写数字识别的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。1.效果图有点low,轻喷点击选择图片会优先从当前目录查找2.数据集这部分我是对MNIST数据...
    99+
    2023-06-22
  • pytorch如何实现手写数字图片识别
    这篇文章给大家分享的是有关pytorch如何实现手写数字图片识别的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。具体内容如下数据集:MNIST数据集,代码中会自动下载,不用自己手动下载。数据集很小,不需要GPU设备...
    99+
    2023-06-15
  • 如何动手做一个识别手写数字的web应用
    如何动手做一个识别手写数字的web应用,相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。 01 进入docker容器我们使用docker容器,可以终端输入 :d...
    99+
    2023-06-19
  • 如何利用Python识别图片中的文字
    这篇文章将为大家详细讲解有关如何利用Python识别图片中的文字,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。一、Tesseract文字识别是ORC的一部分内容,ORC的意思是光学字符识别,通俗讲就是文字...
    99+
    2023-06-15
  • Python如何使用opencv进行手势识别详解
    目录前言原理程序部分附另一个手势识别实例总结前言 本项目是使用了谷歌开源的框架mediapipe,里面有非常多的模型提供给我们使用,例如面部检测,身体检测,手部检测等。 原理 首先...
    99+
    2024-04-02
  • Python中如何实现MNIST手写体识别
    这篇文章主要介绍Python中如何实现MNIST手写体识别,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!1.实验内容简述1.1 实验环境本实验采用的软硬件实验环境如表所示:在Windows操作系统下,采用基于Tens...
    99+
    2023-06-25
  • OpenCV如何利用手势识别实现虚拟拖放效果
    这篇文章主要介绍OpenCV如何利用手势识别实现虚拟拖放效果,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!第一步通过opencv设置显示框和调用摄像头显示当前画面import cv2cap =&n...
    99+
    2023-06-26
  • Python+OpenCV实现信用卡数字识别的方法详解
    目录一、模板图像处理 二、信用卡图片预处理一、模板图像处理 (1)灰度图、二值图转化 template = cv2.imread('C:/Users/bwy/Desktop...
    99+
    2024-04-02
  • python如何基于OpenCV模板匹配识别图片中的数字
    小编给大家分享一下python如何基于OpenCV模板匹配识别图片中的数字,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!程序目标单个数字模板:(这些单个模板是我自...
    99+
    2023-06-14
  • 如何利用Python识别图片中的文字详解
    一、Tesseract 文字识别是ORC的一部分内容,ORC的意思是光学字符识别,通俗讲就是文字识别。Tesseract是一个用于文字识别的工具,我们结合Python使用可以很快的实...
    99+
    2024-04-02
  • TensorFlow中Softmax逻辑回归如何识别手写数字MNIST数据集
    今天就跟大家聊聊有关TensorFlow中Softmax逻辑回归如何识别手写数字MNIST数据集,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。基于MNIST数据集的逻辑回归模型做十分...
    99+
    2023-06-25
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作