patrikhuber / eos

A lightweight 3D Morphable Face Model library in modern C++
Apache License 2.0
1.89k stars 596 forks source link

Python: RuntimeError: bad optional access #240

Closed cfoch closed 5 years ago

cfoch commented 5 years ago

In eos-py==1.0.1 which is the one pip install by default, I get the following error:

Traceback (most recent call last):
  File "cam_face_landmaker.py", line 88, in <module>
    model_contour)
RuntimeError: bad optional access

This is produced by doing:

        ret =\
            eos.fitting.fit_shape_and_pose(morphablemodel_with_expressions,
                                           landmarks_list[0], landmark_mapper,
                                           frame_width, frame_height,
                                           edge_topology, contour_landmarks,
                                           model_contour)

The code to reproduce the error is here: https://gist.github.com/cfoch/1ef5976bbabeb24af20a59c00d84055c

in which I basically do...

model = eos.morphablemodel.load_model(
    os.path.join(EOS_SHARE_PATH, "share/sfm_shape_3448.bin"))
blendshapes = eos.morphablemodel.load_blendshapes(
    os.path.join(EOS_SHARE_PATH, "share/expression_blendshapes_3448.bin"))
morphablemodel_with_expressions = eos.morphablemodel.MorphableModel(model.get_shape_model(),
                                                                    model.get_color_model(),
                                                                    # eos.morphablemodel.PcaModel(),
                                                                    texture_coordinates=model.get_texture_coordinates())
landmark_mapper = eos.core.LandmarkMapper(
    os.path.join(EOS_SHARE_PATH, 'share/ibug_to_sfm.txt'))
edge_topology = eos.morphablemodel.load_edge_topology(
    os.path.join(EOS_SHARE_PATH, 'share/sfm_3448_edge_topology.json'))
contour_landmarks = eos.fitting.ContourLandmarks.load(
    os.path.join(EOS_SHARE_PATH, 'share/ibug_to_sfm.txt'))
model_contour = eos.fitting.ModelContour.load(
    os.path.join(EOS_SHARE_PATH, 'share/sfm_model_contours.json'))

and to create landmarks:

    landmarks_list = []
    for k, d in enumerate(dets):
        shape = predictor(resized_frame, d)

        landmarks = []
        for ibug_index, part in enumerate(shape.parts()):
            keypoint = (int(part.x / SCALE_FACTOR), int(part.y / SCALE_FACTOR))
            landmark = eos.core.Landmark(str(ibug_index + 1), keypoint)

            landmarks.append(landmark)
            cv2.circle(gray, keypoint, 4, (0, 0, 255), -1)
        landmarks_list.append(landmarks)
patrikhuber commented 5 years ago

Hi,

I think this is the expected error. You're passing a model to fit_shape_and_pose that doesn't actually contain expressions (even though you call it morphablemodel_with_expressions). When you construct it, you do not pass it an expression model (i.e. blendshapes in this case):

morphablemodel_with_expressions = eos.morphablemodel.MorphableModel(model.get_shape_model(),
                                                                    model.get_color_model(),
                                                                    # eos.morphablemodel.PcaModel(),
                                                                    texture_coordinates=model.get_texture_coordinates())
cfoch commented 5 years ago

Hi, yes, that was the problem. I had to pass to it blendshapes

morphablemodel_with_expressions = eos.morphablemodel.MorphableModel(
    model.get_shape_model(),
    blendshapes,
    color_model=eos.morphablemodel.PcaModel(),
    texture_coordinates=model.get_texture_coordinates()
cfoch commented 5 years ago

I think this can be closed. Thanks!

p30arena commented 4 years ago

This line solved mine: https://github.com/patrikhuber/eos/blob/698a7d9147f1058c6c703c0b34a3ef773489bd39/python/demo.py#L13