基于卷积神经网络的非图像的手势识别控制系统设计

发布于:2025-06-30 ⋅ 阅读:(18) ⋅ 点赞:(0)

目 录
摘 要 I
Abstract II
第1章 绪论 1
1.1 研究背景与意义 1
1.2 国内外研究现状 1
1.2.1国内研究现状 1
1.2.2国外研究现状 2
1.3 研究内容与目标 3
1.3.1研究内容 3
1.3.2研究目标 3
1.4 论文结构安排 4
第2章 相关理论基础 5
2.1 卷积神经网络(CNN)概述 5
2.1.1 CNN的核心组件 5
2.1.2 CNN的关键操作 5
2.1.3 CNN的应用与优势 6
2.1.4 CNN的公式推导 6
2.2 一维卷积神经网络(1D CNNs)原理 7
2.2.1 1D CNNs的核心结构 7
2.2.2 卷积操作 7
2.2.3 激活函数 7
2.2.4 应用场景 8
2.2.5 1D CNNs的公式推导 8
2.3 MPU6050陀螺仪工作原理及数据采集 9
2.3.1 工作原理 9
2.3.2 数据采集 10
2.4 STM32微控制器简介 10
2.4.1 基本特性 10
2.4.2 系列划分 10
2.4.3 外设资源 10
2.4.4 应用领域 11
2.5 红外通信技术 11
2.5.1 红外通信原理 11
2.5.2 红外通信的应用 11
2.6 卡尔曼滤波算法原理及公式 12
2.6.1卡尔曼滤波算法原理 12
2.6.2卡尔曼滤波核心公式 12
2.6.3算法特性与应用 13
第3章 算法实现 14
3.1 手势识别定位程序设计 14
3.1.1 数据集准备 14
3.1.2 图像预处理程序 15
3.1.3 神经网络程序 15
3.1.4 模型训练程序 17
3.2 模型训练 19
3.2.1 数据集 19
3.2.2 结果解析程序 20
第4章 系统总体设计 23
4.1 系统设计思路 23
4.2 系统硬件架构设计 23
4.2.1 主控模块 23
4.2.2 运动感知模块 24
4.2.3 电源管理模块 24
4.2.4 通信模块 24
4.2.5 扩展接口设计 24
第5章 硬件电路设计 26
5.1单片机最小系统 26
5.1.1主控模块电路 26
5.1.2 晶振电路 28
5.1.3 复位电路 30
5.1.4 电源电路 31
5.1.5下载电路 32
5.2 MPU6050手势识别模块 33
第6章 系统程序设计 36
6.1 编程软件介绍 36
6.2 主机系统主流程设计 36
6.3 红外通信子流程设计 38
第7章 实物测试 39
7.1 项目介绍 39
7.2 实物展示 39
7.3 项目功能简介 42
7.4 原理解析(硬件说明) 43
7.4.1硬件说明 43
7.4.2红外通信实现原理与测试过程 43
结 论 45
参考文献 46
附 录 48
附录一:原理图 48
附录二:PCB 48
附录三:BOM清单 49
致 谢 53
1.3 研究内容与目标
1.3.1研究内容
本研究围绕基于卷积神经网络的非图像手势识别控制系统展开,主要研究内容包括以下几个方面:
1.手势数据采集与处理:利用MPU6050陀螺仪实时采集时间序列的加速度传感器数据,并对采集到的数据进行预处理,包括去噪、滤波、归一化等操作,以提高数据质量,为后续的手势识别提供可靠的数据基础。
一维卷积神经网络模型设计与训练:针对预处理后的手势数据,设计一维卷积神经网络(1D CNNs)模型,用于对手势动作进行识别。通过大量数据集的训练,不断优化模型参数,提高手势识别的准确性和鲁棒性。
手势识别算法实现:基于训练好的一维卷积神经网络模型,实现手势识别算法。该算法能够实时接收来自MPU6050陀螺仪的数据,进行手势动作预测,并输出识别结果。
2.系统硬件设计与实现:设计并制作基于STM32F103CBT6主控芯片的硬件系统,包括陀螺仪模块、射频遥控模块、蓝牙通信模块等,实现手势数据的采集、处理与传输,以及基于识别结果对外部设备的控制。
系统集成与测试:将软件算法与硬件系统进行集成,构建完整的基于卷积神经网络的非图像手势识别控制系统。对系统进行全面测试,包括手势识别准确率测试、系统响应时间测试、稳定性与可靠性测试等,确保系统性能满足设计要求。
1.3.2研究目标
本研究旨在实现以下具体目标:
1.提高手势识别的准确性和鲁棒性:通过一维卷积神经网络模型的设计与训练,提高手势识别的准确性,并能在低光照、复杂背景等特定环境下保持稳定的识别性能。
2.实现基于手势识别的智能控制:构建基于卷积神经网络的非图像手势识别控制系统,实现通过手势动作对外部设备的智能控制,如智能家居控制、智能穿戴设备交互等。
3.推动手势识别技术的发展:本研究的研究成果将为手势识别技术的发展提供新的思路和方法,推动该领域的技术进步和创新。
促进人机交互方式的变革:通过实现基于手势识别的智能控制系统,为用户提供更加自然、高效的人机交互方式,促进人机交互方式的变革和发展。
1.4 论文结构安排
本文共分为若干章节,结构安排如下:
第1章 绪论:介绍研究背景、意义,国内外研究现状,以及本研究的内容、目标和论文结构。
第2章 相关理论基础:阐述卷积神经网络、MPU6050陀螺仪等相关技术原理。
第3章 系统设计与实现:详细描述系统硬件设计、软件算法实现及系统集成过程。
第4章 实验与结果分析:展示实验设计、数据收集、模型训练及测试结果,并进行深入分析。
第5章 结论与展望:总结研究成果,讨论存在的问题,并对未来研究方向提出展望。
此结构旨在确保论文内容条理清晰,逻辑连贯。

