您当前的位置: 首页 >  分类
  • 2浏览

    0关注

    417博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文

人脸识别0-07:insightFace-半监督系统搭建(2)-人脸分类

江南才尽,年少无知! 发布时间:2019-08-27 15:29:48 ,浏览量:2

以下链接是个人关于insightFace所有见解,如有错误欢迎大家指出,我会第一时间纠正,如有兴趣可以加微信:17575010159 相互讨论技术。 人脸识别0-00:insightFace目录:https://blog.csdn.net/weixin_43013761/article/details/99646731: 这是本人项目的源码:https://github.com/944284742/1.FaceRecognition 其中script目录下的文件为本人编写,主要用于适应自己的项目,可以查看该目录下的redeme文件。

使用模型人脸分类

这里我们不是使用人工对人脸进行分类,而是使=使用已经训练好的模型对人脸进行分类,其实除了使用训练好的模型进行分类之外,还有其他人脸聚类的方法,这些方法,我后续会再该章节的下面为大家补上,当然,也可能做为另外一个章节为大家单独的讲解。这些东西都不涉及算法,所以我就直接贴出自己编写的代码,希望对大家有帮助。在执行该程序时,需要对人脸库进行规则化,其规则化在该博库最后面有介绍: script/faces_classer.py

from __future__ import print_function
import os
import sys

curr_path = os.path.abspath(os.path.dirname(__file__))
sys.path.append(os.path.join(curr_path, "../python"))
import mxnet as mx
import random
import argparse
import cv2
import time
import traceback
import numpy as  np
import sklearn
import shutil
from mxnet import ndarray as nd
np.set_printoptions(suppress=True)
from sklearn.cluster import DBSCAN

try:
    import multiprocessing
except ImportError:
    multiprocessing = None

class Model():
    # 模型加载
    def __init__(self,image_size, args):
        prefix, epoch = args.model.split(',')
        sym, arg_params, aux_params = mx.model.load_checkpoint(prefix, int(epoch))
        all_layers = sym.get_internals()
        self.model = mx.mod.Module(symbol=sym, context=mx.gpu())
        self.model.bind(data_shapes=[('data', (1, 3, image_size[0], image_size[1]))])
        self.model.set_params(arg_params, aux_params)

    # 得到输入图像的特征向量
    def predict(self,img):
        img = nd.array(img)
        #print(img.shape)
        img = nd.transpose(img, axes=(2, 0, 1)).astype('float32')
        img = nd.expand_dims(img, axis=0)
        #print(img.shape)
        db = mx.io.DataBatch(data=(img,))

        self.model.forward(db, is_train=False)
        net_out = self.model.get_outputs()
        embedding = net_out[0].asnumpy()
        embedding = sklearn.preprocessing.normalize(embedding,axis=1)
        return embedding



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)
            pass
    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 write_list(path_out, image_list):
    """Hepler function to write image list into the file.
    The format is as below,
    integer_image_index \t float_label_index \t path_to_image
    Note that the blank between number and tab is only used for readability.
    Parameters
    ----------
    path_out: string
    image_list: list
    """
    with open(path_out, 'w') as fout:
        for i, item in enumerate(image_list):
            line = '%d\t' % item[0]
            for j in item[2:]:
                line += '%f\t' % j
            line += '%s\n' % item[1]
            fout.write(line)
    print('生成文件:%s'%path_out)
def make_list(args):
    """Generates .lst file.
    Parameters
    ----------
    args: object that contains all the arguments
    """
    image_list = list_image(args.root, args.recursive, args.exts)
    image_list = list(image_list)
    if args.shuffle is True:
        random.seed(100)
        random.shuffle(image_list)

    path = os.path.join(args.root,'.lst')
    write_list(path, image_list)


