Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

COCOReader: Support for uncompressed RLE masks #2478

Merged
merged 8 commits into from
Nov 30, 2020

Conversation

jantonguirao
Copy link
Contributor

@jantonguirao jantonguirao commented Nov 18, 2020

Signed-off-by: Joaquin Anton janton@nvidia.com

Why we need this PR?

Pick one, remove the rest

  • It adds a new feature needed to support uncompressed RLE counts
  • It adds a new feature needed to support load from preprocessed annotations, including RLE masks

What happened in this PR?

Fill relevant points, put NA otherwise. Replace anything inside []

  • What solution was applied:
    Added support for preprocessed annotation files describing RLE masks
    Using cocoapi RLE struct to store the RLE masks.
  • Affected modules and functionalities:
    COCOReader
  • Key points relevant for the review:
    All
  • Validation and testing:
    C++ Tests enhanced, new data added to DALI_extra
  • Documentation (including examples):
    N/A

JIRA TASK: [DALI-1732]

ASSERT_EQ(pixelwise_masks_shape[i][0], s.height);
EXPECT_EQ(0, std::memcmp(mask.data, labels.data(), s.width * s.height * sizeof(uchar)));
Pipeline pipe2(expected_size, 1, 0, kSeed);
pipe2.AddOperator(
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

second pipeline to test loading from preprocessed binary files

@jantonguirao jantonguirao changed the title [WIP] COCOReader: Support for uncompressed RLE masks COCOReader: Support for uncompressed RLE masks Nov 19, 2020
@jantonguirao
Copy link
Contributor Author

!build

@@ -59,6 +63,39 @@ inline bool HasSavePreprocessedAnnotationsDir(const OpSpec &spec) {
(spec.HasArgument("dump_meta_files_path") && spec.GetArgument<bool>("dump_meta_files_path"));
}

struct RLEMask {
Copy link
Contributor

@mzient mzient Nov 19, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder... if you expose all the fields for modification, then this looks more like a C++ variant of the RLE structure - then maybe this should be handled by inheritance?

Suggested change
struct RLEMask {
struct RLEMask : RLE {

Otherwise, you can treat RLE as a resource and use struct RLEMask : UniqueResource<RLE>:

struct RLEMask : UniqueResource<RLE> {
  RLEMask(const char* str, int h, int w) {
    rleFrString(&handle_, const_cast<char*>(str), h, w);
  }
  RLEMask(span<const unsigned int> counts, int h, int w) {
    rleInit(&handle_, h, w, counts.size(), const_cast<unsigned int*>(counts.data()));
  }

  RLE* operator->() { return &rle_; }  // do you really need this one?
  const RLE* operator->() const { return &rle_; }

  void DestroyHandle(RLE rle) {
     if (rle.cnts)
       rleFree(&rle);
  }
};

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

@dali-automaton
Copy link
Collaborator

CI MESSAGE: [1814491]: BUILD STARTED

@dali-automaton
Copy link
Collaborator

CI MESSAGE: [1814491]: BUILD FAILED

@jantonguirao
Copy link
Contributor Author

!build

@dali-automaton
Copy link
Collaborator

CI MESSAGE: [1814766]: BUILD STARTED

@dali-automaton
Copy link
Collaborator

CI MESSAGE: [1814766]: BUILD FAILED

Copy link
Contributor Author

@jantonguirao jantonguirao left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

!build

@jantonguirao
Copy link
Contributor Author

!build

return;

unsigned size;
file.read(reinterpret_cast<char*>(&size), sizeof(unsigned));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we are already touching this can you:

  • check size is smaller than the file size and >=0
  • m * sizeof(uint) is smaller than the file size and >= 0
  • h and w are sane as well?

Do the same for other LoadFromFile variants?

@dali-automaton
Copy link
Collaborator

CI MESSAGE: [1815816]: BUILD STARTED

@dali-automaton
Copy link
Collaborator

CI MESSAGE: [1815816]: BUILD FAILED

@jantonguirao
Copy link
Contributor Author

!build

@dali-automaton
Copy link
Collaborator

CI MESSAGE: [1824283]: BUILD STARTED

@dali-automaton
Copy link
Collaborator

CI MESSAGE: [1824283]: BUILD FAILED

@jantonguirao
Copy link
Contributor Author

!build

@dali-automaton
Copy link
Collaborator

CI MESSAGE: [1824670]: BUILD STARTED

@dali-automaton
Copy link
Collaborator

CI MESSAGE: [1824670]: BUILD FAILED

@jantonguirao
Copy link
Contributor Author

!build

@dali-automaton
Copy link
Collaborator

CI MESSAGE: [1824967]: BUILD STARTED

@dali-automaton
Copy link
Collaborator

CI MESSAGE: [1824967]: BUILD FAILED

Signed-off-by: Joaquin Anton <janton@nvidia.com>
Signed-off-by: Joaquin Anton <janton@nvidia.com>
@dali-automaton
Copy link
Collaborator

CI MESSAGE: [1828400]: BUILD STARTED

@dali-automaton
Copy link
Collaborator

CI MESSAGE: [1828400]: BUILD PASSED

.AddArg("dump_meta_files_path", "/tmp/")
,
.AddArg("save_preprocessed_annotations", true)
.AddArg("save_preprocessed_annotations_dir", "/tmp/"),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder if we should use mkdtmp instead of hardcode to just /tmp/.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

Signed-off-by: Joaquin Anton <janton@nvidia.com>
@@ -1 +1 @@
fdd536addddc0f1a5bd52a15db708f95492c813e
rle_uncompressed
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Change to a commit tag before merging!

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

of course

rleFrString(&handle_, const_cast<char*>(str), h, w);
}

static constexpr RLE null_handle() { return {0, 0, 0, nullptr}; }
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you need this? Won't the default just work?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I remember it didn't work (ptr was not nullptr, if I remember correctly). I could double-check

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems to work, so I am removing it

sample_rles_idx.push_back(objects_in_sample);
sample_rles.push_back(std::move(annotation.rle_.rle_));
masks_rles_idx_.push_back(objects_in_sample);
masks_rles_.emplace_back(std::move(annotation.rle_));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nitpick:

Suggested change
masks_rles_.emplace_back(std::move(annotation.rle_));
masks_rles_.push_back(std::move(annotation.rle_));

std::vector<RLEMask> masks_rles_;
std::vector<int> masks_rles_idx_;
std::vector<int64_t> masks_offset_; // per sample offset
std::vector<int64_t> masks_count_; // per sample size
Copy link
Contributor

@mzient mzient Nov 26, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nitpick

Suggested change
std::vector<int64_t> masks_count_; // per sample size
std::vector<int64_t> mask_counts_ // number of masks per sample

@awolant awolant assigned awolant and unassigned awolant Nov 26, 2020
@awolant awolant self-requested a review November 26, 2020 10:37
std::vector<std::vector<int>> masks_rles_idx_;
std::vector<RLEMask> masks_rles_;
std::vector<int> masks_rles_idx_;
std::vector<int64_t> masks_offset_; // per sample offset
Copy link
Contributor

@mzient mzient Nov 26, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
std::vector<int64_t> masks_offset_; // per sample offset
std::vector<int64_t> mask_offsets_; // per-sample offsets of masks

int64_t polygons_sample_offset = polygon_data_.size();
int64_t polygons_sample_count = 0;
int64_t vertices_sample_offset = vertices_data_.size();
int64_t vertices_sample_count = 0;
int64_t masks_offset = masks_rles_.size();
int64_t masks_count = 0;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
int64_t masks_count = 0;
int64_t mask_count = 0;

@@ -392,14 +504,14 @@ void CocoLoader::ParseJsonAnnotations() {

for (auto &image_info : image_infos) {
int objects_in_sample = 0;
std::vector<int> sample_rles_idx;
std::vector<std::string> sample_rles;
int64_t polygons_sample_offset = polygon_data_.size();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This reads as "offset of a sample in polygons". I think it means the opposite and then it should be sample_polygon(s)_offset, sample_polygon_count, sample_vertex_offset / vertices_offset, sample_vertex_count etc.
Offsets can be preceded by a plural form because it's the offset of a block/range of polygons - "polygons" is the object.
Count should be preceded by a singular form, because we're going into the aforementioned region and counting individual object. If you're terribly attached to a plural form, then it could be polygons_size / vertices_size.

@@ -2,7 +2,7 @@

# Fetch test data
export DALI_EXTRA_PATH=${DALI_EXTRA_PATH:-/opt/dali_extra}
export DALI_EXTRA_URL=${DALI_EXTRA_URL:-"https://github.com/NVIDIA/DALI_extra.git"}
export DALI_EXTRA_URL="https://github.com/jantonguirao/DALI_extra.git"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fix before merging.

@@ -13,6 +13,5 @@ if [ ! -d "$DALI_EXTRA_PATH" ] ; then
fi

pushd "$DALI_EXTRA_PATH"
git fetch origin ${DALI_EXTRA_VERSION}
git checkout ${DALI_EXTRA_VERSION}
git checkout rle_uncompressed
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fix before merging.

Copy link
Contributor

@awolant awolant left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

With fixes to DALI_extra that Michał pointed out it looks ok

@jantonguirao
Copy link
Contributor Author

!build

@dali-automaton
Copy link
Collaborator

CI MESSAGE: [1839138]: BUILD STARTED

@dali-automaton
Copy link
Collaborator

CI MESSAGE: [1839138]: BUILD FAILED

Signed-off-by: Joaquin Anton <janton@nvidia.com>
@jantonguirao
Copy link
Contributor Author

!build

@dali-automaton
Copy link
Collaborator

CI MESSAGE: [1839192]: BUILD STARTED

@dali-automaton
Copy link
Collaborator

CI MESSAGE: [1839192]: BUILD PASSED

@jantonguirao jantonguirao merged commit 737b7b9 into NVIDIA:master Nov 30, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

6 participants