-
Notifications
You must be signed in to change notification settings - Fork 621
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
Use BrightnessContrast as implementation of Brightness and Contrast ops #2981
Conversation
Signed-off-by: Rafal <Banas.Rafal97@gmail.com>
!build |
CI MESSAGE: [2396121]: BUILD STARTED |
CI MESSAGE: [2396121]: BUILD FAILED |
Signed-off-by: Rafal <Banas.Rafal97@gmail.com>
!build |
CI MESSAGE: [2402733]: BUILD STARTED |
if (this->spec_.ArgumentDefined("brightness_shift")) { | ||
this->GetPerSampleArgument(brightness_shift_, "brightness_shift", ws, curr_batch_size); | ||
} else { | ||
brightness_shift_ = std::vector<float>(curr_batch_size, 0); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shouldn't it just get a default value from schema? Why we need this here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Because getting an arg that is not present in the schema (e.g. it's Contrast
op and we fetch for brightness
) results in exception.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we have one constant that defines this default value here and in the schema?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I tend to disagree. The code with 0 and 1 is easier to understand.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would agree that it doesn't make much sense to name those constants, but in this case it connects the default values in the schema with the ones here, so I think it useful.
for device in ['cpu', 'gpu']: | ||
pipe1 = bricon_ref_pipe(ri1, 0.4, device, batch_size=batch_size) | ||
pipe2 = bricon_pipe(ri2, 0.4, device, batch_size=batch_size) | ||
yield compare_pipelines, pipe1, pipe2, batch_size, n_iters |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Newline.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
!build |
CI MESSAGE: [2405630]: BUILD STARTED |
CI MESSAGE: [2405630]: BUILD PASSED |
If not set, the input type is used.)code", DALI_NO_TYPE); | ||
|
||
DALI_SCHEMA(Contrast) | ||
.DocStr(R"code(Changes the color contrast of the image.)code") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
color contrast -> color (?)
Also, I'd keep the formula here, for completeness
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
.DocStr(R"code(Changes the color contrast of the image.)code") | |
.DocStr(R"code(Adjusts the contrast of the image.)code") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
|
||
This operator can also change the type of data.)code") | ||
DALI_SCHEMA(Brightness) | ||
.DocStr(R"code(Changes the brightness of the image.)code") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I guess we should keep the full explanation with the formula, adjusted for this case.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
this->GetPerSampleArgument(brightness_, "brightness", ws, curr_batch_size); | ||
this->GetPerSampleArgument(brightness_shift_, "brightness_shift", ws, curr_batch_size); | ||
this->GetPerSampleArgument(contrast_, "contrast", ws, curr_batch_size); | ||
if (this->spec_.ArgumentDefined("brightness")) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
perhaps out of scope, but consider using the ArgValue utility. The code is much simpler to write this way.
fn.random.uniform(range=[0.4, 0.6], seed=123) | ||
|
||
|
||
@pipeline_def(num_threads=12, device_id=0, seed=1234) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
that's quite a high number of threads. Maybe 4?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
ri2 = RandomDataIterator(batch_size, shape=(512, 256, 3), dtype=np.float32) | ||
for device in ['cpu', 'gpu']: | ||
pipe1 = bri_and_con_pipe(ri1, 0.4, device, batch_size=batch_size) | ||
pipe2 = bricon_pipe(ri2, 0.4, device, batch_size=batch_size) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can you put that 0.4
in a variable so that it is easier to understand what it is?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
return fn.random.uniform(range=[0.5, 2.0], seed=123), \ | ||
fn.random.uniform(range=[0.5, 2.0], seed=123), \ | ||
fn.random.uniform(range=[0.4, 0.6], seed=123) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
return fn.random.uniform(range=[0.5, 2.0], seed=123), \ | |
fn.random.uniform(range=[0.5, 2.0], seed=123), \ | |
fn.random.uniform(range=[0.4, 0.6], seed=123) | |
return fn.random.uniform(range=[0.0, 5.0], seed=123), \ | |
fn.random.uniform(range=[0.0, 5.0], seed=123), \ | |
fn.random.uniform(range=[-1,0, 1.0], seed=123) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
|
||
|
||
def bricon_ref(input, brightness, brightness_shift, contrast, contrast_center): | ||
return brightness_shift + brightness * (contrast_center + contrast * (input - contrast_center)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Where is the output's dynamic range?
return brightness_shift + brightness * (contrast_center + contrast * (input - contrast_center)) | |
return brightness_shift * output_range + brightness * (contrast_center + contrast * (input - contrast_center)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Extended tests to check different input/output types
ri1 = RandomDataIterator(batch_size, shape=(512, 256, 3), dtype=np.float32) | ||
ri2 = RandomDataIterator(batch_size, shape=(512, 256, 3), dtype=np.float32) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The operator's output depends on the type (type's dynamic range is used) - please include this fact in the test.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Extended tests to check different input/output types
@@ -84,16 +86,32 @@ class BrightnessContrastOp : public Operator<Backend> { | |||
// out = (brightness_shift * brightness_range + | |||
// brightness * (contrast_center - contrast * contrast_center)) + | |||
// brightness * contrast * in | |||
float norm_brightness = (brightness * brightness_contrast::FullRange<OutputType>()) / |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is the bugfix. It adds normalization to the output range.
Signed-off-by: Rafal <Banas.Rafal97@gmail.com>
.DocStr(R"code(Adjusts the brightness of the images based on the following formula:: | ||
out = brightness_shift * output_range + brightness * in | ||
Where output_range is 1 for float outputs or the maximum positive value for integral types. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
.DocStr(R"code(Adjusts the brightness of the images based on the following formula:: | |
out = brightness_shift * output_range + brightness * in | |
Where output_range is 1 for float outputs or the maximum positive value for integral types. | |
.DocStr(R"code(Adjusts the brightness of the images based on the following formula:: | |
out = brightness_shift * output_range + brightness * in | |
Where output_range is 1 for float outputs or the maximum positive value for integral types. |
You need an empty line between formula and the comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
.DocStr(R"code(Adjusts the contrast of the images based on the following formula:: | ||
out = grey + contrast * (in - grey) | ||
Where: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
.DocStr(R"code(Adjusts the contrast of the images based on the following formula:: | |
out = grey + contrast * (in - grey) | |
Where: | |
.DocStr(R"code(Adjusts the contrast of the images based on the following formula:: | |
out = grey + contrast * (in - grey) | |
Where: |
Similar
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
clipped = np.round(clipped) | ||
return clipped.astype(out_dtype) | ||
|
||
def dali_to_np_type(dtype): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe you can use dali_type_to_np ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please adjust Copyright notices as well.
- The output_range is 1 for float outputs or the maximum positive value for integral types. | ||
- Grey denotes the value of 0.5 for ``float``, 128 for ``uint8``, and 16384 for ``int16``, and so on. | ||
DALI_SCHEMA(Brightness) | ||
.DocStr(R"code(Adjusts the brightness of the images based on the following formula:: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This won't work well with the operators table, the first sentence should be short to fit into the table:
.DocStr(R"code(Adjusts the brightness of the images based on the following formula:: | |
.DocStr(R"code(Adjusts the brightness of images. | |
The brightness is adjusted based on the following formula:: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
If not set, the input type is used.)code", DALI_NO_TYPE); | ||
|
||
DALI_SCHEMA(Contrast) | ||
.DocStr(R"code(Adjusts the contrast of the images based on the following formula:: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
.DocStr(R"code(Adjusts the contrast of the images based on the following formula:: | |
.DocStr(R"code(Adjusts the contrast of images. | |
The contrast is adjusted based on the following formula:: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
Where: | ||
|
||
- The output_range is 1 for float outputs or the maximum positive value for integral types. | ||
- Grey denotes the value of 0.5 for ``float``, 128 for ``uint8``, and 16384 for ``int16``, and so on. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Suggestion: rename grey to "midrange", "halfrange" or similar.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually, there is an argument contrast_center
that is used is this value, so I renamed gray
to contrast_center
. It has its own description so I removed this information from here.
DALI_SCHEMA(BrightnessContrast) | ||
.AddParent("Brightness") | ||
.AddParent("Contrast") | ||
.DocStr(R"code(Adjusts the brightness and contrast of the images based on the following |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
.DocStr(R"code(Adjusts the brightness and contrast of the images based on the following | |
.DocStr(R"code(Adjusts the brightness and contrast the images. | |
The brightness and contrast is adjusted based on the following |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
} | ||
|
||
void AcquireArguments(const workspace_t<Backend> &ws) { | ||
auto curr_batch_size = ws.GetInputBatchSize(0); | ||
if (this->spec_.ArgumentDefined("brightness")) { | ||
this->GetPerSampleArgument(brightness_, "brightness", ws, curr_batch_size); | ||
} else { | ||
brightness_ = std::vector<float>(curr_batch_size, 1.f); | ||
brightness_ = std::vector<float>(curr_batch_size, kDefaultBrightness); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
1 and 0 are not considered magic numbers - and it's much easier to understand the code when you see a default argument of multiplication or addition without having to look up the remote definition.
} | ||
|
||
if (this->spec_.ArgumentDefined("brightness_shift")) { | ||
this->GetPerSampleArgument(brightness_shift_, "brightness_shift", ws, curr_batch_size); | ||
} else { | ||
brightness_shift_ = std::vector<float>(curr_batch_size, 0); | ||
brightness_shift_ = std::vector<float>(curr_batch_size, kDefaultBrightnessShift); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Likewise.
} | ||
|
||
if (this->spec_.ArgumentDefined("contrast")) { | ||
this->GetPerSampleArgument(contrast_, "contrast", ws, curr_batch_size); | ||
} else { | ||
contrast_ = std::vector<float>(curr_batch_size, 1.f); | ||
contrast_ = std::vector<float>(curr_batch_size, kDefaultContrast); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
...and again.
const float kDefaultBrightness = 1.f; | ||
const float kDefaultBrightnessShift = 0; | ||
const float kDefaultContrast = 1.f; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please don't. It's much easier to understand the purpose of having a multiplier of 1 or an addend of 0 than to look for definition somewhere. This also may create a misconception that these values are somehow arbitrarily chosen, when in fact they are mathematically fixed.
Signed-off-by: Rafal <Banas.Rafal97@gmail.com>
39c37ce
to
644857b
Compare
inp = fn.brightness(inp, brightness=brightness, brightness_shift=brightness_shift, dtype=dtype) | ||
return inp |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
inp = fn.brightness(inp, brightness=brightness, brightness_shift=brightness_shift, dtype=dtype) | |
return inp | |
out = fn.brightness(inp, brightness=brightness, brightness_shift=brightness_shift, dtype=dtype) | |
return out |
And similar in other functions.
Just a suggestion.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Changed to directly returning
Signed-off-by: Rafal <Banas.Rafal97@gmail.com>
!build |
CI MESSAGE: [2455714]: BUILD STARTED |
CI MESSAGE: [2455714]: BUILD FAILED |
Signed-off-by: Rafal <Banas.Rafal97@gmail.com>
!build |
CI MESSAGE: [2455858]: BUILD STARTED |
CI MESSAGE: [2455858]: BUILD FAILED |
!build |
CI MESSAGE: [2461351]: BUILD STARTED |
CI MESSAGE: [2461351]: BUILD PASSED |
Signed-off-by: Rafal Banas.Rafal97@gmail.com
Why we need this PR?
Brightness and Contrast operators are now implemented as ColorTwist which less performant than BrightnessContrast.
What happened in this PR?
Brightness and Contrast are now implemented as BrightnessContrast with limited args.
Brightness and Contrast were moved from color_twist to brightness_contrast.
brightness_contrast.cc/h
I added new python tests for BrightnessContrast.
Changes in operators documentation.
JIRA TASK: DALI-2104