10_hand_from_image.cpp 10.4 KB
Newer Older
G
gineshidalgo99 已提交
1 2 3 4 5 6
// ----------------------------- OpenPose C++ API Tutorial - Example 9 - Face from Image -----------------------------
// It reads an image and the hand location, process it, and displays the hand keypoints. In addition,
// it includes all the OpenPose configuration flags.
// Input: An image and the hand rectangle locations.
// Output: OpenPose hand keypoint detection.
// NOTE: This demo is auto-selecting the following flags: `--body_disable --hand --hand_detector 2`
G
gineshidalgo99 已提交
7 8 9 10 11 12 13 14 15 16

// Command-line user intraface
#define OPENPOSE_FLAGS_DISABLE_PRODUCER
#define OPENPOSE_FLAGS_DISABLE_DISPLAY
#include <openpose/flags.hpp>
// OpenPose dependencies
#include <openpose/headers.hpp>

// Custom OpenPose flags
// Producer
G
gineshidalgo99 已提交
17
DEFINE_string(image_path, "examples/media/COCO_val2014_000000000241.jpg",
G
gineshidalgo99 已提交
18
    "Process an image. Read all standard formats (jpg, png, bmp, etc.).");
G
gineshidalgo99 已提交
19 20 21
// Display
DEFINE_bool(no_display,                 false,
    "Enable to disable the visual display.");
G
gineshidalgo99 已提交
22 23

// This worker will just read and return all the jpg files in a directory
G
gineshidalgo99 已提交
24
void display(const std::shared_ptr<std::vector<std::shared_ptr<op::Datum>>>& datumsPtr)
G
gineshidalgo99 已提交
25
{
G
gineshidalgo99 已提交
26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
    try
    {
        // User's displaying/saving/other processing here
            // datum.cvOutputData: rendered frame with pose or heatmaps
            // datum.poseKeypoints: Array<float> with the estimated pose
        if (datumsPtr != nullptr && !datumsPtr->empty())
        {
            // Display image
            cv::imshow("User worker GUI", datumsPtr->at(0)->cvOutputData);
            cv::waitKey(0);
        }
        else
            op::log("Nullptr or empty datumsPtr found.", op::Priority::High);
    }
    catch (const std::exception& e)
G
gineshidalgo99 已提交
41
    {
G
gineshidalgo99 已提交
42
        op::error(e.what(), __LINE__, __FUNCTION__, __FILE__);
G
gineshidalgo99 已提交
43 44 45
    }
}

G
gineshidalgo99 已提交
46
void printKeypoints(const std::shared_ptr<std::vector<std::shared_ptr<op::Datum>>>& datumsPtr)
G
gineshidalgo99 已提交
47
{
G
gineshidalgo99 已提交
48 49 50 51 52 53 54 55 56 57 58 59 60 61
    try
    {
        // Example: How to use the pose keypoints
        if (datumsPtr != nullptr && !datumsPtr->empty())
        {
            op::log("Body keypoints: " + datumsPtr->at(0)->poseKeypoints.toString());
            op::log("Face keypoints: " + datumsPtr->at(0)->faceKeypoints.toString());
            op::log("Left hand keypoints: " + datumsPtr->at(0)->handKeypoints[0].toString());
            op::log("Right hand keypoints: " + datumsPtr->at(0)->handKeypoints[1].toString());
        }
        else
            op::log("Nullptr or empty datumsPtr found.", op::Priority::High);
    }
    catch (const std::exception& e)
G
gineshidalgo99 已提交
62
    {
G
gineshidalgo99 已提交
63
        op::error(e.what(), __LINE__, __FUNCTION__, __FILE__);
G
gineshidalgo99 已提交
64 65 66
    }
}

