def load_all_data(self):
     # 将以前标记的数据全部读入(直接读入的是特征), 用LSH Forest保存,方便计算距离
     current_day = get_current_day()
     log_file = open(os.path.join(log_dir, current_day + '.txt'), 'a')
     try:
         all_pic_feature, all_label = self.load_train_data(
             self.all_pic_feature_data_folder)
         train_label = np.asarray(all_label)
         if len(all_pic_feature) == len(
                 train_label) and len(train_label) > 0:
             start = time.time()
             self.lshf.fit(all_pic_feature, train_label)
             self.all_pic_feature = list(all_pic_feature)
             self.all_labels = list(train_label)
             end = time.time()
             self.load_time = end
             self.user_count = Counter(self.all_labels)
             log_file.write('\t'.join(
                 map(str, [
                     self.user_count, 'fit all data time :', (end - start)
                 ])) + '\n')
             log_file.close()
     except:
         traceback.print_exc()
         log_file.close()
         return
def extract_feature(face_array):
    '''
        先计算角度, 满足条件后再进行对齐和识别
    :param face_array: RGB读入的数据(dtype=uint8) [0-255]
    :return:
    '''
    start = time.time()
    current_day = get_current_day()
    current_time = get_current_time()
    log_file = open(os.path.join(log_dir, current_day + '.txt'), 'a')

    blur_sign, blur_var = is_blur(face_array)
    if blur_sign:
        print 'blur_filter', blur_var
        feature_vector = np.reshape(np.asarray([0] * feature_dim), (1, feature_dim))
        log_file.write('\t'.join(map(str, [current_time, 'blur', 'not_process', 'recognition_time :',
                                           (time.time() - start)])) + '\n')
        return feature_vector

    need_process = check_face_img(face_img=face_array)
    if not need_process:
        feature_vector = np.reshape(np.asarray([0] * feature_dim), (1, feature_dim))
        log_file.write('\t'.join(map(str, [current_time, 'pose', 'not_process', 'recognition_time :',
                                           (time.time() - start)])) + '\n')
        return feature_vector

    # 自己检测对齐
    face_align_array = align_face_rgb_array(face_array, bb=None)
    face_align_array = normalize_rgb_array(cv2.resize(face_align_array, (size, size)))
    feature_vector = get_Conv_FeatureMap([face_align_array, 0])[0].copy()
    log_file.write('\t'.join(map(str, [current_time, 'process', 'recognition_time :', (time.time() - start)])) + '\n')
    log_file.close()
    return feature_vector
 def add_one_new_pic(self, pic_path, label):
     current_day = get_current_day()
     log_file = open(os.path.join(log_dir, current_day + '.txt'), 'a')
     try:
         # 读入数据时已经转换成需要的尺寸
         result = self.extract_pic_feature(pic_path)
         if result == None:
             return False
         face_pic, pic_feature = result
         self.add_one_pic(pic_feature, label)
         pic_name = os.path.split(pic_path)[1]
         this_person_pic_folder = os.path.join(self.all_pic_data_folder,
                                               label)
         this_person_feature_folder = os.path.join(
             self.all_pic_feature_data_folder, label)
         if not os.path.exists(this_person_pic_folder):
             os.makedirs(this_person_pic_folder)
         if not os.path.exists(this_person_feature_folder):
             os.makedirs(this_person_feature_folder)
         # 直接存储图片对应的特征, 同时保存图片文件
         this_pic_feature_name = os.path.join(this_person_feature_folder,
                                              pic_name + '.p')
         msgpack_numpy.dump(pic_feature, open(this_pic_feature_name, 'wb'))
         this_pic_face_name = os.path.join(this_person_pic_folder,
                                           pic_name + '.jpg')
         cv2.imwrite(this_pic_face_name, face_pic)
         log_file.write(
             '\t'.join(map(str, [pic_path, this_pic_face_name])) + '\n')
         return True
     except:
         traceback.print_exc()
         return False
    def cal_nearest_sim(self, current_feature):
        nearest_sim_list = []
        current_day = get_current_day()
        log_file = open(os.path.join(log_dir, current_day + '.txt'), 'a')

        try:
            length = len(self.nearest)
            for k in range(length):
                try:
                    person_name, pre_feature = self.nearest[k]
                    # 不在考虑时间, 只考虑图片的相似度

                    this_sim = pw.cosine_similarity(
                        np.reshape(np.asarray(pre_feature),
                                   (1, len(pre_feature))),
                        np.reshape(np.asarray(current_feature),
                                   (1, len(current_feature))))
                    nearest_sim_list.append(
                        (this_sim, verification_model.predict(this_sim),
                         person_name))
                except:
                    log_file.write('cal_nearest_sim error' + '\n')
                    traceback.print_exc()
                    continue
            return nearest_sim_list
        except:
            traceback.print_exc()
            return nearest_sim_list
 def add_one_new_pic(self, pic_path, label):
     current_day = get_current_day()
     log_file = open(os.path.join(log_dir, current_day+'.txt'), 'a')
     try:
         # 读入数据时已经转换成需要的尺寸
         result = self.extract_pic_feature(pic_path)
         if result == None:
             return False
         face_pic, pic_feature = result
         self.add_one_pic(pic_feature, label)
         pic_name = os.path.split(pic_path)[1]
         this_person_pic_folder = os.path.join(self.all_pic_data_folder, label)
         this_person_feature_folder = os.path.join(self.all_pic_feature_data_folder, label)
         if not os.path.exists(this_person_pic_folder):
             os.makedirs(this_person_pic_folder)
         if not os.path.exists(this_person_feature_folder):
             os.makedirs(this_person_feature_folder)
         # 直接存储图片对应的特征, 同时保存图片文件
         this_pic_feature_name = os.path.join(this_person_feature_folder, pic_name + '.p')
         msgpack_numpy.dump(pic_feature, open(this_pic_feature_name, 'wb'))
         this_pic_face_name = os.path.join(this_person_pic_folder, pic_name + '.jpg')
         cv2.imwrite(this_pic_face_name, face_pic)
         log_file.write('\t'.join(map(str, [pic_path, this_pic_face_name]))+'\n')
         return True
     except:
         traceback.print_exc()
         return False
    def add_all_new_pic(self):
        '''
            将从上次加载数据到当前新增的文件都加载到LSH Forest(有可能是新增加一个人,还有可能是对已有的人增加新图片)
            遍历文件夹(self.all_pic_data_folder),根据文件的时间判断是否需要加入该图片
            用户新加入的图片先进行人脸检测, 如果能够检测到人脸,使用检测结果, 否则使用用户的原始图片
        '''
        current_day = get_current_day()
        log_file = open(os.path.join(log_dir, current_day + '.txt'), 'a')

        start = time.time()
        person_list = os.listdir(self.all_pic_data_folder)
        add_num = 0
        for person in person_list:
            if self.must_same_str in person or self.maybe_same_str in person or self.new_person_str in person:
                continue
            person_path = os.path.join(self.all_pic_data_folder, person)
            if not os.path.isdir(person_path):
                continue
            pic_list = os.listdir(person_path)
            for pic in pic_list:
                pic_path = os.path.join(person_path, pic)
                last_modify_time = os.stat(pic_path).st_atime
                if last_modify_time > self.load_time:
                    # 请求本地服务
                    request = {
                        "label": person,
                        "request_type": 'add',
                        "one_pic_feature": pic_path
                    }
                    url = "http://127.0.0.1:%d/" % port
                    result = image_request(request, url)
                    try:
                        add_flag = json.loads(result)["add"]
                        if not add_flag:  # 加载失败
                            log_file.write('\t'.join(
                                map(str, ['no add file :', pic_path])) + '\n')
                        else:
                            add_num += 1
                    except:
                        log_file.write(
                            '\t'.join(map(str, ['no add file :', pic_path])) +
                            '\n')
                        traceback.print_exc()
                        continue
                    add_num += 1
        end = time.time()
        if add_num > 0:
            self.load_time = end
            log_file.write(
                '\t'.join(map(str, ['self.load_time', self.load_time])) + '\n')
            log_file.write('\t'.join(
                map(str, [
                    'add pic num :', add_num, 'Dynamic increase time :',
                    (end - start)
                ])) + '\n')
            log_file.close()
        else:
            log_file.close()
