win10+Python3.7.3+OpenCV3.4.1入门学习(二十章 K近邻算法)————20.2 K近邻算法计算

Python版本是Python3.7.3,OpenCV版本OpenCV3.4.1,开发环境为PyCharm

文章目录

    • 20.2 计算
        • 20.2.1 归一化
        • 20.2.2 距离计算

20.2 计算

计算机的“感觉”是通过逻辑计算和数值计算来实现的。所以,在大多数的情况下,我们要对计算机要处理的对象进行数值化处理,将其量化为具体的值,以便后续处理。比较典型的方法是取某几个固定的特征,然后将这些特征量化。例如,在人脸识别的过程中,可以根据人脸部器官的形状描述以及它们之间的距离特性来获取有助于分类的特征数据。这些特征数据可能包括特征点间的距离、曲率和角度等。这样,人脸图像就可以表示为类似于[156, 34, 890, 457]的数据形式了。
K近邻算法在获取各个样本的特征值之后,计算待识别样本的特征值与各个已知分类的样本特征值之间的距离,然后找出k个最邻近的样本,根据k个最邻近样本中占比最高的样本所属的分类,来确定待识别样本的分类。

20.2.1 归一化

对于简单的情况,直接计算与特征值的距离(差距)即可。例如,在某影视剧中,已经通过技术手段获知犯罪嫌疑人的身高为186 cm,受害人身高为172 cm。而面对警察,甲、乙二人都宣称自己是受害人。此时,我们可以通过测量二人身高判定谁是真正的受害人:
● 甲身高为185 cm,与嫌疑人身高的距离=186-185=1cm,与受害人身高的距离=185-172=7cm。甲的身高与嫌疑人更接近,因此确认甲为嫌疑人。
● 乙身高为173 cm,与嫌疑人身高的距离=186-173=13cm,与受害人身高的距离=173-172=1cm。乙的身高与受害人更接近,因此确认乙为受害人。
上面的例子是非常简单的特例。而在实际场景中,可能需要通过更多参数进行判断。例如,在一部国外影视剧中,警察通过技术手段获知嫌疑人的身高为180 cm,缺一根手指;受害人身高为173cm,十指健全。此时,前来投案的甲、乙二人都宣称自己是受害人。
当有多个参数时,一般将这些参数构成列表(数组)进行综合判断。本例以(身高,手指数量)作为特征。因此,嫌疑人的特征值为(180, 9),受害人的特征值为(173, 10)。
此时,可以对二人进行以下判断:
● 甲身高为175 cm,缺一根手指,甲的特征值为(175, 9)。
● 甲与嫌疑人特征值的距离= (180-175) + (9-9) = 5
● 甲与受害人特征值的距离= (175-173) + (10-9) = 3
此时,甲的特征值与受害人更接近,断定甲为受害人。
● 乙身高为178 cm,十指健全,乙的特征值为(178, 10)。
● 乙与嫌疑人特征值的距离= (180-178) + (10-9) = 3
● 乙与受害人特征值的距离= (178-173) + (10-10) = 5
此时,乙与嫌疑人的特征值更接近,断定乙为嫌疑人。
当然,我们知道上述结果是错误的。因为身高、手指数量有着不同的量纲(权值),所以在计算与特征值的距离时要充分考虑不同参数之间的权值。通常情况下,由于各个参数的量纲不一致等原因,需要对参数进行处理,让所有参数具有相等的权值。
一般情况下,对参数进行归一化处理即可。做归一化时,通常使用特征值除以所有特征值中的最大值(或者最大值与最小值的差)。例如,上例中用身高除以最高身高180(cm),手指数量除以10(10根手指),得到新的特征值,计算方式为:
== 归一化特征=(身高/最高身高180,手指数量/10)==
因此,经过归一化以后:
● 嫌疑人的特征值为(180/180, 9/10) = (1, 0.9)
● 受害人的特征值为(173/180, 10/10) = (0.96, 1)
此时,可以根据归一化以后的特征值,对二人进行判断:
● 甲的特征值为(175/180, 9/10)=(0.97, 0.9)
● 甲与嫌疑人特征值的距离= (1-0.97) + (0.9-0.9) = 0.03
● 甲与受害人特征值的距离= (0.97-0.96) + (1-0.9) = 0.11
此时,甲与犯罪嫌疑人的特征值更接近,断定甲为犯罪嫌疑人。
● 乙的特征值为(178/180, 10/10)=(0.99, 1)
● 乙与嫌疑人的特征值距离= (1-0.99) + (1-0.9) = 0.11
● 乙与受害人的特征值距离= (0.99-0.96) + (1-1) = 0.03
此时,乙与受害人的特征值更接近,断定乙为受害人。

