tianbwin 2019-03-23
要构建SLR(手语识别),我们需要三件事:
可以在此处下载手势数据集(https://www.kaggle.com/datamunge/sign-language-mnist)。
我们的机器学习数据集包含24个(J和Z除外)American Sign Laguage字母表的许多图像。每个图像的大小为28x28像素,这意味着每个图像总共784个像素。
要加载数据集,请使用以下Python代码:
import keras import numpy as np import pandas as pd import cv2 from matplotlib import pyplot as plt from keras.models import Sequential from keras.layers import Conv2D,MaxPooling2D, Dense,Flatten, Dropout from keras.datasets import mnist import matplotlib.pyplot as plt from keras.utils import np_utils from keras.optimizers import SGD train = pd.read_csv('train.csv') test = pd.read_csv('test.csv') y_train = train['label'].values y_test = test['label'].values X_train = train.drop(['label'],axis=1) X_test = test.drop(['label'], axis=1)
我们的数据集采用CSV(逗号分隔值)格式。train_X和test_X包含每个像素的值。train_Y和test_Y包含图像标签。您可以使用以下Python代码查看机器学习数据集:
display(X_train.info()) display(X_test.info()) display(X_train.head(n = 2)) display(X_test.head(n = 2))
train_X和test_X包含所有像素像素值的数组。我们从这些值创建了一个图像。我们的图像尺寸是28x28,因此我们必须将阵列分成28x28像素组。为此,我们将使用以下代码:
X_train = np.array(X_train.iloc[:,:]) X_train = np.array([np.reshape(i, (28,28)) for i in X_train]) X_test = np.array(X_test.iloc[:,:]) X_test = np.array([np.reshape(i, (28,28)) for i in X_test]) num_classes = 26 y_train = np.array(y_train).reshape(-1) y_test = np.array(y_test).reshape(-1) y_train = np.eye(num_classes)[y_train] y_test = np.eye(num_classes)[y_test] X_train = X_train.reshape((27455, 28, 28, 1)) X_test = X_test.reshape((7172, 28, 28, 1))
现在我们可以使用这个数据集来训练我们的机器学习模型了。
我们将使用CNN(卷积神经网络)来识别字母。我们用keras。
机器学习模型的Python实现如下:
classifier = Sequential() classifier.add(Conv2D(filters=8, kernel_size=(3,3),strides=(1,1),padding='same',input_shape=(28,28,1),activation='relu', data_format='channels_last')) classifier.add(MaxPooling2D(pool_size=(2,2))) classifier.add(Conv2D(filters=16, kernel_size=(3,3),strides=(1,1),padding='same',activation='relu')) classifier.add(Dropout(0.5)) classifier.add(MaxPooling2D(pool_size=(4,4))) classifier.add(Dense(128, activation='relu')) classifier.add(Flatten()) classifier.add(Dense(26, activation='softmax'))
我们的模型由Conv2D和MaxPooling层组成,然后是一些全连接层(Dense)。
第一个Conv2D(卷积)层采用(28,28,1)的输入图像。最后一个全连接层为我们提供了26个字母的输出。
我们正在使用第二个Conv2D层之后的Dropout来正则化我们的训练。
我们在最后一层使用softmax激活函数。
最后我们的模型看起来像这样:
我们必须编译并拟合机器学习模型。为此,我们将使用如下Python代码:
classifier.compile(optimizer='SGD', loss='categorical_crossentropy', metrics=['accuracy']) classifier.fit(X_train, y_train, epochs=50, batch_size=100)
我们正在使用SGD优化器来编译我们的模型。您也可以将时期减少到25。
最后要检查准确性:
accuracy = classifier.evaluate(x=X_test,y=y_test,batch_size=32) print("Accuracy: ",accuracy[1])
要保存训练过的机器学习模型,我们可以使用:
classifier.save('CNNmodel.h5')
以下Python实现方法为示例,可以根据需要自己调整。
import cv2 import numpy as np from keras.models import load_model from skimage.transform import resize, pyramid_reduce import PIL from PIL import Image model = load_model('CNNmodel.h5')
def crop_image(image, x, y, width, height): return image[y:y + height, x:x + width] def prediction(pred): if pred == 0: print('A') elif pred == 1: print('B') elif pred == 2: print('C') elif pred == 3: print('D') elif pred == 14: print('O') elif pred == 8: print('I') elif pred == 20: print('U') elif pred == 21: print('V') elif pred == 22: print('W') elif pred == 24: print('Y') elif pred == 11: print('L') def keras_process_image(img): image_x = 28 image_y = 28 img = cv2.resize(img, (1,28,28), interpolation = cv2.INTER_AREA) #img = get_square(img, 28) #img = np.reshape(img, (image_x, image_y)) return img
我们必须从输入图像预测字母。我们的模型将输出作为整数而不是字母,因为标签是以整数形式给出的(A为1,B为2,C为3,依此类推......)
def keras_predict(model, image): data = np.asarray( image, dtype="int32" ) pred_probab = model.predict(data)[0] pred_class = list(pred_probab).index(max(pred_probab)) return max(pred_probab), pred_class
我们必须创建一个窗口来从我们的网络摄像头获取输入。我们作为输入的图像应该是28x28灰度图像。因为我们在28x28尺寸的图像上训练我们的模型。示例代码如下:
def main(): while True: cam_capture = cv2.VideoCapture(0) _, image_frame = cam_capture.read() # Select ROI im2 = crop_image(image_frame, 300,300,300,300) image_grayscale = cv2.cvtColor(im2, cv2.COLOR_BGR2GRAY) image_grayscale_blurred = cv2.GaussianBlur(image_grayscale, (15,15), 0) im3 = cv2.resize(image_grayscale_blurred, (28,28), interpolation = cv2.INTER_AREA) #ar = np.array(resized_img) #ar = resized_img.reshape(1,784) im4 = np.resize(im3, (28, 28, 1)) im5 = np.expand_dims(im4, axis=0) pred_probab, pred_class = keras_predict(model, im5) #print(pred_class, pred_probab) prediction(pred_class) # Display cropped image cv2.imshow("Image2",im2) #cv2.imshow("Image4",resized_img) cv2.imshow("Image3",image_grayscale_blurred) if cv2.waitKey(25) & 0xFF == ord('q'): cv2.destroyAllWindows() break keras_predict(model, np.zeros((1, 28, 28, 1), dtype=np.uint8)) if __name__ == '__main__': main() cam_capture.release() cv2.destroyAllWindows()
我们的机器学习模型准确度约为94%,因此它应该识别字母而没有任何问题。