def check_face_img(face_img):
    # pose_predict(姿势): [[pitch, yaw, roll]](Pitch: 俯仰; Yaw: 摇摆; Roll: 倾斜)
    '''
    :param face_img: 人脸对应的矩阵
    :param image_id: 图片id
    :return: 是否进行识别(False:不进行识别)
    '''

    current_day = get_current_day()
    log_file = open(os.path.join(log_dir, current_day + '.txt'), 'a')

    face_img_str = base64.b64encode(msgpack_numpy.dumps(face_img))
    request = {
        "request_type": 'check_pose',
        "face_img_str": face_img_str,
        "image_id": str(time.time())
    }
    result = requests.post(angle_url, data=request)

    try:
        if result.status_code == 200:
            pose_predict = json.loads(result.content)["pose_predict"]
            if not pose_predict:  # 加载失败
                log_file.write('\t'.join(map(str, ['pose filter request'])) +
                               '\n')
                log_file.close()
                return False
            else:
                pose_predict = msgpack_numpy.loads(
                    base64.b64decode(pose_predict))
                if pose_predict == None:
                    log_file.write(
                        '\t'.join(map(str, ['pose filter detect'])) + '\n')
                    log_file.close()
                    return False
                pitch, yaw, roll = pose_predict[0]
                if math.fabs(pitch) < pitch_threshold and math.fabs(
                        yaw) < yaw_threshold and math.fabs(
                            roll) < roll_threshold:
                    log_file.write('\t'.join(
                        map(str, ['pose not filter',
                                  str(pose_predict[0])])) + '\n')
                    log_file.close()
                    return True
                else:
                    log_file.write('\t'.join(
                        map(str,
                            ['pose filter threshold',
                             str(pose_predict[0])])) + '\n')
                    log_file.close()
                    return False
        else:
            return False
    except:
        traceback.print_exc()
        log_file.close()
        return False
    def check_face_img(self, face_img, image_id):
        # 计算角度
        '''
        :param face_img: 人脸对应的矩阵
        :param image_id: 图片id
        :return: 是否进行识别(False:不进行识别)
        '''
        # 姿势检测

        current_day = get_current_day()
        log_file = open(os.path.join(log_dir, current_day + '.txt'), 'a')

        face_img_str = base64.b64encode(msgpack_numpy.dumps(face_img))
        request = {
            "request_type": 'check_pose',
            "face_img_str": face_img_str,
            "image_id": image_id,
        }
        url = "http://%s:%d/" % (check_ip, check_port)
        result = image_request(request, url)
        try:
            pose_predict = json.loads(result)["pose_predict"]
            if not pose_predict:  # 加载失败
                log_file.write(
                    '\t'.join(map(str, [image_id, 'pose filter request'])) +
                    '\n')
                log_file.close()
                return False
            else:
                pose_predict = msgpack_numpy.loads(
                    base64.b64decode(pose_predict))
                if pose_predict == None:
                    log_file.write(
                        '\t'.join(map(str, [image_id, 'pose filter detect'])) +
                        '\n')
                    log_file.close()
                    return False
                pitch, yaw, roll = pose_predict[0]
                if math.fabs(pitch) < self.pitch_threshold and \
                        math.fabs(yaw) < self.yaw_threshold and \
                        math.fabs(roll) < self.roll_threshold:
                    log_file.close()
                    return True
                else:
                    log_file.write('\t'.join(
                        map(str, [image_id, 'pose filter threshold'])) + '\n')
                    log_file.close()
                    return False
        except:
            traceback.print_exc()
            log_file.close()
            return False
    def add_all_new_pic(self):
        '''
            将从上次加载数据到当前新增的文件都加载到LSH Forest(有可能是新增加一个人,还有可能是对已有的人增加新图片)
            遍历文件夹(self.all_pic_data_folder),根据文件的时间判断是否需要加入该图片
            用户新加入的图片先进行人脸检测, 如果能够检测到人脸,使用检测结果, 否则使用用户的原始图片
        '''
        current_day = get_current_day()
        log_file = open(os.path.join(log_dir, current_day+'.txt'), 'a')

        start = time.time()
        person_list = os.listdir(self.all_pic_data_folder)
        add_num = 0
        for person in person_list:
            if self.must_same_str in person or self.maybe_same_str in person or self.new_person_str in person:
                continue
            person_path = os.path.join(self.all_pic_data_folder, person)
            if not os.path.isdir(person_path):
                continue
            pic_list = os.listdir(person_path)
            for pic in pic_list:
                pic_path = os.path.join(person_path, pic)
                last_modify_time = os.stat(pic_path).st_atime
                if last_modify_time > self.load_time:
                    # 请求本地服务
                    request = {
                        "label": person,
                        "request_type": 'add',
                        "one_pic_feature": pic_path
                    }
                    url = "http://127.0.0.1:%d/"%port
                    result = image_request(request, url)
                    try:
                        add_flag = json.loads(result)["add"]
                        if not add_flag:# 加载失败
                            log_file.write('\t'.join(map(str, ['no add file :', pic_path]))+'\n')
                        else:
                            add_num += 1
                    except:
                        log_file.write('\t'.join(map(str, ['no add file :', pic_path]))+'\n')
                        traceback.print_exc()
                        continue
                    add_num += 1
        end = time.time()
        if add_num > 0:
            self.load_time = end
            log_file.write('\t'.join(map(str, ['self.load_time', self.load_time]))+'\n')
            log_file.write('\t'.join(map(str, ['add pic num :', add_num,
                                               'Dynamic increase time :', (end - start)]))+'\n')
            log_file.close()
        else:
            log_file.close()
