dlib 人臉辨識

      在〈dlib 人臉辨識〉中尚無留言

早期 dlib 是常見的人臉辨識套件,但現今已停止維護,再加上新版 cmake 編譯出支援 GPU 的函數庫,所以不建議使用,本篇僅作記錄用。

dlib Windows系統

dlib 使用 C++ 編寫,應用在機器學習、影像處理以及影像辨識等功能。此套件為 Open Source 且 free ,license 基於 BSD 授權條款。安裝 dlib 套件時是下載原始檔,必需經過編譯才能使用。所以在 Windows 需安裝 cmake 及 Visual Studio 2022 c++桌面開發。

2024/09/01 實際測試,dlib 可以在 Python 3.12.6/Cuda 12.6 正常執行,而且在 Windows10 及 ubunt 24.04 皆沒問題。

CMake : https://cmake.org/download/

Cmake 只有 3.24 版本可以正確編譯,3.25/3.26/3.27皆無法編譯出 GPU 版本。請注意 CMake安裝完後 Pycharm 需退出重新執行。

Visual Studio 2019/2022 : 工具/取得工具與功能, 需安裝 使用 C++的桌面開發,注意一定要使用 VS2019 或 VS2022的版本。VS2020 好像無法編譯出 GPU的版本。

python_face_track1

Ubuntu

sudo apt-get install cmake python3-pip

安裝套件

dlib 自 19.21.0 版開始,不論在 Windows  或 Linux , 只要有安裝 Cuda/cudnn,直接使用如下指令即可編出支援 GPU 的 Dlib 版本。

pip install dlib --no-cache-dir

測試 GPU

測試是否支援 GPU 的代碼如下

import dlib
print(dlib.DLIB_USE_CUDA)
print(dlib.cuda.get_num_devices())
結果 :
True
1

上述結果如果為 True,表示能啟動 GPU 執行

如果 Cmake 或 VS 版本錯誤,卻又安裝了 dlib,則需先移除 Cmake 及 VS ,改裝正確版本。

然後重裝 dlib 時,又會使用 Python cache 安裝先前 dlib 錯誤版本。所以在 PyCharm 重新安裝 dlib 時,要執行如下指令

pip uninstall dlib
pip install dlib --no-cache-dir

Python程式碼

讀取圖片後丟給 dlib.get_frontal_face_detector 人臉偵測器(detector),即會傳回相關人臉的資訊。

detector 函數的第二個參數是指定反取樣 (unsample) 次數,預設值為 0。如果圖片太小,可將其設高一點以提高偵測精準度,當然也較耗時間。

圖檔解析度愈高當然愈精準,但更加耗時。若縮小圖片再偵測,速度較快但較不精準。此時就可以考慮提高反取樣參數。

detector 傳回的人臉資訊為 dlib.rectangle 資料結構, 如
[(256,61) (654,100)]
此結構分別是左上角座標及右下角座標, 可以用 left(), right() 等函數分別取出

import cv2
import dlib
import numpy as np
def resize(src, w=None, h=None, scale=1):
    if w is None or h is None:
        h, w = src.shape[:2]
        w = int(w * scale)
        h = int(h * scale)
    dst = cv2.resize(src, (w, h), interpolation=cv2.INTER_LINEAR)
    return dst
img=cv2.imdecode(np.fromfile('face4.jpg', dtype=np.uint8), cv2.IMREAD_COLOR)
img=resize(img, scale=0.2)
detector = dlib.get_frontal_face_detector()
faces=detector(img, 1)
for f in faces:
    x1=f.left()
    y1=f.top()
    x2=f.right()
    y2=f.bottom()
    img=cv2.rectangle(img, (x1, y1), (x2, y2), (0,255,0), 2, cv2.LINE_AA)
cv2.imshow("Image", img)
cv2.waitKey(0)
cv2.destroyAllWindows()

python_face_track

偵測分數