G
gineshidalgo99 已提交
67
void configureWrapper(op::Wrapper& opWrapper)
G
gineshidalgo99 已提交
68
{
G
gineshidalgo99 已提交
69 70
    try
    {
G
gineshidalgo99 已提交
71
        // Configuring OpenPose
G
gineshidalgo99 已提交
72

G
gineshidalgo99 已提交
73 74 75 76 77 78
        // logging_level
        op::check(0 <= FLAGS_logging_level && FLAGS_logging_level <= 255, "Wrong logging_level value.",
                  __LINE__, __FUNCTION__, __FILE__);
        op::ConfigureLog::setPriorityThreshold((op::Priority)FLAGS_logging_level);
        op::Profiler::setDefaultX(FLAGS_profile_speed);

G
gineshidalgo99 已提交
79 80 81 82 83 84 85 86 87 88 89 90 91 92 93
        // Applying user defined configuration - GFlags to program variables
        // outputSize
        const auto outputSize = op::flagsToPoint(FLAGS_output_resolution, "-1x-1");
        // netInputSize
        const auto netInputSize = op::flagsToPoint(FLAGS_net_resolution, "-1x368");
        // faceNetInputSize
        const auto faceNetInputSize = op::flagsToPoint(FLAGS_face_net_resolution, "368x368 (multiples of 16)");
        // handNetInputSize
        const auto handNetInputSize = op::flagsToPoint(FLAGS_hand_net_resolution, "368x368 (multiples of 16)");
        // poseModel
        const auto poseModel = op::flagsToPoseModel(FLAGS_model_pose);
        // JSON saving
        if (!FLAGS_write_keypoint.empty())
            op::log("Flag `write_keypoint` is deprecated and will eventually be removed."
                    " Please, use `write_json` instead.", op::Priority::Max);
94 95
        // keypointScaleMode
        const auto keypointScaleMode = op::flagsToScaleMode(FLAGS_keypoint_scale);
G
gineshidalgo99 已提交
96 97 98
        // heatmaps to add
        const auto heatMapTypes = op::flagsToHeatMaps(FLAGS_heatmaps_add_parts, FLAGS_heatmaps_add_bkg,
                                                      FLAGS_heatmaps_add_PAFs);
99
        const auto heatMapScaleMode = op::flagsToHeatMapScaleMode(FLAGS_heatmaps_scale);
G
gineshidalgo99 已提交
100 101
        // >1 camera view?
        const auto multipleView = (FLAGS_3d || FLAGS_3d_views > 1);
G
gineshidalgo99 已提交
102 103 104
        // Face and hand detectors
        const auto faceDetector = op::flagsToDetector(FLAGS_face_detector);
        const auto handDetector = op::Detector::Provided;
G
gineshidalgo99 已提交
105 106
        // Enabling Google Logging
        const bool enableGoogleLogging = true;
G
gineshidalgo99 已提交
107

G
gineshidalgo99 已提交
108
        // Pose configuration (use WrapperStructPose{} for default and recommended configuration)
G
gineshidalgo99 已提交
109
        const auto bodyEnable = false;
G
gineshidalgo99 已提交
110
        const op::WrapperStructPose wrapperStructPose{
G
gineshidalgo99 已提交
111
            bodyEnable, netInputSize, outputSize, keypointScaleMode, FLAGS_num_gpu, FLAGS_num_gpu_start,
G
gineshidalgo99 已提交
112 113
            FLAGS_scale_number, (float)FLAGS_scale_gap, op::flagsToRenderMode(FLAGS_render_pose, multipleView),
            poseModel, !FLAGS_disable_blending, (float)FLAGS_alpha_pose, (float)FLAGS_alpha_heatmap,
114
            FLAGS_part_to_show, FLAGS_model_folder, heatMapTypes, heatMapScaleMode, FLAGS_part_candidates,
115
            (float)FLAGS_render_threshold, FLAGS_number_people_max, FLAGS_maximize_positives, FLAGS_fps_max,
116
            FLAGS_prototxt_path, FLAGS_caffemodel_path, enableGoogleLogging};
G
gineshidalgo99 已提交
117 118 119
        opWrapper.configure(wrapperStructPose);
        // Face configuration (use op::WrapperStructFace{} to disable it)
        const op::WrapperStructFace wrapperStructFace{
G
gineshidalgo99 已提交
120 121
            FLAGS_face, faceDetector, faceNetInputSize,
            op::flagsToRenderMode(FLAGS_face_render, multipleView, FLAGS_render_pose),
G
gineshidalgo99 已提交
122 123 124
            (float)FLAGS_face_alpha_pose, (float)FLAGS_face_alpha_heatmap, (float)FLAGS_face_render_threshold};
        opWrapper.configure(wrapperStructFace);
        // Hand configuration (use op::WrapperStructHand{} to disable it)
G
gineshidalgo99 已提交
125
        const auto hand = true;
G
gineshidalgo99 已提交
126
        const op::WrapperStructHand wrapperStructHand{
G
gineshidalgo99 已提交
127
            hand, handDetector, handNetInputSize, FLAGS_hand_scale_number, (float)FLAGS_hand_scale_range,
G
gineshidalgo99 已提交
128 129 130 131 132 133 134
            op::flagsToRenderMode(FLAGS_hand_render, multipleView, FLAGS_render_pose), (float)FLAGS_hand_alpha_pose,
            (float)FLAGS_hand_alpha_heatmap, (float)FLAGS_hand_render_threshold};
        opWrapper.configure(wrapperStructHand);
        // Extra functionality configuration (use op::WrapperStructExtra{} to disable it)
        const op::WrapperStructExtra wrapperStructExtra{
            FLAGS_3d, FLAGS_3d_min_views, FLAGS_identification, FLAGS_tracking, FLAGS_ik_threads};
        opWrapper.configure(wrapperStructExtra);
135
        // Output (comment or use default argument to disable any output)
G
gineshidalgo99 已提交
136
        const op::WrapperStructOutput wrapperStructOutput{
G
gineshidalgo99 已提交
137 138
            FLAGS_cli_verbose, FLAGS_write_keypoint, op::stringToDataFormat(FLAGS_write_keypoint_format),
            FLAGS_write_json, FLAGS_write_coco_json, FLAGS_write_coco_foot_json, FLAGS_write_coco_json_variant,
139
            FLAGS_write_images, FLAGS_write_images_format, FLAGS_write_video, FLAGS_write_video_fps,
G
gineshidalgo99 已提交
140 141
            FLAGS_write_video_with_audio, FLAGS_write_heatmaps, FLAGS_write_heatmaps_format, FLAGS_write_video_3d,
            FLAGS_write_video_adam, FLAGS_write_bvh, FLAGS_udp_host, FLAGS_udp_port};
G
gineshidalgo99 已提交
142
        opWrapper.configure(wrapperStructOutput);
143
        // No GUI. Equivalent to: opWrapper.configure(op::WrapperStructGui{});
G
gineshidalgo99 已提交
144 145 146
        // Set to single-thread (for sequential processing and/or debugging and/or reducing latency)
        if (FLAGS_disable_multi_thread)
            opWrapper.disableMultiThreading();
G
gineshidalgo99 已提交
147 148 149 150 151 152 153
    }
    catch (const std::exception& e)
    {
        op::error(e.what(), __LINE__, __FUNCTION__, __FILE__);
    }
}

