Ejemplo n.º 1
0
    def process_faces(self,
                      faces: List[Face],
                      extract_embedding: bool = True,
                      extract_ga: bool = True,
                      return_face_data: bool = False):
        chunked_faces = to_chunks(faces, self.max_rec_batch_size)
        for chunk in chunked_faces:
            chunk = list(chunk)
            crops = [e.facedata for e in chunk]
            total = len(crops)
            embeddings = [None] * total
            ga = [[None, None]] * total

            if extract_embedding:
                t0 = time.time()
                embeddings = self.rec_model.get_embedding(crops)
                t1 = time.time()
                took = t1 - t0
                logging.debug(
                    f'Embedding {total} faces took: {took} ({took/total} per face)'
                )

            if extract_ga:
                t0 = time.time()
                ga = [self.ga_model.get(face.facedata) for face in chunk]
                t1 = time.time()
                logging.debug(
                    f'Extracting g/a for {total} faces took: {t1 - t0}')

            for i, crop in enumerate(crops):
                embedding = None
                embedding_norm = None
                normed_embedding = None
                gender = None
                age = None

                embedding = embeddings[i]
                if extract_embedding:
                    embedding_norm = norm(embedding)
                    normed_embedding = embedding / embedding_norm
                _ga = ga[i]
                if extract_ga:
                    gender = int(_ga[0])
                    age = _ga[1]

                face = chunk[i]
                if return_face_data is False:
                    face = face._replace(facedata=None)

                face = face._replace(embedding=embedding,
                                     embedding_norm=embedding_norm,
                                     normed_embedding=normed_embedding,
                                     gender=gender,
                                     age=age)
                yield face
Ejemplo n.º 2
0
 def embed_faces(self, faces: List[Face]):
     chunked_faces = to_chunks(faces, self.max_rec_batch_size)
     for chunk in chunked_faces:
         chunk = list(chunk)
         crops = [e.facedata for e in chunk]
         embeddings = self.rec_model.get_embedding(crops)
         for i, emb in enumerate(embeddings):
             embedding = emb
             embedding_norm = norm(embedding)
             normed_embedding = embedding / embedding_norm
             face = chunk[i]._replace(embedding=embedding, embedding_norm=embedding_norm,
                                      normed_embedding=normed_embedding)
             yield face
Ejemplo n.º 3
0
    async def get(self, images, extract_embedding: bool = True, extract_ga: bool = True, detect_masks: bool = True,
                  return_face_data: bool = True, max_size: List[int] = None, threshold: float = 0.6,
                  mask_thresh: float = 0.89,
                  limit_faces: int = 0):

        ts = time.perf_counter()

        # If detector has input_shape attribute, use it instead of provided value
        try:
            max_size = self.det_model.retina.input_shape[2:][::-1]
        except:
            pass

        # Pre-assign max_size to resize function
        _partial_resize = partial(resize_image, max_size=max_size)
        # Pre-assign threshold to detect function
        _partial_detect = partial(self.det_model.detect, threshold=threshold)

        # Initialize resied images iterator
        res_images = map(_partial_resize, images)
        batches = to_chunks(res_images, self.max_det_batch_size)

        faces = []
        faces_per_img = {}

        for bid, batch in enumerate(batches):
            batch_imgs, scales = zip(*batch)
            t0 = time.perf_counter()
            det_predictions = zip(*_partial_detect(batch_imgs))
            t1 = time.perf_counter()
            logging.debug(f'Detection took: {(t1 - t0) * 1000:.3f} ms.')
            for idx, pred in enumerate(det_predictions):
                await asyncio.sleep(0)

                orig_id = (bid * self.max_det_batch_size) + idx
                boxes, probs, landmarks = pred


                faces_per_img[orig_id] = len(boxes)

                if not isinstance(boxes, type(None)):
                    t0 = time.perf_counter()
                    if limit_faces > 0:
                        boxes, probs, landmarks = self.sort_boxes(boxes, probs, landmarks,
                                                                              shape=batch_imgs[idx].shape,
                                                                              max_num=limit_faces)

                    # Translate points to original image size
                    boxes = reproject_points(boxes, scales[idx])
                    landmarks = reproject_points(landmarks, scales[idx])
                    # Crop faces from original image instead of resized to improve quality
                    if extract_ga or extract_embedding or return_face_data or detect_masks:
                        crops = face_align.norm_crop_batched(images[orig_id], landmarks)
                    else:
                        crops = [None] * len(boxes)

                    for i, _crop in enumerate(crops):

                        face = Face(bbox=boxes[i], landmark=landmarks[i], det_score=probs[i],
                                    num_det=i, scale=scales[idx], facedata=_crop)

                        faces.append(face)

                    t1 = time.perf_counter()
                    logging.debug(f'Cropping {len(boxes)} faces took: {(t1 - t0) * 1000:.3f} ms.')

        # Process detected faces
        faces = list(self.process_faces(faces,
                                   extract_embedding=extract_embedding,
                                   extract_ga=extract_ga,
                                   return_face_data=return_face_data,
                                   detect_masks=detect_masks, mask_thresh=mask_thresh))

        faces_by_img = []
        offset = 0
        for key in faces_per_img:
            value = faces_per_img[key]
            faces_by_img.append(faces[offset:offset + value])
            offset += value

        tf = time.perf_counter()

        logging.debug(colorize_log(f'Full processing took: {(tf - ts) * 1000:.3f} ms.', 'red'))
        return faces_by_img