dlib 人臉偵測演算法使用方向梯度直方圖(HOG) 的特徵, 加上線性分類器(linear classifier)、影像金字塔(image pyramid) 與滑動窗格 (sliding window) 計算出來。演算的結果會有一個分數,此分數愈大,表示愈接近人臉。分數愈低表示愈接近誤判。調用 detector.run() 即可取得分數

faces, scores, indexs = detector.run(img, 1, 0.5)

上述第二個參數為反取樣次數,第三個參數為分數的門檻值,要超過 0.5 才會列出。至於返回值 indexs 為子偵測器的編號,用來判斷人臉的方向,詳細說明請看官網

完整代碼如下

import cv2
import dlib
def resize(src, w=None, h=None, scale=1):
    if w is None or h is None:
        h, w = src.shape[:2]
        w = int(w * scale)
        h = int(h * scale)
    dst = cv2.resize(src, (w, h), interpolation=cv2.INTER_LINEAR)
    return dst
img=cv2.imdecode(np.fromfile('face4.jpg', dtype=np.uint8), cv2.IMREAD_COLOR)
img=resize(img, scale=0.3)
detector = dlib.get_frontal_face_detector()
faces, scores, indexs=detector.run(img, 1, 0.5)
print(faces)
print(scores)
print(indexs)
for i, f in enumerate(faces):
    x1=f.left()
    y1=f.top()
    x2=f.right()
    y2=f.bottom()
    img=cv2.rectangle(img, (x1, y1), (x2, y2), (0,255,0), 2, cv2.LINE_AA)
    text = f"{indexs[i]}({scores[i]:2.2f})"
    cv2.putText(img, text, (x1, y1-5), cv2.FONT_HERSHEY_DUPLEX, 0.4, (0, 0, 255), 1,)
cv2.imshow("Image", img)
cv2.waitKey(0)
cv2.destroyAllWindows()

Web Came 人臉偵測 – GPU版

偵測人臉位置的偵測器,使用 dlib.cnn_face_detection_model_v1 卷積神經網路人臉偵測器,此偵測器需載入 mmod_human_face_detector.data 人臉訓練資料。下網址下載 :  mmod_human_face_detector.bz2 。下載完後請將 .bz2 檔解壓縮成 .dat 檔

cnn_face_detection_model_v1 比get_frontal_face_detector 更加的精準,且因使用 GPU 運算,就算偵測影片也非常順暢,感覺不到任何延遲,但如果沒有 GPU 的話就論當別論。

import cv2
import dlib
print(dlib.DLIB_USE_CUDA)
print(dlib.cuda.get_num_devices())
cam=cv2.VideoCapture(0)
cam.set(cv2.CAP_PROP_FRAME_WIDTH, 1920)
cam.set(cv2.CAP_PROP_FRAME_HEIGHT, 1080)
#cam.set(cv2.CAP_PROP_POS_MSEC, 900000)
#detector = dlib.get_frontal_face_detector()
detector=dlib.cnn_face_detection_model_v1('mmod_human_face_detector.dat')
while True:
    _,frame=cam.read()
    rate=4
    h, w, _=frame.shape
    x = cv2.resize(
        frame,
        (int(w/rate), int(h/rate)),
        interpolation=cv2.INTER_LINEAR
    )
    faces=detector(x, 1)
    for face in faces:
        f=face.rect
        x1=f.left()*rate
        y1=f.top()*rate
        x2=f.right()*rate
        y2=f.bottom()*rate
        cv2.rectangle(
            frame,
            (x1, y1),
            (x2, y2),
            (0,255,0), 2, cv2.LINE_AA)
    img=cv2.resize(
        frame,
        (1280,720),
        interpolation=cv2.INTER_LINEAR
    )
    cv2.imshow("Face",img)
    key=cv2.waitKey(1)
    if key==ord('q') or key==27:break;
cam.release()
cv2.destroyAllWindows()

安裝套件

pip install dlib opencv-python

辨識流程

