以下链接是个人关于insightFace所有见解,如有错误欢迎大家指出,我会第一时间纠正,如有兴趣可以加QQ:17575010159 相互讨论技术。 人脸识别0-00:insightFace目录:https://blog.csdn.net/weixin_43013761/article/details/99646731: 这是本人项目的源码:https://github.com/944284742/1.FaceRecognition 其中script目录下的文件为本人编写,主要用于适应自己的项目,可以查看该目录下的redeme文件。
系统搭建目的做过深度学习的哥们应该都知道,收集数据的过程是十分复杂的,无论是手工标签,还是通过其他商家购买,都是十分消耗财力和人力的,为了人脸系统有足够的训练数据,所以我打算搭建这套系统,也分享给大家。这里的是半监督学习,也就是说,还是需要一些人力工作,才能维持该系统的正常运转。搭建这套系统之后,只需要包含人脸的图像就可以了,不需要做任何分类,标定,直接丢到该系统中,就能当作训练的数据(需要人进行小量的筛选)。下面我们就开始把。
人脸检测假设,我们随便收集了一下,或者抓拍了一下包含人脸,也可能没有包含人脸的照片,那么我们首先是要把这些人脸的都截取出来,并且还要进行人脸矫正。编写insightface-master\src\align\align_my.py(在本人的源码中,作者的代码不知道如何就设置人脸矫正,所以自己重新改写了一下)脚本如下:
from __future__ import absolute_import from __future__ import division from __future__ import print_function from scipy import misc import sys import os import argparse import tensorflow as tf import numpy as np # import facenet import detect_face import random from time import sleep sys.path.append(os.path.join(os.path.dirname(__file__), '..', 'common')) import face_image import src.common.face_preprocess as face_preprocess from skimage import transform as trans import cv2 def to_rgb(img): w, h = img.shape ret = np.empty((w, h, 3), dtype=np.uint8) ret[:, :, 0] = ret[:, :, 1] = ret[:, :, 2] = img return ret def IOU(Reframe, GTframe): x1 = Reframe[0]; y1 = Reframe[1]; width1 = Reframe[2] - Reframe[0]; height1 = Reframe[3] - Reframe[1]; x2 = GTframe[0] y2 = GTframe[1] width2 = GTframe[2] - GTframe[0] height2 = GTframe[3] - GTframe[1] endx = max(x1 + width1, x2 + width2) startx = min(x1, x2) width = width1 + width2 - (endx - startx) endy = max(y1 + height1, y2 + height2) starty = min(y1, y2) height = height1 + height2 - (endy - starty) if width <= 0 or height <= 0: ratio = 0 else: Area = width * height Area1 = width1 * height1 Area2 = width2 * height2 ratio = Area * 1. / (Area1 + Area2 - Area) return ratio def list_image(root, recursive, exts): """Traverses the root of directory that contains images and generates image list iterator. Parameters ---------- root: string recursive: bool exts: string Returns ------- image iterator that contains all the image under the specified path """ i = 0 if recursive: cat = {} for path, dirs, files in os.walk(root, followlinks=True): dirs.sort() files.sort() for fname in files: fpath = os.path.join(path, fname) suffix = os.path.splitext(fname)[1].lower() if os.path.isfile(fpath) and (suffix in exts): if path not in cat: cat[path] = len(cat) yield (i, os.path.relpath(fpath, root), cat[path]) i += 1 for k, v in sorted(cat.items(), key=lambda x: x[1]): print(os.path.relpath(k, root), v) else: for fname in sorted(os.listdir(root)): fpath = os.path.join(root, fname) suffix = os.path.splitext(fname)[1].lower() if os.path.isfile(fpath) and (suffix in exts): yield (i, os.path.relpath(fpath, root), 0) i += 1 def main(args): imgs_info = list_image(args.indir, args.recursive, args.exts) print('Creating networks and loading parameters') with tf.Graph().as_default(): # gpu_options = tf.GPUOptions(per_process_gpu_memory_fraction=args.gpu_memory_fraction) # sess = tf.Session(config=tf.ConfigProto(gpu_options=gpu_options, log_device_placement=False)) sess = tf.Session() with sess.as_default(): pnet, rnet, onet = detect_face.create_mtcnn(sess, None) minsize = 20 threshold = [0.6, 0.7, 0.9] factor = 0.85 # Add a random key to the filename to allow alignment using multiple processes # random_key = np.random.randint(0, high=99999) # bounding_boxes_filename = os.path.join(output_dir, 'bounding_boxes_%05d.txt' % random_key) # output_filename = os.path.join(output_dir, 'faceinsight_align_%s.lst' % args.name) if not os.path.exists(args.outdir): os.makedirs(args.outdir) output_filename = os.path.join(args.outdir, 'lst') nrof_images_total = 0 nrof = np.zeros((5,), dtype=np.int32) face_count = 0 for src_img_info in imgs_info: src_img_path = os.path.join(args.indir,src_img_info[1]) if nrof_images_total % 100 == 0: print("Processing %d, (%s)" % (nrof_images_total, nrof)) nrof_images_total += 1 if not os.path.exists(src_img_path): print('image not found (%s)' % src_img_path) continue # print(image_path) try: img = misc.imread(src_img_path) except (IOError, ValueError, IndexError) as e: errorMessage = '{}: {}'.format(src_img_path, e) print(errorMessage) else: if img.ndim < 2: print('Unable to align "%s", img dim error' % src_img_path) # text_file.write('%s\n' % (output_filename)) continue if img.ndim == 2: img = to_rgb(img) img = img[:, :, 0:3] target_dir = '' src_img_path_list = src_img_info[1].replace('\\','/').split('/') #print(src_img_path_list) if len(src_img_path_list) <= 1: target_dir = args.outdir elif len(src_img_path_list) ==2: src_img_path_prefix = src_img_path_list[:-1] target_dir = os.path.join(args.outdir, str(src_img_path_prefix[0])) else: src_img_path_prefix = ['/'.join(bar) for bar in src_img_path_list[:-1]] #print('src_img_path_prefix: ',src_img_path_prefix) target_dir = os.path.join(args.outdir, str(src_img_path_prefix[0])) #print(target_dir) if not os.path.exists(target_dir): os.makedirs(target_dir) _minsize = minsize _bbox = None _landmark = None bounding_boxes, points = detect_face.detect_face(img, _minsize, pnet, rnet, onet, threshold, factor) #print(points) if points == []: points = None else: _landmark = points.T #print(_landmark.shape) faces_sumnum = bounding_boxes.shape[0] for num in range(faces_sumnum): warped = face_preprocess.preprocess(img, bbox=bounding_boxes[num], landmark=_landmark[num].reshape([2,5]).T, image_size=args.image_size) bgr = warped[..., ::-1] #cv2.imshow(str(num),bgr) target_file = os.path.join(target_dir, '%08d.jpg'%face_count) #print(target_file) cv2.imwrite(target_file,bgr) face_count += 1 def parse_arguments(argv): parser = argparse.ArgumentParser() parser.add_argument('--indir', default='D:/03.work/02.development/04.PaidOn/1.FaceRecognition/2.Dataset/2.PaidOnData/1.TrainData/CASIA-WebFace/CASIA-WebFace', type=str, help='Directory with unaligned images.') parser.add_argument('--outdir', default='D:/03.work/02.development/04.PaidOn/1.FaceRecognition/2.Dataset/2.PaidOnData/1.TrainData/CASIA-WebFace/CASIA-WebFace_112x112a', type=str, help='Directory with aligned face thumbnails.') parser.add_argument('--image-size', type=str, help='Image size (height, width) in pixels.', default='112,112') # parser.add_argument('--margin', type=int, # help='Margin for the crop around the bounding box (height, width) in pixels.', default=44) parser.add_argument('--exts', nargs='+', default=['.jpeg', '.jpg', '.png','.bmp'], help='list of acceptable image extensions.') parser.add_argument('--recursive', default=True, help='If true recursively walk through subdirs and assign an unique label\ to images in each folder. Otherwise only include images in the root folder\ and give them label 0.') return parser.parse_args(argv) if __name__ == '__main__': main(parse_arguments(sys.argv[1:]))
该脚本我们部位大家讲解了,有兴趣的哥们可以自己去分析。使用该脚本只需要指定输入输出目录,以及输出的图片大小即可,下面是演示的效果:
这里提示一下大家,作者源码的检测,不知道什么原因,不能进行人脸矫正,如果需要人脸矫正的,请粘贴我的代码,如果运行不了,可以拷贝我的整个项目,保证是没有问题的。
下面我们当然就需要对人脸进行分类,如何分类呢?请看下小节。