0
点赞
收藏
分享

微信扫一扫

图像基础23 KNN 算法实现形状检测

另两篇关联文章:
机器学习笔记十一 k-近邻算法

机器学习笔记十二 k-近邻算法实现手写识别系统

KNN算法介绍

邻近算法,或者说K最近邻(kNN,k-NearestNeighbor)分类算法是数据挖掘分类技术中最简单的方法之一。所谓K最近邻,就是k个最近的邻居的意思,说的是每个样本都可以用它最接近的k个邻居来代表。
kNN算法的核心思想是如果一个样本在特征空间中的k个最相邻的样本中的大多数属于某一个类别,则该样本也属于这个类别,并具有这个类别上样本的特性。该方法在确定分类决策上只依据最邻近的一个或者几个样本的类别来决定待分样本所属的类别。 kNN方法在类别决策时,只与极少量的相邻样本有关。由于kNN方法主要靠周围有限的邻近的样本,而不是靠判别类域的方法来确定所属类别的,因此对于类域的交叉或重叠较多的待分样本集来说,kNN方法较其他方法更为适合。

通俗的解释 : 计算一个点A与其他所有点之间的距离,取出与该点最近的k个点,然后统计这k个点里面所属分类比例最大的,则点A属于该分类。

这里的距离,一般用的是欧氏距离。

示意

图像基础23 KNN 算法实现形状检测_算法

如果要判断样本的绿色是蓝色还是红色
当k=3时,红色:蓝色=2:1,为红色
当k=5时,红色:蓝色=2:3,为蓝色
KNN算法简单有效,但没有优化的暴力法效率容易达到瓶颈。如样本个数为N,特征维度为D的时候,该算法时间复杂度呈图像基础23 KNN 算法实现形状检测_数据挖掘_02增长。

所以通常KNN的实现会把训练数据构建成K-D Tree(K-dimensional tree),构建过程很快,甚至不用计算D维欧氏距离,而搜索速度高达 图像基础23 KNN 算法实现形状检测_算法_03
不过当D维度过高,会产生所谓的”维度灾难“,最终效率会降低到与暴力法一样。
因此通常D>20以后,最好使用更高效率的Ball-Tree,其时间复杂度为O(D*log(N))。
人们经过长期的实践发现KNN算法虽然简单,但能处理大规模的数据分类,尤其适用于样本分类边界不规则的情况。最重要的是该算法是很多高级机器学习算法的基础。

形状特征提取

图像基础23 KNN 算法实现形状检测_数据_04

上图三个典型的形状,如何提取特征呢?可使用距中心距离法:

  1. 确定图像的中心点,通常是图片的中心位置
  2. 计算图像线条上的每个点x与中心点的距离,形成距离向量d
  3. 计算距离向量d的标准差,以标准差为最终特征值

形状分类

算法实现中只为每个形状准备了一个样本,所以将k取值为1.

  1. 首先采集样本图像的特征值,
  2. 然后以未知形状图像的特征值为分类数据,进行kNN分类,
  3. 最后将未知图像归为上图所示3类中。方形:0 圆形:1 三角形:2
# -*- coding: utf-8 -*-
# 开状检测

import cv2
import numpy as np

def mydist(point1,point2):
return np.sqrt(np.power((point1[0]-point2[0]),2)+np.power((point1[1]-point2[1]),2))

# 离中心点距离的标准差
def getstd(tmpimg,centerpoint):
w=tmpimg.shape[1]
h=tmpimg.shape[0]
dst = []
print (tmpimg)
for i in range(h):
for j in range(w):

if tmpimg[i,j]<255:
print('YES')
# 该像素不是空白,是线条中的点
dst.append(mydist((i,j),centerpoint))

mysd = np.std(dst)
return mysd

# 读取样本形状图像,计算标准差
imgsd = []
testimgsd = []
mysdratio = []
centerpoint=(26,26)
for i in range(3):
tmpimg = (cv2.imread("shape"+str(i)+".png"))
myimg = cv2.cvtColor(tmpimg,cv2.COLOR_BGR2GRAY)
retval , newimg = cv2.threshold(myimg,40,255,cv2.THRESH_BINARY)
myimg = cv2.resize(newimg,(51,51))
imgsd.append(getstd(myimg,centerpoint))

print("---------")

for i in range(4):
#测试样本
fn = "shapetest_"+str(i)+".png"
tmpimg = cv2.imread(fn)
myimg = cv2.cvtColor(tmpimg,cv2.COLOR_BGR2GRAY)
retval,newimg = cv2.threshold(myimg,40,255,cv2.THRESH_BINARY)
myimg = cv2.resize(newimg,(51,51))
# 得到距离标准差
testimgsd.append(getstd(myimg,centerpoint))
mysdratio.append([])
for ii in range(3):
# 与样本进行比较
mysdratio[i].append(abs(testimgsd[i]-imgsd[ii]))
print(u"KNN距离矩阵如下")
print(mysdratio)
print("-------------")

#KNN算法 找到最近邻
for i in range(4):
fn = "shapetest_"+str(i)+".png"
myindex = 0
mymin = np.min(mysdratio[i])
for ii in range(3):
#测试样本最终分类
if (mysdratio[i][ii])==mymin:
myindex=ii
break
print (fn+u"分类为:"+str(myindex))

代码测试未通过。


举报

相关推荐

0 条评论