1. 首先在FaceBase目錄下, 存放多張人臉照片, 每張照片只能有一個人, 且影像愈清晰愈好, 然後使用此人的名字當作檔名, 副檔名為jpg or png皆可
2. 在主目錄下, 存放其他不同的照片, 檔名可以隨便命名, 比如img1.jpg, img2.jpg
3. 執行python程式, 並輸入要判別的照片檔名, 比如python face.py img1.jpg. 此時就會到FaceBase目錄下把所有照片載入, 再跟img1.jpg裏的人物進行比對, 找到最符合的照片, 然後把圖片檔名標示在img1.jpg裏

訓練模型

人臉外型68個特徵訓練模型
shape_predictor_68_face_landmarks.dat.bz2

ResNet人臉辨識訓練模型,ResNet用於影像辨識深度學習,非常簡潔的網路框架
dlib_face_recognition_resnet_model_v1.dat.bz2

將上面二個下載解開後, 置於跟程式碼同一目錄即可. 這二個訓練模型都是由dlib免費提供的

線性代數

在一個二維的平面上,一條線的方程式為 ax+by=c (一階方程式)。所以在三維的立体空間中,一條線的方程式為 ax+by+cz=d。x, y, z代表三個維度的軸。

那麼在n維度的空間中,一條線的方程式為 $(a_{1}x_{1}+a_{2}x_{2}+a_{3}x_{3}+….=k)$

四維

空間明明就只有 x(左右),  y(前後),  z(上下)三個方向,也就是所謂的三度(Dimension)空間,每一維度都是公尺這個單位來計算。那為什麼還要多一個莫名奇妙的四維空間呢 ? 那第四維的單位是什麼?? 如果單位也是公尺的話,那三軸不就可以表示出來了嗎,為什麼還要多一個煩人的軸??

但很多不懂數學或不懂物理的人,發明了四度空間這個名詞。所以在這邊修正一下,空間就只有 x, y, z三度空間,沒有四度空間。

那麼四維又是什麼?? 請再注意一下,是四維,不是四度空間。

四維是只加入另一項條件,比如加入時間這個條件,如下圖,當在第1秒時,位置位於(1,1,1), 而在第二秒時,位置位於(1, 1, 2),那麼二者的距離單位就不是公尺,而是速度(m/s)。

圖例–todo

因此當人類跨入四維時,就能感受到~~移動的速度(好快喔,好恐怖。或者是好慢喔,真無聊。或者是明天早上9:00am 時要去那麼遠的地方上班,好焦慮)

todo

歐幾里得直線距離

歐幾里得距離就是二點之間的直線距離, 源自於歐幾里得空間計算演算法。

二維空間的歐氏距離公式

$(\rho =\sqrt{{(x_{2}-x_{1})}^{2}+(y_{2}-y_{1})^{2}})$ , ρ為點(x2, y2)與點(x1, y1)之間的歐幾里得距離

三維空間的歐幾里得距離公式

$(\rho =\sqrt{{(x_{2}-x_{1})}^{2}+(y_{2}-y_{1})^{2}+(z_{2}-z_{1})^{2}})$

n維空間的歐幾里得距離公式

$(\rho =\sqrt{{(x_{1}-y_{1})}^{2}+(x_{2}-y_{2})^{2}+…+(x_{n}-y_{n})^{2}} = \sqrt{\sum_{i=1}^{n}(x_{i}-y_{i})^{2}})$

np.linalg.norm

numpy 的 lin 即為線性的意思,alg即為代數,norm則是求得 n 維空間的歐幾里得距離,又稱為範數。比如在四維中,有一點的座標為 [1,1,1,1] ,另一點的座標為 [1,2,3,4],則二點的直線距離則為

$(\sqrt{(1-1)^{2}+(2-1)^{2}+(3-1)^{2}+(4-1)^{2})}=\sqrt{1+4+9}=\sqrt{14}=3.7416573867739413)$

這麼複雜的算式,可以用 np.linalg.norm()來計算

