|
|
|
@ -26,7 +26,7 @@ namespace dataset {
|
|
|
|
|
const float BoundingBoxAugmentOp::kDefRatio = 0.3;
|
|
|
|
|
|
|
|
|
|
BoundingBoxAugmentOp::BoundingBoxAugmentOp(std::shared_ptr<TensorOp> transform, float ratio)
|
|
|
|
|
: ratio_(ratio), transform_(std::move(transform)) {
|
|
|
|
|
: ratio_(ratio), uniform_(0, 1), transform_(std::move(transform)) {
|
|
|
|
|
rnd_.seed(GetSeed());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -34,41 +34,38 @@ Status BoundingBoxAugmentOp::Compute(const TensorRow &input, TensorRow *output)
|
|
|
|
|
IO_CHECK_VECTOR(input, output);
|
|
|
|
|
BOUNDING_BOX_CHECK(input); // check if bounding boxes are valid
|
|
|
|
|
uint32_t num_of_boxes = input[1]->shape()[0];
|
|
|
|
|
uint32_t num_to_aug = num_of_boxes * ratio_; // cast to int
|
|
|
|
|
std::vector<uint32_t> boxes(num_of_boxes);
|
|
|
|
|
std::vector<uint32_t> selected_boxes;
|
|
|
|
|
for (uint32_t i = 0; i < num_of_boxes; i++) boxes[i] = i;
|
|
|
|
|
// sample bboxes according to ratio picked by user
|
|
|
|
|
std::sample(boxes.begin(), boxes.end(), std::back_inserter(selected_boxes), num_to_aug, rnd_);
|
|
|
|
|
std::shared_ptr<Tensor> crop_out;
|
|
|
|
|
std::shared_ptr<Tensor> res_out;
|
|
|
|
|
std::shared_ptr<CVTensor> input_restore = CVTensor::AsCVTensor(input[0]);
|
|
|
|
|
for (uint32_t i = 0; i < num_to_aug; i++) {
|
|
|
|
|
float min_x = 0;
|
|
|
|
|
float min_y = 0;
|
|
|
|
|
float b_w = 0;
|
|
|
|
|
float b_h = 0;
|
|
|
|
|
// get the required items
|
|
|
|
|
RETURN_IF_NOT_OK(input[1]->GetItemAt<float>(&min_x, {selected_boxes[i], 0}));
|
|
|
|
|
RETURN_IF_NOT_OK(input[1]->GetItemAt<float>(&min_y, {selected_boxes[i], 1}));
|
|
|
|
|
RETURN_IF_NOT_OK(input[1]->GetItemAt<float>(&b_w, {selected_boxes[i], 2}));
|
|
|
|
|
RETURN_IF_NOT_OK(input[1]->GetItemAt<float>(&b_h, {selected_boxes[i], 3}));
|
|
|
|
|
RETURN_IF_NOT_OK(Crop(input_restore, &crop_out, static_cast<int>(min_x), static_cast<int>(min_y),
|
|
|
|
|
static_cast<int>(b_w), static_cast<int>(b_h)));
|
|
|
|
|
// transform the cropped bbox region
|
|
|
|
|
RETURN_IF_NOT_OK(transform_->Compute(crop_out, &res_out));
|
|
|
|
|
// place the transformed region back in the restored input
|
|
|
|
|
std::shared_ptr<CVTensor> res_img = CVTensor::AsCVTensor(res_out);
|
|
|
|
|
// check if transformed crop is out of bounds of the box
|
|
|
|
|
if (res_img->mat().cols > b_w || res_img->mat().rows > b_h || res_img->mat().cols < b_w ||
|
|
|
|
|
res_img->mat().rows < b_h) {
|
|
|
|
|
// if so, resize to fit in the box
|
|
|
|
|
std::shared_ptr<TensorOp> resize_op =
|
|
|
|
|
std::make_shared<ResizeOp>(static_cast<int32_t>(b_h), static_cast<int32_t>(b_w));
|
|
|
|
|
RETURN_IF_NOT_OK(resize_op->Compute(std::static_pointer_cast<Tensor>(res_img), &res_out));
|
|
|
|
|
res_img = CVTensor::AsCVTensor(res_out);
|
|
|
|
|
for (uint32_t i = 0; i < num_of_boxes; i++) {
|
|
|
|
|
// using a uniform distribution to ensure op happens with probability ratio_
|
|
|
|
|
if (uniform_(rnd_) < ratio_) {
|
|
|
|
|
float min_x = 0;
|
|
|
|
|
float min_y = 0;
|
|
|
|
|
float b_w = 0;
|
|
|
|
|
float b_h = 0;
|
|
|
|
|
// get the required items
|
|
|
|
|
RETURN_IF_NOT_OK(input[1]->GetItemAt<float>(&min_x, {i, 0}));
|
|
|
|
|
RETURN_IF_NOT_OK(input[1]->GetItemAt<float>(&min_y, {i, 1}));
|
|
|
|
|
RETURN_IF_NOT_OK(input[1]->GetItemAt<float>(&b_w, {i, 2}));
|
|
|
|
|
RETURN_IF_NOT_OK(input[1]->GetItemAt<float>(&b_h, {i, 3}));
|
|
|
|
|
RETURN_IF_NOT_OK(Crop(input_restore, &crop_out, static_cast<int>(min_x), static_cast<int>(min_y),
|
|
|
|
|
static_cast<int>(b_w), static_cast<int>(b_h)));
|
|
|
|
|
// transform the cropped bbox region
|
|
|
|
|
RETURN_IF_NOT_OK(transform_->Compute(crop_out, &res_out));
|
|
|
|
|
// place the transformed region back in the restored input
|
|
|
|
|
std::shared_ptr<CVTensor> res_img = CVTensor::AsCVTensor(res_out);
|
|
|
|
|
// check if transformed crop is out of bounds of the box
|
|
|
|
|
if (res_img->mat().cols > b_w || res_img->mat().rows > b_h || res_img->mat().cols < b_w ||
|
|
|
|
|
res_img->mat().rows < b_h) {
|
|
|
|
|
// if so, resize to fit in the box
|
|
|
|
|
std::shared_ptr<TensorOp> resize_op =
|
|
|
|
|
std::make_shared<ResizeOp>(static_cast<int32_t>(b_h), static_cast<int32_t>(b_w));
|
|
|
|
|
RETURN_IF_NOT_OK(resize_op->Compute(std::static_pointer_cast<Tensor>(res_img), &res_out));
|
|
|
|
|
res_img = CVTensor::AsCVTensor(res_out);
|
|
|
|
|
}
|
|
|
|
|
res_img->mat().copyTo(input_restore->mat()(cv::Rect(min_x, min_y, res_img->mat().cols, res_img->mat().rows)));
|
|
|
|
|
}
|
|
|
|
|
res_img->mat().copyTo(input_restore->mat()(cv::Rect(min_x, min_y, res_img->mat().cols, res_img->mat().rows)));
|
|
|
|
|
}
|
|
|
|
|
(*output).push_back(std::move(std::static_pointer_cast<Tensor>(input_restore)));
|
|
|
|
|
(*output).push_back(input[1]);
|
|
|
|
|