cleardusk / 3DDFA_V2

The official PyTorch implementation of Towards Fast, Accurate and Stable 3D Dense Face Alignment, ECCV 2020.
MIT License
2.92k stars 515 forks source link

Negative dimensions problem #164

Closed Devilben4 closed 1 month ago

Devilben4 commented 1 month ago

Hi,

with this code :

import sys
import argparse
import cv2
import yaml
import os
import time

from FaceBoxes import FaceBoxes
from TDDFA import TDDFA
from utils.render import render
from utils.depth import depth
from utils.pncc import pncc
from utils.uv import uv_tex
from utils.pose import viz_pose
from utils.serialization import ser_to_ply, ser_to_obj
from utils.functions import draw_landmarks, get_suffix
from utils.tddfa_util import str2bool

def capture_from_webcam(cap, output_path):
    """Capture an image from the already opened webcam and save it to the specified path."""
    ret, frame = cap.read()  # Capture a single frame
    if not ret:
        print("Failed to capture image from webcam")
        return False

    # Save the captured frame to the specified path
    cv2.imwrite(output_path, frame)
    print(f"Image saved to {output_path}")
    return True

def process_uv_map(args, webcam_image_path):
    """Process UV map generation from the captured image."""
    cfg = yaml.load(open(args.config), Loader=yaml.SafeLoader)

    # Init FaceBoxes and TDDFA, recommend using onnx flag
    if args.onnx:
        os.environ['KMP_DUPLICATE_LIB_OK'] = 'True'
        os.environ['OMP_NUM_THREADS'] = '4'

        from FaceBoxes.FaceBoxes_ONNX import FaceBoxes_ONNX
        from TDDFA_ONNX import TDDFA_ONNX

        face_boxes = FaceBoxes_ONNX()
        tddfa = TDDFA_ONNX(**cfg)
    else:
        gpu_mode = args.mode == 'gpu'
        tddfa = TDDFA(gpu_mode=gpu_mode, **cfg)
        face_boxes = FaceBoxes()

    # Given a still image path and load to BGR channel
    img = cv2.imread(webcam_image_path)

    # Detect faces, get 3DMM params and roi boxes
    boxes = face_boxes(img)
    n = len(boxes)
    if n == 0:
        print(f'No face detected, skipping UV generation')
        return
    print(f'Detect {n} faces')

    param_lst, roi_box_lst = tddfa(img, boxes)

    # Visualization and serialization
    dense_flag = args.opt in ('2d_dense', '3d', 'depth', 'pncc', 'uv_tex', 'ply', 'obj')
    old_suffix = get_suffix(webcam_image_path)
    new_suffix = f'.{args.opt}' if args.opt in ('ply', 'obj') else '.jpg'

    wfp = f'examples/results/{webcam_image_path.split("/")[-1].replace(old_suffix, "")}_{args.opt}' + new_suffix

    ver_lst = tddfa.recon_vers(param_lst, roi_box_lst, dense_flag=dense_flag)

    if args.opt == '2d_sparse':
        draw_landmarks(img, ver_lst, show_flag=args.show_flag, dense_flag=dense_flag, wfp=wfp)
    elif args.opt == '2d_dense':
        draw_landmarks(img, ver_lst, show_flag=args.show_flag, dense_flag=dense_flag, wfp=wfp)
    elif args.opt == '3d':
        render(img, ver_lst, tddfa.tri, alpha=0.6, show_flag=args.show_flag, wfp=wfp)
    elif args.opt == 'depth':
        depth(img, ver_lst, tddfa.tri, show_flag=args.show_flag, wfp=wfp, with_bg_flag=True)
    elif args.opt == 'pncc':
        pncc(img, ver_lst, tddfa.tri, show_flag=args.show_flag, wfp=wfp, with_bg_flag=True)
    elif args.opt == 'uv_tex':
        uv_tex(img, ver_lst, tddfa.tri, show_flag=args.show_flag, wfp=wfp)
    elif args.opt == 'pose':
        viz_pose(img, param_lst, ver_lst, show_flag=args.show_flag, wfp=wfp)
    elif args.opt == 'ply':
        ser_to_ply(ver_lst, tddfa.tri, height=img.shape[0], wfp=wfp)
    elif args.opt == 'obj':
        ser_to_obj(img, ver_lst, tddfa.tri, height=img.shape[0], wfp=wfp)
    else:
        raise ValueError(f'Unknown opt {args.opt}')

def main(args):
    webcam_image_path = 'C:/Users/benkl/OneDrive/Documents/face recognition/3DDFA_v2/examples/inputs/webcam_capture.jpg'

    # Open the webcam once
    cap = cv2.VideoCapture(0)
    if not cap.isOpened():
        print("Cannot open webcam")
        sys.exit()

    try:
        while True:  # Loop indefinitely
            print("Starting new capture session...")

            # Capture an image from the webcam (webcam stays open)
            if capture_from_webcam(cap, webcam_image_path):
                # Process UV map generation
                process_uv_map(args, webcam_image_path)
            else:
                print("Failed to capture image, retrying...")

            # Wait for 4 seconds before the next UV map generation
            print("Waiting for 4 seconds before next UV generation...")
            time.sleep(4)  # 4 seconds delay

    except KeyboardInterrupt:
        print("Program terminated by user.")
    finally:
        # Release the webcam when done
        cap.release()

if __name__ == '__main__':
    parser = argparse.ArgumentParser(description='The demo of still image of 3DDFA_V2 with continuous webcam capture')
    parser.add_argument('-c', '--config', type=str, default='C:/Users/benkl/OneDrive/Documents/face recognition/3DDFA_V2/configs/mb1_120x120.yml')
    parser.add_argument('-f', '--img_fp', type=str, default='C:/Users/benkl/OneDrive/Documents/face recognition/3DDFA_v2/examples/inputs/webcam_capture.jpg')
    parser.add_argument('-m', '--mode', type=str, default='gpu', help='gpu or cpu mode')
    parser.add_argument('-o', '--opt', type=str, default='uv_tex',
                        choices=['2d_sparse', '2d_dense', '3d', 'depth', 'pncc', 'uv_tex', 'pose', 'ply', 'obj'])
    parser.add_argument('--show_flag', type=str2bool, default='true', help='whether to show the visualization result')
    parser.add_argument('--onnx', action='store_true', default=False)

    args = parser.parse_args()
    main(args)

i got : An error occurred during 3DDFA processing: negative dimensions are not allowed

can someone tell me why ?