cv::Mat Process()

in src/io/image_det_aug_default.cc [509:670]


  cv::Mat Process(const cv::Mat &src, std::vector<float> *label,
                  common::RANDOM_ENGINE *prnd) override {
    using mshadow::index_t;
    cv::Mat res;
    if (param_.resize != -1) {
      int new_height, new_width;
      if (src.rows > src.cols) {
        new_height = param_.resize*src.rows/src.cols;
        new_width = param_.resize;
      } else {
        new_height = param_.resize;
        new_width = param_.resize*src.cols/src.rows;
      }
      int interpolation_method = GetInterMethod(param_.inter_method,
                   src.cols, src.rows, new_width, new_height, prnd);
      cv::resize(src, res, cv::Size(new_width, new_height),
                   0, 0, interpolation_method);
    } else {
      res = src;
    }

    // build a helper class for processing labels
    ImageDetLabel det_label(*label);
    // random engine
    std::uniform_real_distribution<float> rand_uniform(0, 1);

    // color space augmentation
    if (param_.random_hue_prob > 0.f || param_.random_saturation_prob > 0.f ||
        param_.random_illumination_prob > 0.f || param_.random_contrast_prob > 0.f) {
      std::uniform_real_distribution<float> uniform_range(-1.f, 1.f);
      int h = uniform_range(*prnd) * param_.max_random_hue;
      int s = uniform_range(*prnd) * param_.max_random_saturation;
      int l = uniform_range(*prnd) * param_.max_random_illumination;
      float c = uniform_range(*prnd) * param_.max_random_contrast;
      h = rand_uniform(*prnd) < param_.random_hue_prob ? h : 0;
      s = rand_uniform(*prnd) < param_.random_saturation_prob ? s : 0;
      l = rand_uniform(*prnd) < param_.random_illumination_prob ? l : 0;
      c = rand_uniform(*prnd) < param_.random_contrast_prob ? c : 0;
      if (h != 0 || s != 0 || l != 0) {
        int temp[3] = {h, l, s};
        int limit[3] = {180, 255, 255};
        cv::cvtColor(res, res, CV_BGR2HLS);
        for (int i = 0; i < res.rows; ++i) {
          for (int j = 0; j < res.cols; ++j) {
            for (int k = 0; k < 3; ++k) {
              int v = res.at<cv::Vec3b>(i, j)[k];
              v += temp[k];
              v = std::max(0, std::min(limit[k], v));
              res.at<cv::Vec3b>(i, j)[k] = v;
            }
          }
        }
        cv::cvtColor(res, res, CV_HLS2BGR);
      }
      if (std::fabs(c) > 1e-3) {
        cv::Mat tmp = res;
        tmp.convertTo(res, -1, c + 1.f, 0);
      }
    }

    // random mirror logic
    if (param_.rand_mirror_prob > 0 && rand_uniform(*prnd) < param_.rand_mirror_prob) {
      if (det_label.TryMirror()) {
        // flip image
        cv::flip(res, temp_, 1);
        res = temp_;
      }
    }

    // random padding logic
    if (param_.rand_pad_prob > 0 && param_.max_pad_scale > 1.f) {
      if (rand_uniform(*prnd) < param_.rand_pad_prob) {
        Rect pad_box = GeneratePadBox(param_.max_pad_scale, prnd);
        if (pad_box.area() > 0) {
          if (det_label.TryPad(pad_box)) {
            // pad image
            temp_ = res;
            int left = static_cast<int>(-pad_box.x * res.cols);
            int top = static_cast<int>(-pad_box.y * res.rows);
            int right = static_cast<int>((pad_box.width + pad_box.x - 1) * res.cols);
            int bot = static_cast<int>((pad_box.height + pad_box.y - 1) * res.rows);
            cv::copyMakeBorder(temp_, res, top, bot, left, right, cv::BORDER_ISOLATED,
              cv::Scalar(param_.fill_value, param_.fill_value, param_.fill_value));
          }
        }
      }
    }

    // random crop logic
    if (param_.rand_crop_prob > 0 && param_.num_crop_sampler > 0) {
      if (rand_uniform(*prnd) < param_.rand_crop_prob) {
        // random crop sampling logic: randomly pick a sampler, return if success
        // continue to next sampler if failed(exceed max_trial)
        // return original sample if every sampler has failed
        std::vector<int> indices(param_.num_crop_sampler);
        for (int i = 0; i < param_.num_crop_sampler; ++i) {
          indices[i] = i;
        }
        std::shuffle(indices.begin(), indices.end(), *prnd);
        int num_processed = 0;
        for (auto idx : indices) {
          if (num_processed > 0) break;
          for (int t = 0; t < param_.max_crop_trials[idx]; ++t) {
            Rect crop_box = GenerateCropBox(param_.min_crop_scales[idx],
              param_.max_crop_scales[idx], param_.min_crop_aspect_ratios[idx],
              param_.max_crop_aspect_ratios[idx], prnd,
              static_cast<float>(res.cols) / res.rows);
            if (det_label.TryCrop(crop_box, param_.min_crop_overlaps[idx],
                param_.max_crop_overlaps[idx], param_.min_crop_sample_coverages[idx],
                param_.max_crop_sample_coverages[idx], param_.min_crop_object_coverages[idx],
                param_.max_crop_object_coverages[idx], param_.crop_emit_mode,
                param_.emit_overlap_thresh)) {
              ++num_processed;
              // crop image
              int left = static_cast<int>(crop_box.x * res.cols);
              int top = static_cast<int>(crop_box.y * res.rows);
              int width = static_cast<int>(crop_box.width * res.cols);
              int height = static_cast<int>(crop_box.height * res.rows);
              res = res(cv::Rect(left, top, width, height));
              break;
            }
          }
        }
      }
    }

    if (image_det_aug_default_enum::kForce == param_.resize_mode) {
      // force resize to specified data_shape, regardless of aspect ratio
      int new_height = param_.data_shape[1];
      int new_width = param_.data_shape[2];
      int interpolation_method = GetInterMethod(param_.inter_method,
                   res.cols, res.rows, new_width, new_height, prnd);
      cv::resize(res, res, cv::Size(new_width, new_height),
                   0, 0, interpolation_method);
    } else if (image_det_aug_default_enum::kShrink == param_.resize_mode) {
      // try to keep original size, shrink if too large
      float h = param_.data_shape[1];
      float w = param_.data_shape[2];
      if (res.rows > h || res.cols > w) {
        float ratio = std::min(h / res.rows, w / res.cols);
        int new_height = ratio * res.rows;
        int new_width = ratio * res.cols;
        int interpolation_method = GetInterMethod(param_.inter_method,
                     res.cols, res.rows, new_width, new_height, prnd);
        cv::resize(res, res, cv::Size(new_width, new_height),
                    0, 0, interpolation_method);
      }
    } else if (image_det_aug_default_enum::kFit == param_.resize_mode) {
      float h = param_.data_shape[1];
      float w = param_.data_shape[2];
      float ratio = std::min(h / res.rows, w / res.cols);
      int new_height = ratio * res.rows;
      int new_width = ratio * res.cols;
      int interpolation_method = GetInterMethod(param_.inter_method,
                   res.cols, res.rows, new_width, new_height, prnd);
      cv::resize(res, res, cv::Size(new_width, new_height),
                  0, 0, interpolation_method);
    }

    *label = det_label.ToArray();  // put back processed labels
    return res;
  }