KNN实现人物姿势判断(图像分类)

0. 说明

实现人物的姿势判断(当然是很简单的那种,KNN对于复杂的图像是解决不了的,另外还有经典的手写数字识别,也是简单的图像)

0

在这里插入图片描述

如上图所示,人物姿势有两种,【站】和【蹲】,实际上还有第三种【趴】,对于这种简单的图像,再添加许多种都是一样的。(实际上这就是在pubg游戏上截的图,每类图像不用很多)

直接贴代码

#训练(使用的话要修改根目录)

import cv2
import numpy as np
import os
import matplotlib.pyplot as plt
from sklearn.neighbors import KNeighborsClassifier as KNN
from sklearn.model_selection import cross_val_score

def main():
    # 根目录
    path = r"C:\Users\cun\Desktop\test"

    # 训练目标数组和训练集数组
    train = []
    target = []
    # 用于剔除根目录,子文件夹名称可以作为分类目标
    index = -1
    # 遍历根目录下的文件夹和文件
    for root, dirs, files in os.walk(path):
        # 在路径中筛选出分类目标
        pathArr = root.split('\\')
        type = pathArr[len(pathArr) - 1]  # 当前类别
        # 丢掉根目录
        if index == -1:
            index += 1
            continue

        # 遍历图像文件
        for image in files:
            # 读取图像文件
            digit = cv2.imread(root + "\\" + image)
            # 降维到二维
            twoDimensional = digit[:, :, 0]
            # 获取图像高度和宽度
            height = twoDimensional.shape[0]  # 高度
            weight = twoDimensional.shape[1]  # 宽度
            # 降维到一维
            res = twoDimensional.reshape(height * weight)

            # 手工将人物和背景区分开
            for rn in range(len(res)):
                res[rn] = 0 if res[rn] < 220 else 1
            # 加入训练集
            train.append(res)
            # 分类目标
            target.append(type)
        index += 1

        # 训练
    knn = KNN(n_neighbors=5, weights='distance', p=2, n_jobs=-1)  # p=2 欧式距离;n_jobs=-1 所有线程都工作;
    knn.fit(train, target)  # KNN模型已生成
    
if __name__ == '__main__':
    main()
#测试(使用的话要修改测试目录)

    test, test_target = [], []
    digit = cv2.imread(r"C:\Users\cun\Desktop\test\A\17.png")
    plt.imshow(digit)
    plt.show()
    # 降维到二维
    twoDimensional1 = digit[:, :, 0]
    # 获取图像高度和宽度
    height1 = twoDimensional1.shape[0]  # 高度
    weight1 = twoDimensional1.shape[1]  # 宽度
    # 降维到一维
    res1 = twoDimensional1.reshape(height1 * weight1)
    # 手工将人物和背景区分开
    for rn in range(len(res1)):
        res1[rn] = 0 if res1[rn] < 220 else 255
    test.append(res1)
    pred_res = knn.predict(test)
    print(pred_res)

使用的包如下图所示。

image-20211013232749004

1. 训练

1.1 IO

这里有一个io的操作,使用者不用写很多文件夹,只需要写一个根目录即可,里面放着图像的类别和对应的图像。

image-20211013233018657

程序读到根目录后,获取到目录下的文件夹,并将文件夹的名称作为训练的目标,把文件夹内的图像数据当作训练集。

以test文件夹作为根目录,os.walk()可以找出特定目录下的所有文件夹和文件,

  • root 表示当前正在访问的文件夹路径
  • dirs 表示该文件夹下的子目录名list
  • files 表示该文件夹下的文件list

以输出root为例

for root, dirs, files in os.walk(path):
    print(root)

image-20211013233758895

可以看到输出了根目录,和下属的两个子目录,而跟目录我们是不需要的,这里使用了一个索引直接抛弃了根目录。

接下来根据“\”拆分字符串,留下了需要的文件名作为训练目标。

# 在路径中筛选出分类目标
pathArr = root.split('\\')
type = pathArr[len(pathArr) - 1]  # 当前类别
print(type)

image-20211013234247679

1.2 降维

knn训练使用的是一维数组,所以必须从三维降到一维。

另外,在knn中,怎么让数组代表这种人物姿势呢?因为本示例的图像很简单,这里人工规定将一维数组中所有数值大于或等于220的都变为1,小于220的则变为0

为了便于理解,这里挑选了一张图像

0

将经过转化后并且二维化的数据输出成了txt文件(建议离远一点看下图,近视的童鞋摘掉眼镜看下图会更加直观)

image-20211014001605166

感兴趣的可以试试,程序放到了下面

import cv2
import numpy as np
import os
import matplotlib.pyplot as plt
from sklearn.neighbors import KNeighborsClassifier as KNN
from sklearn.model_selection import cross_val_score

def main():
    # 根目录
    path = r"C:\Users\cun\Desktop\test"

    # 读取图像文件
    digit = cv2.imread(path + "\\A\\0.png")
    plt.imshow(digit)
    plt.show()

    # 降维到二维
    twoDimensional = digit[:, :, 0]
    # 获取图像高度和宽度
    height = twoDimensional.shape[0]  # 高度
    weight = twoDimensional.shape[1]  # 宽度

    # 手工将人物和背景区分开
    for i in range(height):
        for j in range(weight):
            twoDimensional[i][j] = 0 if twoDimensional[i][j] < 220 else 1
    arr = np.array(twoDimensional)
    np.savetxt(r"C:\Users\cun\Desktop\test\aaa.txt", arr, fmt="%d")

if __name__ == '__main__':
    main()
1.3 训练

记得把训练数据和目标数据存储到数组中

这里直接使用sklearn中的knn模型进行训练

# 训练
knn = KNN(n_neighbors=5, weights='distance', p=2, n_jobs=-1)  # p=2 欧式距离;n_jobs=-1 所有线程都工作;
knn.fit(train, target)  # KNN模型已生成

测试和训练使用了同样的程序,这里不再赘述。

  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

纸照片

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

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

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

打赏作者

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

抵扣说明:

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

余额充值