G
gineshidalgo99 已提交
154
int tutorialApiCpp()
G
gineshidalgo99 已提交
155 156 157 158
{
    try
    {
        op::log("Starting OpenPose demo...", op::Priority::High);
G
gineshidalgo99 已提交
159
        const auto opTimer = op::getTimerInit();
G
gineshidalgo99 已提交
160 161 162 163 164 165

        // Configuring OpenPose
        op::log("Configuring OpenPose...", op::Priority::High);
        op::Wrapper opWrapper{op::ThreadManagerMode::Asynchronous};
        configureWrapper(opWrapper);

G
gineshidalgo99 已提交
166 167 168
        // Starting OpenPose
        op::log("Starting thread(s)...", op::Priority::High);
        opWrapper.start();
G
gineshidalgo99 已提交
169

G
gineshidalgo99 已提交
170
        // Read image and hand rectangle locations
G
gineshidalgo99 已提交
171
        const auto imageToProcess = cv::imread(FLAGS_image_path);
G
gineshidalgo99 已提交
172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198
        const std::vector<std::array<op::Rectangle<float>, 2>> handRectangles{
            // Left/Right hands person 0
            std::array<op::Rectangle<float>, 2>{
                op::Rectangle<float>{320.035889f, 377.675049f, 69.300949f, 69.300949f},
                op::Rectangle<float>{0.f, 0.f, 0.f, 0.f}},
            // Left/Right hands person 1
            std::array<op::Rectangle<float>, 2>{
                op::Rectangle<float>{80.155792f, 407.673492f, 80.812706f, 80.812706f},
                op::Rectangle<float>{46.449715f, 404.559753f, 98.898178f, 98.898178f}},
            // Left/Right hands person 2
            std::array<op::Rectangle<float>, 2>{
                op::Rectangle<float>{185.692673f, 303.112244f, 157.587555f, 157.587555f},
                op::Rectangle<float>{88.984360f, 268.866547f, 117.818230f, 117.818230f}}
        };

        // Create new datum
        auto datumsPtr = std::make_shared<std::vector<std::shared_ptr<op::Datum>>>();
        datumsPtr->emplace_back();
        auto& datumPtr = datumsPtr->at(0);
        datumPtr = std::make_shared<op::Datum>();
        // Fill datum with image and handRectangles
        datumPtr->cvInputData = imageToProcess;
        datumPtr->handRectangles = handRectangles;

        // Process and display image
        opWrapper.emplaceAndPop(datumsPtr);
        if (datumsPtr != nullptr)
G
gineshidalgo99 已提交
199
        {
G
gineshidalgo99 已提交
200
            printKeypoints(datumsPtr);
G
gineshidalgo99 已提交
201
            if (!FLAGS_no_display)
G
gineshidalgo99 已提交
202
                display(datumsPtr);
G
gineshidalgo99 已提交
203 204 205
        }
        else
            op::log("Image could not be processed.", op::Priority::High);
G
gineshidalgo99 已提交
206

G
gineshidalgo99 已提交
207 208 209 210 211 212 213 214
        // Info
        op::log("NOTE: In addition with the user flags, this demo has auto-selected the following flags:"
                " `--body_disable --hand --hand_detector 2`", op::Priority::High);

        // Measuring total time
        op::printTime(opTimer, "OpenPose demo successfully finished. Total time: ", " seconds.", op::Priority::High);

        // Return
G
gineshidalgo99 已提交
215 216 217
        return 0;
    }
    catch (const std::exception& e)
G
gineshidalgo99 已提交
218
    {
G
gineshidalgo99 已提交
219
        return -1;
G
gineshidalgo99 已提交
220 221 222 223 224 225 226 227
    }
}

int main(int argc, char *argv[])
{
    // Parsing command line flags
    gflags::ParseCommandLineFlags(&argc, &argv, true);

G
gineshidalgo99 已提交
228 229
    // Running tutorialApiCpp
    return tutorialApiCpp();
G
gineshidalgo99 已提交
230
}