Project import generated by Copybara.

GitOrigin-RevId: f4b1fe3f15810450fb6539e733f6a260d3ee082c
This commit is contained in:
MediaPipe Team
2021-09-01 18:15:31 -07:00
committed by jqtang
parent 710fb3de58
commit 6abec128ed
64 changed files with 2384 additions and 161 deletions
+31
View File
@@ -81,6 +81,12 @@ mediapipe_proto_library(
deps = ["//mediapipe/framework/formats/annotation:rasterization_proto"],
)
mediapipe_proto_library(
name = "affine_transform_data_proto",
srcs = ["affine_transform_data.proto"],
visibility = ["//visibility:public"],
)
mediapipe_proto_library(
name = "time_series_header_proto",
srcs = ["time_series_header.proto"],
@@ -119,6 +125,31 @@ cc_library(
],
)
cc_library(
name = "affine_transform",
srcs = ["affine_transform.cc"],
hdrs = ["affine_transform.h"],
visibility = [
"//visibility:public",
],
deps = [
"//mediapipe/framework:port",
"//mediapipe/framework:type_map",
"//mediapipe/framework/formats:affine_transform_data_cc_proto",
"//mediapipe/framework/port:integral_types",
"//mediapipe/framework/port:logging",
"//mediapipe/framework/port:point",
"//mediapipe/framework/port:ret_check",
"//mediapipe/framework/port:status",
"//mediapipe/framework/port:statusor",
"//mediapipe/framework/tool:status_util",
"@com_google_absl//absl/base:core_headers",
"@com_google_absl//absl/memory",
"@com_google_absl//absl/strings",
"@com_google_protobuf//:protobuf",
],
)
cc_library(
name = "image_frame",
srcs = ["image_frame.cc"],
@@ -0,0 +1,228 @@
// 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
@@ -0,0 +1,86 @@
// 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.
//
// A container for affine transform data
// This wrapper provides two functionalities:
// 1. Factory methods for creation of Transform objects and thus
// AffineTransformData protocol buffers. These methods guarantee a valid
// affine transform data and are the preferred way of creating such.
// 2. Accessors which allow for access of the data and the convertion to proto
// format
#ifndef MEDIAPIPE_FRAMEWORK_FORMATS_AFFINE_TRANSFORM_H_
#define MEDIAPIPE_FRAMEWORK_FORMATS_AFFINE_TRANSFORM_H_
#include <memory>
#include <vector>
#include "mediapipe/framework/formats/affine_transform_data.pb.h"
#include "mediapipe/framework/port.h"
#include "mediapipe/framework/port/point2.h"
namespace mediapipe {
class AffineTransform {
public:
// CREATION METHODS.
AffineTransform();
// Constructs a affine transform wrapping the specified affine transform data.
// Checks the validity of the input and crashes upon failure.
explicit AffineTransform(const AffineTransformData& transform_data);
static AffineTransform Create(const Point2_f& translation = Point2_f(0, 0),
const Point2_f& scale = Point2_f(1, 1),
float rotation = 0,
const Point2_f& shear = Point2_f(0, 0));
// ACCESSORS
// Accessor for the composition matrix
std::vector<float> GetCompositionMatrix();
Point2_f GetScale() const;
Point2_f GetTranslation() const;
Point2_f GetShear() const;
float GetRotation() const;
void SetScale(const Point2_f& scale);
void SetTranslation(const Point2_f& translation);
void SetShear(const Point2_f& shear);
void SetRotation(float rotation);
void AddScale(const Point2_f& scale);
void AddTranslation(const Point2_f& translation);
void AddShear(const Point2_f& shear);
void AddRotation(float rotation);
// Serializes and deserializes the affine transform object.
void ConvertToProto(AffineTransformData* proto) const;
AffineTransformData ConvertToProto() const;
void SetFromProto(const AffineTransformData& proto);
bool Equals(const AffineTransform& other, float epsilon = 0.001f) const;
static bool Equal(const AffineTransform& lhs, const AffineTransform& rhs,
float epsilon = 0.001f);
private:
// The wrapped transform data.
AffineTransformData affine_transform_data_;
std::vector<float> matrix_ = {1, 0, 0, 0, 1, 0, 0, 0, 1};
bool is_dirty_ = false;
};
} // namespace mediapipe
#endif // MEDIAPIPE_FRAMEWORK_FORMATS_AFFINE_TRANSFORM_H_
@@ -0,0 +1,33 @@
// 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.
syntax = "proto2";
package mediapipe;
option objc_class_prefix = "MediaPipe";
// Proto for serializing Vector2 data
message Vector2Data {
optional float x = 1;
optional float y = 2;
}
// Proto for serializing Affine Transform data.
message AffineTransformData {
optional Vector2Data translation = 1;
optional Vector2Data scale = 2;
optional Vector2Data shear = 3;
optional float rotation = 4; // in radians
}
@@ -0,0 +1,94 @@
#include "mediapipe/framework/formats/affine_transform.h"
#include <string>
#include "base/logging.h"
#include "mediapipe/framework/formats/affine_transform_data.pb.h"
#include "mediapipe/framework/port/point2.h"
#include "testing/base/public/gmock.h"
#include "testing/base/public/gunit.h"
namespace mediapipe {
TEST(AffineTransformTest, TraslationTest) {
AffineTransform transform;
transform.SetTranslation(Point2_f(10, -3));
auto trans = transform.GetTranslation();
EXPECT_FLOAT_EQ(10, trans.x());
EXPECT_FLOAT_EQ(-3, trans.y());
transform.AddTranslation(Point2_f(-10, 3));
trans = transform.GetTranslation();
EXPECT_FLOAT_EQ(0, trans.x());
EXPECT_FLOAT_EQ(0, trans.y());
}
TEST(AffineTransformTest, ScaleTest) {
AffineTransform transform;
transform.SetScale(Point2_f(10, -3));
auto scale = transform.GetScale();
EXPECT_FLOAT_EQ(10, scale.x());
EXPECT_FLOAT_EQ(-3, scale.y());
transform.AddScale(Point2_f(-10, 3));
scale = transform.GetScale();
EXPECT_FLOAT_EQ(0, scale.x());
EXPECT_FLOAT_EQ(0, scale.y());
}
TEST(AffineTransformTest, RotationTest) {
AffineTransform transform;
transform.SetRotation(0.7);
float rot = transform.GetRotation();
EXPECT_FLOAT_EQ(0.7, rot);
transform.AddRotation(-0.7);
rot = transform.GetRotation();
EXPECT_FLOAT_EQ(0, rot);
}
TEST(AffineTransformTest, ShearTest) {
AffineTransform transform;
transform.SetShear(Point2_f(10, -3));
auto shear = transform.GetShear();
EXPECT_FLOAT_EQ(10, shear.x());
EXPECT_FLOAT_EQ(-3, shear.y());
transform.AddShear(Point2_f(-10, 3));
shear = transform.GetShear();
EXPECT_FLOAT_EQ(0, shear.x());
EXPECT_FLOAT_EQ(0, shear.y());
}
TEST(AffineTransformTest, TransformTest) {
AffineTransform transform1;
transform1 = AffineTransform::Create(Point2_f(0.1, -0.2), Point2_f(0.3, -0.4),
0.5, Point2_f(0.6, -0.7));
AffineTransform transform2;
transform2 = AffineTransform::Create(Point2_f(0.1, -0.2), Point2_f(0.3, -0.4),
0.5, Point2_f(0.6, -0.7));
EXPECT_THAT(true, transform1.Equals(transform2));
EXPECT_THAT(true, AffineTransform::Equal(transform1, transform2));
transform1 = AffineTransform::Create(Point2_f(0.00001, -0.00002),
Point2_f(0.00003, -0.00004), 0.00005,
Point2_f(0.00006, -0.00007));
transform2 = AffineTransform::Create(Point2_f(0.00001, -0.00002),
Point2_f(0.00003, -0.00004), 0.00005,
Point2_f(0.00006, -0.00007));
EXPECT_THAT(true, transform1.Equals(transform2, 0.000001));
EXPECT_THAT(true, AffineTransform::Equal(transform1, transform2, 0.000001));
}
} // namespace mediapipe