コード例 #1
0
    def __match_faces(self, encoded_faces):
        if len(self.__pattern_encodings) == 0:
            log.warning('Empty patterns')

        for i in range(len(encoded_faces)):
            if self.__step_stage_face():
                return False
            encoding = encoded_faces[i]['encoding']
            dist, name, pattern = self.__match_face_by_nearest(
                encoding, patterns.PATTERN_TYPE_GOOD)
            if dist > 0.001:  # skip zero match
                dist_bad, name_bad, pattern_bad = self.__match_face_by_nearest(
                    encoding, patterns.PATTERN_TYPE_BAD)
                # match to bad only equal faces
                if dist_bad < self.__threshold_equal and dist_bad < dist:
                    name = name_bad + '_bad'
                    dist = dist_bad
                    pattern = pattern_bad

            log.debug(f'matched: {name}: {dist}: {pattern}')
            if 'name' in encoded_faces[i]:
                encoded_faces[i]['oldname'] = encoded_faces[i]['name']

            if dist < self.__threshold:
                pass
            elif dist < self.__threshold_weak:
                name += '_weak'
            else:
                name = ''
                dist = 1

            encoded_faces[i]['name'] = name
            encoded_faces[i]['dist'] = dist
            encoded_faces[i]['pattern'] = pattern
        return True
コード例 #2
0
    def recognize_files(self, filenames, debug_out_folder,
                        skip_face_gen=False):
        self.__make_debug_out_folder(debug_out_folder)

        self.__start_stage(len(filenames))
        for f in filenames:
            if self.__step_stage():
                break
            try:
                ext = tools.get_low_ext(f)
                if ext in tools.IMAGE_EXTS:
                    encoded_faces, media = self.recognize_image(f)
                elif ext in tools.VIDEO_EXTS:
                    encoded_faces, media = self.recognize_video(f)
                else:
                    log.warning(f'Unknown ext: {ext}')
                    continue
                if media is None:
                    continue
                self.__db.insert(f, encoded_faces, commit=False)
                if debug_out_folder:
                    debug_out_file_name = self.__extract_filename(f)
                    self.__save_debug_images(
                        encoded_faces, media,
                        debug_out_folder, debug_out_file_name,
                        is_video=ext in tools.VIDEO_EXTS,
                        skip_face_gen=skip_face_gen)
            except Exception as ex:
                log.exception(f'Image {f} recognition failed')
        self.__end_stage()
コード例 #3
0
ファイル: plexdb.py プロジェクト: sashacmc/face-rec-tools
    def clean_tags(self, filename, tags=None, tag_prefix=None, commit=True):
        fid = self.__get_id(filename)
        if fid is None:
            log.warning(f'Filename not found: {filename}')
            return 0

        res = 0
        if tags is not None:
            for tag in tags:
                res += self.__clean_tag(fid,
                                        self.__get_tag_id(tag, TAG_TYPE_PHOTO),
                                        commit)
                res += self.__clean_tag(fid,
                                        self.__get_tag_id(tag, TAG_TYPE_VIDEO),
                                        commit)
        if tag_prefix is not None:
            tag_ids = self.__get_tag_ids(tag_prefix)
            for tag_id in tag_ids:
                res += self.__clean_tag(fid, tag_id, commit)

        if commit:
            self.__conn.commit()

        log.debug(f'Removed {res} tags for {filename}')

        return res
コード例 #4
0
 def __filenames_to_dict(self, filenames):
     res = {}
     for f in filenames:
         path, name = os.path.split(f)
         if name in res:
             log.warning(f'Duplicate file {name} in {path} and {res[name]}')
         res[name] = path
     return res
コード例 #5
0
ファイル: server.py プロジェクト: SkyFox277/face-rec-tools
    def __start_recognizer(self, method, *args):
        self.status()
        if self.__recognizer is not None:
            log.warning('Trying to create second recognizer')
            raise Exception('Recognizer already started')

        self.__recognizer = recognizer_runner.RecognizerRunner(
            self.__cfg.filename(), method, *args)
        self.__recognizer.start()
コード例 #6
0
 def __analyze_duplicates(self, print_out):
     log.info(f'Analyze duplicates')
     fset = {}
     for f in self.__files:
         f = self.fullpath(f)
         filename = os.path.split(f)[1]
         if filename in fset:
             log.warning(f'Duplicate pattern file: {f} ({fset[filename]})')
             if print_out:
                 print(f)
                 print(fset[filename])
         else:
             fset[filename] = f
