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

Add Salt and Pepper noise CPU operator #2889

Merged
merged 12 commits into from
May 13, 2021

Conversation

jantonguirao
Copy link
Contributor

@jantonguirao jantonguirao commented Apr 21, 2021

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

Why we need this PR?

Pick one, remove the rest

  • It adds a new feature needed because to generate Salt and Pepper noise in DALI. A separate PR will follow with the GPU implementation.

What happened in this PR?

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

  • What solution was applied:
    Implemented salt and pepper CPU operator in terms of the existing random noise template operator
  • Affected modules and functionalities:
    New operator
  • Key points relevant for the review:
    RNGBase changes, SaltAndPepper implementation
  • Validation and testing:
    Python Tests added
  • Documentation (including examples):
    Docstr added

JIRA TASK: [DALI-1969]

@jantonguirao jantonguirao changed the title [WIP] Add Salt and Pepper noise CPU and GPU operator Add Salt and Pepper noise CPU and GPU operator Apr 27, 2021
@jantonguirao jantonguirao marked this pull request as ready for review April 27, 2021 16:29
@JanuszL JanuszL self-assigned this Apr 27, 2021
salt_prob_(noise_prob_ * clamp<float>(salt_to_pepper_prob, 0, 1)),
salt_val_(ConvertNorm<T>(1.0f)),
pepper_val_(std::is_unsigned<T>::value ? ConvertSatNorm<T>(0.0f) :
ConvertSatNorm<T>(-1.0f)) {}
Copy link
Contributor

Choose a reason for hiding this comment

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

So the assumption is that float images has range from -1 to 1, what if someone has uint8 based image and then convert it to float?


template <typename T>
bool SetupDists(typename Dist<T>::type* dists_data, int nsamples) {
if (!prob_.IsDefined() && !salt_to_pepper_prob_.IsDefined()) {
Copy link
Contributor

@JanuszL JanuszL Apr 28, 2021

Choose a reason for hiding this comment

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

If no "prob" and "salt_to_pepper_prob" are provided you just get a uniform random noise instead of the image?
Or just default salt_and_pepper_noise_impl will be used?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

In case of return false, the default constructed implementation is used.

Copy link
Contributor

Choose a reason for hiding this comment

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

What if the probabilities are left a default, but salt and pepper values are not?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

True, that's a bug

@pipeline_def
def pipe_salt_and_pepper_noise(prob, salt_to_pepper_prob, device='cpu'):
encoded, _ = fn.readers.file(file_root=images_dir)
in_data = fn.decoders.image(encoded, device="cpu", output_type=types.RGB)
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
in_data = fn.decoders.image(encoded, device="cpu", output_type=types.RGB)
in_data = fn.decoders.image(encoded, output_type=types.RGB)

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>
Signed-off-by: Joaquin Anton <janton@nvidia.com>
Signed-off-by: Joaquin Anton <janton@nvidia.com>
Signed-off-by: Joaquin Anton <janton@nvidia.com>
Signed-off-by: Joaquin Anton <janton@nvidia.com>
Signed-off-by: Joaquin Anton <janton@nvidia.com>
Signed-off-by: Joaquin Anton <janton@nvidia.com>
Signed-off-by: Joaquin Anton <janton@nvidia.com>
@jantonguirao jantonguirao changed the title Add Salt and Pepper noise CPU and GPU operator Add Salt and Pepper noise CPU operator May 12, 2021
Signed-off-by: Joaquin Anton <janton@nvidia.com>
@jantonguirao jantonguirao marked this pull request as ready for review May 12, 2021 16:26
Comment on lines 44 to 45
: noise_prob_(clamp<float>(noise_prob, 0, 1)),
salt_prob_(noise_prob_ * clamp<float>(salt_to_pepper_prob, 0, 1)),
Copy link
Contributor

@JanuszL JanuszL May 12, 2021

Choose a reason for hiding this comment

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

Do we want to clamp or enforce ranges in L112.

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'll change to enforce.

Copy link
Contributor

@mzient mzient May 13, 2021

Choose a reason for hiding this comment

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

Is this constructor (with non-default arguments) ever used in device code? If not, we should probably throw std::range_error. If it is, clamping here is the right thing to do.
I suggest that you remove the default arguments from here and initialize the fields - hopefully with that you could mark this constructor as host-only and throw?

is generated once and applied to all channels, so that all channels in a pixel should either be
kept intact, take the "pepper" value, or the "salt" value.

Note: Per-channel noise generation requires the input layout to contain a channels ('C') dimension.)code",
Copy link
Contributor

Choose a reason for hiding this comment

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

L138 in dali/operators/random/rng_base_cpu.h states that the layout can be empty and channel-last is assumed

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'll update this note.

DistGen<IsNoiseGen> dist_gen_;
for (int sample_id = 0; sample_id < nsamples; ++sample_id) {
auto sample_sz = out_shape.tensor_size(sample_id);
int64_t N = sample_sz;
Copy link
Contributor

Choose a reason for hiding this comment

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

Can you rename N to something more meaningful?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Will do

passthrough_mask = np.all(output == input, axis=-1)
pepper_mask = np.all(output == pepper_val, axis=-1)
salt_mask = np.all(output == salt_val, axis=-1)
pixel_mask = np.logical_and(np.all(input != pepper_val, axis=-1),
Copy link
Contributor

Choose a reason for hiding this comment

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

How it is different from passthrough_mask?

Copy link
Contributor

Choose a reason for hiding this comment

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

Now I see. How about renaming it to input_pixel_mask?

Copy link
Contributor

Choose a reason for hiding this comment

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

I would add a comment that you want to filter out pixels in the input that already have salt/pepper values.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Will do

Signed-off-by: Joaquin Anton <janton@nvidia.com>
.AddOptionalArg<float>("prob",
R"code(Probability of an output value to take a salt or pepper value.)code",
0.05f, true)
.AddOptionalArg<float>("salt_to_pepper_prob",
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
.AddOptionalArg<float>("salt_to_pepper_prob",
.AddOptionalArg<float>("salt_vs_pepper",

The "salt_to_pepper" suggests a ratio and this is not a ratio but rather relative amount of salt.

Signed-off-by: Joaquin Anton <janton@nvidia.com>
Comment on lines 47 to 48
assert(0.0f <= noise_prob && noise_prob <= 1.0);
assert(0.0f <= salt_vs_pepper && salt_vs_pepper <= 1.0);
Copy link
Contributor

Choose a reason for hiding this comment

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

Please remove this from device code. Asserts cost, sometimes a lot. Do you even know if this works in debug mode without exceeding launch resources?

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've tested it in debug mode. Anyway, removed the assert.

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

!build

@dali-automaton
Copy link
Collaborator

CI MESSAGE: [2366259]: BUILD STARTED

@dali-automaton
Copy link
Collaborator

CI MESSAGE: [2366259]: BUILD PASSED

@jantonguirao jantonguirao merged commit 7e8b890 into NVIDIA:master May 13, 2021
@JanuszL JanuszL mentioned this pull request May 20, 2021
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.

4 participants