From bb7bda1d6b77ea92f58744da00bdf72d864e440e Mon Sep 17 00:00:00 2001 From: xiefangqi Date: Mon, 3 Aug 2020 10:59:18 +0800 Subject: [PATCH] new dataset api -- Coco --- .../ccsrc/minddata/dataset/api/datasets.cc | 101 +++++++ .../ccsrc/minddata/dataset/include/datasets.h | 46 +++ tests/ut/cpp/dataset/c_api_test.cc | 267 ++++++++++++++++++ 3 files changed, 414 insertions(+) diff --git a/mindspore/ccsrc/minddata/dataset/api/datasets.cc b/mindspore/ccsrc/minddata/dataset/api/datasets.cc index e12906499ac..99e657d93d3 100644 --- a/mindspore/ccsrc/minddata/dataset/api/datasets.cc +++ b/mindspore/ccsrc/minddata/dataset/api/datasets.cc @@ -22,6 +22,7 @@ #include "minddata/dataset/engine/dataset_iterator.h" // Source dataset headers (in alphabetical order) #include "minddata/dataset/engine/datasetops/source/cifar_op.h" +#include "minddata/dataset/engine/datasetops/source/coco_op.h" #include "minddata/dataset/engine/datasetops/source/image_folder_op.h" #include "minddata/dataset/engine/datasetops/source/mnist_op.h" #include "minddata/dataset/engine/datasetops/source/voc_op.h" @@ -106,6 +107,15 @@ std::shared_ptr Cifar100(const std::string &dataset_dir, std::s return ds->ValidateParams() ? ds : nullptr; } +// Function to create a CocoDataset. +std::shared_ptr Coco(const std::string &dataset_dir, const std::string &annotation_file, + const std::string &task, bool decode, std::shared_ptr sampler) { + auto ds = std::make_shared(dataset_dir, annotation_file, task, decode, sampler); + + // Call derived class validation method. + return ds->ValidateParams() ? ds : nullptr; +} + // Function to create a ImageFolderDataset. std::shared_ptr ImageFolder(std::string dataset_dir, bool decode, std::shared_ptr sampler, std::set extensions, @@ -384,6 +394,97 @@ std::vector> Cifar100Dataset::Build() { return node_ops; } +// Constructor for CocoDataset +CocoDataset::CocoDataset(const std::string &dataset_dir, const std::string &annotation_file, const std::string &task, + bool decode, std::shared_ptr sampler) + : dataset_dir_(dataset_dir), annotation_file_(annotation_file), task_(task), decode_(decode), sampler_(sampler) {} + +bool CocoDataset::ValidateParams() { + Path dir(dataset_dir_); + if (!dir.IsDirectory()) { + MS_LOG(ERROR) << "Invalid dataset path or no dataset path is specified."; + return false; + } + Path annotation_file(annotation_file_); + if (!annotation_file.Exists()) { + MS_LOG(ERROR) << "annotation_file is invalid or not exist"; + return false; + } + std::set task_list = {"Detection", "Stuff", "Panoptic", "Keypoint"}; + auto task_iter = task_list.find(task_); + if (task_iter == task_list.end()) { + MS_LOG(ERROR) << "Invalid task type"; + return false; + } + return true; +} + +// Function to build CocoDataset +std::vector> CocoDataset::Build() { + // A vector containing shared pointer to the Dataset Ops that this object will create + std::vector> node_ops; + + // If user does not specify Sampler, create a default sampler based on the shuffle variable. + if (sampler_ == nullptr) { + sampler_ = CreateDefaultSampler(); + } + + CocoOp::TaskType task_type; + if (task_ == "Detection") { + task_type = CocoOp::TaskType::Detection; + } else if (task_ == "Stuff") { + task_type = CocoOp::TaskType::Stuff; + } else if (task_ == "Keypoint") { + task_type = CocoOp::TaskType::Keypoint; + } else if (task_ == "Panoptic") { + task_type = CocoOp::TaskType::Panoptic; + } + + std::unique_ptr schema = std::make_unique(); + RETURN_EMPTY_IF_ERROR( + schema->AddColumn(ColDescriptor(std::string("image"), DataType(DataType::DE_UINT8), TensorImpl::kFlexible, 1))); + switch (task_type) { + case CocoOp::TaskType::Detection: + RETURN_EMPTY_IF_ERROR(schema->AddColumn( + ColDescriptor(std::string("bbox"), DataType(DataType::DE_FLOAT32), TensorImpl::kFlexible, 1))); + RETURN_EMPTY_IF_ERROR(schema->AddColumn( + ColDescriptor(std::string("category_id"), DataType(DataType::DE_UINT32), TensorImpl::kFlexible, 1))); + RETURN_EMPTY_IF_ERROR(schema->AddColumn( + ColDescriptor(std::string("iscrowd"), DataType(DataType::DE_UINT32), TensorImpl::kFlexible, 1))); + break; + case CocoOp::TaskType::Stuff: + RETURN_EMPTY_IF_ERROR(schema->AddColumn( + ColDescriptor(std::string("segmentation"), DataType(DataType::DE_FLOAT32), TensorImpl::kFlexible, 1))); + RETURN_EMPTY_IF_ERROR(schema->AddColumn( + ColDescriptor(std::string("iscrowd"), DataType(DataType::DE_UINT32), TensorImpl::kFlexible, 1))); + break; + case CocoOp::TaskType::Keypoint: + RETURN_EMPTY_IF_ERROR(schema->AddColumn( + ColDescriptor(std::string("keypoints"), DataType(DataType::DE_FLOAT32), TensorImpl::kFlexible, 1))); + RETURN_EMPTY_IF_ERROR(schema->AddColumn( + ColDescriptor(std::string("num_keypoints"), DataType(DataType::DE_UINT32), TensorImpl::kFlexible, 1))); + break; + case CocoOp::TaskType::Panoptic: + RETURN_EMPTY_IF_ERROR(schema->AddColumn( + ColDescriptor(std::string("bbox"), DataType(DataType::DE_FLOAT32), TensorImpl::kFlexible, 1))); + RETURN_EMPTY_IF_ERROR(schema->AddColumn( + ColDescriptor(std::string("category_id"), DataType(DataType::DE_UINT32), TensorImpl::kFlexible, 1))); + RETURN_EMPTY_IF_ERROR(schema->AddColumn( + ColDescriptor(std::string("iscrowd"), DataType(DataType::DE_UINT32), TensorImpl::kFlexible, 1))); + RETURN_EMPTY_IF_ERROR( + schema->AddColumn(ColDescriptor(std::string("area"), DataType(DataType::DE_UINT32), TensorImpl::kFlexible, 1))); + break; + default: + MS_LOG(ERROR) << "CocoDataset::Build : Invalid task type"; + return {}; + } + std::shared_ptr op = + std::make_shared(task_type, dataset_dir_, annotation_file_, num_workers_, rows_per_buffer_, + connector_que_size_, decode_, std::move(schema), std::move(sampler_->Build())); + node_ops.push_back(op); + return node_ops; +} + ImageFolderDataset::ImageFolderDataset(std::string dataset_dir, bool decode, std::shared_ptr sampler, bool recursive, std::set extensions, std::map class_indexing) diff --git a/mindspore/ccsrc/minddata/dataset/include/datasets.h b/mindspore/ccsrc/minddata/dataset/include/datasets.h index df56e71b96c..ba6ae5ff1b9 100644 --- a/mindspore/ccsrc/minddata/dataset/include/datasets.h +++ b/mindspore/ccsrc/minddata/dataset/include/datasets.h @@ -43,6 +43,7 @@ class SamplerObj; // Datasets classes (in alphabetical order) class Cifar10Dataset; class Cifar100Dataset; +class CocoDataset; class ImageFolderDataset; class MnistDataset; class VOCDataset; @@ -75,6 +76,26 @@ std::shared_ptr Cifar10(const std::string &dataset_dir, std::sha std::shared_ptr Cifar100(const std::string &dataset_dir, std::shared_ptr sampler = nullptr); +/// \brief Function to create a CocoDataset +/// \notes The generated dataset has multi-columns : +/// - task='Detection', column: [['image', dtype=uint8], ['bbox', dtype=float32], ['category_id', dtype=uint32], +/// ['iscrowd', dtype=uint32]]. +/// - task='Stuff', column: [['image', dtype=uint8], ['segmentation',dtype=float32], ['iscrowd', dtype=uint32]]. +/// - task='Keypoint', column: [['image', dtype=uint8], ['keypoints', dtype=float32], +/// ['num_keypoints', dtype=uint32]]. +/// - task='Panoptic', column: [['image', dtype=uint8], ['bbox', dtype=float32], ['category_id', dtype=uint32], +/// ['iscrowd', dtype=uint32], ['area', dtype=uitn32]]. +/// \param[in] dataset_dir Path to the root directory that contains the dataset +/// \param[in] annotation_file Path to the annotation json +/// \param[in] task Set the task type of reading coco data, now support 'Detection'/'Stuff'/'Panoptic'/'Keypoint' +/// \param[in] decode Decode the images after reading +/// \param[in] sampler Object used to choose samples from the dataset. If sampler is `nullptr`, A `RandomSampler` +/// will be used to randomly iterate the entire dataset +/// \return Shared pointer to the current Dataset +std::shared_ptr Coco(const std::string &dataset_dir, const std::string &annotation_file, + const std::string &task = "Detection", bool decode = false, + std::shared_ptr sampler = nullptr); + /// \brief Function to create an ImageFolderDataset /// \notes A source dataset that reads images from a tree of directories /// All images within one folder have the same label @@ -298,6 +319,31 @@ class Cifar100Dataset : public Dataset { std::shared_ptr sampler_; }; +class CocoDataset : public Dataset { + public: + /// \brief Constructor + CocoDataset(const std::string &dataset_dir, const std::string &annotation_file, const std::string &task, bool decode, + std::shared_ptr sampler); + + /// \brief Destructor + ~CocoDataset() = default; + + /// \brief a base class override function to create the required runtime dataset op objects for this class + /// \return shared pointer to the list of newly created DatasetOps + std::vector> Build() override; + + /// \brief Parameters validation + /// \return bool true if all the params are valid + bool ValidateParams() override; + + private: + std::string dataset_dir_; + std::string annotation_file_; + std::string task_; + bool decode_; + std::shared_ptr sampler_; +}; + /// \class ImageFolderDataset /// \brief A Dataset derived class to represent ImageFolder dataset class ImageFolderDataset : public Dataset { diff --git a/tests/ut/cpp/dataset/c_api_test.cc b/tests/ut/cpp/dataset/c_api_test.cc index f302854c087..de24d6a6556 100644 --- a/tests/ut/cpp/dataset/c_api_test.cc +++ b/tests/ut/cpp/dataset/c_api_test.cc @@ -45,6 +45,7 @@ using mindspore::dataset::TensorImpl; using mindspore::dataset::DataType; using mindspore::dataset::Status; using mindspore::dataset::BorderType; +using mindspore::dataset::dsize_t; class MindDataTestPipeline : public UT::DatasetOpTesting { @@ -1415,6 +1416,272 @@ TEST_F(MindDataTestPipeline, TestVOCClassIndex) { iter->Stop(); } +TEST_F(MindDataTestPipeline, TestCocoDetection) { + MS_LOG(INFO) << "Doing MindDataTestPipeline-TestCocoDetection."; + // Create a Coco Dataset + std::string folder_path = datasets_root_path_ + "/testCOCO/train"; + std::string annotation_file = datasets_root_path_ + "/testCOCO/annotations/train.json"; + + std::shared_ptr ds = Coco(folder_path, annotation_file, "Detection", false, SequentialSampler(0, 6)); + EXPECT_NE(ds, nullptr); + + // Create an iterator over the result of the above dataset + // This will trigger the creation of the Execution Tree and launch it. + std::shared_ptr iter = ds->CreateIterator(); + EXPECT_NE(iter, nullptr); + + // Iterate the dataset and get each row + std::unordered_map> row; + iter->GetNextRow(&row); + + std::string expect_file[] = {"000000391895", "000000318219", "000000554625", "000000574769", "000000060623", + "000000309022"}; + std::vector> expect_bbox_vector = {{10.0, 10.0, 10.0, 10.0, 70.0, 70.0, 70.0, 70.0}, + {20.0, 20.0, 20.0, 20.0, 80.0, 80.0, 80.0, 80.0}, + {30.0, 30.0, 30.0, 30.0}, {40.0, 40.0, 40.0, 40.0}, + {50.0, 50.0, 50.0, 50.0}, {60.0, 60.0, 60.0, 60.0}}; + std::vector> expect_catagoryid_list = {{1, 7}, {2, 8}, {3}, {4}, {5}, {6}}; + uint64_t i = 0; + while (row.size() != 0) { + auto image = row["image"]; + auto bbox = row["bbox"]; + auto category_id = row["category_id"]; + std::shared_ptr expect_image; + Tensor::CreateFromFile(folder_path + "/" + expect_file[i] + ".jpg", &expect_image); + EXPECT_EQ(*image, *expect_image); + std::shared_ptr expect_bbox; + dsize_t bbox_num = static_cast(expect_bbox_vector[i].size() / 4); + Tensor::CreateFromVector(expect_bbox_vector[i], TensorShape({bbox_num, 4}), &expect_bbox); + EXPECT_EQ(*bbox, *expect_bbox); + std::shared_ptr expect_categoryid; + Tensor::CreateFromVector(expect_catagoryid_list[i], TensorShape({bbox_num, 1}), &expect_categoryid); + EXPECT_EQ(*category_id, *expect_categoryid); + iter->GetNextRow(&row); + i++; + } + + EXPECT_EQ(i, 6); + + // Manually terminate the pipeline + iter->Stop(); +} + +TEST_F(MindDataTestPipeline, TestCocoStuff) { + MS_LOG(INFO) << "Doing MindDataTestPipeline-TestCocoStuff."; + // Create a Coco Dataset + std::string folder_path = datasets_root_path_ + "/testCOCO/train"; + std::string annotation_file = datasets_root_path_ + "/testCOCO/annotations/train.json"; + + std::shared_ptr ds = Coco(folder_path, annotation_file, "Stuff", false, SequentialSampler(0, 6)); + EXPECT_NE(ds, nullptr); + + // Create an iterator over the result of the above dataset + // This will trigger the creation of the Execution Tree and launch it. + std::shared_ptr iter = ds->CreateIterator(); + EXPECT_NE(iter, nullptr); + + // Iterate the dataset and get each row + std::unordered_map> row; + iter->GetNextRow(&row); + + std::string expect_file[] = {"000000391895", "000000318219", "000000554625", "000000574769", "000000060623", + "000000309022"}; + std::vector> expect_segmentation_vector = + {{10.0, 12.0, 13.0, 14.0, 15.0, 16.0, 17.0, 18.0, 19.0, 20.0, + 70.0, 72.0, 73.0, 74.0, 75.0, -1.0, -1.0, -1.0, -1.0, -1.0}, + {20.0, 22.0, 23.0, 24.0, 25.0, 26.0, 27.0, 28.0, 29.0, 30.0, 31.0, + 10.0, 12.0, 13.0, 14.0, 15.0, 16.0, 17.0, 18.0, 19.0, 20.0, -1.0}, + {40.0, 42.0, 43.0, 44.0, 45.0, 46.0, 47.0, 48.0, 49.0, 40.0, 41.0, 42.0}, + {50.0, 52.0, 53.0, 54.0, 55.0, 56.0, 57.0, 58.0, 59.0, 60.0, 61.0, 62.0, 63.0}, + {60.0, 62.0, 63.0, 64.0, 65.0, 66.0, 67.0, 68.0, 69.0, 70.0, 71.0, 72.0, 73.0, 74.0}, + {60.0, 62.0, 63.0, 64.0, 65.0, 66.0, 67.0, 68.0, 69.0, 70.0, 71.0, 72.0, 73.0, 74.0}}; + std::vector> expect_size = {{2, 10}, {2, 11}, {1, 12}, {1, 13}, {1, 14}, {2, 7}}; + uint64_t i = 0; + while (row.size() != 0) { + auto image = row["image"]; + auto segmentation = row["segmentation"]; + auto iscrowd = row["iscrowd"]; + std::shared_ptr expect_image; + Tensor::CreateFromFile(folder_path + "/" + expect_file[i] + ".jpg", &expect_image); + EXPECT_EQ(*image, *expect_image); + std::shared_ptr expect_segmentation; + Tensor::CreateFromVector(expect_segmentation_vector[i], TensorShape(expect_size[i]), &expect_segmentation); + EXPECT_EQ(*segmentation, *expect_segmentation); + iter->GetNextRow(&row); + i++; + } + + EXPECT_EQ(i, 6); + + // Manually terminate the pipeline + iter->Stop(); +} + +TEST_F(MindDataTestPipeline, TestCocoKeypoint) { + MS_LOG(INFO) << "Doing MindDataTestPipeline-TestCocoKeypoint."; + // Create a Coco Dataset + std::string folder_path = datasets_root_path_ + "/testCOCO/train"; + std::string annotation_file = datasets_root_path_ + "/testCOCO/annotations/key_point.json"; + + std::shared_ptr ds = Coco(folder_path, annotation_file, "Keypoint", false, SequentialSampler(0, 2)); + EXPECT_NE(ds, nullptr); + + // Create an iterator over the result of the above dataset + // This will trigger the creation of the Execution Tree and launch it. + std::shared_ptr iter = ds->CreateIterator(); + EXPECT_NE(iter, nullptr); + + // Iterate the dataset and get each row + std::unordered_map> row; + iter->GetNextRow(&row); + + std::string expect_file[] = {"000000391895", "000000318219"}; + std::vector> expect_keypoint_vector = + {{368.0, 61.0, 1.0, 369.0, 52.0, 2.0, 0.0, 0.0, 0.0, 382.0, 48.0, 2.0, 0.0, 0.0, 0.0, 368.0, 84.0, 2.0, 435.0, + 81.0, 2.0, 362.0, 125.0, 2.0, 446.0, 125.0, 2.0, 360.0, 153.0, 2.0, 0.0, 0.0, 0.0, 397.0, 167.0, 1.0, 439.0, + 166.0, 1.0, 369.0, 193.0, 2.0, 461.0, 234.0, 2.0, 361.0, 246.0, 2.0, 474.0, 287.0, 2.0}, + {244.0, 139.0, 2.0, 0.0, 0.0, 0.0, 226.0, 118.0, 2.0, 0.0, 0.0, 0.0, 154.0, 159.0, 2.0, 143.0, 261.0, 2.0, 135.0, + 312.0, 2.0, 271.0, 423.0, 2.0, 184.0, 530.0, 2.0, 261.0, 280.0, 2.0, 347.0, 592.0, 2.0, 0.0, 0.0, 0.0, 123.0, + 596.0, 2.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0}}; + std::vector> expect_size = {{1, 51}, {1, 51}}; + std::vector> expect_num_keypoints_list = {{14}, {10}}; + uint64_t i = 0; + while (row.size() != 0) { + auto image = row["image"]; + auto keypoints = row["keypoints"]; + auto num_keypoints = row["num_keypoints"]; + std::shared_ptr expect_image; + Tensor::CreateFromFile(folder_path + "/" + expect_file[i] + ".jpg", &expect_image); + EXPECT_EQ(*image, *expect_image); + std::shared_ptr expect_keypoints; + dsize_t keypoints_size = expect_size[i][0]; + Tensor::CreateFromVector(expect_keypoint_vector[i], TensorShape(expect_size[i]), &expect_keypoints); + EXPECT_EQ(*keypoints, *expect_keypoints); + std::shared_ptr expect_num_keypoints; + Tensor::CreateFromVector(expect_num_keypoints_list[i], TensorShape({keypoints_size, 1}), &expect_num_keypoints); + EXPECT_EQ(*num_keypoints, *expect_num_keypoints); + iter->GetNextRow(&row); + i++; + } + + EXPECT_EQ(i, 2); + + // Manually terminate the pipeline + iter->Stop(); +} + +TEST_F(MindDataTestPipeline, TestCocoPanoptic) { + MS_LOG(INFO) << "Doing MindDataTestPipeline-TestCocoPanoptic."; + // Create a Coco Dataset + std::string folder_path = datasets_root_path_ + "/testCOCO/train"; + std::string annotation_file = datasets_root_path_ + "/testCOCO/annotations/panoptic.json"; + + std::shared_ptr ds = Coco(folder_path, annotation_file, "Panoptic", false, SequentialSampler(0, 2)); + EXPECT_NE(ds, nullptr); + + // Create an iterator over the result of the above dataset + // This will trigger the creation of the Execution Tree and launch it. + std::shared_ptr iter = ds->CreateIterator(); + EXPECT_NE(iter, nullptr); + + // Iterate the dataset and get each row + std::unordered_map> row; + iter->GetNextRow(&row); + + std::string expect_file[] = {"000000391895", "000000574769"}; + std::vector> expect_bbox_vector = {{472, 173, 36, 48, 340, 22, 154, 301, 486, 183, 30, 35}, + {103, 133, 229, 422, 243, 175, 93, 164}}; + std::vector> expect_categoryid_vector = {{1, 1, 2}, {1, 3}}; + std::vector> expect_iscrowd_vector = {{0, 0, 0}, {0, 0}}; + std::vector> expect_area_vector = {{705, 14062, 626}, {43102, 6079}}; + std::vector> expect_size = {{3, 4}, {2, 4}}; + uint64_t i = 0; + while (row.size() != 0) { + auto image = row["image"]; + auto bbox = row["bbox"]; + auto category_id = row["category_id"]; + auto iscrowd = row["iscrowd"]; + auto area = row["area"]; + std::shared_ptr expect_image; + Tensor::CreateFromFile(folder_path + "/" + expect_file[i] + ".jpg", &expect_image); + EXPECT_EQ(*image, *expect_image); + std::shared_ptr expect_bbox; + dsize_t bbox_size = expect_size[i][0]; + Tensor::CreateFromVector(expect_bbox_vector[i], TensorShape(expect_size[i]), &expect_bbox); + EXPECT_EQ(*bbox, *expect_bbox); + std::shared_ptr expect_categoryid; + Tensor::CreateFromVector(expect_categoryid_vector[i], TensorShape({bbox_size, 1}), &expect_categoryid); + EXPECT_EQ(*category_id, *expect_categoryid); + std::shared_ptr expect_iscrowd; + Tensor::CreateFromVector(expect_iscrowd_vector[i], TensorShape({bbox_size, 1}), &expect_iscrowd); + EXPECT_EQ(*iscrowd, *expect_iscrowd); + std::shared_ptr expect_area; + Tensor::CreateFromVector(expect_area_vector[i], TensorShape({bbox_size, 1}), &expect_area); + EXPECT_EQ(*area, *expect_area); + iter->GetNextRow(&row); + i++; + } + + EXPECT_EQ(i, 2); + + // Manually terminate the pipeline + iter->Stop(); +} + +TEST_F(MindDataTestPipeline, TestCocoDefault) { + MS_LOG(INFO) << "Doing MindDataTestPipeline-TestCocoDetection."; + // Create a Coco Dataset + std::string folder_path = datasets_root_path_ + "/testCOCO/train"; + std::string annotation_file = datasets_root_path_ + "/testCOCO/annotations/train.json"; + + std::shared_ptr ds = Coco(folder_path, annotation_file); + EXPECT_NE(ds, nullptr); + + // Create an iterator over the result of the above dataset + // This will trigger the creation of the Execution Tree and launch it. + std::shared_ptr iter = ds->CreateIterator(); + EXPECT_NE(iter, nullptr); + + // Iterate the dataset and get each row + std::unordered_map> row; + iter->GetNextRow(&row); + + uint64_t i = 0; + while (row.size() != 0) { + auto image = row["image"]; + auto bbox = row["bbox"]; + auto category_id = row["category_id"]; + MS_LOG(INFO) << "Tensor image shape: " << image->shape(); + MS_LOG(INFO) << "Tensor bbox shape: " << bbox->shape(); + MS_LOG(INFO) << "Tensor category_id shape: " << category_id->shape(); + iter->GetNextRow(&row); + i++; + } + + EXPECT_EQ(i, 6); + + // Manually terminate the pipeline + iter->Stop(); +} + +TEST_F(MindDataTestPipeline, TestCocoException) { + MS_LOG(INFO) << "Doing MindDataTestPipeline-TestCocoDetection."; + // Create a Coco Dataset + std::string folder_path = datasets_root_path_ + "/testCOCO/train"; + std::string annotation_file = datasets_root_path_ + "/testCOCO/annotations/train.json"; + std::string invalid_folder_path = "./NotExist"; + std::string invalid_annotation_file = "./NotExistFile"; + + std::shared_ptr ds = Coco(invalid_folder_path, annotation_file); + EXPECT_EQ(ds, nullptr); + + std::shared_ptr ds1 = Coco(folder_path, invalid_annotation_file); + EXPECT_EQ(ds1, nullptr); + + std::shared_ptr ds2 = Coco(folder_path, annotation_file, "valid_mode"); + EXPECT_EQ(ds2, nullptr); +} + TEST_F(MindDataTestPipeline, TestConcatSuccess) { MS_LOG(INFO) << "Doing MindDataTestPipeline-TestConcatSuccess.";