コード例 #7
0
ファイル: server.py プロジェクト: SkyFox277/face-rec-tools
    def do_GET(self):
        log.debug('do_GET: ' + self.path)
        try:
            path, params = self.__path_params()
            if path == '/list_cache':
                self.__list_cache(params)
                return

            if path == '/get_names':
                self.__get_names()
                return

            if path == '/get_name_image':
                self.__get_name_image(params)
                return

            if path == '/get_folders':
                self.__get_folders()
                return

            if path == '/get_status':
                self.__get_status()
                return

            if path == '/get_face_src':
                self.__get_face_src(params)
                return

            if path == '/get_face_pattern':
                self.__get_face_pattern(params)
                return

            if path == '/':
                path = 'index.html'

            if '..' in path:
                log.warning('".." in path: ' + path)
                self.__not_found_response()
                return

            ext = tools.get_low_ext(path)
            if ext in ('.html', '.js', '.css', '.png', '.jpg'):
                self.__file_request(path, params)
                return

            log.warning('Wrong path: ' + path)
            self.__not_found_response()
        except Exception as ex:
            self.__server_error_response(str(ex))
            log.exception(ex)
コード例 #8
0
ファイル: plexdb.py プロジェクト: sashacmc/face-rec-tools
    def get_tags(self, filename):
        fid = self.__get_id(filename)
        if fid is None:
            log.warning(f'Filename not found: {filename}')
            return None

        c = self.__conn.cursor()
        res = c.execute(
            'SELECT tags.tag \
             FROM taggings \
             JOIN tags ON tags.id=taggings.tag_id \
             WHERE taggings.metadata_item_id=?', (fid, ))

        return [r[0] for r in res.fetchall()]
コード例 #9
0
ファイル: plexdb.py プロジェクト: sashacmc/face-rec-tools
    def set_tags(self, filename, tags, tag_type, commit=True):
        fid = self.__get_id(filename)
        if fid is None:
            log.warning(f'Filename not found: {filename}')
            return False

        for tag in tags:
            tag_id = self.__get_tag_id(tag, tag_type)
            if tag_id is None:
                log.warning(f'Tag not found: {tag}')
                continue

            self.__set_tag(fid, tag_id, commit)

        return True
コード例 #10
0
    def optimize(self):
        encoder = self.__get_encoder()

        # get encodings and reverse to preserve old patterns
        encs, names, files = self.encodings()
        encs.reverse()
        names.reverse()
        files.reverse()

        # convert to numpy array and get length for optimization reasons
        encs = np.array(encs)
        encs_len = len(encs)

        to_remove = []
        while 0 < encs_len:
            log.debug(f'to optimize check: {encs_len}')
            name = names.pop()
            fname = files.pop()

            # numpy array pop()
            enc, encs = encs[-1], encs[:-1]
            encs_len -= 1

            dists = encoder.distance(encs, enc)
            i = 0
            while i < encs_len:
                if dists[i] < self.__threshold_equal:
                    if name != names[i]:
                        fn1 = self.fullpath(fname)
                        fn2 = self.fullpath(files[i])
                        log.warning(
                            f'Different persons {dists[i]} "{fn1}" "{fn2}"')
                    else:
                        to_remove.append(self.fullpath(files[i]))
                        log.info(f'eq: {fname} {files[i]}')

                        names.pop(i)
                        files.pop(i)

                        encs = np.delete(encs, i, axis=0)
                        dists = np.delete(dists, i, axis=0)
                        encs_len -= 1
                i += 1

        self.remove_files(to_remove)
        log.info(f'{len(to_remove)} files was optimized.')
コード例 #11
0
 def __analyze_encodings_size(self, print_out):
     log.info(f'Analyze encodings')
     dct = collections.defaultdict(list)
     for f, (enc, name, time, tp) in self.__files.items():
         f = self.fullpath(f)
         dct[len(enc)].append(f)
     if len(dct) != 1:
         log.warning('Inconsistent encoding: ' + str(dct.keys()))
         max_key = list(dct.keys())[0]
         for key in dct:
             if len(dct[max_key]) < len(dct[key]):
                 max_key = key
         del dct[max_key]
         for lst in dct.values():
             for f in lst:
                 log.warning(f'wrong encoding: {f}')
                 if print_out:
                     print(f)
コード例 #12
0
 def reencode_files(self, files_faces):
     self.__start_stage(len(files_faces))
     for ff in files_faces:
         try:
             encoded_faces = ff['faces']
             filename = ff['filename']
             ext = tools.get_low_ext(filename)
             if ext in tools.IMAGE_EXTS:
                 self.reencode_image(filename, encoded_faces)
                 encoded_faces = self.__filter_encoded_faces(encoded_faces)
             elif ext in tools.VIDEO_EXTS:
                 encoded_faces, media = self.recognize_video(filename)
             else:
                 log.warning(f'Unknown ext: {ext}')
                 continue
             self.__db.insert(filename, encoded_faces, commit=False)
         except Exception as ex:
             log.exception(f'{filename} reencoding failed')
     self.__end_stage()
