在传统编程中, 图像识别一直是一个难点, 虽然人能轻松做到, 但是用逻辑来描述这个过程, 并转换成程序是很难的。机器学习的出现让图像识别技术有了突破性的进展, 卷积神经网络的出现, 又使图像识别更上了一次层次。
卷积神经网络由一个或多个卷积层和顶端的全连通层组成, 这一结构使得卷积神经网络能够利用输入数据的二维结构。与其他深度学习结构相比,卷积神经网络在图像和语音识别方面能够给出更好的结果。
这里我们使用卷积神经网络对人脸进行性别识别, 项目中使用了TensorFlow
机器学习库。
项目地址 face-gender-classification
数据收集与处理 机器学习的基础就是大量的数据。我以前从网上爬了一万张证件照, 现在正好用上, 作为训练数据。 简便的也可以从谷歌直接搜搜索 男(女)性证件照
也可以得到并且有标签的数据。 由于我收集的照片没有标签, 于是我花了一点时间从其中人工选出男女照片各200张并打上标记。
为了使识别更加准确, 项目中利用openCV
裁剪出人脸部分的图像, 并缩放至28*28
大小。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 recognizer = cv2.CascadeClassifier("model/haarcascade_frontalface_default.xml" ) crop(img_path): try : img = cv2.imread(img_path) gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) faces = recognizer.detectMultiScale(gray) if len (faces): x, y, w, h = faces[0 ] c_img = img[y:y + h, x:x + w] return cv2.resize(c_img, (28 , 28 ), interpolation=cv2.INTER_AREA) except : pass return None
对所有的数据都进行这样处理, 结果如下: 最后我们还需要清理异常的数据, 过一遍训练集, 把其中没有定位到人脸的图片去除掉。
训练模型 读取训练数据。
1 2 3 4 5 6 7 8 9 10 11 12 def read_img (files ): arr = [] for file in files: img = Image.open ("%s" % file) pix = img.load() view = np.zeros((IMAGE_H, IMAGE_W, 1 ), dtype=np.float ) for x in range (IMAGE_H): for y in range (IMAGE_W): r, g, b = pix[y, x] view[x, y, 0 ] = (r + g + b) // 3 arr.append(view) return np.array(arr)
这里对训练图像灰度化, 并且将训练数据中的一小部分作为验证集。
开始创建模型。
1 2 3 4 5 6 7 8 9 10 model = keras.Sequential([ keras.layers.Conv2D(32 , (3 , 3 ), input_shape=(IMAGE_W, IMAGE_H, 1 ), strides=(1 , 1 ), activation='relu' ), keras.layers.MaxPool2D(pool_size=(2 , 2 )), keras.layers.Conv2D(64 , (3 , 3 ), strides=(1 , 1 ), activation='relu' ), keras.layers.MaxPool2D(pool_size=(2 , 2 )), keras.layers.Flatten(), keras.layers.Dense(128 , activation=tf.nn.relu), keras.layers.Dropout(0.2 ), keras.layers.Dense(2 , activation=tf.nn.softmax) ])
选择适当的优化器和损失函数编译模型。
1 2 3 model.compile (optimizer=tf.train.AdamOptimizer(learning_rate=0.001 ), loss='categorical_crossentropy' , metrics=['accuracy' ])
开始训练模型。
1 2 3 4 5 6 7 8 9 model.fit(x=train_x, y=train_y, batch_size=32 , epochs=30 , verbose=1 , callbacks=my_callbacks, validation_split=0.05 , shuffle=True )
测试模型 这里使用matplotlib来显示测试图片及结果。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 predictions = model.predict(test_x) class_names = ["Female" , "Male" ] plt.figure(figsize=(12 , 6 )) for i in range (min (9 , len (test_y))): result = predictions[i] max_label = int (np.argmax(result)) correct_label = int (np.argmax(test_y[i])) plt.subplot(3 , 6 , 2 * i + 1 ) plt.grid(False ) plt.xticks([]) plt.yticks([]) img = test_x.reshape(test_x.shape[0 ], IMAGE_W, IMAGE_H)[i] plt.imshow(img, cmap="gray" ) plt.xlabel("{} - prob:{:2.0f}%" .format (class_names[max_label], 100 * np.max (result))) plt.subplot(3 , 6 , 2 * i + 2 ) plt.grid(False ) plt.yticks([]) plt.ylim([0 , 1 ]) bar = plt.bar(range (2 ), result) bar[max_label].set_color('red' ) bar[correct_label].set_color('green' ) plt.show()
脸部头像右侧的两列分别代表女性概率
和男性概率
。 这里我们看到全都对了, 正确率非常高。 模型并不复杂, 大部分工作都在收集数据和调整训练参数上, 这也体现出了卷积神经网络对图像强大的处理能力。