基于深度学习的人脸表情识别实现
1. 前言
關于人臉識別,其實我一直以來做過蠻多的項目,有些是整理出帖子了,有些是沒有整理出,因為學業比較繁重,所以也是斷斷續續的來整理。最近剛好是五一假期,也出不去,就想著來整理一篇關于人臉表情識別的文章。這是可以既可以識別人的身份,還可以識別出人的表情出來,如開心、悲傷等基本情緒。
2. 相關工作
依我比較有限的知識來說的話,無論是人臉識別還是表情識別,亦或是把兩者結合起來,也就是本文要實現的人臉+表情識別任務,其本質都是分類任務。關于人臉識別,我之前分別實現了不戴口罩和戴口罩的識別任務,具體可參考下面鏈接。
戴口罩的人臉識別_James Ken的博客-CSDN博客https://blog.csdn.net/weixin_36431280/article/details/115668719簡單人臉識別一之使用opencv+cnn網絡實現人臉識別_James Ken的博客-CSDN博客_cnn人臉識別https://blog.csdn.net/weixin_36431280/article/details/91996066?spm=1001.2014.3001.5502無論是戴口罩還是不戴口罩,識別的步驟均是:人臉檢測、人臉區域特征表示、人臉識別。兩個任務最直接的區別就是人臉特征表示,檢測到的人臉區域會有不同,戴口罩之后人臉區域明顯會被遮擋,如何從有限區域內提取到足夠多的特征用于最終的分類,這是我們考慮的問題,具體的分析在以上兩篇帖子里有介紹。而最終的人臉識別都是采用了卷積神經網絡來做分類任務。到了本文這里,無非就是在人臉識別的任務上再加上了表情識別的任務。其實表情識別的步驟同樣還是三步:人臉檢測、人臉區域特征表示、表情識別。預設的表情標簽為: ['angry', 'disgust', 'fear', 'happy', 'sad', 'surprise', 'neutral'],我們需要做的那就還是有監督的分類任務。
3. 項目實現
3.1 環境設置
1. python 3.8; 建議裝Anaconda環境再來創建一個python3.8的虛擬環境;2. Windows10系統; windows對opencv庫支持性最好
3. face_recognition, dlib庫;注意,得先安裝dlib, cmake, boost庫,才能完整安裝face_recognition;
其中,版本為:dlib-19.19.0; face_recognition-1.3.0; 這一塊可參考該帖子
4. onnxruntime, opencv-python, pandas, matplotlib, keras 均無版本限制;
5. tensorflow, 2.0版本以上均行;
3.2 實現流程
1)人臉檢測
人臉檢測步驟顧名思義,就是從一張圖片中檢測出人臉的區域。現有的人臉檢測模型的原理其實都是從預先裁剪出的人臉金字塔中不斷的篩選出符合要求的人臉框圖片,如MTCNN模型,就是在P-Net、O-Net、R-Net結構中不斷運用NMS非極大值抑制策略來篩選出人臉框圖片出來。核心代碼如下所示:
# 輸入圖片(numpy),輸出人臉框體最大的box def detect(self, image, conf_thresh=0.6, iou_thresh=0.4, target_shape=(360, 360)):height, width, _ = image.shapeimage_resized = cv2.resize(image, target_shape)image_np = image_resized / 255.0 # 歸一化到0~1image_exp = np.expand_dims(image_np, axis=0)image_transposed = image_exp.transpose((0, 3, 1, 2)).astype(np.float32)ort_inputs = {self.ort_session.get_inputs()[0].name: image_transposed}y_bboxes_output, y_cls_output = self.ort_session.run(None, ort_inputs)# remove the batch dimension, for batch is always 1 for inference.y_bboxes = decode_bbox(self.anchors_exp, y_bboxes_output)[0]y_cls = y_cls_output[0]# To speed up, do single class NMS, not multiple classes NMS.bbox_max_scores = np.max(y_cls, axis=1)bbox_max_score_classes = np.argmax(y_cls, axis=1)# keep_idx is the alive bounding box after nms.keep_idxs = single_class_non_max_suppression(y_bboxes, bbox_max_scores, conf_thresh, iou_thresh)max_area, r_item = -1, Nonefor idx in keep_idxs:# conf = float(bbox_max_scores[idx])class_id = bbox_max_score_classes[idx]bbox = y_bboxes[idx]# clip the coordinate, avoid the value exceed the image boundary.xmin = max(0, int(bbox[0] * width))ymin = max(0, int(bbox[1] * height))xmax = min(int(bbox[2] * width), width)ymax = min(int(bbox[3] * height), height)item = (xmin, ymin, xmax, ymax), class_idarea = (xmax - xmin) * (ymax - ymin)if max_area < area:max_area, r_item = area, itemreturn r_item人臉檢測效果大概就是如此,把人臉單獨框出來。
2)人臉特征表示
這一塊就是將人臉區域的圖片用其中的一些關鍵特征點來表示,相當于降維來減低計算成本吧,一般就是用opencv庫的haar級聯檢測器來表示。一般就是采用其中68個特征點來表示,如眼睛、鼻子、嘴唇等,其效果如下所示:
3)人臉識別或表情識別
前面說過,這兩個都是分類任務。先說說表情識別吧,其實就是根據預設的表情標簽來做多分類識別,識別模型代碼如下:
def make_model():"""表情識別模型結構"""model = Sequential()model.add(Conv2D(32, (3, 3), padding='same', input_shape=(48, 48, 1)))model.add(MaxPooling2D(pool_size=(2, 2)))model.add(BatchNormalization())model.add(Activation('relu'))model.add(Dropout(0.4))model.add(Conv2D(64, (3, 3), padding='same'))model.add(MaxPooling2D(pool_size=(2, 2)))model.add(BatchNormalization())model.add(Activation('relu'))model.add(Dropout(0.4))model.add(Conv2D(96, (3, 3), padding='same'))model.add(MaxPooling2D(pool_size=(2, 2)))model.add(BatchNormalization())model.add(Activation('relu'))model.add(Dropout(0.4))model.add(Conv2D(128, (3, 3), padding='same'))model.add(MaxPooling2D(pool_size=(2, 2)))model.add(BatchNormalization())model.add(Activation('relu'))model.add(Dropout(0.4))model.add(Conv2D(160, (3, 3), padding='same'))model.add(MaxPooling2D(pool_size=(2, 2)))model.add(BatchNormalization())model.add(Activation('relu'))model.add(Dropout(0.4))model.add(Flatten())model.add(Dense(128, activation='relu'))model.add(Dropout(0.4))model.add(Dense(7, activation='sigmoid'))return model其表示識別效果如下圖所示:
?人臉識別同樣如此,可以不同的是,人臉身份較多,不是簡單的幾個,所以訓練起來難度會比較大。我們一般就是直接調用face_recognition庫中的人臉識別模型,不然幾萬甚至幾十萬個人臉圖片拿來訓練,一般的電腦是訓練不了的。代碼如下所示:
def _get_face_feat(self, img_x, box):"""獲取臉部的128維特征向量:param img_x::param box::return:"""rec = dlib.rectangle(*box)shape = self.sp(img_x, rec)feat = self.facerec.compute_face_descriptor(img_x, shape)return featdef _face_distance(self, face_encodings, face_to_compare):"""基于人臉編碼信息矩陣,比較不同人臉之間的距離"""if len(face_encodings) == 0:return np.empty((0))face_encodings = np.asarray(face_encodings)return np.linalg.norm(face_encodings - face_to_compare, axis=1)def recognize(self, image, score_threshold=0.6):"""識別人臉:param image: 圖片路徑:param score_threshold: 人臉識別得分閾值:return: (know_name[ix], face_locations, cls) (人員id,box坐標(left,top,right,bottom),是否戴了口罩(0,1))"""if isinstance(image, str):image = cv2.imread(image)image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)item = self.face_detector.detect(image)if item:box, cls = itemface_feat = self._get_face_feat(image, box)scores = 1 - self._face_distance(self._known_faces, face_feat)ix = np.argmax(scores).item()if scores[ix] > score_threshold:# 1 for maskreturn self._know_name[ix], box, 1 - int(cls), scores[ix]return None其人臉識別效果如下圖所示:
?最終實現的人臉識別+表情識別的效果如下所示:
?人臉識別方面蠻多的領域的,也歡迎加QQ:1018721901前來咨詢。
總結
以上是生活随笔為你收集整理的基于深度学习的人脸表情识别实现的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Django中的Model模型
- 下一篇: python之虚拟环境