poseExtractorNet.cpp 15.3 KB
Newer Older
1 2
#ifdef USE_CUDA
    #include <cuda_runtime_api.h>
G
gineshidalgo99 已提交
3
    #include <openpose/gpu/cuda.hpp>
4
#endif
G
Gines Hidalgo 已提交
5 6
#include <openpose/core/enumClasses.hpp>
#include <openpose/utilities/fastMath.hpp>
7
#include <openpose/pose/poseExtractorNet.hpp>
G
gineshidalgo99 已提交
8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32

namespace op
{
    bool heatMapTypesHas(const std::vector<HeatMapType>& heatMapTypes, const HeatMapType heatMapType)
    {
        try
        {
            for (auto heatMapTypeVector : heatMapTypes)
                if (heatMapTypeVector == heatMapType)
                    return true;
            return false;
        }
        catch (const std::exception& e)
        {
            error(e.what(), __LINE__, __FUNCTION__, __FILE__);
            return false;
        }
    }

    int getNumberHeatMapChannels(const std::vector<HeatMapType>& heatMapTypes, const PoseModel poseModel)
    {
        try
        {
            auto numberHeatMapChannels = 0;
            if (heatMapTypesHas(heatMapTypes, HeatMapType::Parts))
33
                numberHeatMapChannels += getPoseNumberBodyParts(poseModel);
G
gineshidalgo99 已提交
34 35 36
            if (heatMapTypesHas(heatMapTypes, HeatMapType::Background))
                numberHeatMapChannels += 1;
            if (heatMapTypesHas(heatMapTypes, HeatMapType::PAFs))
37
                numberHeatMapChannels += (int)getPosePartPairs(poseModel).size();
G
gineshidalgo99 已提交
38 39 40 41 42 43 44 45 46
            return numberHeatMapChannels;
        }
        catch (const std::exception& e)
        {
            error(e.what(), __LINE__, __FUNCTION__, __FILE__);
            return 0;
        }
    }

47
    PoseExtractorNet::PoseExtractorNet(const PoseModel poseModel, const std::vector<HeatMapType>& heatMapTypes,
48
                                       const ScaleMode heatMapScaleMode, const bool addPartCandidates,
G
gineshidalgo99 已提交
49
                                       const bool maximizePositives) :
G
gineshidalgo99 已提交
50
        mPoseModel{poseModel},
51
        mNetOutputSize{0,0},
G
gineshidalgo99 已提交
52
        mHeatMapTypes{heatMapTypes},
53
        mHeatMapScaleMode{heatMapScaleMode},
54
        mAddPartCandidates{addPartCandidates}
G
gineshidalgo99 已提交
55 56 57 58
    {
        try
        {
            // Error check
59
            if (mHeatMapScaleMode != ScaleMode::ZeroToOne && mHeatMapScaleMode != ScaleMode::PlusMinusOne
60
                && mHeatMapScaleMode != ScaleMode::UnsignedChar && mHeatMapScaleMode != ScaleMode::NoScale)
61
                error("The ScaleMode heatMapScaleMode must be ZeroToOne, PlusMinusOne, UnsignedChar, or NoScale.",
62
                      __LINE__, __FUNCTION__, __FILE__);
G
gineshidalgo99 已提交
63

G
gineshidalgo99 已提交
64
            // Properties - Init to 0
G
gineshidalgo99 已提交
65 66
            for (auto& property : mProperties)
                property = 0.;
G
gineshidalgo99 已提交
67 68
            // Properties - Fill default values
            mProperties[(int)PoseProperty::NMSThreshold] = getPoseDefaultNmsThreshold(mPoseModel, maximizePositives);
69
            mProperties[(int)PoseProperty::ConnectInterMinAboveThreshold]
G
gineshidalgo99 已提交
70 71 72 73 74 75
                = getPoseDefaultConnectInterMinAboveThreshold(maximizePositives);
            mProperties[(int)PoseProperty::ConnectInterThreshold] = getPoseDefaultConnectInterThreshold(
                mPoseModel, maximizePositives);
            mProperties[(int)PoseProperty::ConnectMinSubsetCnt] = getPoseDefaultMinSubsetCnt(maximizePositives);
            mProperties[(int)PoseProperty::ConnectMinSubsetScore] = getPoseDefaultConnectMinSubsetScore(
                maximizePositives);
G
gineshidalgo99 已提交
76 77 78 79 80 81 82
        }
        catch (const std::exception& e)
        {
            error(e.what(), __LINE__, __FUNCTION__, __FILE__);
        }
    }

83
    PoseExtractorNet::~PoseExtractorNet()
G
Gines Hidalgo 已提交
84 85 86
    {
    }

87
    void PoseExtractorNet::initializationOnThread()
G
gineshidalgo99 已提交
88
    {
89 90 91 92 93 94 95 96 97 98 99
        try
        {
            // Get thread id
            mThreadId = {std::this_thread::get_id()};
            // Deep net initialization
            netInitializationOnThread();
        }
        catch (const std::exception& e)
        {
            error(e.what(), __LINE__, __FUNCTION__, __FILE__);
        }
G
gineshidalgo99 已提交
100 101
    }

102
    Array<float> PoseExtractorNet::getHeatMapsCopy() const
G
gineshidalgo99 已提交
103 104 105 106
    {
        try
        {
            checkThread();
107
            Array<float> heatMaps;
G
gineshidalgo99 已提交
108 109
            if (!mHeatMapTypes.empty())
            {
G
gineshidalgo99 已提交
110 111 112
                #ifdef USE_CUDA
                    cudaCheck(__LINE__, __FUNCTION__, __FILE__);
                #endif
113 114 115
                // Get heatmaps size
                const auto heatMapSize = getHeatMapSize();

G
gineshidalgo99 已提交
116 117
                // Allocate memory
                const auto numberHeatMapChannels = getNumberHeatMapChannels(mHeatMapTypes, mPoseModel);
118
                heatMaps.reset({numberHeatMapChannels, heatMapSize[2], heatMapSize[3]});
G
gineshidalgo99 已提交
119 120

                // Copy memory
121
                const auto channelOffset = heatMaps.getVolume(1, 2);
122 123 124
                const auto volumeBodyParts = getPoseNumberBodyParts(mPoseModel) * channelOffset;
                const auto volumePAFs = getPosePartPairs(mPoseModel).size() * channelOffset;
                auto totalOffset = 0u;
125
                // Body parts
G
gineshidalgo99 已提交
126 127
                if (heatMapTypesHas(mHeatMapTypes, HeatMapType::Parts))
                {
128 129 130 131 132 133 134
                    #ifdef USE_CUDA
                        cudaMemcpy(heatMaps.getPtr(), getHeatMapGpuConstPtr(),
                                   volumeBodyParts * sizeof(float), cudaMemcpyDeviceToHost);
                    #else
                        const auto* heatMapCpuPtr = getHeatMapCpuConstPtr();
                        std::copy(heatMapCpuPtr, heatMapCpuPtr+volumeBodyParts, heatMaps.getPtr());
                    #endif
135 136 137 138 139 140 141 142 143
                    if (mHeatMapScaleMode != ScaleMode::NoScale)
                    {
                        // Change from [0,1] to [-1,1]
                        if (mHeatMapScaleMode == ScaleMode::PlusMinusOne)
                            for (auto i = 0u ; i < volumeBodyParts ; i++)
                                heatMaps[i] = fastTruncate(heatMaps[i]) * 2.f - 1.f;
                        // [0, 255]
                        else if (mHeatMapScaleMode == ScaleMode::UnsignedChar)
                            for (auto i = 0u ; i < volumeBodyParts ; i++)
G
gineshidalgo99 已提交
144
                                heatMaps[i] = (float)positiveIntRound(fastTruncate(heatMaps[i]) * 255.f);
145 146 147 148 149
                        // Avoid values outside original range
                        else
                            for (auto i = 0u ; i < volumeBodyParts ; i++)
                                heatMaps[i] = fastTruncate(heatMaps[i]);
                    }
G
Gines Hidalgo 已提交
150
                    totalOffset += (unsigned int)volumeBodyParts;
G
gineshidalgo99 已提交
151
                }
152
                // Background
G
gineshidalgo99 已提交
153 154
                if (heatMapTypesHas(mHeatMapTypes, HeatMapType::Background))
                {
G
Gines Hidalgo 已提交
155
                    if (addBkgChannel(mPoseModel))
156
                    {
G
Gines Hidalgo 已提交
157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187
                        auto* heatMapsPtr = heatMaps.getPtr() + totalOffset;
                        #ifdef USE_CUDA
                            cudaMemcpy(heatMapsPtr, getHeatMapGpuConstPtr() + volumeBodyParts,
                                       channelOffset * sizeof(float), cudaMemcpyDeviceToHost);
                        #else
                            const auto* heatMapCpuPtr = getHeatMapCpuConstPtr();
                            std::copy(
                                heatMapCpuPtr + volumeBodyParts, heatMapCpuPtr + volumeBodyParts + channelOffset,
                                heatMapsPtr);
                        #endif
                        if (mHeatMapScaleMode != ScaleMode::NoScale)
                        {
                            // Change from [0,1] to [-1,1]
                            if (mHeatMapScaleMode == ScaleMode::PlusMinusOne)
                                for (auto i = 0u ; i < channelOffset ; i++)
                                    heatMapsPtr[i] = fastTruncate(heatMapsPtr[i]) * 2.f - 1.f;
                            // [0, 255]
                            else if (mHeatMapScaleMode == ScaleMode::UnsignedChar)
                                for (auto i = 0u ; i < channelOffset ; i++)
                                    heatMapsPtr[i] = (float)positiveIntRound(fastTruncate(heatMapsPtr[i]) * 255.f);
                            // Avoid values outside original range
                            else
                                for (auto i = 0u ; i < channelOffset ; i++)
                                    heatMapsPtr[i] = fastTruncate(heatMapsPtr[i]);
                        }
                        totalOffset += (unsigned int)channelOffset;
                    }
                    else
                    {
                        error("You enabled `--heatmaps_add_bkg` for a model that does not contain one. Please,"
                              " remove this flag for this model.", __LINE__, __FUNCTION__, __FILE__);
188
                    }
G
gineshidalgo99 已提交
189
                }
190
                // PAFs
G
gineshidalgo99 已提交
191 192
                if (heatMapTypesHas(mHeatMapTypes, HeatMapType::PAFs))
                {
193
                    auto* heatMapsPtr = heatMaps.getPtr() + totalOffset;
194
                    #ifdef USE_CUDA
195
                        cudaMemcpy(heatMapsPtr,
G
Gines Hidalgo 已提交
196
                                   getHeatMapGpuConstPtr() + volumeBodyParts + (addBkgChannel(mPoseModel) ? channelOffset : 0),
197 198 199
                                   volumePAFs * sizeof(float), cudaMemcpyDeviceToHost);
                    #else
                        const auto* heatMapCpuPtr = getHeatMapCpuConstPtr();
G
Gines Hidalgo 已提交
200 201
                        std::copy(heatMapCpuPtr + volumeBodyParts + (addBkgChannel(mPoseModel) ? channelOffset : 0),
                                  heatMapCpuPtr + volumeBodyParts + (addBkgChannel(mPoseModel) ? channelOffset : 0) + volumePAFs,
202
                                  heatMapsPtr);
203
                    #endif
204 205 206 207 208 209 210 211 212
                    if (mHeatMapScaleMode != ScaleMode::NoScale)
                    {
                        // Change from [-1,1] to [0,1]. Note that PAFs are in [-1,1]
                        if (mHeatMapScaleMode == ScaleMode::ZeroToOne)
                            for (auto i = 0u ; i < volumePAFs ; i++)
                                heatMapsPtr[i] = fastTruncate(heatMapsPtr[i], -1.f) * 0.5f + 0.5f;
                        // [0, 255]
                        else if (mHeatMapScaleMode == ScaleMode::UnsignedChar)
                            for (auto i = 0u ; i < volumePAFs ; i++)
G
gineshidalgo99 已提交
213
                                heatMapsPtr[i] = (float)positiveIntRound(
214 215 216 217 218 219 220
                                    fastTruncate(heatMapsPtr[i], -1.f) * 128.5f + 128.5f
                                );
                        // Avoid values outside original range
                        else
                            for (auto i = 0u ; i < volumePAFs ; i++)
                                heatMapsPtr[i] = fastTruncate(heatMapsPtr[i], -1.f);
                    }
G
Gines Hidalgo 已提交
221
                    totalOffset += (unsigned int)volumePAFs;
G
gineshidalgo99 已提交
222 223
                }
                // Copy all at once
224 225
                // cudaMemcpy(heatMaps.getPtr(), getHeatMapGpuConstPtr(), heatMaps.getVolume() * sizeof(float),
                //            cudaMemcpyDeviceToHost);
G
gineshidalgo99 已提交
226
            }
G
gineshidalgo99 已提交
227 228 229
            #ifdef USE_CUDA
                cudaCheck(__LINE__, __FUNCTION__, __FILE__);
            #endif
230
            return heatMaps;
G
gineshidalgo99 已提交
231 232 233 234 235 236 237 238
        }
        catch (const std::exception& e)
        {
            error(e.what(), __LINE__, __FUNCTION__, __FILE__);
            return Array<float>{};
        }
    }

239
    std::vector<std::vector<std::array<float,3>>> PoseExtractorNet::getCandidatesCopy() const
240 241 242
    {
        try
        {
243
            // Sanity check
244 245 246 247 248 249 250 251 252 253 254 255 256
            checkThread();
            // Initialization
            std::vector<std::vector<std::array<float,3>>> candidates;
            // Fill candidates
            if (mAddPartCandidates)
            {
                const auto numberBodyParts = getPoseNumberBodyParts(mPoseModel);
                candidates.resize(numberBodyParts);
                const auto peaksArea = (POSE_MAX_PEOPLE+1) * 3;
                // Memory copy
                const auto* candidatesCpuPtr = getCandidatesCpuConstPtr();
                for (auto part = 0u ; part < numberBodyParts ; part++)
                {
G
gineshidalgo99 已提交
257
                    const auto numberPartCandidates = (int)std::round(candidatesCpuPtr[part*peaksArea]);
258 259 260
                    candidates[part].resize(numberPartCandidates);
                    const auto* partCandidatesPtr = &candidatesCpuPtr[part*peaksArea+3];
                    for (auto candidate = 0 ; candidate < numberPartCandidates ; candidate++)
G
gineshidalgo99 已提交
261 262 263 264
                        candidates[part][candidate] = {
                            partCandidatesPtr[3*candidate] * mScaleNetToOutput,
                            partCandidatesPtr[3*candidate+1] * mScaleNetToOutput,
                            partCandidatesPtr[3*candidate+2]};
265 266 267 268 269 270 271 272 273 274 275 276
                }
            }
            // Return
            return candidates;
        }
        catch (const std::exception& e)
        {
            error(e.what(), __LINE__, __FUNCTION__, __FILE__);
            return std::vector<std::vector<std::array<float,3>>>{};
        }
    }

277
    Array<float> PoseExtractorNet::getPoseKeypoints() const
G
gineshidalgo99 已提交
278 279 280 281
    {
        try
        {
            checkThread();
282
            return mPoseKeypoints;
G
gineshidalgo99 已提交
283 284 285 286 287 288 289 290
        }
        catch (const std::exception& e)
        {
            error(e.what(), __LINE__, __FUNCTION__, __FILE__);
            return Array<float>{};
        }
    }

291
    Array<float> PoseExtractorNet::getPoseScores() const
292 293 294 295 296 297 298 299 300 301 302 303 304
    {
        try
        {
            checkThread();
            return mPoseScores;
        }
        catch (const std::exception& e)
        {
            error(e.what(), __LINE__, __FUNCTION__, __FILE__);
            return Array<float>{};
        }
    }

305
    float PoseExtractorNet::getScaleNetToOutput() const
G
gineshidalgo99 已提交
306 307 308 309 310 311 312 313 314 315 316 317 318
    {
        try
        {
            checkThread();
            return mScaleNetToOutput;
        }
        catch (const std::exception& e)
        {
            error(e.what(), __LINE__, __FUNCTION__, __FILE__);
            return 0.;
        }
    }

319
    double PoseExtractorNet::get(const PoseProperty property) const
G
gineshidalgo99 已提交
320 321 322 323 324 325 326 327 328 329 330 331
    {
        try
        {
            return mProperties.at((int)property);
        }
        catch (const std::exception& e)
        {
            error(e.what(), __LINE__, __FUNCTION__, __FILE__);
            return 0.;
        }
    }

332
    void PoseExtractorNet::set(const PoseProperty property, const double value)
G
gineshidalgo99 已提交
333 334 335
    {
        try
        {
336 337 338 339 340
            auto& propertyElement = mProperties.at((int)property);
            log("Property " + std::to_string((int)property)
                + " set from " + std::to_string(propertyElement)
                + " to " + std::to_string(value), Priority::High);
            propertyElement = {value};
G
gineshidalgo99 已提交
341 342 343 344 345 346 347
        }
        catch (const std::exception& e)
        {
            error(e.what(), __LINE__, __FUNCTION__, __FILE__);
        }
    }

348
    void PoseExtractorNet::increase(const PoseProperty property, const double value)
G
gineshidalgo99 已提交
349 350 351
    {
        try
        {
352
            set(property, get(property) + value);
G
gineshidalgo99 已提交
353 354 355 356 357 358 359
        }
        catch (const std::exception& e)
        {
            error(e.what(), __LINE__, __FUNCTION__, __FILE__);
        }
    }

G
gineshidalgo99 已提交
360 361 362 363 364 365 366 367 368 369 370 371 372
    void PoseExtractorNet::clear()
    {
        try
        {
            mPoseKeypoints.reset();
            mPoseScores.reset();
        }
        catch (const std::exception& e)
        {
            error(e.what(), __LINE__, __FUNCTION__, __FILE__);
        }
    }

373
    void PoseExtractorNet::checkThread() const
G
gineshidalgo99 已提交
374 375 376
    {
        try
        {
377
            if (mThreadId != std::this_thread::get_id())
378 379
                error("The CPU/GPU pointer data cannot be accessed from a different thread.",
                      __LINE__, __FUNCTION__, __FILE__);
G
gineshidalgo99 已提交
380 381 382 383 384 385 386
        }
        catch (const std::exception& e)
        {
            error(e.what(), __LINE__, __FUNCTION__, __FILE__);
        }
    }
}