コード例 #13
0
ファイル: tools.py プロジェクト: sashacmc/face-rec-tools
def enable_landmarks(filename, enable):
    descr, thumbnail = load_face_description(filename)
    enabled = thumbnail is not None

    if enable == enabled:
        log.debug(f'enable_landmarks skip: {filename}')
        return

    if descr is None or 'landmarks' not in descr:
        log.warning(f'has no landmarks: {filename}')
        return

    image = Image.open(filename)
    if enable:
        thumbnail = image.copy()
        __set_landmarks_lines(image, descr['landmarks'])
    else:
        image = thumbnail
        thumbnail = None
    save_with_description(image, descr, thumbnail, filename)
コード例 #14
0
 def __analyze_landmarks(self, print_out):
     log.info(f'Analyze landmarks')
     for f in self.__files:
         f = self.fullpath(f)
         descr = tools.load_face_description(f)[0]
         if descr is None:
             log.warning(f'missed description: {f}')
             if print_out:
                 print(f)
             continue
         if 'landmarks' not in descr:
             log.warning(f'missed landmarks: {f}')
             if print_out:
                 print(f)
             continue
         if not tools.test_landmarks(descr['landmarks']):
             log.warning(f'wrong landmarks: {f}')
             if print_out:
                 print(f)
コード例 #15
0
ファイル: server.py プロジェクト: SkyFox277/face-rec-tools
 def __get_face_pattern(self, params):
     path = params['path'][0]
     descr = self.__get_face_file_description(path)
     if descr is None:
         self.__not_found_response()
         return
     face_id = descr.get('face_id', None)
     if face_id is None:
         log.warning(f'face file {path} without face_id')
         self.__not_found_response()
         return
     count, ff = self.server.db().get_face(face_id)
     if count == 0:
         log.warning(f'face with id {face_id} not found')
         self.__not_found_response()
         return
     pattern_filename = next(ff)['faces'][0]['pattern']
     if pattern_filename == '':
         log.warning(f'pattern file not specified')
         self.__not_found_response()
         return
     self.__ok_response(pattern_filename)
コード例 #16
0
    def generate(self, regenerate=False):
        log.info(f'Patterns generation: {self.__folder} ({regenerate})')

        image_files = {}
        for image_file in tools.list_files(self.__folder, tools.IMAGE_EXTS):
            if os.path.split(image_file)[1] == FACE_FILENAME:
                continue
            image_files[image_file] = os.stat(image_file).st_mtime

        if not regenerate:
            self.load()
            filtered = {}
            for image_file in image_files:
                filename_exsists = self.relpath(image_file) in self.__files
                if not filename_exsists or \
                   self.__files[self.relpath(image_file)][self.FILES_TIME] != \
                   image_files[image_file]:

                    filtered[image_file] = image_files[image_file]
                    if filename_exsists:
                        self.__remove_file(image_file)

            if len(filtered) == 0:
                log.info('Nothing changed')
                return

            image_files = filtered

        for (i, image_file) in enumerate(image_files):
            splitted = image_file.split(os.path.sep)
            name = splitted[-2]
            if name == BAD_FOLDERNAME:
                name = splitted[-3]
                tp = PATTERN_TYPE_BAD
            elif name == OTHER_FOLDERNAME:
                name = splitted[-3]
                tp = PATTERN_TYPE_OTHER
            else:
                tp = PATTERN_TYPE_GOOD

            log.info(f'{i + 1}/{len(image_files)} file: {image_file}')

            descr, thumbnail = tools.load_face_description(image_file)
            try:
                encoding = descr['encoding']
            except Exception:
                encoding = None

            if encoding is None:
                import face_recognition
                try:
                    image = tools.read_image(image_file, self.__max_size)
                except Exception:
                    log.exception(f'read_image failed')
                    continue

                boxes = face_recognition.face_locations(image,
                                                        model=self.__model)
                if len(boxes) != 1:
                    log.warning(
                        f'{len(boxes)} faces detected in {image_file}. Skip.')
                    continue
                encodings, landmarks = \
                    self.__get_encoder().encode(image, boxes)
                if not tools.test_landmarks(landmarks[0]):
                    log.warning(f'bad face detected in {image_file}. Skip.')
                    continue

                encoding = encodings[0]

            self.__files[self.relpath(image_file)] = \
                [encoding,
                 name,
                 image_files[image_file],
                 tp]

        self.__init_basenames()
        self.__persons = self.__calc_persons()
        self.__save()