TensorFlow2.X结合OpenCV 实现手势识别功能

1. 引言

手势识别技术在现在的科技应用中有着广泛的应用,比如在游戏、人机交互、健康医疗等方面。传统的手势识别技术受限于算法和设备,而深度学习结合计算机视觉技术的出现,使手势识别有了质的飞跃。

2. TensorFlow2.X和OpenCV介绍

TensorFlow2.X是一个基于数据流图的机器学习框架,能够在CPU和GPU上运行,并且支持分布式部署。TensorFlow具有很高的灵活性和可扩展性,能够帮助开发者轻松地构建和训练深度学习模型。

import tensorflow as tf

print(tf.__version__)

OpenCV是一个开源的计算机视觉库,用于处理图像和视频。它是一个跨平台的库,支持Windows、Linux、Android和iOS等操作系统。OpenCV内置了很多图像处理算法和工具,可以帮助开发者用很少的代码完成很多复杂的任务。

import cv2

print(cv2.__version__)

3. 手势识别技术

3.1 涉及技术

手势识别技术主要涉及计算机视觉、深度学习等领域的知识。

计算机视觉是一种利用计算机对图像、视频等数字信号进行处理和解析的学科,是实现手势识别的基础。

深度学习是机器学习领域的一个分支,通过多层神经网络实现对数据的特征学习和分类,是实现手势识别的核心技术。

3.2 数据集

实现手势识别需要大量的手势数据,用于模型的训练和测试。常见的手势数据集有美国手语ASL(American Sign Language)数据集、手指细节数据集等。

4. TensorFlow2.X和OpenCV实现手势识别

4.1 环境准备

在实现手势识别之前,我们需要安装必要的Python库,比如TensorFlow、OpenCV等。

!pip install tensorflow opencv-python

4.2 数据处理

在实现手势识别之前,我们需要对手势数据进行预处理,比如对图像进行裁剪、缩放等操作。

假设我们使用的是美国手语ASL数据集,图像大小为200x200,手势种类为26个字母。

import os

import numpy as np

import cv2

data_path = 'asl_alphabet_train'

categories = os.listdir(data_path) # 26个字母的文件夹名称

labels = [i for i in range(len(categories))] # 标签

label_dict = dict(zip(categories, labels)) # 字典:字符到标签的映射

print(label_dict)

img_size = 200

data = []

target = []

for category in categories:

folder_path = os.path.join(data_path, category)

img_names = os.listdir(folder_path)

for img_name in img_names:

img_path = os.path.join(folder_path, img_name)

img = cv2.imread(img_path)

try:

# 裁剪左上角的手部图像

gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

gray = cv2.GaussianBlur(gray, (7, 7), 0)

_, thresh = cv2.threshold(gray, 100, 255, cv2.THRESH_BINARY_INV+cv2.THRESH_OTSU)

contours, _ = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)

cnt = max(contours, key = cv2.contourArea)

x, y, w, h = cv2.boundingRect(cnt)

hand_img = img[y:y+h, x:x+w]

# 缩放图像

hand_img = cv2.resize(hand_img, (img_size, img_size))

data.append(hand_img)

target.append(label_dict[category])

except Exception as e:

print('Exception:', e)

pass

data = np.array(data)

target = np.array(target)

print(data.shape, target.shape)

上述代码中,我们将26个字母分别作为一个类别处理,读入相应的图像,对图像进行裁剪、缩放等操作,然后将处理后的图像数据和标签保存到datatarget数组中。

4.3 搭建模型

在搭建模型之前,需要对数据进行预处理,比如将数据归一化、划分训练集和测试集等操作。

from sklearn.model_selection import train_test_split

X_train, X_test, y_train, y_test = train_test_split(data, target, test_size=0.2, random_state=42)

X_train = X_train / 255.0

X_test = X_test / 255.0

model = tf.keras.models.Sequential([

tf.keras.layers.Conv2D(32, (3,3), padding='same', activation='relu', input_shape=X_train.shape[1:]),

tf.keras.layers.MaxPooling2D(pool_size=(2,2), strides=(2,2)),

tf.keras.layers.Dropout(0.2),

tf.keras.layers.Conv2D(64, (3,3), padding='same', activation='relu'),

tf.keras.layers.MaxPooling2D(pool_size=(2,2), strides=(2,2)),

tf.keras.layers.Dropout(0.2),

tf.keras.layers.Conv2D(128, (3,3), padding='same', activation='relu'),

tf.keras.layers.MaxPooling2D(pool_size=(2,2), strides=(2,2)),

tf.keras.layers.Dropout(0.2),

tf.keras.layers.Flatten(),

tf.keras.layers.Dense(512, activation='relu'),

tf.keras.layers.Dropout(0.2),

tf.keras.layers.Dense(len(categories), activation='softmax')

])

model.compile(optimizer='adam',

loss='sparse_categorical_crossentropy',

metrics=['accuracy'])

model.summary()

上述代码中,我们使用了简单的卷积神经网络结构,并使用sparse_categorical_crossentropy作为损失函数进行模型的训练。

4.4 训练模型

在模型搭建完成后,我们还需要对模型进行训练和优化,以提高识别准确率。

history = model.fit(X_train, y_train, batch_size=32, epochs=10, validation_data=(X_test, y_test))

训练完成后,我们可以使用evaluate方法评估模型在测试集上的表现。此外,我们可以使用save方法保存模型。

model.evaluate(X_test, y_test)

model.save('asl_model.h5')

4.5 手势识别

最后,我们可以使用训练好的模型进行手势识别。

def predict(model, img):

img = cv2.resize(img, (img_size, img_size))

img = img.reshape(-1, img_size, img_size, 3)

img = img / 255.0

pred = model.predict(img)

result = np.argmax(pred)

return result

cap = cv2.VideoCapture(0)

while(True):

ret, frame = cap.read()

cv2.rectangle(frame, (100, 100), (300, 300), (255,0,0), 2)

img = frame[100:300, 100:300]

pred = predict(model, img)

alphabet = list(label_dict.keys())[list(label_dict.values()).index(pred)]

cv2.putText(frame, alphabet, (100, 90), cv2.FONT_HERSHEY_SIMPLEX, 3, (0,0,255), 2, cv2.LINE_AA)

cv2.imshow('frame', frame)

if cv2.waitKey(1) & 0xFF == ord('q'):

break

cap.release()

cv2.destroyAllWindows()

上述代码中,我们使用cv2.VideoCapture调用摄像头,并从视频流中获取图像。然后,我们将待识别的手势部分裁剪出来,对其进行预处理,并调用predict方法进行手势识别。最后,我们将识别结果绘制在原图上,并将原图显示出来。

5. 结论

本文介绍了如何使用TensorFlow2.X和OpenCV实现手势识别功能。通过对美国手语ASL数据集的处理,使用卷积神经网络模型进行训练和优化,并通过调用摄像头实时获取图像进行手势识别。该方法可以为游戏、人机交互、健康医疗等方面提供一种简便的解决方案。

后端开发标签