基于openpose的K聚类算法手势识别

【写在前面的话】

记录信息

  • 记录时间:2022.1.10
  • 记录地点:实验室
  • 记录背景:年终总结的时候,想到的有个综合设计的课题没有整理。

说明

当初学校那边考虑到大部分同学在考研没有时间做,所以给的要求比较低,一组六个人实际上就我一个人做。所以我给自己的目标就是找个简单的方法,同时尽量学明白。找了很多教程之后,选择了最简单的算法进行分类。

【正文内容】

1. 数据集采集

基本前提是利用openpose提取特征点,并基于特征点进行识别(区分),所以我是更具自己的目标进行动作设计的。这个目标就是自己所使用的【K聚类分类算法】,因为动作之间的区分明显,算法很好区分。[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jraTK7sO-1641805254276)(C:\Users\LittleDC\Pictures\12_LI (2)].jpg)

2. 数据集预处理

  • 拍摄照片大小统一处理成64*64像素大小进行归一化。
  • 每张图以3个数据作为 邻居样本:分别是左右手腕位置、手腕与肩部距离的左右差值。
  • 计算待分类的图像的这三个数据,与已有10组图像样本的数据进行对比,每组差别最小的获取它的手势标签作为识别结果。
  • 一共得到10组结果,取众数作为识别结果。
  • 说明:(标签定义为:左侧–0,右侧–1,中间–2)

def train_pose(image_path, out_dir, inWidth=368, inHeight=368, threshhold=0.2):

  frame = cv.imread(image_path)

  frame = cv.resize(frame, (480, 480))

  frameWidth = frame.shape[1]

  frameHeight = frame.shape[0]

  net = cv.dnn.readNetFromCaffe(protoFile, weightsFile)

  inp = cv.dnn.blobFromImage(frame, 1.0 / 255, (inWidth, inHeight), (0, 0, 0), swapRB=False, crop=False)

  net.setInput(inp)

  out = net.forward()

  out = out[:, :9, :, :]

3. 基于openpose的身体姿态提取

- 标定需要用到的点:上肢姿态点,左三个右三个。肩膀、手肘、手腕


BODY_PARTS = {"Nose": 0, "Neck": 1, "RShoulder": 2, "RElbow": 3, "RWrist": 4,
              "LShoulder": 5, "LElbow": 6, "LWrist": 7, "RHip": 8, "RKnee": 9,
              "RAnkle": 10, "LHip": 11, "LKnee": 12, "LAnkle": 13, "REye": 14,
              "LEye": 15, "REar": 16, "LEar": 17, "Background": 18}

POSE_PAIRS = [["Neck", "RShoulder"], ["Neck", "LShoulder"], ["RShoulder", "RElbow"],
              ["RElbow", "RWrist"], ["LShoulder", "LElbow"], ["LElbow", "LWrist"],
              ["Neck", "RHip"], ["RHip", "RKnee"], ["RKnee", "RAnkle"], ["Neck", "LHip"],
              ["LHip", "LKnee"], ["LKnee", "LAnkle"], ["Neck", "Nose"], ["Nose", "REye"],
              ["REye", "REar"], ["Nose", "LEye"], ["LEye", "LEar"]]

protoFile = "pose_deploy_linevec.prototxt"
weightsFile = "pose_iter_440000.caffemodel"
model_path = "graph_opt.pb"

def train_pose(image_path, out_dir, inWidth=368, inHeight=368, threshhold=0.2):

    net = cv.dnn.readNetFromCaffe(protoFile, weightsFile)
    inp = cv.dnn.blobFromImage(frame, 1.0 / 255, (inWidth, inHeight), (0, 0, 0), swapRB=False, crop=False)

