149 lines
7.5 KiB
Python
149 lines
7.5 KiB
Python
'''
|
|
Created on May 8, 2014
|
|
|
|
@author: eran
|
|
'''
|
|
from adiencealign.cascade_detection.cascade_face_finder import CascadeFaceFinder
|
|
from adiencealign.affine_alignment.affine_aligner import AffineAligner
|
|
import glob
|
|
import os
|
|
from adiencealign.landmarks_detection.landmarks_detector import detect_landmarks
|
|
from adiencealign.common.landmarks import read_fidu, unwarp_fidu, draw_fidu
|
|
import cv2
|
|
|
|
class CascadeFaceAligner(object):
|
|
'''
|
|
classdocs
|
|
'''
|
|
|
|
|
|
def __init__(self, haar_file = 'adiencealign/resources/haarcascade_frontalface_default.xml',
|
|
lbp_file = 'adiencealign/resources/lbpcascade_frontalface.xml',
|
|
fidu_model_file = 'adiencealign/resources/model_ang_0.txt',
|
|
fidu_exec_dir = 'adiencealign/resources/'):
|
|
'''
|
|
Constructor
|
|
'''
|
|
self.face_finder = CascadeFaceFinder(haar_file = haar_file,
|
|
lbp_file = lbp_file)
|
|
|
|
self.aligner = AffineAligner(fidu_model_file = fidu_model_file)
|
|
self.fidu_exec_dir = fidu_exec_dir
|
|
|
|
self.valid_angles = [-45,-30,-15,0,15,30,45]
|
|
|
|
def detect_faces(self, input_folder, output_folder, mark_dones = True):
|
|
'''
|
|
mark_dones - if True, will create a hidden file, marking this file as done with a hidden file, starting with '.done.'
|
|
'''
|
|
input_files1 = glob.glob(os.path.join(input_folder, '*.jpg'))
|
|
input_files2 = glob.glob(os.path.join(input_folder, '*.png'))
|
|
input_files = input_files1 + input_files2
|
|
N = len(input_files)
|
|
|
|
for n_file, input_file in enumerate(input_files):
|
|
a,b = os.path.split(input_file)
|
|
done_file = os.path.join(a, '.done.' + b.rsplit('.',1)[0])
|
|
|
|
if os.path.exists(done_file):
|
|
continue
|
|
|
|
print("... processing", input_file)
|
|
|
|
target_faces_file = os.path.join( output_folder, os.path.split(input_file)[1].rsplit('.',1)[0] + '.faces.txt')
|
|
|
|
faces_file = self.face_finder.create_faces_file( input_file, is_overwrite = False, target_file = target_faces_file )
|
|
sub_images_files = self.face_finder.create_sub_images_from_file( original_image_file = input_file,
|
|
faces_file = faces_file,
|
|
target_folder = output_folder,
|
|
img_type = 'jpg')
|
|
#touch
|
|
open(done_file,'w').close()
|
|
print("Detected on %d / %d files" %(n_file, N))
|
|
|
|
def align_faces(self, input_images, output_path, fidu_max_size = None, fidu_min_size = None, is_align = True, is_draw_fidu = False, delete_no_fidu = False):
|
|
'''
|
|
input_images - can be either a folder (all *.jpgs in it) or a list of filenames
|
|
|
|
, fidu_max_size = None, fidu_min_size = None):
|
|
'''
|
|
if type(input_images) == type(''):
|
|
input_images = glob.glob(os.path.join(input_images, '*.jpg'))
|
|
|
|
for input_image in input_images:
|
|
detect_landmarks(fname = os.path.abspath(input_image),
|
|
max_size = fidu_max_size,
|
|
min_size = fidu_min_size,
|
|
fidu_exec_dir = self.fidu_exec_dir)
|
|
|
|
fidu_file = input_image.rsplit('.',1)[0] + '.cfidu'
|
|
fidu_score, yaw_angle, fidu_points = read_fidu(fidu_file)
|
|
|
|
if not (fidu_score is not None and yaw_angle in self.valid_angles):
|
|
# skip face
|
|
if delete_no_fidu:
|
|
os.remove(fidu_file)
|
|
os.remove(input_image)
|
|
continue
|
|
|
|
if is_align:
|
|
# save the aligned image
|
|
sub_img = cv2.imread(input_image)
|
|
_, base_fname = os.path.split(input_image)
|
|
aligned_img, R = self.aligner.align(sub_img, fidu_points)
|
|
aligned_img_file = os.path.join(output_path, base_fname.rsplit('.',1)[0] + '.aligned.png')
|
|
cv2.imwrite(aligned_img_file, aligned_img)
|
|
|
|
# save a copy of the aligned image, with the landmarks drawn
|
|
if is_draw_fidu:
|
|
aligned_img_file = os.path.join(output_path, base_fname.rsplit('.',1)[0] + '.aligned.withpoints.png')
|
|
fidu_points_in_aligned = unwarp_fidu(orig_fidu_points = fidu_points, unwarp_mat = R)
|
|
draw_fidu(aligned_img, fidu_points_in_aligned, radius = 9, color = (255,0,0), thickness = 3)
|
|
cv2.imwrite(aligned_img_file, aligned_img)
|
|
|
|
#
|
|
# def align_faces2(self, input_folder, output_folder, detect_landmarks = True, delete_no_fidu = True, is_align = True, is_draw_fidu = False, fidu_max_size = None, fidu_min_size = None):
|
|
# '''
|
|
# delete_no_fidu - deletes the .cfidu and sub_img if no fidu was found
|
|
# is_draw_fidu - creates a copy of the aligned images with the original fiducial points on it
|
|
# '''
|
|
# input_files = glob.glob(os.path.join(input_folder, '*'))
|
|
# for input_file in input_files:
|
|
# print "... processing", input_file
|
|
# target_faces_file = os.path.join( output_folder, os.path.split(input_file)[1].rsplit('.',1)[0] + '.faces.txt')
|
|
#
|
|
# faces_file = self.face_finder.create_faces_file( input_file, is_overwrite = False, target_file = target_faces_file )
|
|
# sub_images_files = self.face_finder.create_sub_images_from_file( original_image_file = input_file,
|
|
# faces_file = faces_file,
|
|
# target_folder = output_folder,
|
|
# img_type = 'jpg')
|
|
#
|
|
# for sub_image_file in sub_images_files:
|
|
# detect_landmarks(fname = os.path.abspath(sub_image_file),
|
|
# max_size = fidu_max_size,
|
|
# min_size = fidu_min_size,
|
|
# fidu_exec_dir = self.fidu_exec_dir)
|
|
#
|
|
# fidu_file = sub_image_file.rsplit('.',1)[0] + '.cfidu'
|
|
# fidu_score, yaw_angle, fidu_points = read_fidu(fidu_file)
|
|
#
|
|
# if not (fidu_score is not None and yaw_angle in self.valid_angles):
|
|
# # skip face
|
|
# os.remove(fidu_file)
|
|
# os.remove(sub_image_file)
|
|
# continue
|
|
#
|
|
# if is_align:
|
|
# # save the aligned image
|
|
# sub_img = cv2.imread(sub_image_file)
|
|
# aligned_img, R = self.aligner.align(sub_img, fidu_points)
|
|
# aligned_img_file = sub_image_file.rsplit('.',1)[0] + '.aligned.png'
|
|
# cv2.imwrite(aligned_img_file, aligned_img)
|
|
#
|
|
# # save a copy of the aligned image, with the landmarks drawn
|
|
# if is_draw_fidu:
|
|
# aligned_img_file = sub_image_file.rsplit('.',1)[0] + '.aligned.withpoints.png'
|
|
# fidu_points_in_aligned = unwarp_fidu(orig_fidu_points = fidu_points, unwarp_mat = R)
|
|
# draw_fidu(aligned_img, fidu_points_in_aligned, radius = 9, color = (255,0,0), thickness = 3)
|
|
# cv2.imwrite(aligned_img_file, aligned_img)
|