1. 程式人生 > >卷積神經網路, 識別人臉性別

卷積神經網路, 識別人臉性別

原博地址https://laboo.top/2018/12/02/tfjs-face/#more

在傳統程式設計中, 影象識別一直是一個難點, 雖然人能輕鬆做到, 但是用邏輯來描述這個過程, 並轉換成程式是很難的。機器學習的出現讓影象識別技術有了突破性的進展, 卷積神經網路的出現, 又使影象識別更上了一次層次。

卷積神經網路由一個或多個卷積層和頂端的全連通層組成, 這一結構使得卷積神經網路能夠利用輸入資料的二維結構。與其他深度學習結構相比,卷積神經網路在影象和語音識別方面能夠給出更好的結果。

這裡我們使用卷積神經網路對人臉進行性別識別, 專案中使用了TensorFlow機器學習庫。

專案地址

face-gender-classification

資料收集與處理

機器學習的基礎就是大量的資料。我以前從網上爬了一萬張證件照, 現在正好用上, 作為訓練資料。
簡便的也可以從谷歌直接搜搜索 男(女)性證件照也可以得到並且有標籤的資料。
由於我收集的照片沒有標籤, 於是我花了一點時間從其中人工選出男女照片各200張並打上標記。

為了使識別更加準確, 專案中利用openCV裁剪出人臉部分的影象, 並縮放至28*28大小。

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
最後我們還需要清理異常的資料, 過一遍訓練集, 把其中沒有定位到人臉的圖片去除掉。

訓練模型

讀取訓練資料。

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)

這裡對訓練影象灰度化, 並且將訓練資料中的一小部分作為驗證集。

開始建立模型。

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)
])

選擇適當的優化器和損失函式編譯模型。

model.compile(optimizer=tf.train.AdamOptimizer(learning_rate=0.001),
              loss='categorical_crossentropy',
              metrics=['accuracy'])

開始訓練模型。

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來顯示測試圖片及結果。

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()

2
臉部頭像右側的兩列分別代表女性概率男性概率
這裡我們看到全都對了, 正確率非常高。
模型並不複雜, 大部分工作都在收集資料和調整訓練引數上, 這也體現出了卷積神經網路對影象強大的處理能力。

歡迎關注我的部落格公眾號
2018_11_16_0048241709.png