Beispiel #1
0
def run(image_path: str, weights_path: str):

    face_marker = FaceMarker(weights_path=weights_path)
    face_aligner = FaceAligner()

    if path.isdir(image_path):
        image_paths = list_files(image_path, IMAGE_EXT, recursive=True)
        if len(image_paths) == 0:
            raise ValueError(f'No images found in {image_path}.')
    elif path.isfile(image_path):
        image_paths = [image_path]
    else:
        raise ValueError(f'Input "{image_path}" is not file nor a directory.')

    logger.info('Starting analysis...')
    logger.info('Press "space" key to display next result. Press "q" to quit.')

    images = []

    for image_path in image_paths:
        image_name = path.basename(image_path)
        image = cv.imread(image_path)
        if image is None:
            logger.warn(f'Unable to open image file {image_path}')
            continue
        h, w, = image.shape[0:2]
        logger.info(f'{image_name} loaded. Image size is {w}x{h} pixels.')
        images.append(image)

    n_images = len(images)

    tic = time()
    marks, scores = face_marker.mark(images)
    toc = time()
    logger.info(f'Number of images loaded: {n_images}')
    logger.info(f'Total processing time: {(toc - tic):.4f} s.')

    for i in range(n_images):

        image = images[i]
        mark = marks[i]
        score = scores[i]

        aligned_image, nose_dev = face_aligner.align(image, mark)

        for point in mark:
            cv.circle(image, (int(point[0]), int(point[1])), 2, (0, 255, 0),
                      -1)

        cv.imshow(f'Face {i} (score {score:.3f})', image)
        title = f'Aligned Face {i} (dev: {nose_dev[0]:.3f}, {nose_dev[1]:.3f})'
        cv.imshow(title, aligned_image)

        ret = cv.waitKey()
        if ret == ord(' '):
            cv.destroyAllWindows()
        elif ret == ord('q'):
            cv.destroyAllWindows()
            break
Beispiel #2
0
def run(image_path: str, weights_path: str):

    config_logger(level='DEBUG', to_console=True)

    person_detector = PersonDetector(weights_path=weights_path,
                                     resize_height=192)

    images_paths = list_images(image_path)

    logger.info('Starting analysis...')
    logger.info('Press "space" key to display next result. Press "q" to quit.')

    max_image_size = 1920

    drawer = Drawer()
    drawer.font_scale = 0.5
    drawer.font_linewidth = 1

    for image_path in images_paths:
        image_name = path.basename(image_path)

        logger.info(f'Analyzing image {image_name}...')

        image = cv.imread(image_path)

        if image is None:
            logger.warn(f'Unable to open image file {image_path}')
            continue

        h, w, = image.shape[0:2]

        logger.info(f'Image loaded. Image size is {w}x{h} pixels.')

        if max(w, h) > max_image_size:
            image, scale = resize(image, max_image_size)
            h, w, = image.shape[0:2]
            logger.info(f'Image resized to {w}x{h} pixels.')

        tic = time()
        boxes, scores = person_detector.detect(image)
        toc = time()
        logger.info(f'Found {len(boxes)} persons in {(toc - tic):.3f} s.')

        for ind, box in enumerate(boxes):
            drawer.draw_labeled_box(image, f'{int(100*scores[ind])}%', box)

        cv.imshow(f'Faces in {image_name}', image)

        ret = cv.waitKey()
        if ret == ord(' '):
            cv.destroyAllWindows()
        elif ret == ord('q'):
            cv.destroyAllWindows()
            break
