scaleAndSizeExtractor.cpp 5.5 KB
Newer Older
1
#include <openpose/core/scaleAndSizeExtractor.hpp>
2 3 4 5 6 7
#include <openpose/utilities/fastMath.hpp>
#include <openpose/utilities/openCv.hpp> // resizeGetScaleFactor

namespace op
{
    ScaleAndSizeExtractor::ScaleAndSizeExtractor(const Point<int>& netInputResolution,
8 9
        const float netInputResolutionDynamicBehavior, const Point<int>& outputResolution, const int scaleNumber,
        const double scaleGap) :
10
        mNetInputResolution{netInputResolution},
11
        mNetInputResolutionDynamicBehavior{netInputResolutionDynamicBehavior},
12 13 14 15 16 17
        mOutputSize{outputResolution},
        mScaleNumber{scaleNumber},
        mScaleGap{scaleGap}
    {
        try
        {
18
            // Sanity checks
19 20 21 22 23 24 25 26 27 28 29 30 31 32
            if ((netInputResolution.x > 0 && netInputResolution.x % 16 != 0)
                || (netInputResolution.y > 0 && netInputResolution.y % 16 != 0))
                error("Net input resolution must be multiples of 16.", __LINE__, __FUNCTION__, __FILE__);
            if (scaleNumber < 1)
                error("There must be at least 1 scale.", __LINE__, __FUNCTION__, __FILE__);
            if (scaleGap <= 0.)
                error("The gap between scales must be strictly positive.", __LINE__, __FUNCTION__, __FILE__);
        }
        catch (const std::exception& e)
        {
            error(e.what(), __LINE__, __FUNCTION__, __FILE__);
        }
    }

33 34 35 36
    ScaleAndSizeExtractor::~ScaleAndSizeExtractor()
    {
    }

37 38 39 40 41
    std::tuple<std::vector<double>, std::vector<Point<int>>, double, Point<int>> ScaleAndSizeExtractor::extract(
        const Point<int>& inputResolution) const
    {
        try
        {
42
            // Sanity check
43 44
            if (inputResolution.area() <= 0)
                error("Wrong input element (empty cvInputData).", __LINE__, __FUNCTION__, __FILE__);
45 46 47 48
            // Set poseNetInputSize
            auto poseNetInputSize = mNetInputResolution;
            if (poseNetInputSize.x <= 0 || poseNetInputSize.y <= 0)
            {
49
                // Sanity check
50 51 52
                if (poseNetInputSize.x <= 0 && poseNetInputSize.y <= 0)
                    error("Only 1 of the dimensions of net input resolution can be <= 0.",
                          __LINE__, __FUNCTION__, __FILE__);
53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69
                // mNetInputResolutionDynamicBehavior limiting maximum
                if (mNetInputResolutionDynamicBehavior > 0)
                {
                    if (poseNetInputSize.x <= 0)
                        poseNetInputSize.x = 16 * positiveIntRound(1 / 16.f *
                            fastMin(poseNetInputSize.y * mNetInputResolutionDynamicBehavior * 16.f / 9.f, poseNetInputSize.y * inputResolution.x / (float)inputResolution.y));
                    else // if (poseNetInputSize.y <= 0)
                        poseNetInputSize.y = 16 * positiveIntRound(1 / 16.f *
                            fastMin(poseNetInputSize.x * mNetInputResolutionDynamicBehavior * 9.f / 16.f, poseNetInputSize.x * inputResolution.y / (float)inputResolution.x));
                }
                else // No mNetInputResolutionDynamicBehavior behavior
                {
                    if (poseNetInputSize.x <= 0)
                        poseNetInputSize.x = 16 * positiveIntRound(1 / 16.f * poseNetInputSize.y * inputResolution.x / (float)inputResolution.y);
                    else // if (poseNetInputSize.y <= 0)
                        poseNetInputSize.y = 16 * positiveIntRound(1 / 16.f * poseNetInputSize.x * inputResolution.y / (float)inputResolution.x);
                }
70
            }
71
            // scaleInputToNetInputs & netInputSizes - Reescale keeping aspect ratio
72
            std::vector<double> scaleInputToNetInputs(mScaleNumber, 1.f);
73
            std::vector<Point<int>> netInputSizes(mScaleNumber);
74 75 76 77
            for (auto i = 0; i < mScaleNumber; i++)
            {
                const auto currentScale = 1. - i*mScaleGap;
                if (currentScale < 0. || 1. < currentScale)
G
gineshidalgo99 已提交
78
                    error("All scales must be in the range [0, 1], i.e., 0 <= 1-scale_number*scale_gap <= 1",
79 80
                          __LINE__, __FUNCTION__, __FILE__);

G
gineshidalgo99 已提交
81 82 83 84
                const auto targetWidth = fastTruncate(
                    positiveIntRound(poseNetInputSize.x * currentScale) / 16 * 16, 1, poseNetInputSize.x);
                const auto targetHeight = fastTruncate(
                    positiveIntRound(poseNetInputSize.y * currentScale) / 16 * 16, 1, poseNetInputSize.y);
85
                const Point<int> targetSize{targetWidth, targetHeight};
86
                scaleInputToNetInputs[i] = resizeGetScaleFactor(inputResolution, targetSize);
87
                netInputSizes[i] = targetSize;
88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104
            }
            // scaleInputToOutput - Scale between input and desired output size
            Point<int> outputResolution;
            double scaleInputToOutput;
            // Output = mOutputSize3D size
            if (mOutputSize.x > 0 && mOutputSize.y > 0)
            {
                outputResolution = mOutputSize;
                scaleInputToOutput = resizeGetScaleFactor(inputResolution, outputResolution);
            }
            // Output = input size
            else
            {
                outputResolution = inputResolution;
                scaleInputToOutput = 1.;
            }
            // Return result
105
            return std::make_tuple(scaleInputToNetInputs, netInputSizes, scaleInputToOutput, outputResolution);
106 107 108 109 110 111 112 113
        }
        catch (const std::exception& e)
        {
            error(e.what(), __LINE__, __FUNCTION__, __FILE__);
            return std::make_tuple(std::vector<double>{}, std::vector<Point<int>>{}, 1., Point<int>{});
        }
    }
}