import numpy as np
a=np.array([1, 1, 1, 1])
b=np.array([1, 2, 3, 4])
c=np.linalg.norm(b-a)
print(c)
結果 : 
3.7416573867739413

人臉辨識原理

Dlib將人臉分成 68 種特徵。然後再使用這 68 種特徵計算產生 128 個數字(維度),稱為描述子(description)。其實描述子就是將每個人的臉量化的意思。

現在開始要辨識路人甲了,那麼就先計算路人甲這個人的描述子,再與資料庫目錄預先計算的描述子比對,計算這128維度之間的歐幾里得距離,然後取得最小距離的那一張,就判定為同一個人。所以啦,資料庫裏的資料量愈多,就會愈準確。相對的,資料庫就那麼幾個人,判斷出來的就是那幾個鬼囉。

描述子的取得很耗時,需先取得臉部位置,再由此位置取得68組特徵,最後由這68組特徵計算出128組描述子。

請注意,128組描述子並不是陣列格式,所以要使用 np.array(描述子) 將之轉成陣列格式,才可以使用 np.linalg.norm計算歐幾里得距離。

人臉特徵

人臉特徵可以由 dlib.shape_predictor(shape_pattern) 取得偵測器 detector_shape,再把影像及臉部矩型框傳入偵測器後,取得68個特徵點(shape)。

shape.num_parts 變數為特徵數,shape.part(0).x 為第0個特徵點的x座標。所以可以由底下的代碼,將每個特徵列出來。

import cv2
import numpy as np
import dlib
path_face_shape_pattern = "shape_predictor_68_face_landmarks.dat"
detector_face = dlib.get_frontal_face_detector()
detector_shape = dlib.shape_predictor(path_face_shape_pattern)
path_img='./photodb/劉亦菲.jpg'

img=cv2.imdecode(np.fromfile(path_img, dtype=np.uint8), cv2.IMREAD_COLOR)
faces = detector_face(img, 1)
for face in faces:
    shape = detector_shape(img, face)
    print(f'特徵數 : {shape.num_parts}')
    for i in range(shape.num_parts):
        x=shape.part(i).x
        y=shape.part(i).y
        cv2.circle(img, (x,y), 5, (0,0,255), -1)
cv2.imshow('shape', img)
cv2.waitKey(0)
cv2.destroyAllWindows()

描述子 – descriptor

描述子是將人臉量化、數位化的128組數字,為float32形態。

使用 dlib.face_recognition_model_v1傳入人臉辨識訓練模型,取得辨識偵測器 detector_recognition,然後將影像及特徵傳入偵測器,再用np.array()轉成陣列,即可取得這128組數字。

import cv2
import numpy as np
import dlib
path_face_shape_pattern = "shape_predictor_68_face_landmarks.dat"
path_face_recognition_pattern = "dlib_face_recognition_resnet_model_v1.dat"
detector_face = dlib.get_frontal_face_detector()
detector_shape = dlib.shape_predictor(path_face_shape_pattern)
detector_recognition= dlib.face_recognition_model_v1(path_face_recognition_pattern)
path_img='./photodb/劉亦菲.jpg'

img=cv2.imdecode(np.fromfile(path_img, dtype=np.uint8), cv2.IMREAD_COLOR)
faces = detector_face(img, 1)
for face in faces:
    shape = detector_shape(img, face)
    descriptor = detector_recognition.compute_face_descriptor(img, shape)
    print(np.asarray(descriptor))