Beispiel #3
0
def run(
    image_path: str,
    detector_weights_path: str,
    marker_weights_path: str,
    encoder_weights_path: str,
    show_scores: bool = False
):

    from dnfal.vision import FacesVision
    from dnfal.settings import Settings
    from dnfal.loggers import logger

    settings = Settings()
    settings.detector_weights_path = detector_weights_path
    settings.marker_weights_path = marker_weights_path
    settings.encoder_weights_path = encoder_weights_path
    settings.log_to_console = True
    settings.detection_min_height = 24
    settings.detection_min_score = 0.8
    settings.marking_min_score = 0.6

    faces_vision = FacesVision(settings)

    if path.isdir(image_path):
        image_paths = list_files(image_path, IMAGE_EXT, recursive=True)
        if len(image_paths) == 0:
            raise ValueError(f'No images found in {image_path}.')
    elif path.isfile(image_path):
        image_paths = [image_path]
    else:
        raise ValueError(f'Input "{image_path}" is not file nor a directory.')

    logger.info('Starting analysis...')
    logger.info('Press "space" key to display next result. Press "q" to quit.')

    max_image_size = 1920

    drawer = Drawer()
    drawer.font_scale = 0.7
    drawer.font_linewidth = 2
    drawer.font_color = (0, 255, 0)

    for image_path in image_paths:
        image_name = path.basename(image_path)
        image = cv.imread(image_path)
        if image is None:
            logger.warn(f'Unable to open image file {image_path}')
            continue
        h, w, = image.shape[0:2]
        logger.info(f'{image_name} loaded. Image size is {w}x{h} pixels.')

        if max(w, h) > max_image_size:
            image, scale = resize(image, max_image_size)
            h, w, = image.shape[0:2]
            logger.info(f'Image resized to {w}x{h} pixels.')

        tic = time()
        faces, _ = faces_vision.frame_analyzer.find_faces(image)
        toc = time()
        logger.info(f'Found {len(faces)} faces in {(toc - tic):.3f} seconds.')
        for ind, face in enumerate(faces):
            face_image = face.image.copy()
            box = (
                int(w * face.box[0]),
                int(h * face.box[1]),
                int(w * face.box[2]),
                int(h * face.box[3]),
            )
            if show_scores:
                s = (int(100 * face.detect_score), int(100 * face.mark_score))
                label = f'Face {ind}, ({s[0]} %, {s[1]} %)'
            else:
                label = f'Face {ind}'

            drawer.draw_labeled_box(image, label, box)

            for m in face.landmarks:
                cv.circle(face_image, (m[0], m[1]), 2, (0, 255, 0), -1)

            nv = face.nose_deviation
            print(
                f'Detected face [{ind}]: {{ score: {face.detect_score}, '
                f'nose deviation: [{nv[0]:.3f}, {nv[1]:.3f}] }}'
            )

            cv.imshow(f'Face "{ind}"', face_image)

        cv.imshow(f'Faces in {image_name}', image)

        ret = cv.waitKey()
        if ret == ord(' '):
            cv.destroyAllWindows()
        elif ret == ord('q'):
            cv.destroyAllWindows()
            break
Beispiel #4
0
def run(image_path: str, detector_weights_path: str, marker_weights_path: str):

    from dnfal.amazon.faces import analyze_faces, AwsFace
    from dnfal.detection import FaceDetector
    from dnfal.alignment import FaceMarker, FaceAligner
    from dnfal.engine import FrameAnalyzer
    from dnfal.loggers import logger, config_logger

    config_logger(level='info')

    face_detector = FaceDetector(weights_path=detector_weights_path,
                                 min_score=0.9,
                                 nms_thresh=0.7)

    face_marker = FaceMarker(weights_path=marker_weights_path)
    face_aligner = FaceAligner(out_size=256)

    frame_analyzer = FrameAnalyzer(detector=face_detector,
                                   marker=face_marker,
                                   aligner=face_aligner,
                                   encoder=None,
                                   face_padding=0.4,
                                   store_aligned=True)

    if path.isdir(image_path):
        image_paths = list_files(image_path, IMAGE_EXT, recursive=True)
        if len(image_paths) == 0:
            raise ValueError(f'No images found in {image_path}.')
    elif path.isfile(image_path):
        image_paths = [image_path]
    else:
        raise ValueError(f'Input "{image_path}" is not file nor a directory.')

    logger.info('Starting analysis...')
    logger.info('Press "space" key to display next result. Press "q" to quit.')

    max_image_size = 1920

    drawer = Drawer()
    drawer.font_scale = 0.5
    drawer.font_linewidth = 1
    drawer.text_margins = (2, 3, 12, 3)

    GENDER_LABELS = {
        AwsFace.GENDER_MAN: 'Man',
        AwsFace.GENDER_WOMAN: 'Woman',
    }

    for image_path in image_paths:
        image_name = path.basename(image_path)
        image = cv.imread(image_path)
        if image is None:
            logger.warn(f'Unable to open image file {image_path}')
            continue
        h, w, = image.shape[0:2]
        logger.info(f'{image_name} loaded. Image size is {w}x{h} pixels.')

        if max(w, h) > max_image_size:
            image, scale = resize(image, max_image_size)
            h, w, = image.shape[0:2]
            logger.info(f'Image resized to {w}x{h} pixels.')

        image = cv.copyMakeBorder(image,
                                  left=0,
                                  top=100,
                                  right=0,
                                  bottom=0,
                                  borderType=cv.BORDER_CONSTANT,
                                  value=(0, 0, 0))

        h, w, = image.shape[0:2]

        tic = time()
        faces, _ = frame_analyzer.find_faces(image)
        n_faces = len(faces)
        toc = time()
        logger.info(f'Found {n_faces} faces in {(toc - tic):.3f} seconds.')

        if n_faces:
            tic = time()
            aws_faces = analyze_faces([face.image for face in faces])
            delay = time() - tic
            logger.info(f'Faces analyzed in {delay:.3f} seconds.')

            for ind, face in enumerate(faces):

                gender_label = 'Unknown gender'
                age_label = 'Unknown age'

                aws_face = aws_faces[ind]
                if aws_face is not None:
                    gender_pred = GENDER_LABELS[aws_face.gender]
                    gender_prob = 100 * aws_face.gender_score
                    age_low = aws_face.age_low
                    age_high = aws_face.age_high

                    gender_label = f'{gender_pred} ({int(gender_prob)}%)'
                    age_label = f'{age_low}-{age_high} years'

                label = f'{gender_label} \n {age_label}'

                box = (
                    int(w * face.box[0]),
                    int(h * face.box[1]),
                    int(w * face.box[2]),
                    int(h * face.box[3]),
                )

                drawer.draw_labeled_box(image, label, box)

        cv.imshow(f'Faces in {image_name}', image)

        ret = cv.waitKey()
        if ret == ord(' '):
            cv.destroyAllWindows()
        elif ret == ord('q'):
            cv.destroyAllWindows()
            break
