// Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. # include "humanseg.h" # include "humanseg_postprocess.h" // Normalize the image by (pix - mean) * scale void NormalizeImage( const std::vector &mean, const std::vector &scale, cv::Mat& im, // NOLINT float* input_buffer) { int height = im.rows; int width = im.cols; int stride = width * height; for (int h = 0; h < height; h++) { for (int w = 0; w < width; w++) { int base = h * width + w; input_buffer[base + 0 * stride] = (im.at(h, w)[0] - mean[0]) * scale[0]; input_buffer[base + 1 * stride] = (im.at(h, w)[1] - mean[1]) * scale[1]; input_buffer[base + 2 * stride] = (im.at(h, w)[2] - mean[2]) * scale[2]; } } } // Load Model and return model predictor void LoadModel( const std::string& model_dir, bool use_gpu, std::unique_ptr* predictor) { // Config the model info paddle::AnalysisConfig config; auto prog_file = model_dir + "/__model__"; auto params_file = model_dir + "/__params__"; config.SetModel(prog_file, params_file); if (use_gpu) { config.EnableUseGpu(100, 0); } else { config.DisableGpu(); } config.SwitchUseFeedFetchOps(false); config.SwitchSpecifyInputNames(true); // Memory optimization config.EnableMemoryOptim(); *predictor = std::move(CreatePaddlePredictor(config)); } void HumanSeg::Preprocess(const cv::Mat& image_mat) { // Clone the image : keep the original mat for postprocess cv::Mat im = image_mat.clone(); auto eval_wh = cv::Size(eval_size_[0], eval_size_[1]); cv::resize(im, im, eval_wh, 0.f, 0.f, cv::INTER_LINEAR); im.convertTo(im, CV_32FC3, 1.0); int rc = im.channels(); int rh = im.rows; int rw = im.cols; input_shape_ = {1, rc, rh, rw}; input_data_.resize(1 * rc * rh * rw); float* buffer = input_data_.data(); NormalizeImage(mean_, scale_, im, input_data_.data()); } cv::Mat HumanSeg::Postprocess(const cv::Mat& im) { int h = input_shape_[2]; int w = input_shape_[3]; scoremap_data_.resize(3 * h * w * sizeof(float)); float* base = output_data_.data() + h * w; for (int i = 0; i < h * w; ++i) { scoremap_data_[i] = uchar(base[i] * 255); } cv::Mat im_scoremap = cv::Mat(h, w, CV_8UC1); im_scoremap.data = scoremap_data_.data(); cv::resize(im_scoremap, im_scoremap, cv::Size(im.cols, im.rows)); im_scoremap.convertTo(im_scoremap, CV_32FC1, 1 / 255.0); float* pblob = reinterpret_cast(im_scoremap.data); int out_buff_capacity = 10 * im.cols * im.rows * sizeof(float); segout_data_.resize(out_buff_capacity); unsigned char* seg_result = segout_data_.data(); MergeProcess(im.data, pblob, im.rows, im.cols, seg_result); cv::Mat seg_mat(im.rows, im.cols, CV_8UC1, seg_result); cv::resize(seg_mat, seg_mat, cv::Size(im.cols, im.rows)); cv::GaussianBlur(seg_mat, seg_mat, cv::Size(5, 5), 0, 0); float fg_threshold = 0.8; float bg_threshold = 0.4; cv::Mat show_seg_mat; seg_mat.convertTo(seg_mat, CV_32FC1, 1 / 255.0); ThresholdMask(seg_mat, fg_threshold, bg_threshold, show_seg_mat); auto out_im = MergeSegMat(show_seg_mat, im); return out_im; } cv::Mat HumanSeg::Predict(const cv::Mat& im) { // Preprocess image Preprocess(im); // Prepare input tensor auto input_names = predictor_->GetInputNames(); auto in_tensor = predictor_->GetInputTensor(input_names[0]); in_tensor->Reshape(input_shape_); in_tensor->copy_from_cpu(input_data_.data()); // Run predictor predictor_->ZeroCopyRun(); // Get output tensor auto output_names = predictor_->GetOutputNames(); auto out_tensor = predictor_->GetOutputTensor(output_names[0]); auto output_shape = out_tensor->shape(); // Calculate output length int output_size = 1; for (int j = 0; j < output_shape.size(); ++j) { output_size *= output_shape[j]; } output_data_.resize(output_size); out_tensor->copy_to_cpu(output_data_.data()); // Postprocessing result return Postprocess(im); }