def extract_feature(face_array):
    '''
    :param face_array: RGB读入的数据(dtype=uint8) [0-255]
    :return:
    '''
    start = time.time()
    current_day = get_current_day()
    current_time = get_current_time()
    log_file = open(os.path.join(log_dir, current_day + '.txt'), 'a')
    face_align_array = align_face_rgb_array(face_array, bb=dlib.rectangle(0, 0, face_array.shape[1], face_array.shape[0]))
    face_align_array = normalize_rgb_array(cv2.resize(face_align_array, (size, size)))
    feature_vector = get_Conv_FeatureMap([face_align_array, 0])[0].copy()
    log_file.write('\t'.join(map(str, [current_time, 'recognition_time :', (time.time() - start)])) + '\n')
    log_file.close()
    print (time.time() - start)
    return feature_vector
 def post(self):
     start = time.time()
     current_day = get_current_day()
     current_time = get_current_time()
     log_file = open(os.path.join(log_dir, current_day + '.txt'), 'a')
     pic_binary_data = self.request.body
     open('/tmp/face_recog_tmp/'+str(time.time())+'.jpg', 'wb').write(pic_binary_data)
     img_buffer = StringIO(pic_binary_data)
     img_array = np.array(Image.open(img_buffer))
     img_array_bgr = cv2.cvtColor(img_array, cv2.COLOR_RGB2BGR)
     print 'img_array_bgr.shape :', img_array_bgr.shape
     result = detect_recognize_face(img_array_bgr)
     self.write(result)
     end = time.time()
     log_file.write('\t'.join(map(str, [current_time, 'get_pic', 'all_time :', (end - start)])) + '\n')
     log_file.close()
    def check_face_img(self, face_img, image_id):
        # 计算角度
        '''
        :param face_img: 人脸对应的矩阵
        :param image_id: 图片id
        :return: 是否进行识别(False:不进行识别)
        '''
        # 姿势检测

        current_day = get_current_day()
        log_file = open(os.path.join(log_dir, current_day+'.txt'), 'a')

        face_img_str = base64.b64encode(msgpack_numpy.dumps(face_img))
        request = {
            "request_type": 'check_pose',
            "face_img_str": face_img_str,
            "image_id": image_id,
        }
        url = "http://%s:%d/" % (check_ip, check_port)
        result = image_request(request, url)
        try:
            pose_predict = json.loads(result)["pose_predict"]
            if not pose_predict:  # 加载失败
                log_file.write('\t'.join(map(str, [image_id, 'pose filter request'])) + '\n')
                log_file.close()
                return False
            else:
                pose_predict = msgpack_numpy.loads(base64.b64decode(pose_predict))
                if pose_predict == None:
                    log_file.write('\t'.join(map(str, [image_id, 'pose filter detect'])) + '\n')
                    log_file.close()
                    return False
                pitch, yaw, roll = pose_predict[0]
                if math.fabs(pitch) < self.pitch_threshold and \
                        math.fabs(yaw) < self.yaw_threshold and \
                        math.fabs(roll) < self.roll_threshold:
                    log_file.close()
                    return True
                else:
                    log_file.write('\t'.join(map(str, [image_id, 'pose filter threshold'])) + '\n')
                    log_file.close()
                    return False
        except:
            traceback.print_exc()
            log_file.close()
            return False
def extract_feature(face_array):
    '''
        先计算角度, 满足条件后再进行对齐和识别
    :param face_array: RGB读入的数据(dtype=uint8) [0-255]
    :return:
    '''
    start = time.time()
    current_day = get_current_day()
    current_time = get_current_time()
    log_file = open(os.path.join(log_dir, current_day + '.txt'), 'a')

    blur_sign, blur_var = is_blur(face_array)
    if blur_sign:
        print 'blur_filter', blur_var
        feature_vector = np.reshape(np.asarray([0] * feature_dim),
                                    (1, feature_dim))
        log_file.write('\t'.join(
            map(str, [
                current_time, 'blur', 'not_process', 'recognition_time :',
                (time.time() - start)
            ])) + '\n')
        return feature_vector

    need_process = check_face_img(face_img=face_array)
    if not need_process:
        feature_vector = np.reshape(np.asarray([0] * feature_dim),
                                    (1, feature_dim))
        log_file.write('\t'.join(
            map(str, [
                current_time, 'pose', 'not_process', 'recognition_time :',
                (time.time() - start)
            ])) + '\n')
        return feature_vector

    # 自己检测对齐
    face_align_array = align_face_rgb_array(face_array, bb=None)
    face_align_array = normalize_rgb_array(
        cv2.resize(face_align_array, (size, size)))
    feature_vector = get_Conv_FeatureMap([face_align_array, 0])[0].copy()
    log_file.write('\t'.join(
        map(str, [
            current_time, 'process', 'recognition_time :', (time.time() -
                                                            start)
        ])) + '\n')
    log_file.close()
    return feature_vector