Beispiel #5
0
def run(image_path: str, output_path: str, weights_path: str):

    config_logger(level='DEBUG', to_console=True)

    person_encoder = PersonEncoder(weights_path=weights_path)
    images_paths = list_images(image_path)

    logger.info('Starting analysis...')
    logger.info('Press "space" key to display next result. Press "q" to quit.')

    drawer = Drawer()
    drawer.font_scale = 0.5
    drawer.font_linewidth = 1

    images = []

    for image_path in images_paths:
        image_name = path.basename(image_path)
        logger.info(f'Reading image {image_name}...')
        image = cv.imread(image_path)

        if image is None:
            logger.warn(f'Unable to open image file {image_path}')
            continue

        h, w, = image.shape[0:2]
        logger.info(f'Image loaded. Image size is {w}x{h} pixels.')
        images.append(image)

    logger.info(f'Starting encoding images...')
    tic = time()
    embeddings = person_encoder.encode(images)
    toc = time()
    logger.info(f'Encoding {len(images)} images took {(toc - tic):.3f} s.')

    score_matrix = np.matmul(embeddings, embeddings.T)

    logger.info(f'Building matching results image...')

    n_images = len(images)
    grid_width = (n_images + 1) * (SHOW_WIDTH +
                                   SHOW_MARGIN[0]) + SHOW_MARGIN[0]
    grid_height = (n_images + 1) * (SHOW_HEIGHT +
                                    SHOW_MARGIN[1]) + SHOW_MARGIN[1]
    show_grid = np.zeros((grid_height, grid_width, 3), dtype=np.uint8)

    y = SHOW_MARGIN[1]
    for i in range(n_images):
        x = SHOW_MARGIN[0]
        image_row = resize_grid_item(images[i])
        h, w = image_row.shape[0:2]
        show_grid[y:(y + h), x:(x + w)] = image_row
        cv.rectangle(img=show_grid,
                     pt1=(x, y),
                     pt2=(x + w, y + h),
                     color=(0, 0, 255),
                     thickness=1,
                     lineType=cv.LINE_AA)
        x += SHOW_WIDTH + SHOW_MARGIN[0]

        sort_score_ind = np.argsort(score_matrix[i, :])[::-1]
        row_score = score_matrix[i, sort_score_ind]
        row_images = [images[i] for i in sort_score_ind]

        for j in range(n_images):
            image_col = resize_grid_item(row_images[j])
            h, w = image_col.shape[0:2]
            show_grid[y:(y + h), x:(x + w)] = image_col

            score = row_score[j]
            cv.putText(img=show_grid,
                       text=f'{int(100 * score)}%',
                       org=(x, y + SHOW_HEIGHT + 13),
                       color=(255, 255, 255),
                       fontFace=cv.FONT_HERSHEY_PLAIN,
                       fontScale=0.8,
                       lineType=cv.LINE_AA)

            x += SHOW_WIDTH + SHOW_MARGIN[0]

        y += SHOW_HEIGHT + SHOW_MARGIN[1]

    logger.info(f'Saving matching results image...')
    cv.imwrite(output_path, show_grid)

    logger.info(f'Showing matching results image...')
    window_name = 'Person matching scoring matrix'
    cv.namedWindow(window_name, cv.WINDOW_NORMAL)
    cv.resizeWindow(window_name, 1800, 1000)
    cv.imshow(window_name, show_grid)

    if cv.waitKey() == ord('q'):
        cv.destroyAllWindows()

    logger.info(f'Done !!')