Add quality test for InteractiveSegmenter
PiperOrigin-RevId: 516968294
This commit is contained in:
parent
61bcddc671
commit
8f1ce5fef6
|
@ -15,8 +15,8 @@ limitations under the License.
|
||||||
|
|
||||||
#include "mediapipe/tasks/cc/vision/interactive_segmenter/interactive_segmenter.h"
|
#include "mediapipe/tasks/cc/vision/interactive_segmenter/interactive_segmenter.h"
|
||||||
|
|
||||||
#include <cstdint>
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
#include "absl/flags/flag.h"
|
#include "absl/flags/flag.h"
|
||||||
#include "mediapipe/framework/deps/file_path.h"
|
#include "mediapipe/framework/deps/file_path.h"
|
||||||
|
@ -28,6 +28,7 @@ limitations under the License.
|
||||||
#include "mediapipe/framework/port/opencv_core_inc.h"
|
#include "mediapipe/framework/port/opencv_core_inc.h"
|
||||||
#include "mediapipe/framework/port/opencv_imgcodecs_inc.h"
|
#include "mediapipe/framework/port/opencv_imgcodecs_inc.h"
|
||||||
#include "mediapipe/framework/port/status_matchers.h"
|
#include "mediapipe/framework/port/status_matchers.h"
|
||||||
|
#include "mediapipe/tasks/cc/components/containers/keypoint.h"
|
||||||
#include "mediapipe/tasks/cc/components/containers/rect.h"
|
#include "mediapipe/tasks/cc/components/containers/rect.h"
|
||||||
#include "mediapipe/tasks/cc/core/proto/base_options.pb.h"
|
#include "mediapipe/tasks/cc/core/proto/base_options.pb.h"
|
||||||
#include "mediapipe/tasks/cc/core/proto/external_file.pb.h"
|
#include "mediapipe/tasks/cc/core/proto/external_file.pb.h"
|
||||||
|
@ -47,6 +48,7 @@ namespace {
|
||||||
|
|
||||||
using ::mediapipe::Image;
|
using ::mediapipe::Image;
|
||||||
using ::mediapipe::file::JoinPath;
|
using ::mediapipe::file::JoinPath;
|
||||||
|
using ::mediapipe::tasks::components::containers::NormalizedKeypoint;
|
||||||
using ::mediapipe::tasks::components::containers::RectF;
|
using ::mediapipe::tasks::components::containers::RectF;
|
||||||
using ::mediapipe::tasks::vision::core::ImageProcessingOptions;
|
using ::mediapipe::tasks::vision::core::ImageProcessingOptions;
|
||||||
using ::testing::HasSubstr;
|
using ::testing::HasSubstr;
|
||||||
|
@ -55,14 +57,16 @@ using ::testing::Optional;
|
||||||
constexpr char kTestDataDirectory[] = "/mediapipe/tasks/testdata/vision/";
|
constexpr char kTestDataDirectory[] = "/mediapipe/tasks/testdata/vision/";
|
||||||
constexpr char kPtmModel[] = "ptm_512_hdt_ptm_woid.tflite";
|
constexpr char kPtmModel[] = "ptm_512_hdt_ptm_woid.tflite";
|
||||||
constexpr char kCatsAndDogsJpg[] = "cats_and_dogs.jpg";
|
constexpr char kCatsAndDogsJpg[] = "cats_and_dogs.jpg";
|
||||||
|
// Golden mask for the dogs in cats_and_dogs.jpg.
|
||||||
|
constexpr char kCatsAndDogsMaskDog1[] = "cats_and_dogs_mask_dog1.png";
|
||||||
|
constexpr char kCatsAndDogsMaskDog2[] = "cats_and_dogs_mask_dog2.png";
|
||||||
|
|
||||||
constexpr float kGoldenMaskSimilarity = 0.98;
|
constexpr float kGoldenMaskSimilarity = 0.97;
|
||||||
|
|
||||||
// Magnification factor used when creating the golden category masks to make
|
// Magnification factor used when creating the golden category masks to make
|
||||||
// them more human-friendly. Each pixel in the golden masks has its value
|
// them more human-friendly. Since interactive segmenter has only 2 categories,
|
||||||
// multiplied by this factor, i.e. a value of 10 means class index 1, a value of
|
// the golden mask uses 0 or 255 for each pixel.
|
||||||
// 20 means class index 2, etc.
|
constexpr int kGoldenMaskMagnificationFactor = 255;
|
||||||
constexpr int kGoldenMaskMagnificationFactor = 10;
|
|
||||||
|
|
||||||
// Intentionally converting output into CV_8UC1 and then again into CV_32FC1
|
// Intentionally converting output into CV_8UC1 and then again into CV_32FC1
|
||||||
// as expected outputs are stored in CV_8UC1, so this conversion allows to do
|
// as expected outputs are stored in CV_8UC1, so this conversion allows to do
|
||||||
|
@ -155,16 +159,25 @@ TEST_F(CreateFromOptionsTest, FailsWithMissingModel) {
|
||||||
MediaPipeTasksStatus::kRunnerInitializationError))));
|
MediaPipeTasksStatus::kRunnerInitializationError))));
|
||||||
}
|
}
|
||||||
|
|
||||||
class ImageModeTest : public tflite_shims::testing::Test {};
|
struct InteractiveSegmenterTestParams {
|
||||||
|
std::string test_name;
|
||||||
|
RegionOfInterest::Format format;
|
||||||
|
NormalizedKeypoint roi;
|
||||||
|
std::string golden_mask_file;
|
||||||
|
float similarity_threshold;
|
||||||
|
};
|
||||||
|
|
||||||
TEST_F(ImageModeTest, SucceedsWithCategoryMask) {
|
using SucceedSegmentationWithRoi =
|
||||||
|
::testing::TestWithParam<InteractiveSegmenterTestParams>;
|
||||||
|
|
||||||
|
TEST_P(SucceedSegmentationWithRoi, SucceedsWithCategoryMask) {
|
||||||
|
const InteractiveSegmenterTestParams& params = GetParam();
|
||||||
MP_ASSERT_OK_AND_ASSIGN(
|
MP_ASSERT_OK_AND_ASSIGN(
|
||||||
Image image,
|
Image image,
|
||||||
DecodeImageFromFile(JoinPath("./", kTestDataDirectory, kCatsAndDogsJpg)));
|
DecodeImageFromFile(JoinPath("./", kTestDataDirectory, kCatsAndDogsJpg)));
|
||||||
RegionOfInterest interaction_roi;
|
RegionOfInterest interaction_roi;
|
||||||
interaction_roi.format = RegionOfInterest::KEYPOINT;
|
interaction_roi.format = params.format;
|
||||||
interaction_roi.keypoint =
|
interaction_roi.keypoint = params.roi;
|
||||||
components::containers::NormalizedKeypoint{0.25, 0.9};
|
|
||||||
auto options = std::make_unique<InteractiveSegmenterOptions>();
|
auto options = std::make_unique<InteractiveSegmenterOptions>();
|
||||||
options->base_options.model_asset_path =
|
options->base_options.model_asset_path =
|
||||||
JoinPath("./", kTestDataDirectory, kPtmModel);
|
JoinPath("./", kTestDataDirectory, kPtmModel);
|
||||||
|
@ -175,16 +188,26 @@ TEST_F(ImageModeTest, SucceedsWithCategoryMask) {
|
||||||
MP_ASSERT_OK_AND_ASSIGN(auto category_masks,
|
MP_ASSERT_OK_AND_ASSIGN(auto category_masks,
|
||||||
segmenter->Segment(image, interaction_roi));
|
segmenter->Segment(image, interaction_roi));
|
||||||
EXPECT_EQ(category_masks.size(), 1);
|
EXPECT_EQ(category_masks.size(), 1);
|
||||||
|
|
||||||
|
cv::Mat actual_mask = mediapipe::formats::MatView(
|
||||||
|
category_masks[0].GetImageFrameSharedPtr().get());
|
||||||
|
|
||||||
|
cv::Mat expected_mask =
|
||||||
|
cv::imread(JoinPath("./", kTestDataDirectory, params.golden_mask_file),
|
||||||
|
cv::IMREAD_GRAYSCALE);
|
||||||
|
EXPECT_THAT(actual_mask,
|
||||||
|
SimilarToUint8Mask(expected_mask, params.similarity_threshold,
|
||||||
|
kGoldenMaskMagnificationFactor));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ImageModeTest, SucceedsWithConfidenceMask) {
|
TEST_P(SucceedSegmentationWithRoi, SucceedsWithConfidenceMask) {
|
||||||
|
const auto& params = GetParam();
|
||||||
MP_ASSERT_OK_AND_ASSIGN(
|
MP_ASSERT_OK_AND_ASSIGN(
|
||||||
Image image,
|
Image image,
|
||||||
DecodeImageFromFile(JoinPath("./", kTestDataDirectory, kCatsAndDogsJpg)));
|
DecodeImageFromFile(JoinPath("./", kTestDataDirectory, kCatsAndDogsJpg)));
|
||||||
RegionOfInterest interaction_roi;
|
RegionOfInterest interaction_roi;
|
||||||
interaction_roi.format = RegionOfInterest::KEYPOINT;
|
interaction_roi.format = params.format;
|
||||||
interaction_roi.keypoint =
|
interaction_roi.keypoint = params.roi;
|
||||||
components::containers::NormalizedKeypoint{0.25, 0.9};
|
|
||||||
auto options = std::make_unique<InteractiveSegmenterOptions>();
|
auto options = std::make_unique<InteractiveSegmenterOptions>();
|
||||||
options->base_options.model_asset_path =
|
options->base_options.model_asset_path =
|
||||||
JoinPath("./", kTestDataDirectory, kPtmModel);
|
JoinPath("./", kTestDataDirectory, kPtmModel);
|
||||||
|
@ -196,8 +219,32 @@ TEST_F(ImageModeTest, SucceedsWithConfidenceMask) {
|
||||||
MP_ASSERT_OK_AND_ASSIGN(auto confidence_masks,
|
MP_ASSERT_OK_AND_ASSIGN(auto confidence_masks,
|
||||||
segmenter->Segment(image, interaction_roi));
|
segmenter->Segment(image, interaction_roi));
|
||||||
EXPECT_EQ(confidence_masks.size(), 2);
|
EXPECT_EQ(confidence_masks.size(), 2);
|
||||||
|
|
||||||
|
cv::Mat expected_mask =
|
||||||
|
cv::imread(JoinPath("./", kTestDataDirectory, params.golden_mask_file),
|
||||||
|
cv::IMREAD_GRAYSCALE);
|
||||||
|
cv::Mat expected_mask_float;
|
||||||
|
expected_mask.convertTo(expected_mask_float, CV_32FC1, 1 / 255.f);
|
||||||
|
|
||||||
|
cv::Mat actual_mask = mediapipe::formats::MatView(
|
||||||
|
confidence_masks[1].GetImageFrameSharedPtr().get());
|
||||||
|
EXPECT_THAT(actual_mask, SimilarToFloatMask(expected_mask_float,
|
||||||
|
params.similarity_threshold));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
INSTANTIATE_TEST_SUITE_P(
|
||||||
|
SucceedSegmentationWithRoiTest, SucceedSegmentationWithRoi,
|
||||||
|
::testing::ValuesIn<InteractiveSegmenterTestParams>(
|
||||||
|
{{"PointToDog1", RegionOfInterest::KEYPOINT,
|
||||||
|
NormalizedKeypoint{0.44, 0.70}, kCatsAndDogsMaskDog1, 0.84f},
|
||||||
|
{"PointToDog2", RegionOfInterest::KEYPOINT,
|
||||||
|
NormalizedKeypoint{0.66, 0.66}, kCatsAndDogsMaskDog2,
|
||||||
|
kGoldenMaskSimilarity}}),
|
||||||
|
[](const ::testing::TestParamInfo<SucceedSegmentationWithRoi::ParamType>&
|
||||||
|
info) { return info.param.test_name; });
|
||||||
|
|
||||||
|
class ImageModeTest : public tflite_shims::testing::Test {};
|
||||||
|
|
||||||
// TODO: fix this unit test after image segmenter handled post
|
// TODO: fix this unit test after image segmenter handled post
|
||||||
// processing correctly with rotated image.
|
// processing correctly with rotated image.
|
||||||
TEST_F(ImageModeTest, DISABLED_SucceedsWithRotation) {
|
TEST_F(ImageModeTest, DISABLED_SucceedsWithRotation) {
|
||||||
|
@ -206,8 +253,7 @@ TEST_F(ImageModeTest, DISABLED_SucceedsWithRotation) {
|
||||||
DecodeImageFromFile(JoinPath("./", kTestDataDirectory, kCatsAndDogsJpg)));
|
DecodeImageFromFile(JoinPath("./", kTestDataDirectory, kCatsAndDogsJpg)));
|
||||||
RegionOfInterest interaction_roi;
|
RegionOfInterest interaction_roi;
|
||||||
interaction_roi.format = RegionOfInterest::KEYPOINT;
|
interaction_roi.format = RegionOfInterest::KEYPOINT;
|
||||||
interaction_roi.keypoint =
|
interaction_roi.keypoint = NormalizedKeypoint{0.66, 0.66};
|
||||||
components::containers::NormalizedKeypoint{0.25, 0.9};
|
|
||||||
auto options = std::make_unique<InteractiveSegmenterOptions>();
|
auto options = std::make_unique<InteractiveSegmenterOptions>();
|
||||||
options->base_options.model_asset_path =
|
options->base_options.model_asset_path =
|
||||||
JoinPath("./", kTestDataDirectory, kPtmModel);
|
JoinPath("./", kTestDataDirectory, kPtmModel);
|
||||||
|
@ -230,8 +276,7 @@ TEST_F(ImageModeTest, FailsWithRegionOfInterest) {
|
||||||
DecodeImageFromFile(JoinPath("./", kTestDataDirectory, kCatsAndDogsJpg)));
|
DecodeImageFromFile(JoinPath("./", kTestDataDirectory, kCatsAndDogsJpg)));
|
||||||
RegionOfInterest interaction_roi;
|
RegionOfInterest interaction_roi;
|
||||||
interaction_roi.format = RegionOfInterest::KEYPOINT;
|
interaction_roi.format = RegionOfInterest::KEYPOINT;
|
||||||
interaction_roi.keypoint =
|
interaction_roi.keypoint = NormalizedKeypoint{0.66, 0.66};
|
||||||
components::containers::NormalizedKeypoint{0.25, 0.9};
|
|
||||||
auto options = std::make_unique<InteractiveSegmenterOptions>();
|
auto options = std::make_unique<InteractiveSegmenterOptions>();
|
||||||
options->base_options.model_asset_path =
|
options->base_options.model_asset_path =
|
||||||
JoinPath("./", kTestDataDirectory, kPtmModel);
|
JoinPath("./", kTestDataDirectory, kPtmModel);
|
||||||
|
|
4
mediapipe/tasks/testdata/vision/BUILD
vendored
4
mediapipe/tasks/testdata/vision/BUILD
vendored
|
@ -31,6 +31,8 @@ mediapipe_files(srcs = [
|
||||||
"cat_rotated.jpg",
|
"cat_rotated.jpg",
|
||||||
"cat_rotated_mask.jpg",
|
"cat_rotated_mask.jpg",
|
||||||
"cats_and_dogs.jpg",
|
"cats_and_dogs.jpg",
|
||||||
|
"cats_and_dogs_mask_dog1.png",
|
||||||
|
"cats_and_dogs_mask_dog2.png",
|
||||||
"cats_and_dogs_no_resizing.jpg",
|
"cats_and_dogs_no_resizing.jpg",
|
||||||
"cats_and_dogs_rotated.jpg",
|
"cats_and_dogs_rotated.jpg",
|
||||||
"coco_efficientdet_lite0_v1_1.0_quant_2021_09_06.tflite",
|
"coco_efficientdet_lite0_v1_1.0_quant_2021_09_06.tflite",
|
||||||
|
@ -116,6 +118,8 @@ filegroup(
|
||||||
"cat_rotated.jpg",
|
"cat_rotated.jpg",
|
||||||
"cat_rotated_mask.jpg",
|
"cat_rotated_mask.jpg",
|
||||||
"cats_and_dogs.jpg",
|
"cats_and_dogs.jpg",
|
||||||
|
"cats_and_dogs_mask_dog1.png",
|
||||||
|
"cats_and_dogs_mask_dog2.png",
|
||||||
"cats_and_dogs_no_resizing.jpg",
|
"cats_and_dogs_no_resizing.jpg",
|
||||||
"cats_and_dogs_rotated.jpg",
|
"cats_and_dogs_rotated.jpg",
|
||||||
"fist.jpg",
|
"fist.jpg",
|
||||||
|
|
20
third_party/external_files.bzl
vendored
20
third_party/external_files.bzl
vendored
|
@ -67,13 +67,7 @@ def external_files():
|
||||||
http_file(
|
http_file(
|
||||||
name = "com_google_mediapipe_BUILD",
|
name = "com_google_mediapipe_BUILD",
|
||||||
sha256 = "d2b2a8346202691d7f831887c84e9642e974f64ed67851d9a58cf15c94b1f6b3",
|
sha256 = "d2b2a8346202691d7f831887c84e9642e974f64ed67851d9a58cf15c94b1f6b3",
|
||||||
urls = ["https://storage.googleapis.com/mediapipe-assets/BUILD?generation=16618756636939761678323576393653"],
|
urls = ["https://storage.googleapis.com/mediapipe-assets/BUILD?generation=166187566369397616783235763936531678737479599640"],
|
||||||
)
|
|
||||||
|
|
||||||
http_file(
|
|
||||||
name = "com_google_mediapipe_BUILD_orig",
|
|
||||||
sha256 = "d86b98b82e00dd87cd46bd1429bf5eaa007b500c1a24d9316b73309f2e6c8df8",
|
|
||||||
urls = ["https://storage.googleapis.com/mediapipe-assets/BUILD.orig?generation=1678737479599640"],
|
|
||||||
)
|
)
|
||||||
|
|
||||||
http_file(
|
http_file(
|
||||||
|
@ -136,6 +130,18 @@ def external_files():
|
||||||
urls = ["https://storage.googleapis.com/mediapipe-assets/cats_and_dogs.jpg?generation=1661875684064150"],
|
urls = ["https://storage.googleapis.com/mediapipe-assets/cats_and_dogs.jpg?generation=1661875684064150"],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
http_file(
|
||||||
|
name = "com_google_mediapipe_cats_and_dogs_mask_dog1_png",
|
||||||
|
sha256 = "2ab37d56ba1e46e70b3ddbfe35dac51b18b597b76904c68d7d34c7c74c677d4c",
|
||||||
|
urls = ["https://storage.googleapis.com/mediapipe-assets/cats_and_dogs_mask_dog1.png?generation=1678840350058498"],
|
||||||
|
)
|
||||||
|
|
||||||
|
http_file(
|
||||||
|
name = "com_google_mediapipe_cats_and_dogs_mask_dog2_png",
|
||||||
|
sha256 = "2010850e2dd7f520fe53b9086d70913b6fb53b178cae15a373e5ee7ffb46824a",
|
||||||
|
urls = ["https://storage.googleapis.com/mediapipe-assets/cats_and_dogs_mask_dog2.png?generation=1678840352961684"],
|
||||||
|
)
|
||||||
|
|
||||||
http_file(
|
http_file(
|
||||||
name = "com_google_mediapipe_cats_and_dogs_no_resizing_jpg",
|
name = "com_google_mediapipe_cats_and_dogs_no_resizing_jpg",
|
||||||
sha256 = "9d55933ed66bcdc63cd6509ee2518d7eed75d12db609238387ee4cc50b173e58",
|
sha256 = "9d55933ed66bcdc63cd6509ee2518d7eed75d12db609238387ee4cc50b173e58",
|
||||||
|
|
Loading…
Reference in New Issue
Block a user