import os
import re
from nnom import * # type: ignore
import numpy as np
import tensorflow as tf # type: ignore
from tensorflow.keras.models import load_model, save_model # type: ignore
from tensorflow.keras.preprocessing.sequence import pad_sequences # type: ignore
from tensorflow.keras import * # type: ignore
from tensorflow.keras.layers import * # type: ignore
from tensorflow.keras.regularizers import l2 # type: ignore

from sklearn.metrics import classification_report
from sklearn.preprocessing import MinMaxScaler, StandardScaler

# 动作分类名
motion_names = ['RightAngle', 'SharpAngle', 'Lightning', 'Triangle', 'Letter_h', 'letter_R', 'letter_W', 'letter_phi', 'Circle', 'UpAndDown', 'Horn', 'Wave', 'NoMotion']

# 定义目录路径
DEF_SAVE_TO_PATH = './TraningData_8_17/'
DEF_MODEL_NAME = 'model.h5'
DEF_MODEL_H_NAME = 'weights.h'
DEF_FILE_MAX = 50
DEF_MAX_TRIALS = 3
#DEF_N_ROWS = 60
DEF_N_ROWS = 150
#DEF_COLUMNS = (0, 1, 2, 3, 4, 5)
DEF_COLUMNS = (3, 4, 5)
#DEF_COLUMNS = (0, 1, 2)

# 文件格式
DEF_FILE_FORMAT = '.txt'
# 文件名分隔符
DEF_FILE_NAME_SEPERATOR = '_'
DEF_BATCH_SIZE = 80
DEF_NUM_EPOCH = 80

# 动作名称到标签的映射
motion_to_label = {name: idx for idx, name in enumerate(motion_names)}

def train(x_train, y_train, x_test, y_test, input_shape=(DEF_N_ROWS, 3), num_classes=len(motion_names), batch_size=DEF_BATCH_SIZE, epochs=DEF_NUM_EPOCH):
    inputs = layers.Input(shape=input_shape) # type: ignore

    x = layers.Conv1D(30, kernel_size=3, strides=3, padding='same')(inputs) # type: ignore
    x = layers.LeakyReLU()(x)# type: ignore
    x = layers.Conv1D(15, kernel_size=3, strides=3, padding='same')(x)# type: ignore
    x = layers.LeakyReLU()(x)# type: ignore
    #x = layers.MaxPooling1D(pool_size=3, strides=3)(x)# type: ignore
    # LSTM 层
    #x = layers.LSTM(5, return_sequences=True)(x)  # type: ignore
   
    x = layers.Flatten()(x)# type: ignore

    # 全连接层
    x = layers.Dense(num_classes)(x) # type: ignore
    x = layers.Dropout(0.3)(x) # type: ignore
    outputs = layers.Softmax()(x) # type: ignore

    model = models.Model(inputs=inputs, outputs=outputs) # type: ignore
    
    # 编译模型
    model.compile(optimizer=optimizers.Adam(), # type: ignore
                  loss=losses.CategoricalCrossentropy(), # type: ignore
                  metrics=['accuracy'])# type: ignore
    
    model.summary()
    
    # Callbacks
    early_stopping = callbacks.EarlyStopping(monitor='val_loss', patience=10)# type: ignore
    checkpoint = callbacks.ModelCheckpoint(DEF_MODEL_NAME, monitor='val_accuracy', save_best_only=True, mode='max')# type: ignore
    
    # 训练模型
    history = model.fit(
        x_train,
        y_train,
        batch_size=batch_size,
        epochs=epochs,
        verbose=2,
        validation_data=(x_test, y_test),
        shuffle=True,
        callbacks=[early_stopping, checkpoint]
    )
    
    # 清除会话
    del model
    tf.keras.backend.clear_session()
    
    return history