結果 :
[-0.14054909 0.04426124 0.08866009 -0.0849032 -0.17231978 -0.03550968
-0.15141572 -0.16156833 0.12718649 -0.22248644 0.19372776 -0.10991256
-0.11338115 0.00483301 -0.10927599 0.26251966 -0.17240573 -0.15166888
-0.05355994 0.01177765 0.04092671 0.00246176 -0.02759925 0.05761251
-0.07394576 -0.30236602 -0.12749141 -0.00441253 -0.04730844 -0.10283802
-0.06325873 0.0747205 -0.18921919 0.0166836 0.00195603 0.11021935
0.01045647 -0.0985786 0.09239286 0.03786279 -0.27675414 0.10946561
0.07342842 0.18624522 0.19396684 -0.01562991 -0.0532582 -0.17993636
0.14952007 -0.19124591 0.0392213 0.10646417 0.06729751 0.02661212
0.05451194 -0.09769237 0.0426989 0.17178766 -0.13173173 0.0407474
0.1132625 -0.05298508 -0.010373 -0.15945846 0.16453081 0.22108312
-0.07539183 -0.24093667 0.11156385 -0.0860472 -0.09242575 0.07128195
-0.14813027 -0.18270497 -0.26679739 -0.01346047 0.381686 0.13438062
-0.18776414 0.02520162 0.00945836 -0.0469052 0.0667956 0.14827496
-0.00562041 -0.03608906 -0.03143981 0.01517139 0.22938004 -0.00084011
-0.00534477 0.21878409 -0.05320067 0.0191325 -0.03385412 -0.01841521
-0.11414495 0.03488658 -0.1423299 -0.09943943 -0.05250841 -0.01163368
-0.04529496 0.11440216 -0.13531663 0.14290756 -0.04970808 0.02698578
-0.01652338 0.0266864 -0.06138025 0.03710267 0.12207066 -0.16386668
0.2027695 0.11833911 0.11762075 0.07386067 0.1340881 0.09716622
-0.01273496 0.00316571 -0.18475032 0.00855643 0.10987271 -0.09012618
0.08601305 0.02782671]

人臉辨識專案完整程式碼

底下的代碼,先取得多張圖片的所有描述子(R)。再取得要測試圖片的描述子(A)。然後A與R的所有描述子計算歐幾里德距離,取得最小距離的那一組,就是相近的人臉。

請將已知姓名的照片,置於專案下 images 目錄,並將圖片名稱命名如下
許茹芸.jpg
許茹芸_1.jpg
許茹芸_2.jpg

#pip install opencv-python pillow matplotlib dlib --no-cache-dir
from MahalSdk.cv import cv
import os
import pylab as plt
import numpy as np
import dlib
def face_descriptor(img):
    faces = detector_face(img, 1)
    face=faces[0]
    return(
        np.asarray(
            detector_recognition.compute_face_descriptor(
                img,
                detector_shape(img, face)
            )
        )
    )
detector_face = dlib.get_frontal_face_detector()
detector_shape = dlib.shape_predictor(
    "shape_predictor_68_face_landmarks.dat"
)
detector_recognition= dlib.face_recognition_model_v1(
    "dlib_face_recognition_resnet_model_v1.dat"
)
path="./train"
descriptors=[]
names=[]
for file in os.listdir(path):
    names.append(file.split("_")[0])
    img=cv.read(os.path.join(path, file))
    descriptors.append(face_descriptor(img))
print(names)
img=cv.read("./test/劉浩存.jpg")
target=face_descriptor(img)
distance=[np.linalg.norm(d-target) for d in descriptors]
index=np.argmin(distance)
name=names[index]
img=cv.text(img, name,color=(0,255,0), size=50)
cv.imshow(img)
plt.show()

資料庫

前一篇的人臉辨識中,其步驟為 : 載入圖片 -> 取得臉部區域 -> 取得特微 -> 辨識取得描述子。光一張圖片就要經過4個步驟,耗費了好多秒。然後如果有1000張圖片呢,就再乘以1000倍。

每次要驗証一張新的臉孔,就要先耗費上述的幾千秒,然後再驗証,這乾脆把電腦丟掉好了。但如果把上述耗費幾千秒計算所得到的描述子存在資料庫,需要時由資料庫取回,不就是秒殺級的了嗎!!

