主頁 > 後端開發 > 分分鐘自制人臉識別(如何快速識別心儀的小姐姐~)

分分鐘自制人臉識別(如何快速識別心儀的小姐姐~)

2021-10-12 07:18:03 後端開發

文章目錄

  • 環境
  • 使用的函式介面
  • 流程
  • 人臉檢測部分
    • 圖片讀取/尺寸修改
    • 圖片矩形標注
    • 人臉檢測
    • 讀取視頻標注人臉
  • 人臉識別
    • 人臉資訊錄入
    • 資料訓練
    • 人臉識別

通過最近的學習感觸頗多,大資料,人工智能,分布式,云計算,基于云的云安全,萬物互聯真的是未來大方向!所謂的web開發,服務器后端其實只是一個開始,玩了python 后端也在體驗spring全家桶(學習ing)只要做一個像樣的“萬人會話”基本上都不會只是靠那一套“增刪改查”能夠實作的,都會涉及到并發,并行,但是想要做好又涉及到分布式,微服架構等等,此外還有更多的服務細節,例如如何實時分析用戶喜好從而推送對應內容等等,這些與大資料聯系密切,與分布式計算聯系緊密,當然也從這里我意識到python 并不適合,且不論性能,單從這里就可以看到在這一方面python的方案并不如Java,盡管它也有所選擇,不過好在的是python憑借著豐富的類別庫,在機器學習,人工智能這塊使用起來的簡便性讓它魅力依舊,當然這里且不論底層,
當然這里并不是說我那些玩意不玩了,這是不可能的,畢竟還有個web專案沒寫完( White Hole),而且還得用Springboot 重構,

環境

1.python 3.7
2.opencv

pip3 install opencv-python
pip3 install opencv-contrib-python

這個的話目前其實還是簡單的介面呼叫,

使用的函式介面

鐵打的API,流水的程式員呀!

import cv2.cv2 as cv
cv.imread() #讀取圖片
cv.cvtColot() #圖片顏色處理(灰度處理)
cv.imwrite() #保存圖片
cv.imshow()  #展示圖片
cv.waitKey() #視窗展示(其實是等待鍵盤輸入,IO阻塞)停留傳入時間毫秒,回傳鍵盤按下的鍵位的ascll值
cv.resize() #修改圖片大小
cv.rectangle() #繪制矩形
cv.circle() #繪制圓形
cv.CascadeClassifier()#使用訓練模型
cv.VideoCapture() #讀取視頻0表示讀取攝像頭
face.LBPHFaceRecognizer_create() #資料訓練
cv.destoryAllWindows() #釋放記憶體

流程

這里的話主要分為兩個大步走

1.讀取圖片/視頻內的人臉資訊,識別人臉位置(框出人臉位置)
2.將識別出的人臉進行比對(特征提取)

人臉檢測部分

圖片讀取/尺寸修改

import cv2.cv2 as cv

Image = cv.imread("Image/face1.jpg")
cv.imshow("Image",Image)
Image_resize = cv.resize(Image,dsize=(200,200))
cv.imshow("ResizeImage",Image_resize)
cv.waitKey(0)
cv.destroyAllWindows()

圖片矩形標注

import cv2.cv2 as cv
img = cv.imread('Image/face1.jpg')
x,y,w,h = 100,100,100,100 #起始坐標
#繪制矩形
cv.rectangle(img,(x,y,x+w,y+h),color=(0,0,255),thickness=1) # 方框顏色,粗細
#繪制圓形
cv.circle(img,center=(x+w,y+h),radius=100,color=(255,0,0),thickness=5)
#顯示
cv.imshow('re_img',img)
cv.waitKey(0)
cv.destroyAllWindows()

人臉檢測

#匯入cv模塊
import cv2.cv2 as cv
import cv2.data as data

#讀取影像
img = cv.imread('Image/face1.jpg')
gary = cv.cvtColor(img,cv.COLOR_BGR2GRAY)
face_detect = cv.CascadeClassifier(data.haarcascades+"haarcascade_frontalface_alt2.xml")
face = face_detect.detectMultiScale(gary)
for x,y,w,h in face:
    cv.rectangle(img,(x,y),(x+w,y+h),color=(0,0,255),thickness=2)
cv.imshow('result',img)

cv.waitKey(0)
#釋放記憶體
cv.destroyAllWindows()

函式說明

gary = cv.cvtColor(img,cv.COLOR_BGR2GRAY) 二值化處理圖片

face_detect = cv.CascadeClassifier(data.haarcascades+“haarcascade_frontalface_alt2.xml”)
這個是加載使用人家訓練好的提取頭像的模型幫助我們提取出圖片的人臉,此外還有還有提取人眼的,等等,

