void KeypointScaler::scale(std::vector<Array<float>>& arrayToScalesToScale, const double scaleInputToOutput, const double scaleNetToOutput, const Point<int>& producerSize) const { try { if (mScaleMode != ScaleMode::InputResolution) { // OutputResolution if (mScaleMode == ScaleMode::OutputResolution) { for (auto& arrayToScale : arrayToScalesToScale) scaleKeypoints(arrayToScale, float(scaleInputToOutput)); } // NetOutputResolution else if (mScaleMode == ScaleMode::NetOutputResolution) { for (auto& arrayToScale : arrayToScalesToScale) scaleKeypoints(arrayToScale, float(1./scaleNetToOutput)); } // [0,1] else if (mScaleMode == ScaleMode::ZeroToOne) { const auto scaleX = 1.f / ((float)producerSize.x - 1.f); const auto scaleY = 1.f / ((float)producerSize.y - 1.f); for (auto& arrayToScale : arrayToScalesToScale) scaleKeypoints(arrayToScale, scaleX, scaleY); } // [-1,1] else if (mScaleMode == ScaleMode::PlusMinusOne) { const auto scaleX = (2.f / ((float)producerSize.x - 1.f)); const auto scaleY = (2.f / ((float)producerSize.y - 1.f)); const auto offset = -1.f; for (auto& arrayToScale : arrayToScalesToScale) scaleKeypoints(arrayToScale, scaleX, scaleY, offset, offset); } // Unknown else error("Unknown ScaleMode selected.", __LINE__, __FUNCTION__, __FILE__); } } catch (const std::exception& e) { error(e.what(), __LINE__, __FUNCTION__, __FILE__); } }
void scaleKeypoints(Array<float>& keypoints, const float scale) { try { scaleKeypoints(keypoints, scale, scale); } catch (const std::exception& e) { error(e.what(), __LINE__, __FUNCTION__, __FILE__); } }
std::pair<int, std::string> PoseGpuRenderer::renderPose(Array<float>& outputData, const Array<float>& poseKeypoints, const float scaleInputToOutput, const float scaleNetToOutput) { try { // Security checks if (outputData.empty()) error("Empty Array<float> outputData.", __LINE__, __FUNCTION__, __FILE__); // GPU rendering const auto elementRendered = spElementToRender->load(); std::string elementRenderedName; #ifdef USE_CUDA const auto numberPeople = poseKeypoints.getSize(0); if (numberPeople > 0 || elementRendered != 0 || !mBlendOriginalFrame) { cpuToGpuMemoryIfNotCopiedYet(outputData.getPtr(), outputData.getVolume()); cudaCheck(__LINE__, __FUNCTION__, __FILE__); const auto numberBodyParts = getPoseNumberBodyParts(mPoseModel); const auto numberBodyPartsPlusBkg = numberBodyParts+1; const auto numberBodyPAFChannels = getPosePartPairs(mPoseModel).size(); const Point<int> frameSize{outputData.getSize(1), outputData.getSize(0)}; // Draw poseKeypoints if (elementRendered == 0) { // Rescale keypoints to output size auto poseKeypointsRescaled = poseKeypoints.clone(); scaleKeypoints(poseKeypointsRescaled, scaleInputToOutput); // Render keypoints if (!poseKeypoints.empty()) cudaMemcpy(pGpuPose, poseKeypointsRescaled.getConstPtr(), numberPeople * numberBodyParts * 3 * sizeof(float), cudaMemcpyHostToDevice); renderPoseKeypointsGpu(*spGpuMemory, mPoseModel, numberPeople, frameSize, pGpuPose, mRenderThreshold, mShowGooglyEyes, mBlendOriginalFrame, getAlphaKeypoint()); } else { // If resized to input resolution: Replace scaleNetToOutput * scaleInputToOutput by // scaleInputToOutput, and comment the security checks. // Security checks if (scaleNetToOutput == -1.f) error("Non valid scaleNetToOutput.", __LINE__, __FUNCTION__, __FILE__); // Parameters const auto& heatMapSizes = spPoseExtractorNet->getHeatMapSize(); const Point<int> heatMapSize{heatMapSizes[3], heatMapSizes[2]}; const auto lastPAFChannel = numberBodyPartsPlusBkg+2+numberBodyPAFChannels/2; // Add all heatmaps if (elementRendered == 2) // if (elementRendered == numberBodyPartsPlusBkg+1) { elementRenderedName = "Heatmaps"; renderPoseHeatMapsGpu(*spGpuMemory, mPoseModel, frameSize, spPoseExtractorNet->getHeatMapGpuConstPtr(), heatMapSize, scaleNetToOutput * scaleInputToOutput, (mBlendOriginalFrame ? getAlphaHeatMap() : 1.f)); } // Draw PAFs (Part Affinity Fields) else if (elementRendered == 3) // else if (elementRendered == numberBodyPartsPlusBkg+2) { elementRenderedName = "PAFs (Part Affinity Fields)"; renderPosePAFsGpu(*spGpuMemory, mPoseModel, frameSize, spPoseExtractorNet->getHeatMapGpuConstPtr(), heatMapSize, scaleNetToOutput * scaleInputToOutput, (mBlendOriginalFrame ? getAlphaHeatMap() : 1.f)); } // Draw specific body part or background else if (elementRendered <= numberBodyPartsPlusBkg+2) { const auto realElementRendered = (elementRendered == 1 ? numberBodyParts : elementRendered - 4); elementRenderedName = mPartIndexToName.at(realElementRendered); renderPoseHeatMapGpu(*spGpuMemory, mPoseModel, frameSize, spPoseExtractorNet->getHeatMapGpuConstPtr(), heatMapSize, scaleNetToOutput * scaleInputToOutput, realElementRendered, (mBlendOriginalFrame ? getAlphaHeatMap() : 1.f)); } // Draw affinity between 2 body parts else if (elementRendered <= lastPAFChannel) { const auto affinityPart = (elementRendered-numberBodyPartsPlusBkg-3)*2; const auto affinityPartMapped = numberBodyPartsPlusBkg + getPoseMapIndex(mPoseModel).at(affinityPart); elementRenderedName = mPartIndexToName.at(affinityPartMapped); elementRenderedName = elementRenderedName.substr(0, elementRenderedName.find("(")); renderPosePAFGpu(*spGpuMemory, mPoseModel, frameSize, spPoseExtractorNet->getHeatMapGpuConstPtr(), heatMapSize, scaleNetToOutput * scaleInputToOutput, affinityPartMapped, (mBlendOriginalFrame ? getAlphaHeatMap() : 1.f)); } // Draw neck-part distance channel else { if (mPoseModel != PoseModel::BODY_25D) error("Neck-part distance channel only for BODY_25D.", __LINE__, __FUNCTION__, __FILE__); const auto distancePart = (elementRendered - lastPAFChannel - 1); const auto distancePartMapped = numberBodyPartsPlusBkg + numberBodyPAFChannels + distancePart; elementRenderedName = mPartIndexToName.at(distancePartMapped); renderPoseDistance(*spGpuMemory, mPoseModel, frameSize, spPoseExtractorNet->getHeatMapGpuConstPtr(), heatMapSize, scaleNetToOutput * scaleInputToOutput, distancePartMapped, (mBlendOriginalFrame ? getAlphaHeatMap() : 1.f)); } } } // GPU memory to CPU if last renderer gpuToCpuMemoryIfLastRenderer(outputData.getPtr(), outputData.getVolume()); cudaCheck(__LINE__, __FUNCTION__, __FILE__); #else UNUSED(outputData); UNUSED(poseKeypoints); UNUSED(scaleInputToOutput); UNUSED(scaleNetToOutput); error("OpenPose must be compiled with the `USE_CUDA` macro definitions in order to run this" " functionality. You can alternatively use CPU rendering (flag `--render_pose 1`).", __LINE__, __FUNCTION__, __FILE__); #endif // Return result return std::make_pair(elementRendered, elementRenderedName); } catch (const std::exception& e) { error(e.what(), __LINE__, __FUNCTION__, __FILE__); return std::make_pair(-1, ""); } }