人臉定位程式及結果

search7發表於2017-07-31


人臉定位理論方法,參考馮偉興的Visual C++ 數字影像模式識別典型案例詳解

整個程式用python 寫成。因為初涉python和opencv ,不足之處,請看客多多提出,共同交流。

人臉定位建立在膚色相似度檢測的基礎上,將檢測後的圖片,進行二值化處理,閾值設定為整幅圖片的灰度均值,高於均值的設為255,相反則設為0.

人臉定位的關鍵在於找出人臉輪廓的邊界。因為二值化後的人臉圖片為白,因此利用水平和豎直投影計數的方法,閾值設為每行和每列的投影計數最大值的50%。這個閾值根據識別的人臉不同,需要有靈活的調整。

左右上用投影計數,為避免下部脖子影響定位,以1.2乘以臉寬,作為臉長。

用opencv的cv2.line(img1,(left,0),(left,h),(0,255,0),2) 和 cv2.rectangle(img2,(img_left,img_top),(img_right,img_bottom),(0,200,200),1,1,0) 函式確定邊界,並實現矩形輪廓定位。


# -*- coding: utf-8 -*-
# the location and split

import cv2
import numpy as np

img = cv2.imread("image/grayface.jpg")
img2 = cv2.imread("image/t4.jpg")
h = img.shape[0]      #影像高寬
w = img.shape[1]
print(h)
print(w)


sum = 0         
midle = 0
print(img[34,67])
for i in range(h):
    for j in range(w):
        sum += img[i,j][1]   


midle = sum/(h*w)     #影像的灰度均值
print(midle)



for i in range(h):      #二值化
    for j in range(w):
        if img[i,j][1] > midle:
            img[i,j] = 255
        else:
            img[i,j] = 0

cv2.imshow('split',img)                
cv2.imwrite('image/split.jpg',img)


lwrite = np.zeros(h,np.int)
hwrite = lwrite
max = 0
print(img[34,67])
print(lwrite[34])
for j in range(w):      #統計每列中白色畫素點個數
    for i in range(h):
        if img[i,j][1] == 255:
            lwrite[j] +=1
    if lwrite[j] > max:
        max = lwrite[j]
print(max)
img1 = img.copy()
#畫出臉左側輪廓線
for left in range(w):
    if lwrite[left + 1] > max/2:
        #cv2.line(img1,(left,0),(left,h),(0,255,0),2)
        img_left = left
        break

#畫出臉右側輪廓線    
for right in range(w-1,0,-1):
    if lwrite[right - 1] > max/2:
        #cv2.line(img1,(right,0),(right,h),(0,255,0),2)
        img_right = right
        break

ww = img_right - img_left
print(ww)

for i in range(h):      #統計每行中白色畫素點個數
    for j in range(w):
        if img[i,j][1] == 255:
            hwrite[i] +=1
    if lwrite[i] > max:
        max = hwrite[i]
        

#畫出臉上側輪廓線
for top in range(h):
    if hwrite[top + 1] > max/3:
       # cv2.line(img1,(0,top),(w,top),(0,255,0),2)
        img_top = top
        break
    
#畫出臉下側輪廓
img_bottom = int(1.3*ww + img_top)
print(img_bottom)
#cv2.line(img1,(0,img_bottom),(w,img_bottom),(0,255,0),2)

#在二值化圖上畫出臉輪廓
cv2.rectangle(img1,(img_left,img_top),(img_right,img_bottom),(0,0,255),1,1,0)

cv2.imshow('img1',img1)
cv2.imwrite('image/location1.jpg',img1)

#在原圖上畫出臉輪廓

cv2.rectangle(img2,(img_left,img_top),(img_right,img_bottom),(0,200,200),1,1,0)
cv2.imwrite('image/location2.jpg',img2)

    





定位結果:






為什麼每階段選擇的是穎寶不同的照片?

因為儲存了很多穎寶的圖片作為實驗用,雖然不是粉絲,但是做實驗用看著不會心煩,比較可愛。用此圖片,不用上一張,是因為上一張的定位效果並不能很好用在此圖片上。導致臉圈的太長。

別的穎寶的臉在定位的時候,甚至與出現定位到飾品上,因為裸露胳膊、以及木色背景,導致整張圖片定位到整幅圖片,出現定位失敗。


相關文章