face = face_detect.detectMultiScale(gary)按照模型提取出人臉的大小位置,回傳一個元組

重點

face = face_detect.detectMultiScale(gary,1.01,5,0,(100,100),(300,300))
還可以這樣用,1.01表示圖片縮放倍數
5對比次數,意思是對比了五次還是一樣的話就認為是人臉
0默認引數不用管,加上
(100100) (300300) 表示人臉的范圍,這個可以設定
這些引數都可以不設定,直接使用默認的
face_detect = cv.CascadeClassifier(data.haarcascades+"haarcascade_frontalface_alt2.xml")
這里加載的模型其實是在虛擬環境下的site-pakges里面找到的

在這里插入圖片描述
此外如果你安裝了opencv的話那么你也可以在opencv的安裝目錄找到,到時候你要用哪個就搞哪個.
例如我安裝在D盤

face_detect = cv.CascadeClassifier('D:/opencv/opencv/sources/data/haarcascades/haarcascade_frontalface_alt2.xml')

我直接填寫路徑
這邊推薦直接使用默認的,

 face_detect = 
 cv.CascadeClassifier(data.haarcascades+"haarcascade_frontalface_default.x")

讀取視頻標注人臉

cap = cv.VideoCapture(0) 讀取攝像頭
#匯入cv模塊
import cv2.cv2 as cv
import cv2.data as data
import time
#檢測函式
def face_detect_demo(img):
    gary = cv.cvtColor(img,cv.COLOR_BGR2GRAY)
    face_detect = cv.CascadeClassifier(data.haarcascades+"haarcascade_frontalface_default.xml")
    face = face_detect.detectMultiScale(gary)
    for x,y,w,h in face:
        cv.rectangle(img,(x,y),(x+w,y+h),color=(0,0,255),thickness=2)
    cv.imshow('result',img)
    

cap = cv.VideoCapture(0)
while True:
    flag, img = cap.read()
    if not flag:
        break
    face_detect_demo(img)
    if ord('q') == cv.waitKey(1):
        break
cap.release() #釋放視像頭記憶體
#釋放記憶體
cv.destroyAllWindows()

當前是讀取攝像頭的視頻資訊,如果直接填入路徑的話那么就會讀取到視頻的內容進行人臉標注

人臉識別

到目前為止已經可以把人臉從視頻或者圖片當中摳下來了(其實當當前步驟已經可以實作前些日子比較火熱的AI外掛了,不過目前使用的識別模型不咋滴,如果要用得專門訓練一下,然后結合外設驅動,我們這邊回傳獲取的人頭的坐標,更具游戲特色我們還得計算一下槍械的后座偏移量然后驅動游標瞄準射擊,外掛的原理其實也類似,只是人家的坐標是直接在記憶體里面抓到的,不是我們這樣還要通過人臉識別)

人臉資訊錄入

搞人臉識別那必然還是要錄入人臉資訊的,這里由兩個方案,一個是直接準備好圖片(就是需要錄入的人臉的照片)或者通過攝像頭錄入,由于我們識別的時候要調取攝像頭所以建議從攝像頭里面開始錄入,第一個方案準備照片就好了,第二個方案看下面代碼即可:

import cv2.cv2 as cv2
import os
import threading

name = None
save_flag = False
lock = threading.Lock()
def input_name():
    global name,save_flag
    while 1:
        if name =="Q" or name=="q":
            return
        else:
            name=input("\n:")
            save_flag = True


def Get_Face():
    global name,save_flag
    cap = cv2.VideoCapture(0)
    num = 1

    Path_save = r"Image/InPutImg/"
    if not os.path.exists(Path_save):
        os.makedirs(Path_save)

    while(1):
        ret_flag,VImg = cap.read()
        cv2.imshow("Capture_Test",VImg)
        cv2.waitKey(1)
        lock.acquire()
        if name:
            if name == "Q" or name == "q":
                lock.release()
                return
            if save_flag:
                cv2.imwrite(Path_save+str(num)+"."+name+".jpg",VImg)
                print("\n圖片已保存:"+str(num)+"."+name+".jpg")
                num += 1
            save_flag = False

        lock.release()
    cap.release()
    cv2.destroyAllWindows()

if __name__=="__main__":
    t1 = threading.Thread(target=Get_Face)
    t2 = threading.Thread(target=input_name)
    t1.start()
    t2.start()


這里為了控制輸入額外開了個執行緒,不過顯示沒法做到同步,做了就堵死了~
之后在專案的檔案夾下會多出一個檔案

