OpenCV面向Python学习②KNN算法(手写数字识别)

一:KNN算法理论基础

1) K近邻法(k-nearest neighbor, kNN)的本质是将指定对象根据已知特征值分类。
2) K近邻法是一种基本分类与回归方法,其基本做法是:给定测试实例,基于某种距离度量找出训练集中与其最靠近的k个实例点,然后基于这k个最近邻的信息来进行预测。
3) K近邻法不具有显式的学习过程,事实上,它是懒惰学习(lazy learning)的著名代表,此类学习技术在训练阶段仅仅是把样本保存起来,训练时间开销为零,待收到测试样本后再进行处理。

二:手写数字识别的原理

在这里插入图片描述
1)特征值提取
步骤1:我们把数字图像划分成很多小块。
步骤2:计算每个小块内,有多少个黑色的像素点。
步骤3:为了处理上的方便,我们会把得到的特征值排成一行。
步骤4:每个数字图像的特征值都可以用一行数字来表示。
2)数字识别
步骤1:提取特征值,分别提取待识别图像的特征值和特征图像的特征值。
步骤2:计算距离,计算待识别图像与特征图像之间的距离。
步骤3:识别,距离越近越相似。

三:自定义函数手写数字识别

1)数据初始化
2)读取特征图像
3)提取特征图像的特征值
4)计算待识别图像的特征值
5)计算待识别图像与特征图像之间的距离
6)获取k个最短距离及其索引
7)识别
程序如下

import cv2
import numpy as np
import matplotlib.pyplot as plt
import time
#计算运行时间
begin_time = time.time()
#数据初始化
s = 'C:\\Users\\Administrator\\Desktop\\Python\\number_image'  #特征图像所在位置
num = 30   #样本总数  0-9各3个
row = 240  #特征图像的行数
col = 240  #特征图像的列数
a = np.zeros((num,row,col))  #存储所有样本的数值
#存储图像
n = 0
for i in range(0,10):
    for j in range(1,4):
        a[n,:,:] = cv2.imread(s + '\\' + str(i) + '-' + str(j) + '.png',0)
        n = n+1
#提取样本图像特征
feature = np.zeros((num,round(row/5),round(col/5)))  #用来存储所有样本的特征值
for ni in range(0,num):
    for nr in range(0,row):
        for nc in range(0,col):
            if a[ni,nr,nc] == 255:
                feature[ni,int(nr/5),int(nc/5)]+=1
f = feature   #简化变量名称
#计算待识别图像的特征值
o = cv2.imread('C:\\Users\\Administrator\\Desktop\\Python\\number_image\\11.png',0)   #读取待识别图像
of = np.zeros((round(row/5),round(col/5)))  #存储待识别图像特征值
for nr in range(0,row):
    for nc in range(0,col):
        if o[nr,nc] == 255:
            of[int(nr/5),int(nc/5)]+=1
#开始计算,识别数字,计算最邻近的若干个数字是多少,判断结果
d = np.zeros(30)
for i in range(0,30):
    d[i] = np.sum((of-f[i,:,:])*(of-f[i,:,:]))
d = d.tolist()
temp = []
Inf = max(d)
k=3
for i in range(k):
    temp.append(d.index(min(d)))
    d[d.index(min(d))] = Inf
temp = [i/3 for i in temp]
r = np.zeros(10)
for i in temp:
    r[int(i)]+=1
print("当前的数字可能为:"+str(np.argmax(r)))
#计算运行时间
end_time = time.time()
run_time = end_time-begin_time
print("该程序运行时间为:",run_time)

运行结果如下
在这里插入图片描述

四:使用OpenCV自带的KNN模块识别手写数字

程序

import cv2
import numpy as np
import matplotlib.pyplot as plt
import time
#计算运行时间
begin_time = time.time()
#数据初始化
s = 'C:\\Users\\Administrator\\Desktop\\Python\\number_image'  #特征图像所在位置
num = 30   #样本总数  0-9各3个
row = 240  #特征图像的行数
col = 240  #特征图像的列数
a = np.zeros((num,row,col))  #存储所有样本的数值
#存储图像
n = 0
for i in range(0,10):
    for j in range(1,4):
        a[n,:,:] = cv2.imread(s + '\\' + str(i) + '-' + str(j) + '.png',0)
        n = n+1
#提取样本图像特征
feature = np.zeros((num,round(row/5),round(col/5)))  #用来存储所有样本的特征值
for ni in range(0,num):
    for nr in range(0,row):
        for nc in range(0,col):
            if a[ni,nr,nc] == 255:
                feature[ni,int(nr/5),int(nc/5)]+=1
f = feature   #简化变量名称
#将feature处理为单行形式
train = feature[:,:].reshape(-1,round(row/5)*round(col/5)).astype(np.float32)
#贴标签
trainLabels = [int(i/3) for i in range(0,30)]
trainLabels = np.asarray(trainLabels)
#读取待识别特征值
o = cv2.imread('C:\\Users\\Administrator\\Desktop\\Python\\number_image\\11.png',0)
of = np.zeros((round(row/5),round(col/5)))  #存储待识别图像特征值
for nr in range(0,row):
    for nc in range(0,col):
        if o[nr,nc] == 255:
            of[int(nr/5),int(nc/5)]+=1
test = of.reshape(-1,round(row/5)*round(col/5)).astype(np.float32)
#调用函数识别图像
knn = cv2.ml.KNearest_create()
knn.train(train,cv2.ml.ROW_SAMPLE,trainLabels)
ret,result,neighbours,dist = knn.findNearest(test,k=3)
print("当前的数字可能为:",result)
print("距离当前点最近的3个邻居为:",neighbours)
#计算运行时间
end_time = time.time()
run_time = end_time-begin_time
print("该程序运行时间为:",run_time)

运行结果
在这里插入图片描述

五:手写数字图像样例

在这里插入图片描述
如果觉得自己写起来太麻烦可以下载我的。
链接:https://pan.baidu.com/s/10UbY-8LGDO5_F0kpugPYow
提取码:5q9l

  • 5
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Ma lidong

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值