| 173 | } |
| 174 | |
| 175 | void FaceExtractorCaffe::forwardPass( |
| 176 | const std::vector<Rectangle<float>>& faceRectangles, const Matrix& inputData) |
| 177 | { |
| 178 | try |
| 179 | { |
| 180 | #ifdef USE_CAFFE |
| 181 | if (mEnabled && !faceRectangles.empty()) |
| 182 | { |
| 183 | const cv::Mat cvInputData = OP_OP2CVCONSTMAT(inputData); |
| 184 | |
| 185 | // Sanity check |
| 186 | if (cvInputData.empty()) |
| 187 | error("Empty cvInputData.", __LINE__, __FUNCTION__, __FILE__); |
| 188 | |
| 189 | // Fix parameters |
| 190 | const auto netInputSide = fastMin(mNetOutputSize.x, mNetOutputSize.y); |
| 191 | |
| 192 | // Set face size |
| 193 | const auto numberPeople = (int)faceRectangles.size(); |
| 194 | mFaceKeypoints.reset({numberPeople, (int)FACE_NUMBER_PARTS, 3}, 0.f); |
| 195 | |
| 196 | // HeatMaps: define size |
| 197 | if (!mHeatMapTypes.empty()) |
| 198 | mHeatMaps.reset({numberPeople, (int)FACE_NUMBER_PARTS, mNetOutputSize.y, mNetOutputSize.x}); |
| 199 | |
| 200 | // // Debugging |
| 201 | // cv::Mat cvInputDataCopy = cvInputData.clone(); |
| 202 | // Extract face keypoints for each person |
| 203 | for (auto person = 0 ; person < numberPeople ; person++) |
| 204 | { |
| 205 | const auto& faceRectangle = faceRectangles.at(person); |
| 206 | // Sanity check |
| 207 | if (faceRectangle.width != faceRectangle.height) |
| 208 | error("Face rectangle for face keypoint estimation must be squared, i.e.," |
| 209 | " width = height (" + std::to_string(faceRectangle.width) + " vs. " |
| 210 | + std::to_string(faceRectangle.height) + ").", __LINE__, __FUNCTION__, __FILE__); |
| 211 | // Only consider faces with a minimum pixel area |
| 212 | const auto minFaceSize = fastMin(faceRectangle.width, faceRectangle.height); |
| 213 | // // Debugging -> red rectangle |
| 214 | // opLog(std::to_string(cvInputData.cols) + " " + std::to_string(cvInputData.rows)); |
| 215 | // cv::rectangle(cvInputDataCopy, |
| 216 | // cv::Point{(int)faceRectangle.x, (int)faceRectangle.y}, |
| 217 | // cv::Point{(int)faceRectangle.bottomRight().x, |
| 218 | // (int)faceRectangle.bottomRight().y}, |
| 219 | // cv::Scalar{0,0,255}, 2); |
| 220 | // Get parts |
| 221 | if (minFaceSize > 40) |
| 222 | { |
| 223 | // // Debugging -> green rectangle overwriting red one |
| 224 | // opLog(std::to_string(cvInputData.cols) + " " + std::to_string(cvInputData.rows)); |
| 225 | // cv::rectangle(cvInputDataCopy, |
| 226 | // cv::Point{(int)faceRectangle.x, (int)faceRectangle.y}, |
| 227 | // cv::Point{(int)faceRectangle.bottomRight().x, |
| 228 | // (int)faceRectangle.bottomRight().y}, |
| 229 | // cv::Scalar{0,255,0}, 2); |
| 230 | // Resize and shift image to face rectangle positions |
| 231 | const auto faceSize = fastMax(faceRectangle.width, faceRectangle.height); |
| 232 | const double scaleFace = faceSize / (double)netInputSide; |
nothing calls this directly
no test coverage detected