在這里插入圖片描述
里面保存了在攝像頭拍攝的人臉,

資料訓練

這個重復先前的步驟
把獲取的圖片提取出人臉,然后把對應的人臉和人物的id進行訓練

import os
import cv2.cv2 as cv
import numpy as np
import cv2.data as data
def getImageIds(path):
    #函式作用是提取人臉然后回傳人物的人臉和id
    faceseare=[] # 保存檢測出的人臉
    ids=[] #
    imagePaths=[os.path.join(path,f) for f in os.listdir(path)]
    #人臉檢測
    face_detector = cv.CascadeClassifier(data.haarcascades+"haarcascade_frontalface_default.xml")
    if imagePaths:
        print('訓練圖片為:',imagePaths)
    else:
        print("請先錄入人臉")
        return

    for imagePath in imagePaths:
        #二值化處理
        img = cv.imread(imagePath)
        img=cv.cvtColor(img,cv.COLOR_BGR2GRAY)
        img_numpy=np.array(img,'uint8')#獲取圖片矩陣

        faces = face_detector.detectMultiScale(img_numpy)

        id = int(os.path.split(imagePath)[1].split('.')[0])

        for x,y,w,h in faces:
            ids.append(id)
            faceseare.append(img_numpy[y:y+h,x:x+w])
        print('已獲取id:', id)

    return faceseare,ids

if __name__ == '__main__':
    #圖片路徑
    path='Image/InPutImg'
    #獲取影像陣列和id標簽陣列和姓名
    faces,ids=getImageIds(path)
    #獲取訓練物件
    recognizer=cv.face.LBPHFaceRecognizer_create()
    recognizer.train(faces,np.array(ids)) #把對應的人臉和id聯系起來訓練
    #保存訓練檔案
    model_save = "trainer/"
    if not os.path.exists(model_save):
        os.makedirs(model_save)
    recognizer.write('trainer/trainer.yml')

人臉識別

這個就是最后一步了,主要其實就是通過評分進行識別

import cv2.cv2 as cv
import os
import cv2.data as data

recogizer=cv.face.LBPHFaceRecognizer_create()#加載訓練資料集檔案
recogizer.read('trainer/trainer.yml')
names=[]
warningtime = 0