def read_list(path_in):
    """Reads the .lst file and generates corresponding iterator.
    Parameters
    ----------
    path_in: string
    Returns
    -------
    item iterator that contains information in .lst file
    """

    with open(path_in) as fin:
        while True:
            line = fin.readline()
            if not line:
                break
            line = [i.strip() for i in line.strip().split('\t')]
            line_len = len(line)
            # check the data format of .lst file
            if line_len  img.shape[1]:
            newsize = (args.resize, img.shape[0] * args.resize // img.shape[1])
        else:
            newsize = (img.shape[1] * args.resize // img.shape[0], args.resize)
        img = cv2.resize(img, newsize)

    try:
        # 放入队列
        q_out.put((i, img, item))
    except Exception as e:
        traceback.print_exc()
        print('pack_img error on file: %s' % fullpath, e)
        q_out.put((i, None, item))
        return

def read_worker(args, q_in, q_out):
    """Function that will be spawned to fetch the image
    from the input queue and put it back to output queue.
    Parameters
    ----------
    args: object
    q_in: queue
    q_out: queue
    """
    while True:
        # 获取任务
        deq = q_in.get()
        # 判断该任务是否为None
        if deq is None:
            break

        # i代表的是分配的第几个任务,item包含了第几章图片,路径,所属类别
        i, item = deq

        # 读取图片进行解吗
        image_encode(args, i, item, q_out)


def get_outdir_emds(args):
    dir_list = os.listdir(args.outdir)
    if 'embeddings.npz' in dir_list:
        path = os.path.join(args.outdir,'embeddings.npz')
        data =  np.load(path)
        npz_embs = data['npz_embs']
        npz_emb_len = data['npz_emb_len']
        return npz_embs,npz_emb_len
    return None,None


def gen_npz_embs(q_out,model):

    buf = {}
    more = True # 队列处理完成,设置为None
    pre_id = 0 # 记录前一张图片的ID,如果前一张,和当前的ID不同,表示前一个人的所有图片已经预测完成
    count = 0

    # 每个id的特征向量
    id_embeddings = None

    # 存入ngs.npz中embeddi,所有ID的平均特征向量
    npz_embs = None

    # 存入ngs.npz中embeddi,每个特征向量对应的图片张数
    npz_emb_len = None

    # 开始产生开始的时间
    pre_time = time.time()

    while more:
        deq = q_out.get()

        # 如果取出信息不为空,则对其中的img进行预测
        if deq is not None:
            # i代表第几个任务 img表示像素
            # item包含了,第几章图片,路径,所属ID
            i, img, item = deq

            # 为了保存所有的任务没有遗漏
            buf[i] = (img, item)
            print(i)

        # 如果为空,说明已经预测完了所有图片
        else:
            # 计算最后一个人的平均特征向量
            id_mean_emb = np.mean(id_embeddings, axis=0)
            # 为了统一,扩展一个维度
            id_mean_emb = np.expand_dims(id_mean_emb, axis=0)
            # 垂直方向进行拼接
            npz_embs = np.vstack((npz_embs, id_mean_emb))

            # 保存平均向量对应ID图片的数目
            id_mean_embs_len = id_embeddings.shape[0]
            # 为了统一,扩展一个维度
            id_mean_embs_len = np.expand_dims(id_mean_embs_len, axis=0)

            # 垂直方向进行拼接
            npz_emb_len = np.vstack((npz_emb_len, id_mean_embs_len))
            more = False

        while count in buf:
            img, item = buf[count]
            #print(img.shape ,item)
            del buf[count]
            if img is not None:
                # 对一张图片进行特征向量预测
                embedding = model.predict(img)

                # 判断ID的所有图片是否全部预测完成
                if (int(pre_id) != int(item[2])):

                    # 对单个ID的所有特征向量求平均值
                    id_mean_emb = np.mean(id_embeddings, axis=0)
                    # 为了统一增加一个维度
                    id_mean_emb = np.expand_dims(id_mean_emb, axis=0)

                    # 记录单个ID其有多少张图片
                    id_mean_embs_len = id_embeddings.shape[0]
                    # 为了统一增加一个维度
                    id_mean_embs_len = np.expand_dims(id_mean_embs_len, axis=0)

                    # 如果为None,说明这是第一个ID的平均特征向量,直接赋值即可
                    if npz_embs is None:
                        npz_embs = id_mean_emb
                        npz_emb_len = id_mean_embs_len
                    # 如果不是第一个,则进行锤子凭借
                    else:
                        npz_embs = np.vstack((npz_embs, id_mean_emb))
                        npz_emb_len = np.vstack((npz_emb_len, id_mean_embs_len))

                    # 把记录单个ID所有的id_embeddings设置为Nobe
                    id_embeddings = None

                # 如果id_embeddings为None,说明是每个ID的第一张图片
                if id_embeddings is None:
                    # 第一张图片的特征向量直接赋值即可
                    id_embeddings = embedding
                # 不是第一张,则进行水平拼接
                else:
                    id_embeddings = np.vstack((id_embeddings, embedding))

                # 把当前的ID记录下来
                pre_id = int(item[2])

            # 时间打印
            if count % 1000 == 0:
                cur_time = time.time()
                print('time:', cur_time - pre_time, ' count:', count)
                pre_time = cur_time
            count += 1

    # 返回计算完成所有的特征向量,以及特征向量对应的图片数目
    return npz_embs,npz_emb_len



def get_cos_simi(npz_embs,embedding):
    mol = np.matmul(npz_embs, embedding.T).reshape(-1)
    denom = np.linalg.norm(npz_embs, axis=1) * np.linalg.norm(embedding, axis=1)
    cos = mol / denom.reshape(-1)
    sim = 0.5 + 0.5 * cos
    return sim


def face_in_storage(args, npz_embs, npz_emb_len, idx, embedding, item, fd, max_nums):
    # 得到保存图像的目录
    lib_dir_path = os.path.join(args.outdir, '%08d' % idx)
    # 原图像的路径
    old_img_path = os.path.join(args.indir, item[1])
    # 新图片的路径
    new_img_path = os.path.join(lib_dir_path, '%05d' % (npz_emb_len[idx]) + args.encoding)
    # 进行复制

    fd.write(old_img_path + '\t' + new_img_path + '\t' + str(max_nums) + '\n\n')
    shutil.copyfile(old_img_path, new_img_path)

    if args.delete:
        os.remove(old_img_path)

    # 对特征向量,已经对应的长度进行更新
    old_len = npz_emb_len[idx][0]
    new_len = old_len + 1
    npz_embs[idx] = (npz_embs[idx].reshape(1, -1) * old_len + embedding) / new_len
    npz_emb_len[idx] = new_len
    return npz_embs, npz_emb_len

def face_create_lib(args, npz_embs, npz_emb_len, embedding, item, fd, max_nums):
# 得到当前ID的总个数
    id_sum = npz_embs.shape[0]

    # 为新的人脸入库,创建一个新的文件夹
    new_lib_dir = os.path.join(args.outdir, '%08d' % id_sum)
    os.mkdir(new_lib_dir)

    # 为了统一,扩展一个维度
    embedding = np.expand_dims(embedding, axis=0)

    # 特征向量以及对应的ID图片的数目,都进行垂直拼接
    npz_embs = np.vstack((npz_embs, embedding.reshape(1, -1)))
    npz_emb_len = np.vstack((npz_emb_len, np.array([[1]])))

    new_img_path = os.path.join(new_lib_dir, '00000' + args.encoding)
    old_img_path = os.path.join(args.indir, item[1])

    fd.write(old_img_path + '\t' + new_img_path + '\t' + str(max_nums) + '\n\n')
    shutil.copyfile(old_img_path, new_img_path)

    if args.delete:
        os.remove(old_img_path)
    return npz_embs,npz_emb_len

def face_not_recog(args, item, num, fd, max_nums):
    # 为新的人脸入库,创建一个新的文件夹
    recog_dir = os.path.join(args.outdir, 'not_recognition')
    if not os.path.exists(recog_dir):
        os.mkdir(recog_dir)

    #     # 原图像的路径
    old_img_path = os.path.join(args.indir, item[1])
    new_img_path = os.path.join(recog_dir, '%08d' % num + args.encoding)

    fd.write(old_img_path + '\t' + new_img_path + '\t' + str(max_nums) + '\n\n')
    shutil.copyfile(old_img_path, new_img_path)

    if args.delete:
        os.remove(old_img_path)


def write_worker(q_out, fname, args):
    """Function that will be spawned to fetch processed image
    from the output queue and write to the .rec file.
    Parameters
    ----------
    q_out: queue
    """

    # 尝试加载embeddings.npz文件,该文件主要存在两个数组
    # 'npz_embs':保存每ID的平均向量, 'npz_emb_len':每个ID存在多少图片,他们是一一对应的关系
    npz_embs,npz_emb_len = get_outdir_emds(args)

    # 模型加载
    model = Model([112, 112],args)

    # 保存embeddings.npy的路径
    path = os.path.join(args.outdir, 'embeddings')

    # 如果没有embeddings.npz文件,则为输出目录创建embeddings.npz文件
    if npz_embs is None:
        npz_embs,npz_emb_len = gen_npz_embs(q_out,model)


    else:
        buf = {}
        more = True
        count = 0
        pre_time = time.time()
        not_recog_conut = 0
        fd_in_storage = open(os.path.join(args.indir,'in_storage.txt'),'w')
        fd_not_recog = open(os.path.join(args.indir, 'not_recog.txt'),'w')
        fd_create_lib = open(os.path.join(args.indir, 'create_lib.txt'),'w')
        while more:
            deq = q_out.get()
            if deq is not None:
                i, img, item = deq
                # print(i)
                buf[i] = (img, item)
            else:
                #print(npz_embs.shape)
                more = False

            while count in buf:
                img, item = buf[count]

                # print(item)
                del buf[count]
                if img is not None:

                    embedding = model.predict(img)

                    # 求得需要预测的特征向量,与保存的每个特征向量的余弦相似度
                    simi = get_cos_simi(npz_embs,embedding)

                    # 找到最相似的图像
                    idx = np.argmax(simi)
                    idx_min = np.argmin(simi)

                    # 如果大于阈值,说明人脸库中,已经有了相似的人脸,进行人脸入库

                    max_nums = simi.argsort()[-5:][::-1]
                    if simi[idx] > args.max_threshold:
                        npz_embs, npz_emb_len = face_in_storage(args, npz_embs, npz_emb_len, idx, embedding, item, fd_in_storage, max_nums)
                        pass
                    elif simi[idx] > args.min_threshol:

                        face_not_recog(args, item, not_recog_conut, fd_not_recog, max_nums)
                        not_recog_conut += 1
                        pass
                    else:
                        # 人脸库不存在人脸,则创建一个新的文件夹,入库
                        npz_embs, npz_emb_len = face_create_lib(args, npz_embs, npz_emb_len, embedding, item, fd_create_lib, max_nums)
                        #print(simi[idx])
                        #print('请核实文件,认为其为非人脸: %s' %item[1])
                        pass

                if count % 100 == 0:
                    cur_time = time.time()
                    print('time:', cur_time - pre_time, ' count:', count)
                    pre_time = cur_time
                count += 1
        fd_in_storage.close()
        fd_not_recog.close()
        fd_create_lib.close()
    # 保存npz文件
    np.savez(path, npz_embs=npz_embs, npz_emb_len=npz_emb_len)


def parse_args():
    """Defines all arguments.
    Returns
    -------
    args object that contains all the params
    """
    parser = argparse.ArgumentParser(
        formatter_class=argparse.ArgumentDefaultsHelpFormatter,
        description='Create an image list or \
        make a record database by reading from an image list')

    # 想要生成.lst的目录,再人脸为空的情况下,必须提前为输入以及输出文件夹生成一个.lst文件
    #parser.add_argument('--root', default='/data/zwh/1.FaceRecognition/2.Dataset/2.PaidOnData/2.DataDivi/1.Shunde/3.1.no_recognition' ,help='path to folder containing images.')
    parser.add_argument('--root',default='/data/zwh/1.FaceRecognition/2.Dataset/2.PaidOnData/2.DataDivi/1.Shunde/3.2image_classer',help='path to folder containing images.')

    # 需要进行人脸分类的文件夹
    parser.add_argument('--indir', default='/data/zwh/1.FaceRecognition/2.Dataset/2.PaidOnData/2.DataDivi/1.Shunde/3.1.no_recognition' ,help='path to folder containing images.')

    # 把相同的图片复制到该文件夹,让本人确定是否需要删除该类文件,如果需要删除,把下面的delete参数设置为true即可
    parser.add_argument('--outdir', default='/data/zwh/1.FaceRecognition/2.Dataset/2.PaidOnData/2.DataDivi/1.Shunde/3.2image_classer' ,help='path to folder containing images.')

    # 预训练模型的路径
    parser.add_argument('--model', default='../models/model-y1-test2/model,0', help='path to load model.')
    #parser.add_argument('--model', default='../models/model-y1-test2/model,0', help='path to load model.')

    # 判定是否为同一人的相似度阈值
    parser.add_argument('--max_threshold', default=0.75, type=float, help='')

    # 低于该阈值,确定为一个新的人脸
    parser.add_argument('--min_threshol', default=0.66, type=float, help='')

    cgroup = parser.add_argument_group('Options for creating image lists')


    # 该处填写为True,则代表是为root对应的目录下生成.lst文件,注意,此时不会进行人脸分类
    cgroup.add_argument('--list', default=False,help='')

    cgroup.add_argument('--no-shuffle', dest='shuffle', action='store_true',
                        help='If this is passed, \
        im2rec will not randomize the image order in .lst')

    # 需要分类图片的格式
    cgroup.add_argument('--exts', nargs='+', default=['.jpeg', '.jpg', '.png','.bmp'],
                        help='list of acceptable image extensions.')

    # 是否进行递归搜索
    cgroup.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.')


    # 进行分类相关的参数
    rgroup = parser.add_argument_group('Options for creating database')

    # 检测出来人脸保存的大小
    rgroup.add_argument('--resize', type=int, default=0,
                        help='resize the shorter edge of image to the newsize, original images will\
        be packed by default.')

    # 是否删除输入文件夹的文件
    rgroup.add_argument('--delete', default=True, type=bool, help='')

    # 读取图片,进行解码的线程数目
    rgroup.add_argument('--num-thread', type=int, default=3,
                        help='number of thread to use for encoding. order of images will be different\
        from the input list if >1. the input list will be modified to match the\
        resulting order.')

    # 读取的颜色格式,一般选取默认值
    rgroup.add_argument('--color', type=int, default=1, choices=[-1, 0, 1],
                        help='specify the color mode of the loaded image.\
        1: Loads a color image. Any transparency of image will be neglected. It is the default flag.\
        0: Loads image in grayscale mode.\
        -1:Loads image as such including alpha channel.')

    # 需要生成图片的格式
    rgroup.add_argument('--encoding', type=str, default='.jpg', choices=['.jpg', '.png','.bmp'],
                        help='specify the encoding of the images.')

    args = parser.parse_args()
    args.root = os.path.abspath(args.root)
    npz_path = os.path.join(args.outdir,'embeddings.npz')

    # 如果输出目录不存在embeddings文件,则为输出目录先生成embeddings文件
    if not os.path.exists(npz_path):
        args.indir =args.outdir
    return args

if __name__ == '__main__':
    args = parse_args()
    # if the '--list' is used, it generates .lst file
    if args.list:
        make_list(args)
    # otherwise read .lst file to generates .rec file
    else:
        # 列出输入目录的所有文件
        files = [os.path.join(args.indir, fname) for fname in os.listdir(args.indir)
                    if os.path.isfile(os.path.join(args.indir, fname))]

        count = 0
        for fname in files:
            # 判断该文件是否以.lst结尾
            if fname.endswith('.lst'):
                count += 1
                # 读取文件的所有内容
                image_list = read_list(fname)

                # -- write_record -- #
                # 为每个输入进程创建一个队列
                q_in = [multiprocessing.Queue(1024) for i in range(args.num_thread)]
                # 创建单个输出队列
                q_out = multiprocessing.Queue(1024)

                # define the process
                # 定义输入进程,用来读取图片
                read_process = [multiprocessing.Process(target=read_worker, args=(args, q_in[i], q_out)) \
                                for i in range(args.num_thread)]

                # process images with num_thread process
                # 启动所有输入进程,开始读取图片
                for p in read_process:
                    p.start()

                # only use one process to write .rec to avoid race-condtion
                # 创建一个读取进程。并且启动
                write_process = multiprocessing.Process(target=write_worker, args=(q_out, fname, args))
                write_process.start()


                # put the image list into input queue
                # 循环把要读取的图片,分配给每一个读取进程
                for i, item in enumerate(image_list):
                    q_in[i % len(q_in)].put((i, item))

                # 任务分派完成之后,再为每个输入进程分配一个None
                for q in q_in:
                    q.put(None)

                # 等待每个输入进程结束
                for p in read_process:
                    p.join()

                # 给输出队列放入一个None,代表结束
                q_out.put(None)

                # 等待输出进程(写进程)结束
                write_process.join()

        if not count:
            print('Did not find and list file with prefix %s'%args.prefix)

为了大家能够轻松的使用该程序,这里为大家讲解一下,首先是要指定输入和输出目录,输入目录为再上小节博客中,得到的矫正过的人脸图。输出目录可以任意指定,但是必须存在两个子文件夹,并且该两个文件夹必须包含一张人脸图片目录命名如下: 在这里插入图片描述 图片命名如下 在这里插入图片描述 然后为输入以及输出目录生成.lst文件(注意,输入和输出都需要生成lst),生产该文件,要把参数:

    # 该处填写为True,则代表是为root对应的目录下生成.lst文件,注意,此时不会进行人脸分类
    cgroup.add_argument('--list', default=False,
                        help='If this is set im2rec will create image list(s) by traversing root folder\
        and output to .lst.\
        Otherwise im2rec will read .lst and create a database at .rec')

设置为Ture,然后再指定root:

    # 想要生成.lst的目录,再人脸为空的情况下,必须提前为输入以及输出文件夹生成一个.lst文件(手动放入照片)
    parser.add_argument('--root', default='D:/03.work/02.development/04.PaidOn/1.FaceRecognition/2.Dataset/2.PaidOnData/1.TrainData/CASIA-FaceV5/00000009' ,help='path to folder containing images.')

就会为了root目录生成lst文件,为了分别在输入以及输出目录下生成lst文件,需要指定两次,即执行两次该程序。

上述完成之后,再把’–list’设置为True,执行该程序,第一次会在输出目录下生成.npz文件,保存人脸库的特征向量,以及每个ID对应的图片数目。

生成.npz文件之后,再次执行该程序,就能进行人脸分类入库了。

所以,第一次使用该程序的时候,需要执行四次(重点,看看自己执行了几次),还有一个注意的要点就是,'–threshold’阈值的设定,该阈值需要自己调试,一般华人在0.7左右。当然,这个根据每个人的数据集不同,需要进行相应的调整(如果报错请使用下面的规则化)。

文件规则化

如果,你已经有了人脸库,那么需要对人脸库进行规则化,这是本人编写的脚本:

import os
import argparse

def dirs_rename(args):
    newdir_idx = args.stdir_idx
    for old_path, dirs, files in os.walk(args.root, followlinks=True):

        if old_path == args.root:
            print('-'*50)
            continue
        num_file =0
        for old_file in files:
            if old_file[-4:] == args.img_suffix:
                new_file = '%04d%s' %(num_file,args.img_suffix)
                old_fil_path = os.path.join(old_path,old_file)
                new_fil_path = os.path.join(old_path, new_file)
               # print(old_fil_path)
                #print(new_fil_path)
                os.rename(old_fil_path,new_fil_path)
                num_file += 1

        old_path_prefix =  old_path.replace('\\','/').split('/')
        old_path_prefix = '/'.join(old_path_prefix[:-1])

        new_path_suffix = '%08d' %(newdir_idx)

        new_path = os.path.join(old_path_prefix,new_path_suffix)
        #print('old_path',old_path + '/')
        #print('new_path',new_path + '/')
        os.rename(old_path, new_path)
        newdir_idx += 1



def parse_args():
    parser = argparse.ArgumentParser(
        formatter_class=argparse.ArgumentDefaultsHelpFormatter,
        description='文件夹里面的命名')

    parser.add_argument('--root', default='D:/03.work/02.development/04.PaidOn/1.FaceRecognition/2.Dataset/2.PaidOnData/1.TrainData/CASIA-FaceV5/112x112', help='prefix of input/output lst and rec files.')
    parser.add_argument('--stdir_idx', default=0, type=int, help = '文件夹序列的起始数字')
    parser.add_argument('--img_suffix', type=str, default='.bmp', choices=['.jpg', '.png','.bmp'],
                        help='specify the encoding of the images.')
    args = parser.parse_args()
    return args

if __name__ == '__main__':
    args = parse_args()
    dirs_rename(args)
    pass

需要把人脸库规则化之后,才能正确的进行入库。规则化效果如下:

在这里插入图片描述 在这里插入图片描述

生成文件介绍

运行完成之后,我们可以看到输入文件夹下面生成了三个文件: 在这里插入图片描述

在前面的人脸分类程序中,可以看到:

    # 判定是否为同一人的相似度阈值
    parser.add_argument('--max_threshold', default=0.75, type=float, help='')

    # 低于该阈值,确定为一个新的人脸
    parser.add_argument('--min_threshol', default=0.66, type=float, help='')

其中create_lib.txt记录的,就是低于阈值的人脸,表示在人脸库中没有找到合适的人脸,则需要重新创建一个文件夹,create_lib.txt就是创建新的文件夹的记录。 in_storage.txt代表的是入库操作,表示在人脸库中找到了高于阈值的人脸,只要把图片复制过去就可以了。 not_recog.txt表示的是不能识别的图像,他被拷贝到输入文件的not_recognition文件夹下面,在该文件的最右边,我们可以看到一个数组: 在这里插入图片描述 测试的相似度,在两个阈值之间,表示他也不能确定人脸库中有没有对应的人脸,上图的数组,就是表示人脸库中,与他最相似人脸的前四个,从左到右,从大到小进行排序。注意,数组是文件夹的名字。

关注
打赏
1592542134
查看更多评论
立即登录/注册

微信扫码登录

0.0723s