20.2.2 距离计算

在前面的讨论中,我们多次计算了距离。使用的方式是先将特征值中对应的元素相减,然后再求和。例如,有(身高,体重)形式的特征值A(185, 75)和B(175, 86),下面判断C(170, 80)与特征值A和特征值B的距离:
● C与A的距离= (185-170) + (75-80) = 15+(-5) =10
● C与B的距离= (175-170) + (86-80) = 5+6 = 11
通过计算,C与A的距离更近,所以将C划归为A所属的分类。
当然,我们知道上述判断是错误的,因为在计算C与A的距离时存在负数,它抵消了一部分正数。所以,为了避免这种正负相抵的情况,我们通常会计算绝对值的和:
● C与A的距离= |185-170|+|75-80| = 15+5 = 20
● C与B的距离= |175-170|+|86-80| = 5+6 = 11
取绝对值后再求和,计算出C与B的距离更近,将C归为B所属的分类。这种用绝对值之和表示的距离,称为曼哈顿距离。
像这样计算距离已经基本满足要求了,但是还有更好的方法。例如,可以引入计算平方和的方式。此时的计算方法是:
● C与A的距离=(185-1702+(75-802
● C与B的距离=(175-1702+(86-80)2
更普遍的形式是计算平方和的平方根,这种距离就是被广泛使用的欧氏距离,它的计算方法是:
● C与A的距离= sqrt((185-1702+(75-80 2 )
● C与B的距离= sqrt((175-1702+(86-80)2 )

20.3 手写数字识别的原理
20.1节我们仅仅取了两个特征维度进行说明。在实际应用中,可能存在着更多特征维度需要计算。下面以手写数字识别为例进行简单的介绍。
假设我们要让程序识别图20-2中上方的数字(当然,你一眼就知道是“8”,但是现在要让计算机识别出来)。识别的方式是,依次计算该数字图像(即写有数字的图像)与下方数字图像的距离,与哪个数字图像的距离最近(此时k=1),就认为它与哪幅图像最像,从而确定这幅图像中的数字是多少。
[插图]
图20-2 手写数字识别示例

陌上花开 21:22:51
下面分别从特征值提取和数字识别两方面展开介绍。
1.特征值提取
步骤1:我们把数字图像划分成很多小块,如图20-3所示。该图中每个数字被分成5行4列,共计5×4=20个小块。此时,每个小块是由很多个像素点构成的。当然,也可以将每一个像素点理解为一个更小的子块。
[插图]
图20-3 划分子块
为了叙述上的方便,将这些小块表示为B(Bigger),将B内的像素点,记为S(Smaller)。因此,待识别的数字“8”

陌上花开 21:23:01
的图像可以理解为:
● 由5行4列,共计5×4=20个小块B构成。
● 每个小块B内其实是由M×N个像素(更小块S)构成的。为了描述上的方便,假设每个小块大小为10×10=100个像素。
步骤2:计算每个小块B内,有多少个黑色的像素点。或者这样说,计算每个小块B内有多少个更小块S是黑色的。
仍以数字“8”的图像为例,其第1行中:
● 第1个小块B共有0个像素点(更小块S)是黑色的,记为0。
● 第2个小块B共有28个像素点(更小块S)是黑色的,记为28。
● 第3个小块B共有10个像素点(更小块S)是黑色的,记为10。
● 第4个小块B共有0个像素点(更小

陌上花开 21:23:09
块S)是黑色的,记为0。
以此类推,计算出数字“8”的图像中每一个小块B中有多少个像素点是黑色的,如图20-4所示。我们观察后会发现,不同的数字图像中每个小块B内黑色像素点的数量是不一样的。正是这种不同,使我们能用该数量(每个小块B内黑色像素点的个数)作为特征来表示每一个数字。
[插图]
图20-4 每个小块B内黑色像素点的个数
步骤3:有时,为了处理上的方便,我们会把得到的特征值排成一行(写为数组形式),如图20-5所示。

陌上花开 21:23:46
步骤4:与数字“8”的图像类似,每个数字图像的特征值都可以用一行数字来表示。从某种意义上来说,这一行数字类似于我们的身份证号码,一般来说,具有唯一性。
按照同样的方式,获取每个数字图像的特征值,如图20-7所示。
[插图]
图20-7 每个数字图像的特征值
2.数字识别
数字识别要做的就是比较待识别图像与图像集中的哪个图像最近。这里,最近指的是二者之间的欧氏距离最短。

陌上花开 21:24:04
本例中为了便于说明和理解进行了简化,将原来下方的10个数字减少为2个(也即将分类从10个减少为2个)。假设要识别的图像为图20-8中上方的数字“8”图像,需要判断该图像到底属于图20-8中下方的数字“8”图像的分类还是数字“7”图像的分类。
[插图]
图20-8 待识别图像与特征图像
步骤1:提取特征值,分别提取待识别图像的特征值和特征图像的特征值。
为了说明和理解上的方便,将特征进行简化,每个数字图像只提取4个特征值(划分为2× 2=4个子块B),如图20-9所示。此时,提取到的特征值分别为:

陌上花开 21:24:22
● 待识别的数字“8”图像:[3, 7, 8, 13]
● 数字“8”特征图像:[3, 6, 9, 12]
● 数字“7”特征图像:[8, 1, 2, 98]
步骤2:计算距离。按照20.1节介绍的欧氏距离计算方法,计算待识别图像与特征图像之间的距离。
首先,计算待识别的数字“8”图像与下方的数字“8”特征图像之间的距离,如图20-10所示。计算二者之间的距离:

陌上花开 21:24:48
接下来,计算待识别的数字“8”图像与数字“7”特征图像之间的距离,如图20-11所示。二者之间的距离为:
[插图]
图20-11 计算距离2
[插图]
通过计算可知,待识别的数字“8”图

陌上花开 21:25:04
像:
● 与数字“8”特征图像的距离为[插图]。
● 与数字“7”特征图像的距离为[插图]。
步骤3:识别。
根据计算的距离,待识别的数字“8”图像与数字“8”特征图像的距离更近。所以,将待识别的数字“8”图像识别为数字“8”特征图像所代表的数字“8”。
上面介绍的是K近邻算法只考虑最近的一个邻居的情况,相当于K近邻中k=1的情况。在实际操作中,为了提高可靠性,需要选用大量的特征值。例如,每个数字都选用不同的形态的手写体100个,对于0~9这10个数字,共需要100×10=1000幅特征图像。在识别数字时,分别计算待识别的数字图像与这些特征图像之间的距离。这时,可以将k调整为稍大的值,例如

陌上花开 21:25:12
k=11,然后看看其最近的11个邻居分属于哪些特征图像。例如,其中:
● 有8个属于数字“6”特征图像。
● 有2个属于数字“8”特征图像。
● 有1个属于数字“9”特征图像。
通过判断,当前待识别的数字为数字“6”特征图像所代表的数字“6”。

你可能感兴趣的:(Python-OpenCV)