# 加载数据集
def load_dataset(root_dir, max_rows=None):
    file_list = []
    labels = []
    for filename in os.listdir(root_dir):
        if filename.endswith(DEF_FILE_FORMAT):
            match = re.match(rf'^([\w]+)_([\d]+){DEF_FILE_FORMAT}$', filename)
            if match:
                motion_name = match.group(1)
                number_str = match.group(2)
                number = int(number_str)
                if 0 <= number <= DEF_FILE_MAX:
                    if motion_name in motion_to_label:
                        file_path = os.path.join(root_dir, filename)
                        # 使用max_rows参数限制读取的行数
                        data = np.loadtxt(file_path, delimiter=' ', usecols=DEF_COLUMNS, max_rows=max_rows)
                        file_list.append(data)
                        labels.append(motion_to_label[motion_name])
                    else:
                        print(f"Motion name not recognized: {filename}")
                else:
                    print(f"Number out of range: {filename}")
            else:
                print(f"Invalid file name format: {filename}")
    return file_list, labels

file_list, labels = load_dataset(DEF_SAVE_TO_PATH, max_rows=DEF_N_ROWS)

# 数据预处理,例如填充序列以达到统一长度
max_len = max([len(x) for x in file_list])  # 找到最长序列的长度
print(f"Max length of sequences: {max_len}")  # 打印max_len的值
file_list_padded = pad_sequences(file_list, maxlen=max_len, dtype='float32', padding='post', value=0)
    
# 转换标签为one-hot编码
labels_one_hot = utils.to_categorical(labels, num_classes=len(motion_names)) # type: ignore

# 计算分割点前,先确保数据集被完全构建
num_elements = len(file_list_padded)

train_size = int(num_elements * 0.8)

# 训练模型并保存最佳模型
best_val_accuracy = 0
best_model = None
for _ in range(DEF_MAX_TRIALS):  # 重复训练DEF_MAX_TRIALS次
    # 先shuffle再分割
    indices = np.arange(num_elements)
    np.random.shuffle(indices)

    # 分割数据集
    train_indices = indices[:train_size]
    test_indices = indices[train_size:]

    # 获取训练和测试数据
    x_train = file_list_padded[train_indices]
    y_train = labels_one_hot[train_indices]
    x_test = file_list_padded[test_indices]
    y_test = labels_one_hot[test_indices]
        
    history = train(x_train, y_train, x_test, y_test, batch_size=DEF_BATCH_SIZE, epochs=DEF_NUM_EPOCH)
    # 加载最佳模型
    model = load_model(DEF_MODEL_NAME)
    
    # 评估模型
    y_pred = model.predict(x_test)
    y_pred_classes = np.argmax(y_pred, axis=1)
    y_true_classes = np.argmax(y_test, axis=1)
    
    # 获取验证集上的准确率
    val_accuracy = history.history['val_accuracy'][-1]
    print(f"Validation Accuracy: {val_accuracy:.4f}")
    
    # 保存最佳模型
    if val_accuracy > best_val_accuracy:
        best_val_accuracy = val_accuracy
        best_model = model

# 从训练数据集中获取一个批次作为校准数据集
# 这里直接使用x_test
x_test_sample = x_test[:100]  # 使用前100个样本作为校准数据集

# 使用最佳模型进行最终评估
if best_model is not None:
    y_pred = best_model.predict(x_test)
    y_pred_classes = np.argmax(y_pred, axis=1)
    y_true_classes = np.argmax(y_test, axis=1)
    
    # 确保 target_names 的长度与实际类别数相匹配
    unique_classes = np.unique(np.concatenate((y_true_classes, y_pred_classes)))
    target_names = [motion_names[i] for i in sorted(unique_classes)]

    # 打印每个类别的准确率
    print(classification_report(y_true_classes, y_pred_classes, target_names=target_names))

    # 从训练数据集中获取一个批次作为校准数据集
    x_test_sample = x_test[:100]  # 使用前100个样本作为校准数据集
    
    # 假设generate_model函数已经定义在nnom模块中
    generate_model(best_model, x_test_sample, format='hwc', name=DEF_MODEL_H_NAME)

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述


网站公告

今日签到

点亮在社区的每一天
去签到