6abec128ed
GitOrigin-RevId: f4b1fe3f15810450fb6539e733f6a260d3ee082c
229 lines
6.8 KiB
C++
229 lines
6.8 KiB
C++
// Copyright 2021 The MediaPipe Authors.
|
|
//
|
|
// 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 "mediapipe/framework/formats/affine_transform.h"
|
|
|
|
#include <algorithm>
|
|
#include <cmath>
|
|
#include <memory>
|
|
#include <vector>
|
|
|
|
#include "absl/memory/memory.h"
|
|
#include "absl/strings/substitute.h"
|
|
#include "mediapipe/framework/port/canonical_errors.h"
|
|
#include "mediapipe/framework/port/integral_types.h"
|
|
#include "mediapipe/framework/port/logging.h"
|
|
#include "mediapipe/framework/port/point2.h"
|
|
#include "mediapipe/framework/port/ret_check.h"
|
|
#include "mediapipe/framework/port/status.h"
|
|
#include "mediapipe/framework/port/statusor.h"
|
|
#include "mediapipe/framework/tool/status_util.h"
|
|
#include "mediapipe/framework/type_map.h"
|
|
|
|
namespace mediapipe {
|
|
using ::mediapipe::AffineTransformData;
|
|
|
|
AffineTransform::AffineTransform() { SetScale(Point2_f(1, 1)); }
|
|
|
|
AffineTransform::AffineTransform(
|
|
const AffineTransformData& affine_transform_data)
|
|
: affine_transform_data_(affine_transform_data), is_dirty_(true) {
|
|
// make sure scale is set to default (1, 1) when none provided
|
|
if (!affine_transform_data_.has_scale()) {
|
|
SetScale(Point2_f(1, 1));
|
|
}
|
|
}
|
|
|
|
AffineTransform AffineTransform::Create(const Point2_f& translation,
|
|
const Point2_f& scale, float rotation,
|
|
const Point2_f& shear) {
|
|
AffineTransformData affine_transform_data;
|
|
|
|
auto* t = affine_transform_data.mutable_translation();
|
|
t->set_x(translation.x());
|
|
t->set_y(translation.y());
|
|
|
|
auto* s = affine_transform_data.mutable_scale();
|
|
s->set_x(scale.x());
|
|
s->set_y(scale.y());
|
|
|
|
s = affine_transform_data.mutable_shear();
|
|
s->set_x(shear.x());
|
|
s->set_y(shear.y());
|
|
|
|
affine_transform_data.set_rotation(rotation);
|
|
|
|
return AffineTransform(affine_transform_data);
|
|
}
|
|
|
|
// Accessor for the composition matrix
|
|
std::vector<float> AffineTransform::GetCompositionMatrix() {
|
|
float r = affine_transform_data_.rotation();
|
|
const auto t = affine_transform_data_.translation();
|
|
const auto sc = affine_transform_data_.scale();
|
|
const auto sh = affine_transform_data_.shear();
|
|
|
|
if (is_dirty_) {
|
|
// Composition matrix M = T*R*Sh*Sc
|
|
// Column based to match GL matrix store order
|
|
float cos_r = std::cos(r);
|
|
float sin_r = std::sin(r);
|
|
matrix_[0] = (cos_r + sin_r * -sh.y()) * sc.x();
|
|
matrix_[1] = (-sin_r + cos_r * -sh.y()) * sc.x();
|
|
matrix_[2] = 0;
|
|
matrix_[3] = (cos_r * -sh.x() + sin_r) * sc.y();
|
|
matrix_[4] = (-sin_r * -sh.x() + cos_r) * sc.y();
|
|
matrix_[5] = 0;
|
|
matrix_[6] = t.x();
|
|
matrix_[7] = -t.y();
|
|
matrix_[8] = 1;
|
|
is_dirty_ = false;
|
|
}
|
|
|
|
return matrix_;
|
|
}
|
|
|
|
Point2_f AffineTransform::GetScale() const {
|
|
return Point2_f(affine_transform_data_.scale().x(),
|
|
affine_transform_data_.scale().y());
|
|
}
|
|
|
|
Point2_f AffineTransform::GetTranslation() const {
|
|
return Point2_f(affine_transform_data_.translation().x(),
|
|
affine_transform_data_.translation().y());
|
|
}
|
|
|
|
Point2_f AffineTransform::GetShear() const {
|
|
return Point2_f(affine_transform_data_.shear().x(),
|
|
affine_transform_data_.shear().y());
|
|
}
|
|
|
|
float AffineTransform::GetRotation() const {
|
|
return affine_transform_data_.rotation();
|
|
}
|
|
|
|
void AffineTransform::SetScale(const Point2_f& scale) {
|
|
auto* s = affine_transform_data_.mutable_scale();
|
|
s->set_x(scale.x());
|
|
s->set_y(scale.y());
|
|
is_dirty_ = true;
|
|
}
|
|
|
|
void AffineTransform::SetTranslation(const Point2_f& translation) {
|
|
auto* t = affine_transform_data_.mutable_translation();
|
|
t->set_x(translation.x());
|
|
t->set_y(translation.y());
|
|
is_dirty_ = true;
|
|
}
|
|
|
|
void AffineTransform::SetShear(const Point2_f& shear) {
|
|
auto* s = affine_transform_data_.mutable_shear();
|
|
s->set_x(shear.x());
|
|
s->set_y(shear.y());
|
|
is_dirty_ = true;
|
|
}
|
|
|
|
void AffineTransform::SetRotation(float rotationInRadians) {
|
|
affine_transform_data_.set_rotation(rotationInRadians);
|
|
is_dirty_ = true;
|
|
}
|
|
|
|
void AffineTransform::AddScale(const Point2_f& scale) {
|
|
auto* s = affine_transform_data_.mutable_scale();
|
|
s->set_x(s->x() + scale.x());
|
|
s->set_y(s->y() + scale.y());
|
|
is_dirty_ = true;
|
|
}
|
|
|
|
void AffineTransform::AddTranslation(const Point2_f& translation) {
|
|
auto* t = affine_transform_data_.mutable_translation();
|
|
t->set_x(t->x() + translation.x());
|
|
t->set_y(t->y() + translation.y());
|
|
is_dirty_ = true;
|
|
}
|
|
|
|
void AffineTransform::AddShear(const Point2_f& shear) {
|
|
auto* s = affine_transform_data_.mutable_shear();
|
|
s->set_x(s->x() + shear.x());
|
|
s->set_y(s->y() + shear.y());
|
|
is_dirty_ = true;
|
|
}
|
|
|
|
void AffineTransform::AddRotation(float rotationInRadians) {
|
|
affine_transform_data_.set_rotation(affine_transform_data_.rotation() +
|
|
rotationInRadians);
|
|
is_dirty_ = true;
|
|
}
|
|
|
|
void AffineTransform::SetFromProto(const AffineTransformData& proto) {
|
|
affine_transform_data_ = proto;
|
|
}
|
|
|
|
void AffineTransform::ConvertToProto(AffineTransformData* proto) const {
|
|
*proto = affine_transform_data_;
|
|
}
|
|
|
|
AffineTransformData AffineTransform::ConvertToProto() const {
|
|
AffineTransformData affine_transform_data;
|
|
ConvertToProto(&affine_transform_data);
|
|
return affine_transform_data;
|
|
}
|
|
|
|
bool compare(float lhs, float rhs, float epsilon = 0.001f) {
|
|
return std::fabs(lhs - rhs) < epsilon;
|
|
}
|
|
|
|
bool AffineTransform::Equals(const AffineTransform& other,
|
|
float epsilon) const {
|
|
auto trans1 = GetTranslation();
|
|
auto trans2 = other.GetTranslation();
|
|
|
|
if (!(compare(trans1.x(), trans2.x(), epsilon) &&
|
|
compare(trans1.y(), trans2.y(), epsilon)))
|
|
return false;
|
|
|
|
auto scale1 = GetScale();
|
|
auto scale2 = other.GetScale();
|
|
|
|
if (!(compare(scale1.x(), scale2.x(), epsilon) &&
|
|
compare(scale1.y(), scale2.y(), epsilon)))
|
|
return false;
|
|
|
|
auto shear1 = GetShear();
|
|
auto shear2 = other.GetShear();
|
|
|
|
if (!(compare(shear1.x(), shear2.x(), epsilon) &&
|
|
compare(shear1.y(), shear2.y(), epsilon)))
|
|
return false;
|
|
|
|
auto rot1 = GetRotation();
|
|
auto rot2 = other.GetRotation();
|
|
|
|
if (!compare(rot1, rot2, epsilon)) {
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
bool AffineTransform::Equal(const AffineTransform& lhs,
|
|
const AffineTransform& rhs, float epsilon) {
|
|
return lhs.Equals(rhs, epsilon);
|
|
}
|
|
|
|
MEDIAPIPE_REGISTER_TYPE(mediapipe::AffineTransform,
|
|
"::mediapipe::AffineTransform", nullptr, nullptr);
|
|
|
|
} // namespace mediapipe
|