請注意,目前 dlib 19.22.01版本,千萬不要使用dlib.cnn_face_detection_model_v1 來取得人臉偵測位置。因為圖片只要超過4000*3000=12,000,000相素,就算是 RTX 3080Ti 12G的 Ram,都會發生 out of memory的錯誤,而且誤判會更嚴重。

訓練模型

一樣要下載人臉外型68個特徵訓練模型 shape_predictor_68_face_landmarks.dat.bz2 及ResNet人臉辨識訓練模型 dlib_face_recognition_resnet_model_v1.dat.bz2 ,將上面二個下載解開後, 置於跟程式碼同一目錄。

資料表欄位

人臉辨識描述子是numpy的array格式,有128個 float32 數字,要如何存到資料庫中呢? 其實不論有多少個浮點數,在資料表中只要有三個欄位即可

id : int
姓名 : varchar(20)
描述子 : blob

blob是長文字資料形態。所以請先在MySQL中建立一個資料庫(cloud),再建立一個資料表(人臉辨識),然後建立上述三個欄位即可

numpy轉換

描述子是numpy的array格式,裏面的資料是 float32 形態,那又要怎麼存入資料庫的 blob 欄位呢? 此時需先使用 numpy.dumps()。請注意,因為資料格式為 blob,所以需使用 cursor.execute(cmd, args),這樣就不會去檢查字元碼而出現非unicode的錯誤。args必需為tuple,如下所示

npDescriptor = numpy.array(face_descriptor)
dump= npDescriptor.dumps()
cmd = "insert into face (name, descriptor) values (%s, %s)"
cursor.execute(cmd, (name, dump))

那怎麼由資料庫的blob還原成 numpy的array呢?  網路上大都是教你使用 np.loads(),但這方式已被捨棄了,所以正確的方式是要使用 pickle.loads()。請記得需先 import pickle, 如下所示

import pickle
feature=pickle.loads(row[1])

寫入資料庫

底下代碼,可以把photodb資料夾內的圖片,取得描述子數位化後,將描述子寫入資料庫。

注意 :  寫入資料庫的 name 欄位是抓取照片檔名而來,所以照片只能是單獨照,也就是只能有一張臉。

from MahalSdk.cv import cv
from MahalSdk.cloud import cloud
import os
import numpy as np
import dlib
def face_descriptor(img):
    faces = detector_face(img, 1)
    face=faces[0]
    return(
        np.asarray(
            detector_recognition.compute_face_descriptor(
                img,
                detector_shape(img, face)
            )
        )
    )
detector_face = dlib.get_frontal_face_detector()
detector_shape = dlib.shape_predictor(
    "shape_predictor_68_face_landmarks.dat"
)
detector_recognition= dlib.face_recognition_model_v1(
    "dlib_face_recognition_resnet_model_v1.dat"
)
conn=cloud.connect("cloud")
cursor=conn.cursor()
cursor.execute("truncate table 人臉辨識")
cmd="insert into 人臉辨識 (姓名, 描述子) values (%s, %s)"
path="./train"
for file in os.listdir(path):
    name=file.split("_")[0]
    img=cv.read(os.path.join(path, file))[:,:,::-1].copy()
    dump=face_descriptor(img).dumps()
    cursor.execute(cmd, (name, dump))
    conn.commit()
conn.close()

人臉辨識

上述的資料庫都寫好了,那麼就可以由下面的代碼來測試新圖片的辨識效能。請將要偵測的圖片置於專案目錄下的 ./test目錄

from MahalSdk.cv import cv
from MahalSdk.cloud import cloud
import os
import dlib
import numpy as np
import pylab as plt
import pickle

def face_descriptor(img):
    faces = detector_face(img, 1)
    face=faces[0]
    return(
        np.asarray(
            detector_recognition.compute_face_descriptor(
                img,
                detector_shape(img, face)
            )
        )
    )