#準備識別的圖片
def face_detect_demo(img):
    global warningtime
    gray=cv.cvtColor(img,cv.COLOR_BGR2GRAY)
    face_detector=cv.CascadeClassifier(data.haarcascades+"haarcascade_frontalface_default.xm")
    face=face_detector.detectMultiScale(gray)
    for x,y,w,h in face:
        cv.rectangle(img,(x,y),(x+w,y+h),color=(0,0,255),thickness=2)
        cv.circle(img,center=(x+w//2,y+h//2),radius=w//2,color=(0,255,0),thickness=1)

        # 人臉識別
        ids, confidence = recogizer.predict(gray[y:y + h, x:x + w])

        if confidence > 80: #評分越大可信度越低
            warningtime += 1
            if warningtime > 100:
               warningtime = 0
               print("未識別出此人") #這塊的話其實可以再搞一套對應的懲罰機制
            cv.putText(img, 'unkonw', (x + 10, y - 10), cv.FONT_HERSHEY_SIMPLEX, 0.75, (0, 255, 0), 1)
        else:
        #這里也對應一套識別后的機制
            cv.putText(img,str(names[ids-1]), (x + 10, y - 10), cv.FONT_HERSHEY_SIMPLEX, 0.75, (0, 255, 0), 1)
    cv.imshow('result',img)


def get_name(names):
    path = 'Image/InPutImg/'

    imagePaths=[os.path.join(path,f) for f in os.listdir(path)]
    for imagePath in imagePaths:
       name = str(os.path.split(imagePath)[1].split('.',2)[1])
       names.append(name)


cap=cv.VideoCapture(0)
get_name(names)
while True:
    flag,frame=cap.read()
    if not flag:
        break
    face_detect_demo(frame)
    if ord(' ') == cv.waitKey(10): #按下空格關了
        break
cap.release()
cv.destroyAllWindows()


下面是演示,
1.已錄入圖片
在這里插入圖片描述

1.lena.jpg

效果:
在這里插入圖片描述
到這里一個最基本的識別就做好了,那么關于這里面的懲罰機制或者通過識別后的機制其實,如果可以結合樹莓派的話是可以自己做一個寢室專用的門禁系統的,

轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/309524.html

標籤:python

上一篇:誰說“程式員離開電腦就是廢物?我身邊這位大兄弟表示不服!真事

下一篇:實戰!《長津湖》為什么這么火爆?我用 Python 來分析貓眼影評

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • 【C++】Microsoft C++、C 和匯編程式檔案

    ......

    uj5u.com 2020-09-10 00:57:23 more
  • 例外宣告

    相比于斷言適用于排除邏輯上不可能存在的狀態,例外通常是用于邏輯上可能發生的錯誤。 例外宣告 Item 1:當函式不可能拋出例外或不能接受拋出例外時,使用noexcept 理由 如果不打算拋出例外的話,程式就會認為無法處理這種錯誤,并且應當盡早終止,如此可以有效地阻止例外的傳播與擴散。 示例 //不可 ......

    uj5u.com 2020-09-10 00:57:27 more
  • Codeforces 1400E Clear the Multiset(貪心 + 分治)

    鏈接:https://codeforces.com/problemset/problem/1400/E 來源:Codeforces 思路:給你一個陣列,現在你可以進行兩種操作,操作1:將一段沒有 0 的區間進行減一的操作,操作2:將 i 位置上的元素歸零。最終問:將這個陣列的全部元素歸零后操作的最少 ......

    uj5u.com 2020-09-10 00:57:30 more
  • UVA11610 【Reverse Prime】

    本人看到此題沒有翻譯,就附帶了一個自己的翻譯版本 思考 這一題,它的第一個要求是找出所有 $7$ 位反向質數及其質因數的個數。 我們應該需要質數篩篩選1~$10^{7}$的所有數,這里就不慢慢介紹了。但是,重讀題,我們突然發現反向質數都是 $7$ 位,而將它反過來后的數字卻是 $6$ 位數,這就說明 ......

    uj5u.com 2020-09-10 00:57:36 more
  • 統計區間素數數量

    1 #pragma GCC optimize(2) 2 #include <bits/stdc++.h> 3 using namespace std; 4 bool isprime[1000000010]; 5 vector<int> prime; 6 inline int getlist(int ......

    uj5u.com 2020-09-10 00:57:47 more
  • C/C++編程筆記:C++中的 const 變數詳解,教你正確認識const用法

    1、C中的const 1、區域const變數存放在堆疊區中,會分配記憶體(也就是說可以通過地址間接修改變數的值)。測驗代碼如下: 運行結果: 2、全域const變數存放在只讀資料段(不能通過地址修改,會發生寫入錯誤), 默認為外部聯編,可以給其他源檔案使用(需要用extern關鍵字修飾) 運行結果: ......

    uj5u.com 2020-09-10 00:58:04 more
  • 【C++犯錯記錄】VS2019 MFC添加資源不懂如何修改資源宏ID

    1. 首先在資源視圖中,添加資源 2. 點擊新添加的資源,復制自動生成的ID 3. 在解決方案資源管理器中找到Resource.h檔案,編輯,使用整個專案搜索和替換的方式快速替換 宏宣告 4. Ctrl+Shift+F 全域搜索,點擊查找全部,然后逐個替換 5. 為什么使用搜索替換而不使用屬性視窗直 ......

    uj5u.com 2020-09-10 00:59:11 more
  • 【C++犯錯記錄】VS2019 MFC不懂的批量添加資源

    1. 打開資源頭檔案Resource.h,在其中預先定義好宏 ID(不清楚其實ID值應該設定多少,可以先新建一個相同的資源項,再在這個資源的ID值的基礎上遞增即可) 2. 在資源視圖中選中專案資源,按F7編輯資源檔案,按 ID 型別 相對路徑的形式添加 資源。(別忘了先把檔案拷貝到專案中的res檔案 ......

    uj5u.com 2020-09-10 01:00:19 more
  • C/C++編程筆記:關于C++的參考型別,專供新手入門使用

    今天要講的是C++中我最喜歡的一個用法——參考,也叫別名。 參考就是給一個變數名取一個變數名,方便我們間接地使用這個變數。我們可以給一個變數創建N個參考,這N + 1個變數共享了同一塊記憶體區域。(參考型別的變數會占用記憶體空間,占用的記憶體空間的大小和指標型別的大小是相同的。雖然參考是一個物件的別名,但 ......

    uj5u.com 2020-09-10 01:00:22 more
  • 【C/C++編程筆記】從頭開始學習C ++:初學者完整指南

    眾所周知,C ++的學習曲線陡峭,但是花時間學習這種語言將為您的職業帶來奇跡,并使您與其他開發人員區分開。您會更輕松地學習新語言,形成真正的解決問題的技能,并在編程的基礎上打下堅實的基礎。 C ++將幫助您養成良好的編程習慣(即清晰一致的編碼風格,在撰寫代碼時注釋代碼,并限制類內部的可見性),并且由 ......

    uj5u.com 2020-09-10 01:00:41 more
最新发布
  • Rust中的智能指標:Box<T> Rc<T> Arc<T> Cell<T> RefCell<T> Weak

    Rust中的智能指標是什么 智能指標(smart pointers)是一類資料結構,是擁有資料所有權和額外功能的指標。是指標的進一步發展 指標(pointer)是一個包含記憶體地址的變數的通用概念。這個地址參考,或 ” 指向”(points at)一些其 他資料 。參考以 & 符號為標志并借用了他們所 ......

    uj5u.com 2023-04-20 07:24:10 more
  • Java的值傳遞和參考傳遞

    值傳遞不會改變本身,參考傳遞(如果傳遞的值需要實體化到堆里)如果發生修改了會改變本身。 1.基本資料型別都是值傳遞 package com.example.basic; public class Test { public static void main(String[] args) { int ......

    uj5u.com 2023-04-20 07:24:04 more
  • [2]SpinalHDL教程——Scala簡單入門

    第一個 Scala 程式 shell里面輸入 $ scala scala> 1 + 1 res0: Int = 2 scala> println("Hello World!") Hello World! 檔案形式 object HelloWorld { /* 這是我的第一個 Scala 程式 * 以 ......

    uj5u.com 2023-04-20 07:23:58 more
  • 理解函式指標和回呼函式

    理解 函式指標 指向函式的指標。比如: 理解函式指標的偽代碼 void (*p)(int type, char *data); // 定義一個函式指標p void func(int type, char *data); // 宣告一個函式func p = func; // 將指標p指向函式func ......

    uj5u.com 2023-04-20 07:23:52 more
  • Django筆記二十五之資料庫函式之日期函式

    本文首發于公眾號:Hunter后端 原文鏈接:Django筆記二十五之資料庫函式之日期函式 日期函式主要介紹兩個大類,Extract() 和 Trunc() Extract() 函式作用是提取日期,比如我們可以提取一個日期欄位的年份,月份,日等資料 Trunc() 的作用則是截取,比如 2022-0 ......

    uj5u.com 2023-04-20 07:23:45 more
  • 一天吃透JVM面試八股文

    什么是JVM? JVM,全稱Java Virtual Machine(Java虛擬機),是通過在實際的計算機上仿真模擬各種計算機功能來實作的。由一套位元組碼指令集、一組暫存器、一個堆疊、一個垃圾回收堆和一個存盤方法域等組成。JVM屏蔽了與作業系統平臺相關的資訊,使得Java程式只需要生成在Java虛擬機 ......

    uj5u.com 2023-04-20 07:23:31 more
  • 使用Java接入小程式訂閱訊息!

    更新完微信服務號的模板訊息之后,我又趕緊把微信小程式的訂閱訊息給實作了!之前我一直以為微信小程式也是要企業才能申請,沒想到小程式個人就能申請。 訊息推送平臺🔥推送下發【郵件】【短信】【微信服務號】【微信小程式】【企業微信】【釘釘】等訊息型別。 https://gitee.com/zhongfuch ......

    uj5u.com 2023-04-20 07:22:59 more
  • java -- 緩沖流、轉換流、序列化流

    緩沖流 緩沖流, 也叫高效流, 按照資料型別分類: 位元組緩沖流:BufferedInputStream,BufferedOutputStream 字符緩沖流:BufferedReader,BufferedWriter 緩沖流的基本原理,是在創建流物件時,會創建一個內置的默認大小的緩沖區陣列,通過緩沖 ......

    uj5u.com 2023-04-20 07:22:49 more
  • Java-SpringBoot-Range請求頭設定實作視頻分段傳輸

    老實說,人太懶了,現在基本都不喜歡寫筆記了,但是網上有關Range請求頭的文章都太水了 下面是抄的一段StackOverflow的代碼...自己大修改過的,寫的注釋挺全的,應該直接看得懂,就不解釋了 寫的不好...只是希望能給視頻網站開發的新手一點點幫助吧. 業務場景:視頻分段傳輸、視頻多段傳輸(理 ......

    uj5u.com 2023-04-20 07:22:42 more
  • Windows 10開發教程_編程入門自學教程_菜鳥教程-免費教程分享

    教程簡介 Windows 10開發入門教程 - 從簡單的步驟了解Windows 10開發,從基本到高級概念,包括簡介,UWP,第一個應用程式,商店,XAML控制元件,資料系結,XAML性能,自適應設計,自適應UI,自適應代碼,檔案管理,SQLite資料庫,應用程式到應用程式通信,應用程式本地化,應用程式 ......

    uj5u.com 2023-04-20 07:22:35 more