1. <strong id="7actg"></strong>
    2. <table id="7actg"></table>

    3. <address id="7actg"></address>
      <address id="7actg"></address>
      1. <object id="7actg"><tt id="7actg"></tt></object>

        使用Python,Keras和OpenCV進(jìn)行實(shí)時(shí)面部檢測(cè)

        共 9864字,需瀏覽 20分鐘

         ·

        2020-08-01 03:36


        點(diǎn)擊上方小白學(xué)視覺(jué)”,選擇加"星標(biāo)"或“置頂

        重磅干貨,第一時(shí)間送達(dá)

        目前我們?cè)诨ヂ?lián)網(wǎng)和論文中看到的大多數(shù)面部識(shí)別算法都是以圖像為基礎(chǔ)進(jìn)行處理。這些方法在檢測(cè)和識(shí)別來(lái)自攝像頭的圖像、或視頻流各幀中的人臉時(shí)效果很好。但是,他們無(wú)法區(qū)分現(xiàn)實(shí)生活中的人臉和照片上的人臉,因?yàn)檫@些算法處理的是2D幀。

        現(xiàn)在,讓我們想象一下,如果我們想要實(shí)現(xiàn)一個(gè)面部識(shí)別開(kāi)門(mén)器。該系統(tǒng)可以很好地區(qū)分已知面孔和未知面孔,保證只有特定人員才能訪問(wèn)。盡管如此,任意一個(gè)陌生人只要擁有他們的照片就很容易進(jìn)入該區(qū)域,這時(shí)3D檢測(cè)器(類似于Apple的FaceID)就被納入考慮范圍。但是,如果我們沒(méi)有3D探測(cè)器怎么辦?

        奧巴馬臉部照片識(shí)別案例?

        本文旨在實(shí)現(xiàn)一種基于眨眼檢測(cè)的面部活動(dòng)檢測(cè)算法來(lái)阻止照片的使用。該算法通過(guò)網(wǎng)絡(luò)攝像頭實(shí)時(shí)工作,并且僅在眨眼時(shí)才顯示該人的姓名。程序流程如下:

        1. 對(duì)網(wǎng)絡(luò)攝像頭生成的每一幀圖像,進(jìn)行面部檢測(cè)。

        2. 對(duì)于每個(gè)檢測(cè)到的臉部區(qū)域,進(jìn)行眼睛檢測(cè)。

        3. 對(duì)于檢測(cè)到的每只眼睛,進(jìn)行眨眼檢測(cè)。

        4. 如果在某個(gè)時(shí)刻檢測(cè)到眼睛合上后又睜開(kāi)了,則認(rèn)為該人眨了眨眼,程序?qū)@示他的名字(對(duì)于面部識(shí)別開(kāi)門(mén)器,我們將授權(quán)該人進(jìn)入)。

        為了檢測(cè)和識(shí)別面部,我們需要安裝face_recognition庫(kù),該庫(kù)提供了非常棒的深度學(xué)習(xí)算法來(lái)查找和識(shí)別圖像中的人臉。特別是face_locations,face_encodingscompare_faces函數(shù)是3個(gè)最常用的函數(shù)。face_locations函數(shù)有兩種可使用兩種方法進(jìn)行人臉檢測(cè):梯度方向的Histrogram(HOG)和C?onvolutional神經(jīng)網(wǎng)絡(luò)(CNN)。由于時(shí)間限制?,選擇了HOG方法。face_encodings函數(shù)是一個(gè)預(yù)訓(xùn)練的卷積神經(jīng)網(wǎng)絡(luò),能夠?qū)D像編碼為128個(gè)特征的向量。這些向量的信息足夠以區(qū)分兩個(gè)不同的人。最后,使用compare_faces計(jì)算兩個(gè)嵌入向量之間的距離它將允許算法識(shí)別從攝像頭幀中提取的面部,并將其嵌入矢量與我們數(shù)據(jù)集中的所有編碼面部進(jìn)行比較。最接近的向量對(duì)應(yīng)于同一個(gè)人。

        1.已知的人臉數(shù)據(jù)集編碼

        就我們的算法而言,它能夠識(shí)別我們自己和巴拉克·奧巴馬。分別選擇了約10張圖片。以下是用于處理和編碼已知面孔數(shù)據(jù)庫(kù)的代碼。

        def process_and_encode(images):    known_encodings = []    known_names = []    print("[LOG] Encoding dataset ...")
        for image_path in tqdm(images): # Load image image = cv2.imread(image_path) # Convert it from BGR to RGB image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
        # detect face in the image and get its location (square boxes coordinates) boxes = face_recognition.face_locations(image, model='hog')
        # Encode the face into a 128-d embeddings vector encoding = face_recognition.face_encodings(image, boxes)
        # the person's name is the name of the folder where the image comes from name = image_path.split(os.path.sep)[-2]
        if len(encoding) > 0 : known_encodings.append(encoding[0]) known_names.append(name)
        return {"encodings": known_encodings, "names": known_names}

        現(xiàn)在我們知道了要識(shí)別的每個(gè)人的編碼,我們可以嘗試通過(guò)網(wǎng)絡(luò)攝像頭識(shí)別和識(shí)別面部。但是,在進(jìn)行此部分操作之前,我們需要區(qū)分面部照片和活人的面部。

        2.面部活躍度檢測(cè)

        提醒一下,目標(biāo)是在某個(gè)點(diǎn)檢測(cè)“睜開(kāi)-閉合-睜開(kāi)”的眼圖。我訓(xùn)練了卷積神經(jīng)網(wǎng)絡(luò)來(lái)對(duì)眼睛是閉合還是睜開(kāi)進(jìn)行分類。選擇的模型是LeNet-5,該模型已在?Closed Eyes In The Wild (CEW)?數(shù)據(jù)集中進(jìn)行了訓(xùn)練。它由大小約為24x24的4800眼圖像組成。

        from keras.models import Sequentialfrom keras.layers import Conv2Dfrom keras.layers import AveragePooling2Dfrom keras.layers import Flattenfrom keras.layers import Densefrom keras.preprocessing.image import ImageDataGenerator
        IMG_SIZE = 24def train(train_generator, val_generator): STEP_SIZE_TRAIN=train_generator.n//train_generator.batch_size STEP_SIZE_VALID=val_generator.n//val_generator.batch_size model = Sequential()
        model.add(Conv2D(filters=6, kernel_size=(3, 3), activation='relu', input_shape=(IMG_SIZE,IMG_SIZE,1))) model.add(AveragePooling2D())
        model.add(Conv2D(filters=16, kernel_size=(3, 3), activation='relu')) model.add(AveragePooling2D())
        model.add(Flatten())
        model.add(Dense(units=120, activation='relu'))
        model.add(Dense(units=84, activation='relu'))
        model.add(Dense(units=1, activation = 'sigmoid'))

        model.compile(loss='binary_crossentropy', optimizer='adam', metrics=['accuracy']) print('[LOG] Training CNN') model.fit_generator(generator=train_generator, steps_per_epoch=STEP_SIZE_TRAIN, validation_data=val_generator, validation_steps=STEP_SIZE_VALID, epochs=20 ) return model

        在評(píng)估模型時(shí),準(zhǔn)確率達(dá)到94%。

        每次檢測(cè)到眼睛時(shí),我們都會(huì)使用模型預(yù)測(cè)其狀態(tài),并跟蹤每個(gè)人的眼睛狀態(tài)。因此,借助以下功能,可使檢測(cè)眨眼變得很容易,該功能嘗試在眼睛狀態(tài)歷史記錄中查找閉合-閉合-閉合模式。

        def isBlinking(history, maxFrames):    """ @history: A string containing the history of eyes status          where a '1' means that the eyes were closed and '0' open.        @maxFrames: The maximal number of successive frames where an eye is closed """    for i in range(maxFrames):        pattern = '1' + '0'*(i+1) + '1'        if pattern in history:            return True    return False

        3.活人的面部識(shí)別

        我們擁有構(gòu)建“真實(shí)”面部識(shí)別算法的所有要素,只需要一種實(shí)時(shí)檢測(cè)面部和眼睛的方法即可。我們選擇使用OpenCV預(yù)訓(xùn)練的Haar級(jí)聯(lián)分類器執(zhí)行這些任務(wù)。

        def detect_and_display(model, video_capture, face_detector, open_eyes_detector, left_eye_detector, right_eye_detector, data, eyes_detected):        frame = video_capture.read()        # resize the frame        frame = cv2.resize(frame, (0, 0), fx=0.6, fy=0.6)
        gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) rgb = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB) # Detect faces faces = face_detector.detectMultiScale( gray, scaleFactor=1.2, minNeighbors=5, minSize=(50, 50), flags=cv2.CASCADE_SCALE_IMAGE )
        # for each detected face for (x,y,w,h) in faces: # Encode the face into a 128-d embeddings vector encoding = face_recognition.face_encodings(rgb, [(y, x+w, y+h, x)])[0]
        # Compare the vector with all known faces encodings matches = face_recognition.compare_faces(data["encodings"], encoding)
        # For now we don't know the person name name = "Unknown"
        # If there is at least one match: if True in matches: matchedIdxs = [i for (i, b) in enumerate(matches) if b] counts = {} for i in matchedIdxs: name = data["names"][i] counts[name] = counts.get(name, 0) + 1
        # The known encoding with the most number of matches corresponds to the detected face name name = max(counts, key=counts.get)
        face = frame[y:y+h,x:x+w] gray_face = gray[y:y+h,x:x+w]
        eyes = [] # Eyes detection # check first if eyes are open (with glasses taking into account) open_eyes_glasses = open_eyes_detector.detectMultiScale( gray_face, scaleFactor=1.1, minNeighbors=5, minSize=(30, 30), flags = cv2.CASCADE_SCALE_IMAGE ) # if open_eyes_glasses detect eyes then they are open if len(open_eyes_glasses) == 2: eyes_detected[name]+='1' for (ex,ey,ew,eh) in open_eyes_glasses: cv2.rectangle(face,(ex,ey),(ex+ew,ey+eh),(0,255,0),2) # otherwise try detecting eyes using left and right_eye_detector # which can detect open and closed eyes else: # separate the face into left and right sides left_face = frame[y:y+h, x+int(w/2):x+w] left_face_gray = gray[y:y+h, x+int(w/2):x+w]
        right_face = frame[y:y+h, x:x+int(w/2)] right_face_gray = gray[y:y+h, x:x+int(w/2)]
        # Detect the left eye left_eye = left_eye_detector.detectMultiScale( left_face_gray, scaleFactor=1.1, minNeighbors=5, minSize=(30, 30), flags = cv2.CASCADE_SCALE_IMAGE )
        # Detect the right eye right_eye = right_eye_detector.detectMultiScale( right_face_gray, scaleFactor=1.1, minNeighbors=5, minSize=(30, 30), flags = cv2.CASCADE_SCALE_IMAGE )
        eye_status = '1' # we suppose the eyes are open
        # For each eye check wether the eye is closed. # If one is closed we conclude the eyes are closed for (ex,ey,ew,eh) in right_eye: color = (0,255,0) pred = predict(right_face[ey:ey+eh,ex:ex+ew],model) if pred == 'closed': eye_status='0' color = (0,0,255) cv2.rectangle(right_face,(ex,ey),(ex+ew,ey+eh),color,2) for (ex,ey,ew,eh) in left_eye: color = (0,255,0) pred = predict(left_face[ey:ey+eh,ex:ex+ew],model) if pred == 'closed': eye_status='0' color = (0,0,255) cv2.rectangle(left_face,(ex,ey),(ex+ew,ey+eh),color,2) eyes_detected[name] += eye_status
        # Each time, we check if the person has blinked # If yes, we display its name if isBlinking(eyes_detected[name],3): cv2.rectangle(frame, (x, y), (x+w, y+h), (0, 255, 0), 2) # Display name y = y - 15 if y - 15 > 15 else y + 15 cv2.putText(frame, name, (x, y), cv2.FONT_HERSHEY_SIMPLEX,0.75, (0, 255, 0), 2)
        return frame


        上面的功能是用于檢測(cè)和識(shí)別真實(shí)面部的代碼。它所需的輸入?yún)?shù):

        ? 型號(hào):睜眼/閉眼分類器

        ? video_capture:流視頻

        ? face_detector:Haar級(jí)聯(lián)的人臉?lè)诸惼?。我們選擇了haarcascade_frontalface_alt.xml

        ? open_eyes_detector:Haar級(jí)聯(lián)睜眼分類器。我選擇了haarcascade_eye_tree_eyeglasses.xml

        ? left_eye_detector:Haar級(jí)聯(lián)的左眼分類器。我選擇了haarcascade_lefteye_2splits.xml,它可以檢測(cè)睜眼或閉眼。

        ? right_eye_detector:Haar級(jí)聯(lián)的右眼分類器。我們選擇了haarcascade_righteye_2splits.xml,它可以檢測(cè)睜眼或閉眼。

        ? 數(shù)據(jù):已知編碼和已知名稱的字典

        ? eyes_detected:包含每個(gè)名稱的眼睛狀態(tài)歷史記錄的字典。

        第2至4行,我們從網(wǎng)絡(luò)攝像頭流中抓取一幀,然后調(diào)整其大小以加快計(jì)算速度。在第10?行,我們從幀中檢測(cè)人臉,然后在第21行,將其編碼為128-d向量。在第23-38行中,我們將此向量與已知的面部編碼進(jìn)行比較,然后通過(guò)計(jì)算匹配次數(shù)確定該人的姓名。匹配次數(shù)最多的一個(gè)被選中。從第45行開(kāi)始,我們?cè)谀槻糠秶鷥?nèi)檢測(cè)眼睛是否存在。首先,我們嘗試使用open_eye_detector檢測(cè)睜眼。如果檢測(cè)器成功,則在第54行,將?''1''添加到眼睛狀態(tài)歷史記錄。如果第一個(gè)分類器失敗了(可能是因?yàn)殚]眼或僅僅是因?yàn)樗蛔R(shí)別眼睛),這意味著open_eye_detector無(wú)法檢測(cè)到閉合的眼睛,則使用left_eyeright_eye檢測(cè)器。該面部分為左側(cè)和右側(cè),以便對(duì)各個(gè)檢測(cè)器進(jìn)行分類。從第92行開(kāi)始,提取眼睛部分,經(jīng)過(guò)訓(xùn)練的模型預(yù)測(cè)眼睛是否閉合。如果檢測(cè)到一只閉合的眼睛,則預(yù)測(cè)兩只眼睛都閉合,并且將''0''添加到眼睛狀態(tài)歷史記錄中。否則,可以得出結(jié)論,眼睛睜開(kāi)了。最后在第110行,isBlinking()功能用于檢測(cè)眨眼以及是否眨眼的人。

        參考資料

        ? https://docs.opencv.org/3.4.3/d7/d8b/tutorial_py_face_detection.html

        ? https://www.pyimagesearch.com/2018/06/18/face-recognition-with-opencv-python-and-deep-learning/


        流群


        歡迎加入公眾號(hào)讀者群一起和同行交流,目前有SLAM、三維視覺(jué)、傳感器、自動(dòng)駕駛、計(jì)算攝影、檢測(cè)、分割、識(shí)別、醫(yī)學(xué)影像、GAN、算法競(jìng)賽等微信群(以后會(huì)逐漸細(xì)分),請(qǐng)掃描下面微信號(hào)加群,備注:”昵稱+學(xué)校/公司+研究方向“,例如:”張三?+?上海交大?+?視覺(jué)SLAM“。請(qǐng)按照格式備注,否則不予通過(guò)。添加成功后會(huì)根據(jù)研究方向邀請(qǐng)進(jìn)入相關(guān)微信群。請(qǐng)勿在群內(nèi)發(fā)送廣告,否則會(huì)請(qǐng)出群,謝謝理解~


        瀏覽 27
        點(diǎn)贊
        評(píng)論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報(bào)
        評(píng)論
        圖片
        表情
        推薦
        點(diǎn)贊
        評(píng)論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報(bào)
        1. <strong id="7actg"></strong>
        2. <table id="7actg"></table>

        3. <address id="7actg"></address>
          <address id="7actg"></address>
          1. <object id="7actg"><tt id="7actg"></tt></object>
            色欲天天天无码视频 | 亚洲免费视频大全 | 91在线成人免费视频 | 男女做爱免费网站在线看 | 男女生羞羞视频网站在线观看 | 娇喘呻吟趴在雪白肉体耸动图 | 成人 免费视频A片视频 | 免费黄片网站视频 | 国产又黄又硬又湿又黄演员表 | 一级少妇高清性色生活片 |