4. 基于openpose的身体姿态提取

  • 实现一个分类器的基础是一个预先给定的类别集合C={C1,C2,…,Cm}和一批已知类别的样本数据集D={d1,d2,…,dn}。不同分类算法的区别一般体现在所形成的分类规则上。
  • 在分类问题中,一个核心的概念是两个数据点之间的距离。所谓判断一个数据点该属于哪个类,本质上就是看它离哪个类的已知数据点更近。而”距离”在不同的应用背景下可能有不同的定义。以二维数据空间为例,给出三种常见的距离定义,如图2所示。
  • 设(x1,y1)和(x2,y2)为两个数据点p1和p2的坐标,欧式距离、曼哈顿距离和余弦相似度(即平面上两个向量夹角的余弦值)分别为:
    基于openpose的K聚类算法手势识别
  • 针对样本数据D,KNN算法计算待分类数据x与样本数据集D中所有数据的距离,然后取其中最小的K个(也就是”KNN”中的K,而NN表示”最近的邻点”),看它们分别属于哪一个类,判定x应该属于K中出现较多的那个类。针对样本数据D,KNN算法计算待分类数据x与样本数据集D中所有数据的距离,然后取其中最小的K个(也就是”KNN”中的K,而NN表示”最近的邻点”),看它们分别属于哪一个类,判定x应该属于K中出现较多的那个类。
  • 利用openpose识别身体姿态点,标定需要用到的六个上肢姿态点,分别为左半身和右半身的三个肩膀点、手肘点、手腕点。确定3种手势,在不同环境下由不同人拍摄制作采集成10组数据,作为数据集。图片统一处理成64*64像素大小,进行归一化处理。每张图片采用欧式距离定义以3个数据作为样本:分别是左右手腕位置、手腕与肩部距离的左右差值。通过计算待分类的图像的这三个数据,与已有10组图像样本的数据进行对比,计算得到每组中与待分类图像差值最小的手势,获取它的手势标签,作为识别结果。其中第一种手势即左手抬起的标签定义为–0,第二种手势即右手抬起,左手放下的标签定义为–1,第三种手势即双手均放下的标签定义为–2。共得到10组识别结果,取众数作为识别结果。

    path = 'detect.jpg'
    result_path = r'C:\Users\viola\PycharmProjects\hand_re\openpose_dynamic\detect_result'
    dfe = get_pose(path, result_path, inWidth=368, inHeight=368, threshhold=0.2)

    d = np.zeros((30, 5))
    for w in range(30):
        d[w] = np.sum((dfe - train_features[w, :]) ** 2)

    d = d.tolist()
    ma = max(d)
    result_index = []
    k = 10
    for i in range(k):
        a = d.index(min(d))
        result_index.append(a)
        d[a] = ma

    result_labels = [int(i / 10) for i in result_index]
    r = np.zeros(3)
    for n in result_labels:
        r[int(n)] += 1
    result_pose = hand_pose[int(np.argmax(r))]
    print('the pose maybe is' + result_pose)

5. 利用pickle保存模型

  • 在机器学习中,当确定好一个模型后,我们需要将它保存下来,这样当新数据出现时,我们能够调出这个模型来对新数据进行预测。同时这些新数据将被作为历史数据保存起来,经过一段周期后,使用更新的历史数据再次训练,得到更好的模型。
  • 如果模型的流转都在python内部,那么可以使用内置的pickle库来完成模型的存储和调取。
  • pickle是负责将python对象序列化(serialization)和反序列化(de- serialization)的模块。pickle模块可以读入任何python对象,然后将它们转换成字符串,我们再使用dump函数将其储存到文件中,这个过程叫做pickling;反之从文件中提取原始python对象的过程交错unpickling。

    pickle_file = 'parameter.pickle'
    if not os.path.isfile(pickle_file):
        print('Saving data to pickle file...')
        try:
            with open('parameter.pickle', 'wb') as pfile:
                pickle.dump({'train_dataset': fes, 'train_labels': train_labels}, pfile, pickle.HIGHEST_PROTOCOL)
        except Exception as e:
            print('Unable to save data to', pickle_file, ':', e)
            raise
    print('Data cached in pickle file.')

    pickle_file = 'parameter.pickle'
    with open(pickle_file, 'rb') as f:
        pickle_data = pickle.load(f)
        train_features = pickle_data['train_dataset']
        train_labels = pickle_data['train_labels']
        del pickle_data
    print('Data and modules loaded.')

Original: https://blog.csdn.net/emellyduck/article/details/122414655
Author: 小书包@
Title: 基于openpose的K聚类算法手势识别

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/550260/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球