一個實(shí)時的人臉檢測系統(tǒng)——Part2

上一章節(jié)我們得到了一張人臉五個關(guān)鍵點(diǎn)——左眼中心蠢熄,右眼中心逗噩,鼻子尖端,左嘴中心吓肋,右嘴中心凳怨。
這一章節(jié)用python來實(shí)現(xiàn)下人臉的重構(gòu)工作。
我們先定義一個二維數(shù)組 landmark是鬼,它的五個元素分別是:
左眼(landmark[0][0], landmark[0][1])
右眼(landmark[1][0], landmark[0][1])
鼻子(landmark[2][0], landmark[2][1])
左嘴(landmark[3][0], landmark[3][1])
右嘴(landmark[4][0], landmark[4][1])
再定義兩個函數(shù):

def imrotate(img, angle):
imgh = img.shape[0]
imgw = img.shape[1]
center = (imgw/2.0, imgh/2.0)
rot = cv2.getRotationMatrix2D(center, angle, 1.0)
newh = imgh*math.cos(angle/180.0*math.pi) + imgw*abs(math.sin(angle/180.0*math.pi))
neww = imgw*math.cos(angle/180.0*math.pi) + imgh*abs(math.sin(angle/180.0*math.pi))
rot[0][2] += (neww/2.0 - center[0])
rot[1][2] += (newh/2.0 - center[1])
img_rot = cv2.warpAffine(img, rot, ((int)(neww),(int)(newh)))
return img_rot

rot = cv2.getRotationMatrix2D(center, angle, 1.0)的作用是取得圖像繞圖像的中心逆時針旋轉(zhuǎn)angle角度并且縮放比列為1.0時的旋轉(zhuǎn)矩陣猿棉。至于什么是旋轉(zhuǎn)矩陣大家可以看看www.myexception.cn/image/1958561.html
得到的旋轉(zhuǎn)矩陣rot是一個2*3的矩陣磅叛。newh 和 neww表示的是旋轉(zhuǎn)后新生成的圖片的高和寬。
rot[0][2] += (neww/2.0 - center[0])
rot[1][2] += (newh/2.0 - center[1])
這是一個平移的過程萨赁,所以整個過程將會是圖像先繞著中心旋轉(zhuǎn)angle角弊琴,然后我們通過計算得到新圖像的高和寬。為了使原來的圖像的中心和原圖像的中心重合杖爽,我們又做了一次平移的操作敲董。

def transform(x, y,angle, src_shape, dst_shape):
x0 = x - src_shape[1]/2.0
y0 = y - src_shape[0]/2.0
xx = x0*math.cos(angle) - y0*math.sin(angle) + dst_shape[1]/2.0
xx = round(xx)
yy = x0*math.sin(angle) + y0*math.cos(angle) + dst_shape[0]/2.0
yy = round(yy)
return (xx, yy)

transform的操作其實(shí)和imrotate中的圖片中心的變化過程是一樣的。transform是使用getRotationMatrix2D得到了旋轉(zhuǎn)矩陣再平移慰安,imrotate則是自己構(gòu)建了整個過程腋寨。
輸入(x,y)為原始的輸入點(diǎn),(xx,yy)為旋轉(zhuǎn)后的點(diǎn)化焕。
有了這兩個函數(shù)萄窜,我們就可以進(jìn)行重構(gòu)了。

#獲取左眼和右眼的正切值ang_tan和夾角angle
ang_tan = (landmark[0][1]-landmark[1][1])/(landmark[0][0]-landmark[1][0])
angle = math.atan(ang_tan) / math.pi * 180.0  
#根據(jù)角度旋轉(zhuǎn)照片撒桨,并計算旋轉(zhuǎn)后眼睛和嘴巴的中點(diǎn)查刻。
img_rot = imrotate(img, angle)
x = (landmark[0][0]+landmark[1][0]) / 2
y = (landmark[0][1]+landmark[1][1]) / 2
angle = - angle / 180.0 * math.pi
eyec = transform(x, y, angle, img.shape, img_rot.shape)
x = (landmark[3][0]+landmark[4][0]) / 2
y = (landmark[3][1]+landmark[4][1]) / 2
mouthc = transform(x, y, angle, img.shape, img_rot.shape)
resize_scale = ec_mc_y / (mouthc[1]-eyec[1])
resize_shape = [img_rot.shape[0],img_rot.shape[1]]
resize_shape[0] = max(size, math.ceil(resize_shape[0] * resize_scale))
resize_shape[1] = max(size, math.ceil(resize_shape[1] * resize_scale))
resize_shape = ((int)(resize_shape[1]),(int)(resize_shape[0]))

ec_mc_y是我們手動設(shè)置的眼睛和嘴巴之間的垂直距離,設(shè)置的依據(jù)是最后圖片輸出時的size大小凤类,而下面出現(xiàn)的ec_y則是眼睛中點(diǎn)的y軸坐標(biāo)穗泵,這也是通過size來調(diào)整的。通過計算ec_mc_y和旋轉(zhuǎn)后圖片的垂直距離的比值谜疤,可以得到一個縮放比例resize_scale佃延,如果縮放后的圖片大小為:resize_shape[0] *resize_scale,resize_shape[1] * resize_scale夷磕,如果此時二者中任一個小于size履肃,都將把它替換成size,都大于就保持不變坐桩。

