Internal change
PiperOrigin-RevId: 477538515
This commit is contained in:
committed by
Sebastian Schmidt
parent
6cdc6443b6
commit
f8af41b1eb
@@ -1,4 +1,4 @@
|
||||
// Copyright 2019 The MediaPipe Authors.
|
||||
// Copyright 2022 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.
|
||||
@@ -85,14 +85,8 @@ cv::Mat MatView(const ImageFrame* image) {
|
||||
const size_t steps[] = {static_cast<size_t>(image->WidthStep()),
|
||||
static_cast<size_t>(image->ByteDepth())};
|
||||
// Use ImageFrame to initialize in-place. ImageFrame still owns memory.
|
||||
if (steps[0] == sizes[1] * image->NumberOfChannels() * image->ByteDepth()) {
|
||||
// Contiguous memory optimization. See b/78570764
|
||||
return cv::Mat(dims, sizes, type, const_cast<uint8*>(image->PixelData()));
|
||||
} else {
|
||||
// Custom width step.
|
||||
return cv::Mat(dims, sizes, type, const_cast<uint8*>(image->PixelData()),
|
||||
steps);
|
||||
}
|
||||
return cv::Mat(dims, sizes, type, const_cast<uint8_t*>(image->PixelData()),
|
||||
steps);
|
||||
}
|
||||
|
||||
} // namespace formats
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2019 The MediaPipe Authors.
|
||||
// Copyright 2022 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.
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2019 The MediaPipe Authors.
|
||||
// Copyright 2022 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.
|
||||
@@ -21,7 +21,6 @@
|
||||
#include "mediapipe/framework/port/logging.h"
|
||||
|
||||
namespace mediapipe {
|
||||
|
||||
namespace {
|
||||
|
||||
// Set image_frame to a constant per-channel pix_value.
|
||||
@@ -50,8 +49,8 @@ TEST(ImageFrameOpencvTest, ConvertToMat) {
|
||||
ImageFrame frame2(ImageFormat::GRAY8, i_width, i_height);
|
||||
|
||||
// Check adding constant images.
|
||||
const uint8 frame1_val = 12;
|
||||
const uint8 frame2_val = 34;
|
||||
const uint8_t frame1_val = 12;
|
||||
const uint8_t frame2_val = 34;
|
||||
SetToColor<uint8>(&frame1_val, &frame1);
|
||||
SetToColor<uint8>(&frame2_val, &frame2);
|
||||
// Get Mat wrapper around ImageFrame memory (zero copy).
|
||||
@@ -77,6 +76,37 @@ TEST(ImageFrameOpencvTest, ConvertToMat) {
|
||||
EXPECT_EQ(max_loc.y, i_height - 6);
|
||||
}
|
||||
|
||||
TEST(ImageFrameOpencvTest, ConvertToIpl) {
|
||||
const int i_width = 123, i_height = 45;
|
||||
ImageFrame frame1(ImageFormat::GRAY8, i_width, i_height);
|
||||
ImageFrame frame2(ImageFormat::GRAY8, i_width, i_height);
|
||||
|
||||
// Check adding constant images.
|
||||
const uint8_t frame1_val = 12;
|
||||
const uint8_t frame2_val = 34;
|
||||
SetToColor<uint8>(&frame1_val, &frame1);
|
||||
SetToColor<uint8>(&frame2_val, &frame2);
|
||||
const cv::Mat frame1_mat = formats::MatView(&frame1);
|
||||
const cv::Mat frame2_mat = formats::MatView(&frame2);
|
||||
const cv::Mat frame_sum = frame1_mat + frame2_mat;
|
||||
const auto frame_avg = static_cast<int>(cv::mean(frame_sum).val[0]);
|
||||
EXPECT_EQ(frame_avg, frame1_val + frame2_val);
|
||||
|
||||
// Check setting min/max pixels.
|
||||
uint8* frame1_ptr = frame1.MutablePixelData();
|
||||
frame1_ptr[(i_width - 5) + (i_height - 5) * frame1.WidthStep()] = 1;
|
||||
frame1_ptr[(i_width - 6) + (i_height - 6) * frame1.WidthStep()] = 100;
|
||||
double min, max;
|
||||
cv::Point min_loc, max_loc;
|
||||
cv::minMaxLoc(frame1_mat, &min, &max, &min_loc, &max_loc);
|
||||
EXPECT_EQ(min, 1);
|
||||
EXPECT_EQ(min_loc.x, i_width - 5);
|
||||
EXPECT_EQ(min_loc.y, i_height - 5);
|
||||
EXPECT_EQ(max, 100);
|
||||
EXPECT_EQ(max_loc.x, i_width - 6);
|
||||
EXPECT_EQ(max_loc.y, i_height - 6);
|
||||
}
|
||||
|
||||
TEST(ImageFrameOpencvTest, ImageFormats) {
|
||||
const int i_width = 123, i_height = 45;
|
||||
ImageFrame frame_g8(ImageFormat::GRAY8, i_width, i_height);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2019 The MediaPipe Authors.
|
||||
// Copyright 2022 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.
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2019-2020 The MediaPipe Authors.
|
||||
// Copyright 2022 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.
|
||||
|
||||
@@ -37,26 +37,21 @@ namespace mediapipe {
|
||||
bool IsPowerOfTwo(int v) { return (v & (v - 1)) == 0; }
|
||||
|
||||
int BhwcBatchFromShape(const Tensor::Shape& shape) {
|
||||
LOG_IF(FATAL, shape.dims.empty())
|
||||
<< "Tensor::Shape must be non-empty to retrieve a named dimension";
|
||||
if (shape.dims.empty()) {
|
||||
return 1;
|
||||
}
|
||||
return shape.dims[0];
|
||||
}
|
||||
|
||||
int BhwcHeightFromShape(const Tensor::Shape& shape) {
|
||||
LOG_IF(FATAL, shape.dims.empty())
|
||||
<< "Tensor::Shape must be non-empty to retrieve a named dimension";
|
||||
return shape.dims.size() < 4 ? 1 : shape.dims[shape.dims.size() - 3];
|
||||
}
|
||||
|
||||
int BhwcWidthFromShape(const Tensor::Shape& shape) {
|
||||
LOG_IF(FATAL, shape.dims.empty())
|
||||
<< "Tensor::Shape must be non-empty to retrieve a named dimension";
|
||||
return shape.dims.size() < 3 ? 1 : shape.dims[shape.dims.size() - 2];
|
||||
}
|
||||
|
||||
int BhwcDepthFromShape(const Tensor::Shape& shape) {
|
||||
LOG_IF(FATAL, shape.dims.empty())
|
||||
<< "Tensor::Shape must be non-empty to retrieve a named dimension";
|
||||
return shape.dims.size() < 2 ? 1 : shape.dims[shape.dims.size() - 1];
|
||||
}
|
||||
|
||||
@@ -424,14 +419,36 @@ Tensor::Tensor(ElementType element_type, const Shape& shape,
|
||||
|
||||
#if MEDIAPIPE_METAL_ENABLED
|
||||
void Tensor::Invalidate() {
|
||||
absl::MutexLock lock(&view_mutex_);
|
||||
// If memory is allocated and not owned by the metal buffer.
|
||||
// TODO: Re-design cpu buffer memory management.
|
||||
if (cpu_buffer_ && !metal_buffer_) {
|
||||
DeallocateVirtualMemory(cpu_buffer_, AlignToPageSize(bytes()));
|
||||
#if MEDIAPIPE_OPENGL_ES_VERSION >= MEDIAPIPE_OPENGL_ES_30
|
||||
GLuint cleanup_gl_tex = GL_INVALID_INDEX;
|
||||
GLuint cleanup_gl_fb = GL_INVALID_INDEX;
|
||||
#endif // MEDIAPIPE_OPENGL_ES_VERSION >= MEDIAPIPE_OPENGL_ES_30
|
||||
{
|
||||
absl::MutexLock lock(&view_mutex_);
|
||||
// If memory is allocated and not owned by the metal buffer.
|
||||
// TODO: Re-design cpu buffer memory management.
|
||||
if (cpu_buffer_ && !metal_buffer_) {
|
||||
DeallocateVirtualMemory(cpu_buffer_, AlignToPageSize(bytes()));
|
||||
}
|
||||
metal_buffer_ = nil;
|
||||
cpu_buffer_ = nullptr;
|
||||
#if MEDIAPIPE_OPENGL_ES_VERSION >= MEDIAPIPE_OPENGL_ES_30
|
||||
// Don't need to wait for the resource to be deleted bacause if will be
|
||||
// released on last reference deletion inside the OpenGL driver.
|
||||
std::swap(cleanup_gl_tex, opengl_texture2d_);
|
||||
std::swap(cleanup_gl_fb, frame_buffer_);
|
||||
#endif // MEDIAPIPE_OPENGL_ES_VERSION >= MEDIAPIPE_OPENGL_ES_30
|
||||
}
|
||||
metal_buffer_ = nil;
|
||||
cpu_buffer_ = nullptr;
|
||||
#if MEDIAPIPE_OPENGL_ES_VERSION >= MEDIAPIPE_OPENGL_ES_30
|
||||
// Do not hold the view mutex while invoking GlContext::RunWithoutWaiting,
|
||||
// since that method may acquire the context's own lock.
|
||||
if (cleanup_gl_tex != GL_INVALID_INDEX || cleanup_gl_fb != GL_INVALID_INDEX) {
|
||||
gl_context_->RunWithoutWaiting([cleanup_gl_tex, cleanup_gl_fb]() {
|
||||
glDeleteTextures(1, &cleanup_gl_tex);
|
||||
glDeleteFramebuffers(1, &cleanup_gl_fb);
|
||||
});
|
||||
}
|
||||
#endif // MEDIAPIPE_OPENGL_ES_VERSION >= MEDIAPIPE_OPENGL_ES_30
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
#include <algorithm>
|
||||
#include <functional>
|
||||
#include <initializer_list>
|
||||
#include <numeric>
|
||||
#include <tuple>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
@@ -95,9 +96,8 @@ class Tensor {
|
||||
Shape(std::initializer_list<int> dimensions) : dims(dimensions) {}
|
||||
Shape(const std::vector<int>& dimensions) : dims(dimensions) {}
|
||||
int num_elements() const {
|
||||
int res = dims.empty() ? 0 : 1;
|
||||
std::for_each(dims.begin(), dims.end(), [&res](int i) { res *= i; });
|
||||
return res;
|
||||
return std::accumulate(dims.begin(), dims.end(), 1,
|
||||
std::multiplies<int>());
|
||||
}
|
||||
std::vector<int> dims;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user