Ejemplo n.º 4
0
    def process_faces(self, faces: List[Face], extract_embedding: bool = True, extract_ga: bool = True,
                      return_face_data: bool = False, detect_masks: bool = True, mask_thresh: float = 0.89):
        chunked_faces = to_chunks(faces, self.max_rec_batch_size)
        for chunk in chunked_faces:
            chunk = list(chunk)
            crops = [e.facedata for e in chunk]
            total = len(crops)
            embeddings = [None] * total
            ga = [[None, None]] * total

            if extract_embedding:
                t0 = time.perf_counter()
                embeddings = self.rec_model.get_embedding(crops)
                took = time.perf_counter() - t0
                logging.debug(
                    f'Embedding {total} faces took: {took * 1000:.3f} ms. ({(took / total) * 1000:.3f} ms. per face)')

            if extract_ga and self.ga_model:
                t0 = time.perf_counter()
                ga = self.ga_model.get(crops)
                t1 = time.perf_counter()
                took = t1 - t0
                logging.debug(
                    f'Extracting g/a for {total} faces took: {took * 1000:.3f} ms. ({(took / total) * 1000:.3f} ms. per face)')

            if detect_masks and self.mask_model:
                t0 = time.perf_counter()
                masks = self.mask_model.get(crops)
                t1 = time.perf_counter()
                took = t1 - t0
                logging.debug(
                    f'Detecting masks for  {total} faces took: {took * 1000:.3f} ms. ({(took / total) * 1000:.3f} ms. per face)')

            for i, crop in enumerate(crops):
                embedding_norm = None
                normed_embedding = None
                gender = None
                age = None
                mask = None
                mask_probs = None

                embedding = embeddings[i]
                if extract_embedding:
                    embedding_norm = norm(embedding)
                    normed_embedding = embedding / embedding_norm

                if extract_ga and self.ga_model:
                    _ga = ga[i]
                    gender = int(_ga[0])
                    age = _ga[1]


                if detect_masks and self.mask_model:
                    _masks = masks[i]
                    mask = False
                    mask_prob = float(_masks[0])
                    no_mask_prob = float(_masks[1])
                    if mask_prob > no_mask_prob and mask_prob >= mask_thresh:
                        mask = True
                    mask_probs = dict(mask=mask_prob,
                                      no_mask=no_mask_prob)

                face = chunk[i]
                if return_face_data is False:
                    face = face._replace(facedata=None)

                face = face._replace(embedding=embedding, embedding_norm=embedding_norm,
                                     normed_embedding=normed_embedding, gender=gender, age=age, mask=mask, mask_probs=mask_probs)
                yield face