img_resize = cv2.resize(img_rot, resize_shape)
eyec2 = [(eyec[0]-(img_rot.shape[1]/2.0))*resize_scale + (img_resize.shape[1]/2.0),
(eyec[1]-(img_rot.shape[0]/2.0))*resize_scale + (img_resize.shape[0]/2.0)]
eyec2 = ((int)(round(eyec2[0])), (int)(round(eyec2[1])))
img_crop = np.zeros((size, size, img_rot.shape[2]))
crop_y = eyec2[1] - ec_y  #計算此時眼睛中點(diǎn)和設(shè)置中點(diǎn)差值
crop_y_end = crop_y + size - 1 #計算裁剪窗口的移動距離榆浓。
crop_y = min(img_resize.shape[0],max(1, crop_y))
crop_y_end = min(img_resize.shape[0],max(1, crop_y_end))
crop_x = eyec2[0] - (int)(math.floor(size/2.0))
crop_x_end = crop_x + size - 1
crop_x = min(img_resize.shape[1],max(1, crop_x))
crop_x_end = min(img_resize.shape[1],max(1, crop_x_end))

用計算得到的resize_shape把對圖像進(jìn)行縮放,cv2.resize的功能是對圖像進(jìn)行縮放撕攒。接著我們需要重新計算縮放后圖像眼睛的中點(diǎn)陡鹃。先把eyec平移到原點(diǎn),之后進(jìn)行縮放抖坪,然后再平移萍鲸。接下來需要計算裁剪的范圍,計算eyec的y值和ec_y的差值擦俐,來計算y軸的裁剪范圍脊阴,通過計算eyec的x值和圖片中點(diǎn)的差值,來計算x軸的裁剪范圍。定義一個img_crop為了接收最后裁剪得到的圖像嘿期。之后我們計算裁剪的范圍 x方向?yàn)? crop_x ~ crop_x_end y方向?yàn)? crop_y ~ crop_y_end

box = np.array([crop_x, crop_x_end, crop_y, crop_y_end])
img_crop[(box[2]-crop_y+1):(box[3]-crop_y+1), (box[0]-crop_x+1):(box[1]-crop_x+1), :] = img_resize[box[2]:box[3],box[0]:box[1],:]
cropped = img_crop/255.0
img_final = cv2.resize(cropped, (size, size))
img_final = np.uint8(img_final*255.0)

img_resize中的 crop_y ~ crop_y_end 品擎, crop_x ~ crop_x_end區(qū)域復(fù)制到 img_crop中的 1~crop_y_end - crop_y+1 1~crop_x_end - crop_x + 1的區(qū)域
cropped = img_crop/255.0是將像素做歸一化,得到的cropped做最后一次縮放得到img_final备徐,img_final*255.0為恢復(fù)原來的像素值萄传,得到的img_final為最終的調(diào)整結(jié)果。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末蜜猾,一起剝皮案震驚了整個濱河市秀菱,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌蹭睡,老刑警劉巖衍菱,帶你破解...
    沈念sama閱讀 206,378評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異肩豁,居然都是意外死亡脊串,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,356評論 2 382
  • 文/潘曉璐 我一進(jìn)店門清钥,熙熙樓的掌柜王于貴愁眉苦臉地迎上來琼锋,“玉大人,你說我怎么就攤上這事循捺≌独” “怎么了雄人?”我有些...
    開封第一講書人閱讀 152,702評論 0 342
  • 文/不壞的土叔 我叫張陵从橘,是天一觀的道長。 經(jīng)常有香客問我础钠,道長恰力,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,259評論 1 279
  • 正文 為了忘掉前任旗吁,我火速辦了婚禮踩萎,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘很钓。我一直安慰自己香府,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,263評論 5 371
  • 文/花漫 我一把揭開白布码倦。 她就那樣靜靜地躺著企孩,像睡著了一般。 火紅的嫁衣襯著肌膚如雪袁稽。 梳的紋絲不亂的頭發(fā)上勿璃,一...
    開封第一講書人閱讀 49,036評論 1 285
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼补疑。 笑死歧沪,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的莲组。 我是一名探鬼主播诊胞,決...
    沈念sama閱讀 38,349評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼胁编!你這毒婦竟也來了厢钧?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 36,979評論 0 259
  • 序言:老撾萬榮一對情侶失蹤嬉橙,失蹤者是張志新(化名)和其女友劉穎早直,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體市框,經(jīng)...
    沈念sama閱讀 43,469評論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡霞扬,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,938評論 2 323
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了枫振。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片喻圃。...
    茶點(diǎn)故事閱讀 38,059評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖粪滤,靈堂內(nèi)的尸體忽然破棺而出斧拍,到底是詐尸還是另有隱情,我是刑警寧澤杖小,帶...
    沈念sama閱讀 33,703評論 4 323
  • 正文 年R本政府宣布肆汹,位于F島的核電站,受9級特大地震影響予权,放射性物質(zhì)發(fā)生泄漏昂勉。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,257評論 3 307
  • 文/蒙蒙 一扫腺、第九天 我趴在偏房一處隱蔽的房頂上張望岗照。 院中可真熱鬧,春花似錦笆环、人聲如沸攒至。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,262評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽迫吐。三九已至,卻和暖如春习绢,著一層夾襖步出監(jiān)牢的瞬間渠抹,已是汗流浹背蝙昙。 一陣腳步聲響...
    開封第一講書人閱讀 31,485評論 1 262
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留梧却,地道東北人奇颠。 一個月前我還...
    沈念sama閱讀 45,501評論 2 354
  • 正文 我出身青樓,卻偏偏與公主長得像放航,于是被迫代替她去往敵國和親烈拒。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,792評論 2 345

推薦閱讀更多精彩內(nèi)容