def check_face_img(face_img):
    # pose_predict(姿势): [[pitch, yaw, roll]](Pitch: 俯仰; Yaw: 摇摆; Roll: 倾斜)
    '''
    :param face_img: 人脸对应的矩阵
    :param image_id: 图片id
    :return: 是否进行识别(False:不进行识别)
    '''

    current_day = get_current_day()
    log_file = open(os.path.join(log_dir, current_day + '.txt'), 'a')

    face_img_str = base64.b64encode(msgpack_numpy.dumps(face_img))
    request = {"request_type": 'check_pose', "face_img_str": face_img_str, "image_id": str(time.time())}
    result = requests.post(angle_url, data=request)

    try:
        if result.status_code == 200:
            pose_predict = json.loads(result.content)["pose_predict"]
            if not pose_predict:  # 加载失败
                log_file.write('\t'.join(map(str, ['pose filter request'])) + '\n')
                log_file.close()
                return False
            else:
                pose_predict = msgpack_numpy.loads(base64.b64decode(pose_predict))
                if pose_predict == None:
                    log_file.write('\t'.join(map(str, ['pose filter detect'])) + '\n')
                    log_file.close()
                    return False
                pitch, yaw, roll = pose_predict[0]
                if math.fabs(pitch) < pitch_threshold and math.fabs(yaw) < yaw_threshold and math.fabs(roll) < roll_threshold:
                    log_file.write('\t'.join(map(str, ['pose not filter', str(pose_predict[0])])) + '\n')
                    log_file.close()
                    return True
                else:
                    log_file.write('\t'.join(map(str, ['pose filter threshold', str(pose_predict[0])])) + '\n')
                    log_file.close()
                    return False
        else:
            return False
    except:
        traceback.print_exc()
        log_file.close()
        return False
    def find_current_new_person_id(self):
        current_day = get_current_day()
        log_file = open(os.path.join(log_dir, current_day+'.txt'), 'a')

        old_person_id = []
        person_list = os.listdir(self.all_pic_data_folder)
        for person in person_list:
            if person.startswith(self.new_person_str):
                tmp = person[len(self.new_person_str):].split('_')
                if len(tmp) > 0:
                    this_id = int(tmp[0])
                    old_person_id.append(this_id)
        if len(old_person_id) == 0:
            current_new_person_id = 0
        else:
            current_new_person_id = max(old_person_id) + 1
        log_file.write('\t'.join(map(str, ['current_new_person_id :', current_new_person_id]))+'\n')
        log_file.close()
        return current_new_person_id
    def load_all_data(self):
        # 将以前标记的数据全部读入,用LSH Forest保存,方便计算距离
        current_day = get_current_day()
        log_file = open(os.path.join(log_dir, current_day+'.txt'), 'a')

        train_data, train_label = load_train_data(self.all_pic_data_folder)
        if len(train_label) == 0:
            return
        pic_feature = self.extract_pic_feature(train_data)
        start = time.time()
        self.lshf.fit(pic_feature, train_label)
        self.all_pic_feature = list(pic_feature)
        self.all_labels = list(train_label)
        end = time.time()
        self.load_time = end
        self.user_count = Counter(self.all_labels)
        log_file.write('\t'.join(map(str, [self.user_count,
                                           'fit all data time :', (end - start)]))+'\n')
        log_file.close()
 def post(self):
     start = time.time()
     current_day = get_current_day()
     current_time = get_current_time()
     log_file = open(os.path.join(log_dir, current_day + '.txt'), 'a')
     pic_binary_data = self.request.body
     open('/tmp/face_recog_tmp/' + str(time.time()) + '.jpg',
          'wb').write(pic_binary_data)
     img_buffer = StringIO(pic_binary_data)
     img_array = np.array(Image.open(img_buffer))
     img_array_bgr = cv2.cvtColor(img_array, cv2.COLOR_RGB2BGR)
     print 'img_array_bgr.shape :', img_array_bgr.shape
     result = detect_recognize_face(img_array_bgr)
     self.write(result)
     end = time.time()
     log_file.write('\t'.join(
         map(str, [current_time, 'get_pic', 'all_time :', (end - start)])) +
                    '\n')
     log_file.close()
    def load_all_data(self):
        # 将以前标记的数据全部读入,用LSH Forest保存,方便计算距离
        current_day = get_current_day()
        log_file = open(os.path.join(log_dir, current_day + '.txt'), 'a')

        train_data, train_label = load_train_data(self.all_pic_data_folder)
        if len(train_label) == 0:
            return
        pic_feature = self.extract_pic_feature(train_data)
        start = time.time()
        self.lshf.fit(pic_feature, train_label)
        self.all_pic_feature = list(pic_feature)
        self.all_labels = list(train_label)
        end = time.time()
        self.load_time = end
        self.user_count = Counter(self.all_labels)
        log_file.write('\t'.join(
            map(str, [self.user_count, 'fit all data time :',
                      (end - start)])) + '\n')
        log_file.close()
    def find_current_new_person_id(self):
        current_day = get_current_day()
        log_file = open(os.path.join(log_dir, current_day + '.txt'), 'a')

        old_person_id = []
        person_list = os.listdir(self.all_pic_data_folder)
        for person in person_list:
            if person.startswith(self.new_person_str):
                tmp = person[len(self.new_person_str):].split('_')
                if len(tmp) > 0:
                    this_id = int(tmp[0])
                    old_person_id.append(this_id)
        if len(old_person_id) == 0:
            current_new_person_id = 0
        else:
            current_new_person_id = max(old_person_id) + 1
        log_file.write('\t'.join(
            map(str, ['current_new_person_id :', current_new_person_id])) +
                       '\n')
        log_file.close()
        return current_new_person_id
 def load_all_data(self):
     # 将以前标记的数据全部读入(直接读入的是特征), 用LSH Forest保存,方便计算距离
     current_day = get_current_day()
     log_file = open(os.path.join(log_dir, current_day+'.txt'), 'a')
     try:
         all_pic_feature, all_label = self.load_train_data(self.all_pic_feature_data_folder)
         train_label = np.asarray(all_label)
         if len(all_pic_feature) == len(train_label) and len(train_label) > 0:
             start = time.time()
             self.lshf.fit(all_pic_feature, train_label)
             self.all_pic_feature = list(all_pic_feature)
             self.all_labels = list(train_label)
             end = time.time()
             self.load_time = end
             self.user_count = Counter(self.all_labels)
             log_file.write('\t'.join(map(str, [self.user_count,
                                        'fit all data time :', (end - start)]))+'\n')
             log_file.close()
     except:
         traceback.print_exc()
         log_file.close()
         return
    def cal_nearest_sim(self, current_feature):
        nearest_sim_list = []
        current_day = get_current_day()
        log_file = open(os.path.join(log_dir, current_day+'.txt'), 'a')

        try:
            length = len(self.nearest)
            for k in range(length):
                try:
                    person_name, pre_feature = self.nearest[k]
                    # 不在考虑时间, 只考虑图片的相似度

                    this_sim = pw.cosine_similarity(np.reshape(np.asarray(pre_feature), (1, len(pre_feature))),
                                                        np.reshape(np.asarray(current_feature), (1, len(current_feature))))
                    nearest_sim_list.append((this_sim, verification_model.predict(this_sim), person_name))
                except:
                    log_file.write('cal_nearest_sim error'+'\n')
                    traceback.print_exc()
                    continue
            return nearest_sim_list
        except:
            traceback.print_exc()
            return nearest_sim_list
    def recognize_online_cluster(self, image, image_id):
        '''
            :param image: 将得到的图片进行识别,加入的LSH Forest,根据距离计算proba(不同的距离对应不同的准确率,根据已有的dist计算阈值);
                            和已经设定的阈值判断是不是一个新出现的人,确定是原来已有的人,还是不确定是原来已有的人
            :return:
        '''
        start = time.time()
        need_add = False
        need_save = False
        current_day = get_current_day()
        log_file = open(os.path.join(log_dir, current_day+'.txt'), 'a')
        log_file.write('\t'.join(map(str, ["receive image", image_id, time.time()])) + '\n')
        feature_str = ''
        try:
            image = base64.decodestring(image)
            image = zlib.decompress(image)
            im = cv2.imdecode(np.fromstring(image, dtype=np.uint8), 1)
            log_file.write('\t'.join(map(str, ['shape :', im.shape[0], im.shape[1]])) + '\n')
            # 图片尺寸过滤
            if im.shape[0] < size_threshold or im.shape[1] < size_threshold:
                log_file.write('\t'.join(map(str, ['stat recognize_time :', (time.time() - start), 'small_size'])) + '\n')
                log_file.close()
                return self.unknown, 1.0, feature_str, need_save
            # 清晰度过滤
            blur_sign, blur_var = is_blur(cv2.resize(im, (96, 96)))
            if blur_sign:
                log_file.write('\t'.join(map(str, ['stat recognize_time :', (time.time() - start), 'blur_filter', blur_var])) + '\n')
                log_file.close()
                return self.unknown, 1.0, feature_str, need_save
            #  保存传过来的图片
            # img_file = '/tmp/research_face/%s.jpg' %image_id
            time_slot = get_time_slot(image_id)
            if time_slot == None:
                time_slot = 'error'
            time_slot_dir = os.path.join(tmp_face_dir, time_slot)
            if not os.path.exists(time_slot_dir):
                os.makedirs(time_slot_dir)
            img_file = os.path.join(time_slot_dir, image_id+'.jpg')
            cv2.imwrite(img_file, im)
        except:
            traceback.print_exc()
            log_file.close()
            return self.unknown, 1.0, feature_str, need_save
        try:
            # 流程 : 找距离最近的图片 ; 计算prob ; 在线聚类 ; 加入LSH Forest
            result = self.extract_pic_feature(img_file)
            if result == None:
                log_file.write('\t'.join(map(str, ['stat not_find_face', 'time :', (time.time() - start)]))+'\n')
                log_file.close()
                return self.unknown, 1.0, feature_str, need_save
            face_pic, im_feature = result

            try:
                # nearest_sim_list的格式和dist_label_list的格式一样,这样可以将两个list合并,一起计算(这样不用考虑时间的因素)
                # 在识别出人名后将人名和feature放入到self.nearest
                nearest_sim_list = self.cal_nearest_sim(current_feature=im_feature)
            except:
                traceback.print_exc()
                nearest_sim_list = []
            log_file.write('\t'.join(map(str, ['nearest_sim_list :', map(str, nearest_sim_list)])) + '\n')
            feature_str = base64.b64encode(msgpack_numpy.dumps(im_feature))
            log_file.write('\t'.join(map(str, ['extract_feature_time :', (time.time() - start)]))+'\n')
            # 找距离最近的图片 --- 用LSH Forest 找出最近的10张图片,然后分别计算距离

            tmp_list = self.find_k_neighbors_with_lsh(im_feature)
            nearest_sim_list.sort(key=lambda x: x[0], reverse=True)
            nearest_sim_list.extend(tmp_list)
            dist_label_list = nearest_sim_list[:]

            # 计算
            log_file.write('\t'.join(map(str, ['dist_label_list :', map(str, dist_label_list)])) + '\n')
            if dist_label_list == None:
                this_id = self.must_be_not_same_id
                this_label = self.new_person_str + str(self.current_new_person_id)
            else:
                # 计算prob --- 根据距离计算prob
                this_id, this_label = self.evaluate_result(dist_label_list)
            # 不管概率, 都要将最新的一张图片加入到self.nearest
            self.nearest.append((this_label, im_feature))
            log_file.write('\t'.join(map(str, ['self.nearest :', map(str, self.nearest)])) + '\n')
            # 在线聚类 --- 根据dist确定是重新增加一个人还是加入到已有的人中
            if this_id == self.same_pic_id:
                need_add = False
            elif this_id == self.must_be_same_id:
                need_add = False
                need_save = True
                this_person_pic_folder = os.path.join(self.all_pic_data_folder, this_label+self.must_same_str)
                this_person_feature_folder = os.path.join(self.all_pic_feature_data_folder, this_label+self.must_same_str)
            elif this_id == self.must_be_not_same_id:
                this_label = self.new_person_str + str(self.current_new_person_id)
                self.current_new_person_id += 1
                this_person_pic_folder = os.path.join(self.all_pic_data_folder, this_label)
                this_person_feature_folder = os.path.join(self.all_pic_feature_data_folder, this_label)
                need_add = True
                need_save = True
            elif this_id == self.maybe_same_id:
                this_person_pic_folder = os.path.join(self.all_pic_data_folder, this_label + self.maybe_same_str)
                this_person_feature_folder = os.path.join(self.all_pic_feature_data_folder, this_label + self.maybe_same_str)
                need_add = False # prob在灰度区域的不如入,其余情况加入
                need_save = True
            else:
                log_file.write('\t'.join(map(str, ['error para :', this_id]))+'\n')
            if need_save:
                try:
                    if not os.path.exists(this_person_pic_folder):
                        os.makedirs(this_person_pic_folder)
                    if not os.path.exists(this_person_feature_folder):
                        os.makedirs(this_person_feature_folder)
                    # 直接存储图片对应的特征, 同时保存图片文件
                    this_pic_feature_name = os.path.join(this_person_feature_folder, image_id+'.p')
                    msgpack_numpy.dump(im_feature, open(this_pic_feature_name, 'wb'))
                    this_pic_face_name = os.path.join(this_person_pic_folder, image_id+'.jpg')
                    cv2.imwrite(this_pic_face_name, face_pic)
                except:
                    traceback.print_exc()
                    return self.unknown, 1.0, feature_str, False
            # 加入LSH Forest --- partial_fit
            if need_add:
                self.add_one_pic(im_feature, this_label)
                # 根据label和image_id可以存生成文件名,确定是否要存储文件[可以选择在服务器和本地同时存储]
            if this_id == self.same_pic_id or this_id == self.must_be_not_same_id or this_id == self.must_be_same_id:
                end = time.time()
                log_file.write('\t'.join(map(str, ['stat recognize_time :',(end - start), 'this_id :', self.trans_dic.get(this_id)]))+'\n')
                log_file.close()
                need_save = True
                return this_label.replace(self.must_same_str, ''), str(dist_label_list[0][0]), str(feature_str), str(need_save)
            else:
                # 灰度区域,不显示人名
                end = time.time()
                log_file.write('\t'.join(map(str, ['stat gray_area :',(end - start)]))+'\n')
                log_file.close()
                return self.unknown, str(dist_label_list[0][0]), str(feature_str), str(False)
        except:
            traceback.print_exc()
            log_file.close()
            return self.unknown, str(100.0), str(feature_str), str(False)
    def recognize_online_cluster(self, image, image_id):
        '''
            :param image: 将得到的图片进行识别,加入的LSH Forest,根据距离计算proba(不同的距离对应不同的准确率,根据已有的dist计算阈值);
                            和已经设定的阈值判断是不是一个新出现的人,确定是原来已有的人,还是不确定是原来已有的人
            :return:
        '''
        start = time.time()
        need_add = False
        need_save = False
        current_day = get_current_day()
        log_file = open(os.path.join(log_dir, current_day + '.txt'), 'a')
        log_file.write(
            '\t'.join(map(str, ["receive image", image_id,
                                time.time()])) + '\n')
        feature_str = ''
        try:
            image = base64.decodestring(image)
            image = zlib.decompress(image)
            im = cv2.imdecode(np.fromstring(image, dtype=np.uint8), 1)
            log_file.write(
                '\t'.join(map(str, ['shape :', im.shape[0], im.shape[1]])) +
                '\n')
            # 图片尺寸过滤
            if im.shape[0] < size_threshold or im.shape[1] < size_threshold:
                log_file.write('\t'.join(
                    map(str, [
                        'stat recognize_time :', (time.time() -
                                                  start), 'small_size'
                    ])) + '\n')
                log_file.close()
                return self.unknown, 1.0, feature_str, need_save
            # 清晰度过滤
            blur_sign, blur_var = is_blur(cv2.resize(im, (96, 96)))
            if blur_sign:
                log_file.write('\t'.join(
                    map(str, [
                        'stat recognize_time :',
                        (time.time() - start), 'blur_filter', blur_var
                    ])) + '\n')
                log_file.close()
                return self.unknown, 1.0, feature_str, need_save
            #  保存传过来的图片
            # img_file = '/tmp/research_face/%s.jpg' %image_id
            time_slot = get_time_slot(image_id)
            if time_slot == None:
                time_slot = 'error'
            time_slot_dir = os.path.join(tmp_face_dir, time_slot)
            if not os.path.exists(time_slot_dir):
                os.makedirs(time_slot_dir)
            img_file = os.path.join(time_slot_dir, image_id + '.jpg')
            cv2.imwrite(img_file, im)
        except:
            traceback.print_exc()
            log_file.close()
            return self.unknown, 1.0, feature_str, need_save
        try:
            # 流程 : 找距离最近的图片 ; 计算prob ; 在线聚类 ; 加入LSH Forest
            result = self.extract_pic_feature(img_file)
            if result == None:
                log_file.write('\t'.join(
                    map(str, [
                        'stat not_find_face', 'time :', (time.time() - start)
                    ])) + '\n')
                log_file.close()
                return self.unknown, 1.0, feature_str, need_save
            face_pic, im_feature = result

            try:
                # nearest_sim_list的格式和dist_label_list的格式一样,这样可以将两个list合并,一起计算(这样不用考虑时间的因素)
                # 在识别出人名后将人名和feature放入到self.nearest
                nearest_sim_list = self.cal_nearest_sim(
                    current_feature=im_feature)
            except:
                traceback.print_exc()
                nearest_sim_list = []
            log_file.write('\t'.join(
                map(str, ['nearest_sim_list :',
                          map(str, nearest_sim_list)])) + '\n')
            feature_str = base64.b64encode(msgpack_numpy.dumps(im_feature))
            log_file.write('\t'.join(
                map(str, ['extract_feature_time :', (time.time() - start)])) +
                           '\n')
            # 找距离最近的图片 --- 用LSH Forest 找出最近的10张图片,然后分别计算距离

            tmp_list = self.find_k_neighbors_with_lsh(im_feature)
            nearest_sim_list.sort(key=lambda x: x[0], reverse=True)
            nearest_sim_list.extend(tmp_list)
            dist_label_list = nearest_sim_list[:]

            # 计算
            log_file.write('\t'.join(
                map(str, ['dist_label_list :',
                          map(str, dist_label_list)])) + '\n')
            if dist_label_list == None:
                this_id = self.must_be_not_same_id
                this_label = self.new_person_str + str(
                    self.current_new_person_id)
            else:
                # 计算prob --- 根据距离计算prob
                this_id, this_label = self.evaluate_result(dist_label_list)
            # 不管概率, 都要将最新的一张图片加入到self.nearest
            self.nearest.append((this_label, im_feature))
            log_file.write(
                '\t'.join(map(str, ['self.nearest :',
                                    map(str, self.nearest)])) + '\n')
            # 在线聚类 --- 根据dist确定是重新增加一个人还是加入到已有的人中
            if this_id == self.same_pic_id:
                need_add = False
            elif this_id == self.must_be_same_id:
                need_add = False
                need_save = True
                this_person_pic_folder = os.path.join(
                    self.all_pic_data_folder, this_label + self.must_same_str)
                this_person_feature_folder = os.path.join(
                    self.all_pic_feature_data_folder,
                    this_label + self.must_same_str)
            elif this_id == self.must_be_not_same_id:
                this_label = self.new_person_str + str(
                    self.current_new_person_id)
                self.current_new_person_id += 1
                this_person_pic_folder = os.path.join(self.all_pic_data_folder,
                                                      this_label)
                this_person_feature_folder = os.path.join(
                    self.all_pic_feature_data_folder, this_label)
                need_add = True
                need_save = True
            elif this_id == self.maybe_same_id:
                this_person_pic_folder = os.path.join(
                    self.all_pic_data_folder, this_label + self.maybe_same_str)
                this_person_feature_folder = os.path.join(
                    self.all_pic_feature_data_folder,
                    this_label + self.maybe_same_str)
                need_add = False  # prob在灰度区域的不如入,其余情况加入
                need_save = True
            else:
                log_file.write('\t'.join(map(str, ['error para :', this_id])) +
                               '\n')
            if need_save:
                try:
                    if not os.path.exists(this_person_pic_folder):
                        os.makedirs(this_person_pic_folder)
                    if not os.path.exists(this_person_feature_folder):
                        os.makedirs(this_person_feature_folder)
                    # 直接存储图片对应的特征, 同时保存图片文件
                    this_pic_feature_name = os.path.join(
                        this_person_feature_folder, image_id + '.p')
                    msgpack_numpy.dump(im_feature,
                                       open(this_pic_feature_name, 'wb'))
                    this_pic_face_name = os.path.join(this_person_pic_folder,
                                                      image_id + '.jpg')
                    cv2.imwrite(this_pic_face_name, face_pic)
                except:
                    traceback.print_exc()
                    return self.unknown, 1.0, feature_str, False
            # 加入LSH Forest --- partial_fit
            if need_add:
                self.add_one_pic(im_feature, this_label)
                # 根据label和image_id可以存生成文件名,确定是否要存储文件[可以选择在服务器和本地同时存储]
            if this_id == self.same_pic_id or this_id == self.must_be_not_same_id or this_id == self.must_be_same_id:
                end = time.time()
                log_file.write('\t'.join(
                    map(str, [
                        'stat recognize_time :', (end - start), 'this_id :',
                        self.trans_dic.get(this_id)
                    ])) + '\n')
                log_file.close()
                need_save = True
                return this_label.replace(self.must_same_str, ''), str(
                    dist_label_list[0][0]), str(feature_str), str(need_save)
            else:
                # 灰度区域,不显示人名
                end = time.time()
                log_file.write(
                    '\t'.join(map(str, ['stat gray_area :', (end - start)])) +
                    '\n')
                log_file.close()
                return self.unknown, str(
                    dist_label_list[0][0]), str(feature_str), str(False)
        except:
            traceback.print_exc()
            log_file.close()
            return self.unknown, str(100.0), str(feature_str), str(False)
    def recognize_online_cluster(self, image, image_id):
        '''
            :param image: 将得到的图片进行识别,加入的LSH Forest,根据距离计算proba(不同的距离对应不同的准确率,根据已有的dist计算阈值);
                            和已经设定的阈值判断是不是一个新出现的人,确定是原来已有的人,还是不确定是原来已有的人
            # 增加统计的功能, 方便以后计算过滤原因和比例, 以及识别比例(same, not_same, maybe_same)
            :return:
        '''
        start = time.time()
        need_add = False
        has_save_num = 0
        current_day = get_current_day()
        log_file = open(os.path.join(log_dir, current_day + '.txt'), 'a')
        log_file.write(
            '\t'.join(map(str, ["receive image", image_id,
                                time.time()])) + '\n')
        try:
            image = base64.decodestring(image)
            image = zlib.decompress(image)
            im = cv2.imdecode(np.fromstring(image, dtype=np.uint8), 1)
            time_slot = get_time_slot(image_id)
            if time_slot == None:
                time_slot = 'error'
            time_slot_dir = os.path.join(tmp_face_dir, time_slot)
            if not os.path.exists(time_slot_dir):
                os.makedirs(time_slot_dir)
            tmp_pic_path = os.path.join(time_slot_dir, image_id + '.jpg')
            cv2.imwrite(tmp_pic_path, im)
            blur_result = is_blur(im)
            blur_sign, blur_var = blur_result
            if blur_sign:
                log_file.write('\t'.join(
                    map(str, ['stat', 'blur_filter', blur_var, image_id])) +
                               '\n')
                log_file.close()
                return self.unknown, 1.0, self.has_save_pic_feature, need_add
            align_face_img = align_face(tmp_pic_path)
            if align_face_img == None:
                log_file.write('\t'.join(
                    map(str, ['stat', 'detect_filter', blur_var, image_id])) +
                               '\n')
                log_file.close()
                return self.unknown, 1.0, self.has_save_pic_feature, need_add
            else:
                # 使用重新检测并对对齐的人脸进行识别
                im = align_face_img
            # 对检测到的人脸重新进行模糊检测
            blur_result = is_blur(im)
            blur_sign, blur_var = blur_result
            if blur_sign:
                log_file.write('\t'.join(
                    map(str, ['stat', 'blur_filter', blur_var, image_id])) +
                               '\n')
                log_file.close()
                return self.unknown, 1.0, self.has_save_pic_feature, need_add
            need_process = self.check_face_img(im, image_id)
            if not need_process:
                log_file.write('\t'.join(
                    map(str, ['stat', 'pose_filter', blur_var, image_id])) +
                               '\n')
                log_file.close()
                return self.unknown, 1.0, self.has_save_pic_feature, need_add
            im = cv2.resize(im, (PIC_SHAPE[1], PIC_SHAPE[2]),
                            interpolation=cv2.INTER_LINEAR)
            im = im[:, :, ::-1] * 1.0
            im = im - avg
            im = im.transpose((2, 0, 1))
            im = im[None, :]
        except:
            traceback.print_exc()
            return self.unknown, 1.0, self.has_save_pic_feature, need_add
        try:
            # 流程 : 找距离最近的图片 ; 计算prob ; 在线聚类 ; 加入LSH Forest
            im_feature = extract_feature_from_numpy(im)
            try:
                # nearest_sim_list的格式和dist_label_list的格式一样,这样可以将两个list合并,一起计算(这样不用考虑时间的因素)
                # 在识别出人名后将人名和feature放入到self.nearest
                nearest_sim_list = self.cal_nearest_sim(
                    current_feature=im_feature)
            except:
                traceback.print_exc()
                nearest_sim_list = []
            log_file.write('\t'.join(
                map(str, ['nearest_sim_list :',
                          map(str, nearest_sim_list)])) + '\n')

            # 找距离最近的图片 --- 用LSH Forest 找出最近的10张图片,然后分别计算距离
            dist_label_list = self.find_k_neighbors_with_lsh(im_feature)
            dist_label_list.extend(nearest_sim_list)
            dist_label_list = self.filter_result(dist_label_list)
            dist_label_list.sort(key=lambda x: x[0], reverse=True)
            # 计算
            if dist_label_list == None:
                this_id = self.must_be_not_same_id
                this_label = self.new_person_str + str(
                    self.current_new_person_id)
            else:
                # 计算prob --- 根据距离计算prob
                this_id, this_label = self.evaluate_result(dist_label_list)
            # 在线聚类 --- 根据dist确定是重新增加一个人还是加入到已有的人中
            log_file.write('\t'.join(
                map(str, ['stat', 'recognize_id', blur_var, this_id])) + '\n')
            if dist_label_list != None and len(dist_label_list) > 0:
                log_file.write('\t'.join(
                    map(str, ['dist_label_list :',
                              map(str, dist_label_list)])) + '\n')
            need_save = False
            if this_id == self.same_pic_id:
                need_add = False
            elif this_id == self.must_be_same_id:
                need_add = False
                need_save = True
                this_person_folder = os.path.join(
                    self.all_pic_data_folder, this_label + self.must_same_str)
            elif this_id == self.must_be_not_same_id:
                this_label = self.new_person_str + str(
                    self.current_new_person_id)
                self.current_new_person_id += 1
                this_person_folder = os.path.join(self.all_pic_data_folder,
                                                  this_label)
                need_add = True
                need_save = True
            elif this_id == self.maybe_same_id:
                this_person_folder = os.path.join(
                    self.all_pic_data_folder, this_label + self.maybe_same_str)
                need_add = False  # prob在灰度区域的不如入,其余情况加入
                need_save = True
            else:
                log_file.write('\t'.join(map(str, ['error para :', this_id])) +
                               '\n')
            if need_save:
                try:
                    if not os.path.exists(this_person_folder):
                        os.makedirs(this_person_folder)
                        os.chmod(this_person_folder,
                                 stat.S_IRWXG + stat.S_IRWXO + stat.S_IRWXU)
                    this_pic_name = os.path.join(this_person_folder,
                                                 image_id + '.png')
                    imsave(this_pic_name, np.transpose(im[0], (1, 2, 0)))
                except:
                    traceback.print_exc()
                    return self.unknown, 1.0, has_save_num, False

            # 加入LSH Forest --- partial_fit
            if need_add:
                self.add_one_pic(im_feature, this_label)
                has_save_num += 1
                # 根据label和image_id可以存生成文件名,确定是否要存储文件[可以选择在服务器和本地同时存储]
            if this_id == self.same_pic_id or this_id == self.must_be_not_same_id or this_id == self.must_be_same_id:
                end = time.time()
                log_file.write('\t'.join(
                    map(str, [
                        'stat recognize_time :', (end - start), 'this_id :',
                        self.trans_dic.get(this_id)
                    ])) + '\n')
                log_file.close()
                return this_label.replace(self.must_same_str, ''), \
                       str(dist_label_list[0][0]), str(has_save_num), str(need_add)
            else:
                # 灰度区域,不显示人名
                end = time.time()
                log_file.write('\t'.join(
                    map(str, ['gray area recog time :', (end - start)])) +
                               '\n')
                log_file.close()
                # return this_label.replace(self.maybe_same_str, ''), \
                #        str(dist_label_list[0][0]), str(has_save_num), str(need_add)
                return self.unknown, str(
                    dist_label_list[0][0]), str(has_save_num), str(need_add)
        except:
            traceback.print_exc()
            log_file.close()
            return self.unknown, str(100.0), str(has_save_num), str(False)
    def recognize_online_cluster(self, image, image_id):
        '''
            :param image: 将得到的图片进行识别,加入的LSH Forest,根据距离计算proba(不同的距离对应不同的准确率,根据已有的dist计算阈值);
                            和已经设定的阈值判断是不是一个新出现的人,确定是原来已有的人,还是不确定是原来已有的人
            # 增加统计的功能, 方便以后计算过滤原因和比例, 以及识别比例(same, not_same, maybe_same)
            :return:
        '''
        start = time.time()
        need_add = False
        has_save_num = 0
        current_day = get_current_day()
        log_file = open(os.path.join(log_dir, current_day+'.txt'), 'a')
        log_file.write('\t'.join(map(str, ["receive image", image_id, time.time()])) + '\n')
        try:
            image = base64.decodestring(image)
            image = zlib.decompress(image)
            im = cv2.imdecode(np.fromstring(image, dtype=np.uint8), 1)
            time_slot = get_time_slot(image_id)
            if time_slot == None:
                time_slot = 'error'
            time_slot_dir = os.path.join(tmp_face_dir, time_slot)
            if not os.path.exists(time_slot_dir):
                os.makedirs(time_slot_dir)
            tmp_pic_path = os.path.join(time_slot_dir, image_id+'.jpg')
            cv2.imwrite(tmp_pic_path, im)
            blur_result = is_blur(im)
            blur_sign, blur_var = blur_result
            if blur_sign:
                log_file.write('\t'.join(map(str, ['stat', 'blur_filter', blur_var, image_id]))+'\n')
                log_file.close()
                return self.unknown, 1.0, self.has_save_pic_feature, need_add
            align_face_img = align_face(tmp_pic_path)
            if align_face_img == None:
                log_file.write('\t'.join(map(str, ['stat', 'detect_filter', blur_var, image_id])) + '\n')
                log_file.close()
                return self.unknown, 1.0, self.has_save_pic_feature, need_add
            else:
                # 使用重新检测并对对齐的人脸进行识别
                im = align_face_img
            # 对检测到的人脸重新进行模糊检测
            blur_result = is_blur(im)
            blur_sign, blur_var = blur_result
            if blur_sign:
                log_file.write('\t'.join(map(str, ['stat', 'blur_filter', blur_var, image_id]))+'\n')
                log_file.close()
                return self.unknown, 1.0, self.has_save_pic_feature, need_add
            need_process = self.check_face_img(im, image_id)
            if not need_process:
                log_file.write('\t'.join(map(str, ['stat', 'pose_filter', blur_var, image_id])) + '\n')
                log_file.close()
                return self.unknown, 1.0, self.has_save_pic_feature, need_add
            im = cv2.resize(im, (PIC_SHAPE[1], PIC_SHAPE[2]), interpolation=cv2.INTER_LINEAR)
            im = im[:, :, ::-1]*1.0
            im = im - avg
            im = im.transpose((2, 0, 1))
            im = im[None, :]
        except:
            traceback.print_exc()
            return self.unknown, 1.0, self.has_save_pic_feature, need_add
        try:
            # 流程 : 找距离最近的图片 ; 计算prob ; 在线聚类 ; 加入LSH Forest
            im_feature = extract_feature_from_numpy(im)
            try:
                # nearest_sim_list的格式和dist_label_list的格式一样,这样可以将两个list合并,一起计算(这样不用考虑时间的因素)
                # 在识别出人名后将人名和feature放入到self.nearest
                nearest_sim_list = self.cal_nearest_sim(current_feature=im_feature)
            except:
                traceback.print_exc()
                nearest_sim_list = []
            log_file.write('\t'.join(map(str, ['nearest_sim_list :', map(str, nearest_sim_list)])) + '\n')

            # 找距离最近的图片 --- 用LSH Forest 找出最近的10张图片,然后分别计算距离
            dist_label_list = self.find_k_neighbors_with_lsh(im_feature)
            dist_label_list.extend(nearest_sim_list)
            dist_label_list = self.filter_result(dist_label_list)
            dist_label_list.sort(key=lambda x: x[0], reverse=True)
            # 计算
            if dist_label_list == None:
                this_id = self.must_be_not_same_id
                this_label = self.new_person_str + str(self.current_new_person_id)
            else:
                # 计算prob --- 根据距离计算prob
                this_id, this_label = self.evaluate_result(dist_label_list)
            # 在线聚类 --- 根据dist确定是重新增加一个人还是加入到已有的人中
            log_file.write('\t'.join(map(str, ['stat', 'recognize_id', blur_var, this_id])) + '\n')
            if dist_label_list != None and len(dist_label_list) > 0:
                log_file.write('\t'.join(map(str, ['dist_label_list :', map(str, dist_label_list)])) + '\n')
            need_save = False
            if this_id == self.same_pic_id:
                need_add = False
            elif this_id == self.must_be_same_id:
                need_add = False
                need_save = True
                this_person_folder = os.path.join(self.all_pic_data_folder, this_label+self.must_same_str)
            elif this_id == self.must_be_not_same_id:
                this_label = self.new_person_str + str(self.current_new_person_id)
                self.current_new_person_id += 1
                this_person_folder = os.path.join(self.all_pic_data_folder, this_label)
                need_add = True
                need_save = True
            elif this_id == self.maybe_same_id:
                this_person_folder = os.path.join(self.all_pic_data_folder, this_label+self.maybe_same_str)
                need_add = False # prob在灰度区域的不如入,其余情况加入
                need_save = True
            else:
                log_file.write('\t'.join(map(str, ['error para :', this_id])) + '\n')
            if need_save:
                try:
                    if not os.path.exists(this_person_folder):
                        os.makedirs(this_person_folder)
                        os.chmod(this_person_folder, stat.S_IRWXG + stat.S_IRWXO + stat.S_IRWXU)
                    this_pic_name = os.path.join(this_person_folder, image_id+'.png')
                    imsave(this_pic_name, np.transpose(im[0], (1, 2, 0)))
                except:
                    traceback.print_exc()
                    return self.unknown, 1.0, has_save_num, False

            # 加入LSH Forest --- partial_fit
            if need_add:
                self.add_one_pic(im_feature, this_label)
                has_save_num += 1
                # 根据label和image_id可以存生成文件名,确定是否要存储文件[可以选择在服务器和本地同时存储]
            if this_id == self.same_pic_id or this_id == self.must_be_not_same_id or this_id == self.must_be_same_id:
                end = time.time()
                log_file.write('\t'.join(map(str, ['stat recognize_time :', (end - start), 'this_id :', self.trans_dic.get(this_id)])) + '\n')
                log_file.close()
                return this_label.replace(self.must_same_str, ''), \
                       str(dist_label_list[0][0]), str(has_save_num), str(need_add)
            else:
                # 灰度区域,不显示人名
                end = time.time()
                log_file.write('\t'.join(map(str, ['gray area recog time :',(end - start)])) + '\n')
                log_file.close()
                # return this_label.replace(self.maybe_same_str, ''), \
                #        str(dist_label_list[0][0]), str(has_save_num), str(need_add)
                return self.unknown, str(dist_label_list[0][0]), str(has_save_num), str(need_add)
        except:
            traceback.print_exc()
            log_file.close()
            return self.unknown, str(100.0), str(has_save_num), str(False)