detector_face = dlib.get_frontal_face_detector()
detector_shape = dlib.shape_predictor(
    "shape_predictor_68_face_landmarks.dat"
)
detector_recognition= dlib.face_recognition_model_v1(
    "dlib_face_recognition_resnet_model_v1.dat"
)
conn=cloud.connect("cloud")
cursor=conn.cursor()
cursor.execute('select * from 人臉辨識')
rows = cursor.fetchall()
names = [r[1] for r in rows]
descriptors = [pickle.loads(r[2]) for r in rows]
conn.close()

path="./test"
plt.rcParams['font.sans-serif'] = ['Microsoft JhengHei']
for i, file in enumerate(os.listdir(path)):
    img=cv.read(os.path.join(path, file))[:,:,::-1].copy()
    target=face_descriptor(img)
    distance=[np.linalg.norm(d-target) for d in descriptors]
    index=np.argmin(distance)
    if distance[index]<=0.45:
        name = names[index]
    else:
        name = "查無此人"
    ax=plt.subplot(3, 4, i+1)
    ax.set_title(name)
    ax.imshow(img[:,:,::-1].copy())
    ax.axis("off")
plt.show()

後話

理科太太(陳映彤) 與許茹芸長的實在太像,我真的分不出來,但上述的人臉辨識,可以輕易的辨識出來。
辛芷蕾現代及古裝照,完全是不同的二種人,但騙不過上面的人臉辨識,劉亦菲也是如此。

Web Cam 人臉辨識

底下代碼,可以使用 Web Cam 拍攝影像並辨識人臉,亦可播放 .mp4 影片。

train 目錄下的照片請從如下網址下扯 : train.zip

import pickle

import cv2
import dlib
import numpy as np
from MahalSdk.cv import cv
from MahalSdk.cloud import cloud
def face_descriptor(img, face, detector_shape, detector_recognition):
    return (
        np.asarray(
            detector_recognition.compute_face_descriptor(
                img,
                detector_shape(img, face)
            )
        )
    )

#detector_face = dlib.get_frontal_face_detector()
detector_face = dlib.cnn_face_detection_model_v1(
    'mmod_human_face_detector.dat'
)
detector_shape = dlib.shape_predictor(
    "shape_predictor_68_face_landmarks.dat"
)
detector_recognition= dlib.face_recognition_model_v1(
    "dlib_face_recognition_resnet_model_v1.dat"
)
conn=cloud.connect("cloud")
cursor=conn.cursor()
cursor.execute("select * from 人臉辨識")
rs=cursor.fetchall()
names=[r[1] for r in rs]
descriptors=[pickle.loads(r[2]) for r in rs]
cam=cv2.VideoCapture("c.mp4")
#cam.set(cv2.CAP_PROP_POS_MSEC, 930000)#a.mp4
#cam.set(cv2.CAP_PROP_POS_MSEC, 30000)#a.mp4
#cam.set(cv2.CAP_PROP_POS_MSEC, 120_000)#b.mp4
cam.set(cv2.CAP_PROP_POS_MSEC, 200_000)#c.mp4
while True:
    success, img1=cam.read()
    if success:
        h1, w1, _=img1.shape
        img2=cv.resize(img1, width=800)
        h2, w2, _ = img2.shape
        rate=w1/w2
        faces=detector_face(img2, 1)
        for f in faces:
            f=f.rect
            x1=int(f.left()*rate);y1=int(f.top()*rate)
            x2=int(f.right()*rate);y2=int(f.bottom()*rate)
            img1=cv.rectangle(img1, (x1, y1), (x2, y2), color=(0,255,0))
            target=face_descriptor(img2, f, detector_shape, detector_recognition)
            distance=[np.linalg.norm(d-target) for d in descriptors]
            index=np.argmin(distance)
            if distance[index]<=0.40:
                name=names[index]
                img1 = cv.text(img1, names[index], xy=(x1, y1-50), color=(0, 0, 255), size=50)
        cv2.imshow("Video", img1)
        if cv2.waitKey(1)==27:break
    else:
        break
cam.release()

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *