利用dlib+opencv进行人脸裁剪

# -*- coding: utf-8 -*-
import cv2
import os
import dlib
import numpy as np

# 需要自己去网上下载 shape_predictor_68_face_landmarks.dat 文件
predictor_path = "./shape_predictor_68_face_landmarks.dat"
detector = dlib.get_frontal_face_detector()
predictor = dlib.shape_predictor(predictor_path)

# 手动设置裁剪框的大小, 分别表示left, top, right, bottom边框扩大率
rescaleBB = [1.185974, 1.0, 1.135600, 1.17]

def save_crop_images(file_list, save_root_path):
    with open(file_list, 'r') as ins:
        for image_path in ins:
            image_path = image_path.strip('\n')
            print '> crop image', image_path
            img = cv2.imread(image_path)

            dets = detector(img, 1)
            if len(dets) == 0:
                print '> Could not detect the face, skipping the image ...',image_path
                continue
            if len(dets) > 1:
                print '> Process only the first detected face !'
            detected_face = dets[0]
            imcrop = cropByFaceDet(img, detected_face)

            parent_dir, img_name = get_dir_name(image_path)
            save_path = os.path.join(save_root_path, parent_dir)
            if not os.path.exists(save_path):
                os.makedirs(save_path)
            cv2.imwrite(os.path.join(save_path, img_name), imcrop)


def get_dir_name(img_path):
    tmp = img_path.split('/')
    return tmp[-2], tmp[-1]


def cropImg(img, tlx, tly, brx, bry, rescale):
    l = float(tlx)
    t = float(tly)
    ww = float(brx - l)
    hh = float(bry - t)

    # Approximate LM tight BB
    h = img.shape[0]
    w = img.shape[1]
    # cv2.rectangle(img, (int(l), int(t)), (int(brx), int(bry)), \
    #     (0, 255, 255), 2)
    cx = l + ww/2
    cy = t + hh/2
    tsize = max(ww, hh)/2
    l = cx - tsize
    t = cy - tsize

    # Approximate expanded bounding box
    bl = int(round(cx - rescale[0]*tsize))
    bt = int(round(cy - rescale[1]*tsize))
    br = int(round(cx + rescale[2]*tsize))
    bb = int(round(cy + rescale[3]*tsize))
    nw = int(br - bl)
    nh = int(bb - bt)
    imcrop = np.zeros((nh, nw, 3), dtype='uint8')

    ll = 0
    if bl < 0:
        ll = -bl
        bl = 0
    rr = nw
    if br > w:
        rr = w+nw - br
        br = w
    tt = 0
    if bt < 0:
        tt = -bt
        bt = 0
    bbb = nh
    if bb > h:
        bbb = h+nh - bb
        bb = h
    imcrop[tt:bbb,ll:rr,:] = img[bt:bb,bl:br,:]
    return imcrop


def cropByFaceDet(img, detected_face):
    return cropImg(img,detected_face.left(),detected_face.top(),\
        detected_face.right(),detected_face.bottom(), rescaleBB)

if __name__ == '__main__':
    file_list = 'inputs.txt'
    save_crop_images(file_list, 'crops')

扩充训练数据,对原始图片进行旋转,添加噪声等操作
使用多线程加快处理速度

# -*- coding: utf-8 -*-
import cv2
import os
import dlib
import numpy as np
import random
from math import *
from  multiprocessing  import  Pool

# 需要自己去网上下载 shape_predictor_68_face_landmarks.dat 文件
predictor_path = "./shape_predictor_68_face_landmarks.dat"
detector = dlib.get_frontal_face_detector()
predictor = dlib.shape_predictor(predictor_path)

# 手动设置裁剪框的大小, 分别表示left, top, right, bottom边框扩大率
rescaleBB = [1.185974, 1.0, 1.135600, 1.17]

def save_crop_images(args):
        image_path, save_root_path = args
        print '> crop image', image_path
        img = cv2.imread(image_path.strip('\n'))
        dets = detector(img, 1)
        if len(dets) == 0:
            print '> Could not detect the face, skipping the image ...',image_path
            return
        if len(dets) > 1:
            print '> Process only the first detected face !'
        detected_face = dets[0]
        parent_dir, img_name = get_dir_name(image_path)
        save_path = os.path.join(save_root_path, parent_dir)
        if not os.path.exists(save_path):
            os.makedirs(save_path)

        imcrop = cropByFaceDet(img, detected_face)
        im_blur = blurImage(imcrop)
        cv2.imwrite(os.path.join(save_path, img_name), imcrop)
        cv2.imwrite(os.path.join(save_path, 'blur_'+img_name), im_blur)
        for i in range(10):
            degree = random.randrange(0,360,10)
            im_rotate = rotateImage(imcrop, degree)
            cv2.imwrite(os.path.join(save_path, 'rot_'+str(degree)+'_'+img_name), im_rotate)
        for i in range(5):
            degree = random.randrange(0,360,10)
            im_rotate = rotateImage(im_blur, degree)
            cv2.imwrite(os.path.join(save_path, 'rot_'+str(degree)+'_blur_'+img_name), im_rotate)

def get_dir_name(img_path):
    tmp = img_path.split('/')
    return tmp[-2], tmp[-1]


def cropImg(img, tlx, tly, brx, bry, rescale):
    l = float(tlx)
    t = float(tly)
    ww = float(brx - l)
    hh = float(bry - t)

    # Approximate LM tight BB
    h = img.shape[0]
    w = img.shape[1]
    # cv2.rectangle(img, (int(l), int(t)), (int(brx), int(bry)), \
    #     (0, 255, 255), 2)
    cx = l + ww/2
    cy = t + hh/2
    tsize = max(ww, hh)/2
    l = cx - tsize
    t = cy - tsize

    # Approximate expanded bounding box
    bl = int(round(cx - rescale[0]*tsize))
    bt = int(round(cy - rescale[1]*tsize))
    br = int(round(cx + rescale[2]*tsize))
    bb = int(round(cy + rescale[3]*tsize))
    nw = int(br - bl)
    nh = int(bb - bt)
    imcrop = np.zeros((nh, nw, 3), dtype='uint8')

    ll = 0
    if bl < 0:
        ll = -bl
        bl = 0
    rr = nw
    if br > w:
        rr = w+nw - br
        br = w
    tt = 0
    if bt < 0:
        tt = -bt
        bt = 0
    bbb = nh
    if bb > h:
        bbb = h+nh - bb
        bb = h
    imcrop[tt:bbb,ll:rr,:] = img[bt:bb,bl:br,:]
    return imcrop


def cropByFaceDet(img, detected_face):
    return cropImg(img,detected_face.left(),detected_face.top(),\
        detected_face.right(),detected_face.bottom(), rescaleBB)

def rotateImage(img, degree=60):
    rows, cols, channel = img.shape
    # 为了旋转之后不裁剪原图,计算旋转后的尺寸
    rows_new = int(cols*fabs(sin(radians(degree))) + rows*fabs(cos(radians(degree))))
    cols_new= int(rows*fabs(sin(radians(degree))) + cols*fabs(cos(radians(degree))))
    # 旋转60度的仿射矩阵
    M = cv2.getRotationMatrix2D((cols/2, rows/2), degree, 1)
    M[0,2] += (cols_new - cols)/2
    M[1,2] += (rows_new - rows)/2
    im = cv2.warpAffine(img, M, (cols_new, rows_new), borderValue=(255,255,255))  # 旋转60度,得到新图片
    return im

def blurImage(img):
    return cv2.GaussianBlur(img, (5,5), 0)
if __name__ == '__main__':
    file_list = 'inputs.txt'
    images_list = open(file_list, 'r').readlines()
    # for arg in zip(images_list, 'crop'):
    #     save_crop_images(arg)
    pool = Pool(5)
    pool.map(save_crop_images, zip(images_list,['crop',]*len(images_list)))
    pool.close()
    pool.join()
    print 'end...'
    # cv2.waitKey(0)
    # cv2.destroyAllWindows()

你可能感兴趣的:(图像处理)