Project import generated by Copybara.
GitOrigin-RevId: ac03a471f5b9df34de46dd684202e4365c5ceac3
This commit is contained in:
parent
c6fea4c9d9
commit
fce372d153
|
@ -113,8 +113,15 @@ class SpectrogramCalculator : public CalculatorBase {
|
||||||
::mediapipe::Status Close(CalculatorContext* cc) override;
|
::mediapipe::Status Close(CalculatorContext* cc) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Timestamp CurrentOutputTimestamp() {
|
Timestamp CurrentOutputTimestamp(CalculatorContext* cc) {
|
||||||
// Current output timestamp is the *center* of the next frame to be
|
if (use_local_timestamp_) {
|
||||||
|
return cc->InputTimestamp();
|
||||||
|
}
|
||||||
|
return CumulativeOutputTimestamp();
|
||||||
|
}
|
||||||
|
|
||||||
|
Timestamp CumulativeOutputTimestamp() {
|
||||||
|
// Cumulative output timestamp is the *center* of the next frame to be
|
||||||
// emitted, hence delayed by half a window duration compared to relevant
|
// emitted, hence delayed by half a window duration compared to relevant
|
||||||
// input timestamp.
|
// input timestamp.
|
||||||
return initial_input_timestamp_ +
|
return initial_input_timestamp_ +
|
||||||
|
@ -141,6 +148,7 @@ class SpectrogramCalculator : public CalculatorBase {
|
||||||
const OutputMatrixType postprocess_output_fn(const OutputMatrixType&),
|
const OutputMatrixType postprocess_output_fn(const OutputMatrixType&),
|
||||||
CalculatorContext* cc);
|
CalculatorContext* cc);
|
||||||
|
|
||||||
|
bool use_local_timestamp_;
|
||||||
double input_sample_rate_;
|
double input_sample_rate_;
|
||||||
bool pad_final_packet_;
|
bool pad_final_packet_;
|
||||||
int frame_duration_samples_;
|
int frame_duration_samples_;
|
||||||
|
@ -173,6 +181,8 @@ const float SpectrogramCalculator::kLnPowerToDb = 4.342944819032518;
|
||||||
SpectrogramCalculatorOptions spectrogram_options =
|
SpectrogramCalculatorOptions spectrogram_options =
|
||||||
cc->Options<SpectrogramCalculatorOptions>();
|
cc->Options<SpectrogramCalculatorOptions>();
|
||||||
|
|
||||||
|
use_local_timestamp_ = spectrogram_options.use_local_timestamp();
|
||||||
|
|
||||||
if (spectrogram_options.frame_duration_seconds() <= 0.0) {
|
if (spectrogram_options.frame_duration_seconds() <= 0.0) {
|
||||||
::mediapipe::InvalidArgumentErrorBuilder(MEDIAPIPE_LOC)
|
::mediapipe::InvalidArgumentErrorBuilder(MEDIAPIPE_LOC)
|
||||||
<< "Invalid or missing frame_duration_seconds.\n"
|
<< "Invalid or missing frame_duration_seconds.\n"
|
||||||
|
@ -351,11 +361,11 @@ template <class OutputMatrixType>
|
||||||
<< "Inconsistent number of spectrogram channels.";
|
<< "Inconsistent number of spectrogram channels.";
|
||||||
if (allow_multichannel_input_) {
|
if (allow_multichannel_input_) {
|
||||||
cc->Outputs().Index(0).Add(spectrogram_matrices.release(),
|
cc->Outputs().Index(0).Add(spectrogram_matrices.release(),
|
||||||
CurrentOutputTimestamp());
|
CurrentOutputTimestamp(cc));
|
||||||
} else {
|
} else {
|
||||||
cc->Outputs().Index(0).Add(
|
cc->Outputs().Index(0).Add(
|
||||||
new OutputMatrixType(spectrogram_matrices->at(0)),
|
new OutputMatrixType(spectrogram_matrices->at(0)),
|
||||||
CurrentOutputTimestamp());
|
CurrentOutputTimestamp(cc));
|
||||||
}
|
}
|
||||||
cumulative_completed_frames_ += output_vectors.size();
|
cumulative_completed_frames_ += output_vectors.size();
|
||||||
}
|
}
|
||||||
|
|
|
@ -66,4 +66,11 @@ message SpectrogramCalculatorOptions {
|
||||||
// uniformly regardless of output type (i.e., even dBs are multiplied, not
|
// uniformly regardless of output type (i.e., even dBs are multiplied, not
|
||||||
// offset).
|
// offset).
|
||||||
optional double output_scale = 7 [default = 1.0];
|
optional double output_scale = 7 [default = 1.0];
|
||||||
|
|
||||||
|
// If use_local_timestamp is true, the output packet's timestamp is based on
|
||||||
|
// the last sample of the packet and it's inferred from the latest input
|
||||||
|
// packet's timestamp. If false, the output packet's timestamp is based on
|
||||||
|
// the cumulative timestamping, which is inferred from the intial input
|
||||||
|
// timestamp and the cumulative number of samples.
|
||||||
|
optional bool use_local_timestamp = 8 [default = false];
|
||||||
}
|
}
|
||||||
|
|
|
@ -761,3 +761,29 @@ cc_test(
|
||||||
"//mediapipe/framework/port:status",
|
"//mediapipe/framework/port:status",
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
cc_library(
|
||||||
|
name = "stream_to_side_packet_calculator",
|
||||||
|
srcs = ["stream_to_side_packet_calculator.cc"],
|
||||||
|
visibility = ["//visibility:public"],
|
||||||
|
deps = [
|
||||||
|
"//mediapipe/framework:calculator_framework",
|
||||||
|
"//mediapipe/framework:timestamp",
|
||||||
|
"//mediapipe/framework/port:status",
|
||||||
|
],
|
||||||
|
alwayslink = 1,
|
||||||
|
)
|
||||||
|
|
||||||
|
cc_test(
|
||||||
|
name = "stream_to_side_packet_calculator_test",
|
||||||
|
srcs = ["stream_to_side_packet_calculator_test.cc"],
|
||||||
|
deps = [
|
||||||
|
":stream_to_side_packet_calculator",
|
||||||
|
"//mediapipe/framework:calculator_runner",
|
||||||
|
"//mediapipe/framework:packet",
|
||||||
|
"//mediapipe/framework:timestamp",
|
||||||
|
"//mediapipe/framework/port:gtest_main",
|
||||||
|
"//mediapipe/framework/port:status",
|
||||||
|
"@com_google_absl//absl/memory",
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
|
@ -0,0 +1,48 @@
|
||||||
|
// Copyright 2019 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/calculator_framework.h"
|
||||||
|
#include "mediapipe/framework/port/status.h"
|
||||||
|
#include "mediapipe/framework/timestamp.h"
|
||||||
|
|
||||||
|
namespace mediapipe {
|
||||||
|
|
||||||
|
// A calculator that takes a packet of an input stream and converts it to an
|
||||||
|
// output side packet. This calculator only works under the assumption that the
|
||||||
|
// input stream only has a single packet passing through.
|
||||||
|
//
|
||||||
|
// Example config:
|
||||||
|
// node {
|
||||||
|
// calculator: "StreamToSidePacketCalculator"
|
||||||
|
// input_stream: "stream"
|
||||||
|
// output_side_packet: "side_packet"
|
||||||
|
// }
|
||||||
|
class StreamToSidePacketCalculator : public mediapipe::CalculatorBase {
|
||||||
|
public:
|
||||||
|
static mediapipe::Status GetContract(mediapipe::CalculatorContract* cc) {
|
||||||
|
cc->Inputs().Index(0).SetAny();
|
||||||
|
cc->OutputSidePackets().Index(0).SetAny();
|
||||||
|
return mediapipe::OkStatus();
|
||||||
|
}
|
||||||
|
|
||||||
|
mediapipe::Status Process(mediapipe::CalculatorContext* cc) override {
|
||||||
|
mediapipe::Packet& packet = cc->Inputs().Index(0).Value();
|
||||||
|
cc->OutputSidePackets().Index(0).Set(
|
||||||
|
packet.At(mediapipe::Timestamp::Unset()));
|
||||||
|
return mediapipe::OkStatus();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
REGISTER_CALCULATOR(StreamToSidePacketCalculator);
|
||||||
|
|
||||||
|
} // namespace mediapipe
|
|
@ -0,0 +1,67 @@
|
||||||
|
// Copyright 2019 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 <memory>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include "absl/memory/memory.h"
|
||||||
|
#include "mediapipe/framework/calculator_runner.h"
|
||||||
|
#include "mediapipe/framework/packet.h"
|
||||||
|
#include "mediapipe/framework/port/gmock.h"
|
||||||
|
#include "mediapipe/framework/port/gtest.h"
|
||||||
|
#include "mediapipe/framework/port/status.h"
|
||||||
|
#include "mediapipe/framework/port/status_matchers.h"
|
||||||
|
#include "mediapipe/framework/timestamp.h"
|
||||||
|
|
||||||
|
namespace mediapipe {
|
||||||
|
|
||||||
|
using ::testing::Test;
|
||||||
|
|
||||||
|
class StreamToSidePacketCalculatorTest : public Test {
|
||||||
|
protected:
|
||||||
|
StreamToSidePacketCalculatorTest() {
|
||||||
|
const char kConfig[] = R"(
|
||||||
|
calculator: "StreamToSidePacketCalculator"
|
||||||
|
input_stream: "stream"
|
||||||
|
output_side_packet: "side_packet"
|
||||||
|
)";
|
||||||
|
runner_ = absl::make_unique<CalculatorRunner>(kConfig);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::unique_ptr<CalculatorRunner> runner_;
|
||||||
|
};
|
||||||
|
|
||||||
|
TEST_F(StreamToSidePacketCalculatorTest,
|
||||||
|
StreamToSidePacketCalculatorWithEmptyStreamFails) {
|
||||||
|
EXPECT_EQ(runner_->Run().code(), mediapipe::StatusCode::kUnavailable);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(StreamToSidePacketCalculatorTest,
|
||||||
|
StreamToSidePacketCalculatorWithSinglePacketCreatesSidePacket) {
|
||||||
|
runner_->MutableInputs()->Index(0).packets.push_back(
|
||||||
|
Adopt(new std::string("test")).At(Timestamp(1)));
|
||||||
|
MP_ASSERT_OK(runner_->Run());
|
||||||
|
EXPECT_EQ(runner_->OutputSidePackets().Index(0).Get<std::string>(), "test");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(StreamToSidePacketCalculatorTest,
|
||||||
|
StreamToSidePacketCalculatorWithMultiplePacketsFails) {
|
||||||
|
runner_->MutableInputs()->Index(0).packets.push_back(
|
||||||
|
Adopt(new std::string("test1")).At(Timestamp(1)));
|
||||||
|
runner_->MutableInputs()->Index(0).packets.push_back(
|
||||||
|
Adopt(new std::string("test2")).At(Timestamp(2)));
|
||||||
|
EXPECT_EQ(runner_->Run().code(), mediapipe::StatusCode::kAlreadyExists);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace mediapipe
|
|
@ -117,6 +117,7 @@ project.
|
||||||
implementation 'com.google.code.findbugs:jsr305:3.0.2'
|
implementation 'com.google.code.findbugs:jsr305:3.0.2'
|
||||||
implementation 'com.google.guava:guava:27.0.1-android'
|
implementation 'com.google.guava:guava:27.0.1-android'
|
||||||
implementation 'com.google.guava:guava:27.0.1-android'
|
implementation 'com.google.guava:guava:27.0.1-android'
|
||||||
|
implementation 'com.google.protobuf:protobuf-lite:3.0.0'
|
||||||
// CameraX core library
|
// CameraX core library
|
||||||
def camerax_version = "1.0.0-alpha06"
|
def camerax_version = "1.0.0-alpha06"
|
||||||
implementation "androidx.camera:camera-core:$camerax_version"
|
implementation "androidx.camera:camera-core:$camerax_version"
|
||||||
|
|
|
@ -579,6 +579,11 @@ export ANDROID_HOME=<path to the Android SDK>
|
||||||
export ANDROID_NDK_HOME=<path to the Android NDK>
|
export ANDROID_NDK_HOME=<path to the Android NDK>
|
||||||
```
|
```
|
||||||
|
|
||||||
|
In order to use MediaPipe on earlier Android versions, MediaPipe needs to switch
|
||||||
|
to a lower Android API level. You can achieve this by specifying `api_level =
|
||||||
|
<api level integer>` in android_ndk_repository() and/or android_sdk_repository()
|
||||||
|
in the [`WORKSPACE`] file.
|
||||||
|
|
||||||
Please verify all the necessary packages are installed.
|
Please verify all the necessary packages are installed.
|
||||||
|
|
||||||
* Android SDK Platform API Level 28 or 29
|
* Android SDK Platform API Level 28 or 29
|
||||||
|
|
|
@ -64,7 +64,7 @@ videos.
|
||||||
|
|
||||||
4. Generate a MediaSequence metadata from the input video.
|
4. Generate a MediaSequence metadata from the input video.
|
||||||
|
|
||||||
Note: the output file is /tmp/mediapipe/metadata.tfrecord
|
Note: the output file is /tmp/mediapipe/metadata.pb
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# change clip_end_time_sec to match the length of your video.
|
# change clip_end_time_sec to match the length of your video.
|
||||||
|
@ -82,8 +82,17 @@ videos.
|
||||||
|
|
||||||
GLOG_logtostderr=1 bazel-bin/mediapipe/examples/desktop/youtube8m/extract_yt8m_features \
|
GLOG_logtostderr=1 bazel-bin/mediapipe/examples/desktop/youtube8m/extract_yt8m_features \
|
||||||
--calculator_graph_config_file=mediapipe/graphs/youtube8m/feature_extraction.pbtxt \
|
--calculator_graph_config_file=mediapipe/graphs/youtube8m/feature_extraction.pbtxt \
|
||||||
--input_side_packets=input_sequence_example=/tmp/mediapipe/metadata.tfrecord \
|
--input_side_packets=input_sequence_example=/tmp/mediapipe/metadata.pb \
|
||||||
--output_side_packets=output_sequence_example=/tmp/mediapipe/output.tfrecord
|
--output_side_packets=output_sequence_example=/tmp/mediapipe/features.pb
|
||||||
|
```
|
||||||
|
|
||||||
|
6. [Optional] Read the features.pb in Python.
|
||||||
|
|
||||||
|
```
|
||||||
|
import tensorflow as tf
|
||||||
|
|
||||||
|
sequence_example = open('/tmp/mediapipe/features.pb', 'rb').read()
|
||||||
|
print(tf.train.SequenceExample.FromString(sequence_example))
|
||||||
```
|
```
|
||||||
|
|
||||||
## Model Inference for YouTube-8M Challenge
|
## Model Inference for YouTube-8M Challenge
|
||||||
|
@ -136,7 +145,7 @@ the inference for both local videos and the dataset
|
||||||
|
|
||||||
### Steps to run the YouTube-8M model inference graph with a local video
|
### Steps to run the YouTube-8M model inference graph with a local video
|
||||||
|
|
||||||
1. Make sure you have the output tfrecord from the feature extraction pipeline.
|
1. Make sure you have the features.pb from the feature extraction pipeline.
|
||||||
|
|
||||||
2. Copy the baseline model
|
2. Copy the baseline model
|
||||||
[(model card)](https://drive.google.com/file/d/1xTCi9-Nm9dt2KIk8WR0dDFrIssWawyXy/view)
|
[(model card)](https://drive.google.com/file/d/1xTCi9-Nm9dt2KIk8WR0dDFrIssWawyXy/view)
|
||||||
|
@ -158,7 +167,7 @@ the inference for both local videos and the dataset
|
||||||
# overlap is the number of seconds adjacent segments share.
|
# overlap is the number of seconds adjacent segments share.
|
||||||
GLOG_logtostderr=1 bazel-bin/mediapipe/examples/desktop/youtube8m/model_inference \
|
GLOG_logtostderr=1 bazel-bin/mediapipe/examples/desktop/youtube8m/model_inference \
|
||||||
--calculator_graph_config_file=mediapipe/graphs/youtube8m/local_video_model_inference.pbtxt \
|
--calculator_graph_config_file=mediapipe/graphs/youtube8m/local_video_model_inference.pbtxt \
|
||||||
--input_side_packets=input_sequence_example_path=/tmp/mediapipe/output.tfrecord,input_video_path=/absolute/path/to/the/local/video/file,output_video_path=/tmp/mediapipe/annotated_video.mp4,segment_size=5,overlap=4
|
--input_side_packets=input_sequence_example_path=/tmp/mediapipe/features.pb,input_video_path=/absolute/path/to/the/local/video/file,output_video_path=/tmp/mediapipe/annotated_video.mp4,segment_size=5,overlap=4
|
||||||
```
|
```
|
||||||
|
|
||||||
4. View the annotated video.
|
4. View the annotated video.
|
||||||
|
|
|
@ -33,7 +33,7 @@
|
||||||
|
|
||||||
4. Generate a MediaSequence metadata from the input video.
|
4. Generate a MediaSequence metadata from the input video.
|
||||||
|
|
||||||
Note: the output file is /tmp/mediapipe/metadata.tfrecord
|
Note: the output file is /tmp/mediapipe/metadata.pb
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# change clip_end_time_sec to match the length of your video.
|
# change clip_end_time_sec to match the length of your video.
|
||||||
|
@ -51,8 +51,17 @@
|
||||||
|
|
||||||
GLOG_logtostderr=1 bazel-bin/mediapipe/examples/desktop/youtube8m/extract_yt8m_features \
|
GLOG_logtostderr=1 bazel-bin/mediapipe/examples/desktop/youtube8m/extract_yt8m_features \
|
||||||
--calculator_graph_config_file=mediapipe/graphs/youtube8m/feature_extraction.pbtxt \
|
--calculator_graph_config_file=mediapipe/graphs/youtube8m/feature_extraction.pbtxt \
|
||||||
--input_side_packets=input_sequence_example=/tmp/mediapipe/metadata.tfrecord \
|
--input_side_packets=input_sequence_example=/tmp/mediapipe/metadata.pb \
|
||||||
--output_side_packets=output_sequence_example=/tmp/mediapipe/output.tfrecord
|
--output_side_packets=output_sequence_example=/tmp/mediapipe/features.pb
|
||||||
|
```
|
||||||
|
|
||||||
|
6. [Optional] Read the features.pb in Python.
|
||||||
|
|
||||||
|
```
|
||||||
|
import tensorflow as tf
|
||||||
|
|
||||||
|
sequence_example = open('/tmp/mediapipe/features.pb', 'rb').read()
|
||||||
|
print(tf.train.SequenceExample.FromString(sequence_example))
|
||||||
```
|
```
|
||||||
|
|
||||||
### Steps to run the YouTube-8M inference graph with the YT8M dataset
|
### Steps to run the YouTube-8M inference graph with the YT8M dataset
|
||||||
|
@ -118,7 +127,7 @@
|
||||||
|
|
||||||
### Steps to run the YouTube-8M model inference graph with a local video
|
### Steps to run the YouTube-8M model inference graph with a local video
|
||||||
|
|
||||||
1. Make sure you have the output tfrecord from the feature extraction pipeline.
|
1. Make sure you have the features.pb from the feature extraction pipeline.
|
||||||
|
|
||||||
2. Copy the baseline model [(model card)](https://drive.google.com/file/d/1xTCi9-Nm9dt2KIk8WR0dDFrIssWawyXy/view) to local.
|
2. Copy the baseline model [(model card)](https://drive.google.com/file/d/1xTCi9-Nm9dt2KIk8WR0dDFrIssWawyXy/view) to local.
|
||||||
|
|
||||||
|
@ -138,7 +147,7 @@
|
||||||
# overlap is the number of seconds adjacent segments share.
|
# overlap is the number of seconds adjacent segments share.
|
||||||
GLOG_logtostderr=1 bazel-bin/mediapipe/examples/desktop/youtube8m/model_inference \
|
GLOG_logtostderr=1 bazel-bin/mediapipe/examples/desktop/youtube8m/model_inference \
|
||||||
--calculator_graph_config_file=mediapipe/graphs/youtube8m/local_video_model_inference.pbtxt \
|
--calculator_graph_config_file=mediapipe/graphs/youtube8m/local_video_model_inference.pbtxt \
|
||||||
--input_side_packets=input_sequence_example_path=/tmp/mediapipe/output.tfrecord,input_video_path=/absolute/path/to/the/local/video/file,output_video_path=/tmp/mediapipe/annotated_video.mp4,segment_size=5,overlap=4
|
--input_side_packets=input_sequence_example_path=/tmp/mediapipe/features.pb,input_video_path=/absolute/path/to/the/local/video/file,output_video_path=/tmp/mediapipe/annotated_video.mp4,segment_size=5,overlap=4
|
||||||
```
|
```
|
||||||
|
|
||||||
4. View the annotated video.
|
4. View the annotated video.
|
||||||
|
|
|
@ -53,7 +53,7 @@ def main(argv):
|
||||||
flags.FLAGS.clip_start_time_sec * SECONDS_TO_MICROSECONDS, metadata)
|
flags.FLAGS.clip_start_time_sec * SECONDS_TO_MICROSECONDS, metadata)
|
||||||
ms.set_clip_end_timestamp(
|
ms.set_clip_end_timestamp(
|
||||||
flags.FLAGS.clip_end_time_sec * SECONDS_TO_MICROSECONDS, metadata)
|
flags.FLAGS.clip_end_time_sec * SECONDS_TO_MICROSECONDS, metadata)
|
||||||
with open('/tmp/mediapipe/metadata.tfrecord', 'wb') as writer:
|
with open('/tmp/mediapipe/metadata.pb', 'wb') as writer:
|
||||||
writer.write(metadata.SerializeToString())
|
writer.write(metadata.SerializeToString())
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user