update new operator AdjustSharpness

Update new operator AdjustSharpness

Update new operator AdjustSharpness
This commit is contained in:
lizhiheng 2022-06-21 19:09:09 +08:00
parent 1da193fc38
commit e83dd1f222
12 changed files with 450 additions and 7 deletions

View File

@ -22,6 +22,7 @@
#include "minddata/dataset/kernels/ir/vision/adjust_brightness_ir.h"
#include "minddata/dataset/kernels/ir/vision/adjust_gamma_ir.h"
#include "minddata/dataset/kernels/ir/vision/adjust_sharpness_ir.h"
#include "minddata/dataset/kernels/ir/vision/auto_augment_ir.h"
#include "minddata/dataset/kernels/ir/vision/auto_contrast_ir.h"
#include "minddata/dataset/kernels/ir/vision/bounding_box_augment_ir.h"
@ -101,6 +102,16 @@ PYBIND_REGISTER(
}));
}));
PYBIND_REGISTER(AdjustSharpnessOperation, 1, ([](const py::module *m) {
(void)py::class_<vision::AdjustSharpnessOperation, TensorOperation,
std::shared_ptr<vision::AdjustSharpnessOperation>>(*m, "AdjustSharpnessOperation")
.def(py::init([](float sharpness_factor) {
auto adjust_sharpness = std::make_shared<vision::AdjustSharpnessOperation>(sharpness_factor);
THROW_IF_ERROR(adjust_sharpness->ValidateParams());
return adjust_sharpness;
}));
}));
PYBIND_REGISTER(
AutoAugmentOperation, 1, ([](const py::module *m) {
(void)py::class_<vision::AutoAugmentOperation, TensorOperation, std::shared_ptr<vision::AutoAugmentOperation>>(

View File

@ -22,6 +22,7 @@
#include "minddata/dataset/kernels/ir/vision/adjust_brightness_ir.h"
#include "minddata/dataset/kernels/ir/vision/adjust_gamma_ir.h"
#include "minddata/dataset/kernels/ir/vision/adjust_sharpness_ir.h"
#include "minddata/dataset/kernels/ir/vision/affine_ir.h"
#include "minddata/dataset/kernels/ir/vision/auto_augment_ir.h"
#include "minddata/dataset/kernels/ir/vision/auto_contrast_ir.h"
@ -150,6 +151,18 @@ std::shared_ptr<TensorOperation> AdjustGamma::Parse() {
return std::make_shared<AdjustGammaOperation>(data_->gamma_, data_->gain_);
}
// AdjustSharpness Transform Operation.
struct AdjustSharpness::Data {
explicit Data(float sharpness_factor) : sharpness_factor_(sharpness_factor) {}
float sharpness_factor_;
};
AdjustSharpness::AdjustSharpness(float sharpness_factor) : data_(std::make_shared<Data>(sharpness_factor)) {}
std::shared_ptr<TensorOperation> AdjustSharpness::Parse() {
return std::make_shared<AdjustSharpnessOperation>(data_->sharpness_factor_);
}
// AutoAugment Transform Operation.
struct AutoAugment::Data {
Data(AutoAugmentPolicy policy, InterpolationMode interpolation, const std::vector<uint8_t> &fill_value)

View File

@ -99,6 +99,37 @@ class MS_API AdjustGamma final : public TensorTransform {
std::shared_ptr<Data> data_;
};
/// \brief Apply adjust sharpness on input image. Input image is expected to be in [H, W, C] or [H, W] format.
class MS_API AdjustSharpness final : public TensorTransform {
public:
/// \brief Constructor.
/// \param[in] sharpness_factor How much to adjust the sharpness. Can be any Non negative real number.
/// 0 gives a blurred image, 1 gives the original image while 2 increases the Sharpness by a factor of 2.
/// \par Example
/// \code
/// /* Define operations */
/// auto decode_op = vision::Decode();
/// auto adjust_sharpness_op = vision::AdjustSharpness(2.0);
///
/// /* dataset is an instance of Dataset object */
/// dataset = dataset->Map({decode_op, adjust_sharpness_op}, // operations
/// {"image"}); // input columns
/// \endcode
explicit AdjustSharpness(float sharpness_factor);
/// \brief Destructor.
~AdjustSharpness() = default;
protected:
/// \brief Function to convert TensorTransform object into a TensorOperation object.
/// \return Shared pointer to TensorOperation object.
std::shared_ptr<TensorOperation> Parse() override;
private:
struct Data;
std::shared_ptr<Data> data_;
};
/// \brief Apply AutoAugment data augmentation method.
class MS_API AutoAugment final : public TensorTransform {
public:

View File

@ -4,6 +4,7 @@ set_property(SOURCE ${_CURRENT_SRC_FILES} PROPERTY COMPILE_DEFINITIONS SUBMODULE
set(DATASET_KERNELS_IR_VISION_SRC_FILES
adjust_brightness_ir.cc
adjust_gamma_ir.cc
adjust_sharpness_ir.cc
affine_ir.cc
auto_augment_ir.cc
auto_contrast_ir.cc

View File

@ -0,0 +1,58 @@
/**
* Copyright 2022 Huawei Technologies Co., Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "minddata/dataset/kernels/ir/vision/adjust_sharpness_ir.h"
#ifndef ENABLE_ANDROID
#include "minddata/dataset/kernels/image/sharpness_op.h"
#endif
#include "minddata/dataset/kernels/ir/validators.h"
#include "minddata/dataset/util/validators.h"
namespace mindspore {
namespace dataset {
namespace vision {
#ifndef ENABLE_ANDROID
// AdjustSharpnessOperation
AdjustSharpnessOperation::AdjustSharpnessOperation(float sharpness_factor) : sharpness_factor_(sharpness_factor) {}
Status AdjustSharpnessOperation::ValidateParams() {
// sharpness_factor
RETURN_IF_NOT_OK(ValidateFloatScalarNonNegative("AdjustSharpness", "sharpness_factor", sharpness_factor_));
return Status::OK();
}
std::shared_ptr<TensorOp> AdjustSharpnessOperation::Build() {
std::shared_ptr<SharpnessOp> tensor_op = std::make_shared<SharpnessOp>(sharpness_factor_);
return tensor_op;
}
Status AdjustSharpnessOperation::to_json(nlohmann::json *out_json) {
nlohmann::json args;
args["sharpness_factor"] = sharpness_factor_;
*out_json = args;
return Status::OK();
}
Status AdjustSharpnessOperation::from_json(nlohmann::json op_params, std::shared_ptr<TensorOperation> *operation) {
RETURN_IF_NOT_OK(ValidateParamInJson(op_params, "sharpness_factor", kAdjustSharpnessOperation));
float sharpness_factor = op_params["sharpness_factor"];
*operation = std::make_shared<vision::AdjustSharpnessOperation>(sharpness_factor);
return Status::OK();
}
#endif
} // namespace vision
} // namespace dataset
} // namespace mindspore

View File

@ -0,0 +1,58 @@
/**
* Copyright 2022 Huawei Technologies Co., Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef MINDSPORE_CCSRC_MINDDATA_DATASET_KERNELS_IR_VISION_ADJUST_SHARPNESS_IR_H_
#define MINDSPORE_CCSRC_MINDDATA_DATASET_KERNELS_IR_VISION_ADJUST_SHARPNESS_IR_H_
#include <map>
#include <memory>
#include <string>
#include <utility>
#include <vector>
#include "include/api/status.h"
#include "minddata/dataset/include/dataset/constants.h"
#include "minddata/dataset/include/dataset/transforms.h"
#include "minddata/dataset/kernels/ir/tensor_operation.h"
namespace mindspore {
namespace dataset {
namespace vision {
constexpr char kAdjustSharpnessOperation[] = "AdjustSharpness";
class AdjustSharpnessOperation : public TensorOperation {
public:
explicit AdjustSharpnessOperation(float sharpness_factor);
~AdjustSharpnessOperation() = default;
std::shared_ptr<TensorOp> Build() override;
Status ValidateParams() override;
std::string Name() const override { return kAdjustSharpnessOperation; }
Status to_json(nlohmann::json *out_json) override;
static Status from_json(nlohmann::json op_params, std::shared_ptr<TensorOperation> *operation);
private:
float sharpness_factor_;
};
} // namespace vision
} // namespace dataset
} // namespace mindspore
#endif // MINDSPORE_CCSRC_MINDDATA_DATASET_KERNELS_IR_VISION_ADJUST_SHARPNESS_IR_H_

View File

@ -44,8 +44,8 @@ from . import c_transforms
from . import py_transforms
from . import transforms
from . import utils
from .transforms import AdjustBrightness, AdjustGamma, AutoAugment, AutoContrast, BoundingBoxAugment, CenterCrop, \
ConvertColor, Crop, CutMixBatch, CutOut, Decode, Equalize, Erase, FiveCrop, GaussianBlur, Grayscale, \
from .transforms import AdjustBrightness, AdjustGamma, AdjustSharpness, AutoAugment, AutoContrast, BoundingBoxAugment, \
CenterCrop, ConvertColor, Crop, CutMixBatch, CutOut, Decode, Equalize, Erase, FiveCrop, GaussianBlur, Grayscale, \
HorizontalFlip, HsvToRgb, HWC2CHW, Invert, LinearTransformation, MixUp, MixUpBatch, Normalize, NormalizePad, Pad, \
PadToSize, RandomAdjustSharpness, RandomAffine, RandomAutoContrast, RandomColor, RandomColorAdjust, RandomCrop, \
RandomCropDecodeResize, RandomCropWithBBox, RandomEqualize, RandomErasing, RandomGrayscale, RandomHorizontalFlip, \

View File

@ -62,11 +62,11 @@ from mindspore._c_expression import typing
from . import py_transforms_util as util
from .py_transforms_util import is_pil
from .utils import AutoAugmentPolicy, Border, ConvertMode, ImageBatchFormat, Inter, SliceMode, parse_padding
from .validators import check_adjust_brightness, check_adjust_gamma, check_alpha, check_auto_augment, \
check_auto_contrast, check_bounding_box_augment_cpp, check_center_crop, check_convert_color, check_crop, \
check_cut_mix_batch_c, check_cutout_new, check_decode, check_erase, check_five_crop, check_gaussian_blur, \
check_hsv_to_rgb, check_linear_transform, check_mix_up, check_mix_up_batch_c, check_normalize, \
check_normalizepad, check_num_channels, check_pad, check_pad_to_size, check_positive_degrees, \
from .validators import check_adjust_brightness, check_adjust_gamma, check_adjust_sharpness, check_alpha, \
check_auto_augment, check_auto_contrast, check_bounding_box_augment_cpp, check_center_crop, check_convert_color, \
check_crop, check_cut_mix_batch_c, check_cutout_new, check_decode, check_erase, check_five_crop, \
check_gaussian_blur, check_hsv_to_rgb, check_linear_transform, check_mix_up, check_mix_up_batch_c, \
check_normalize, check_normalizepad, check_num_channels, check_pad, check_pad_to_size, check_positive_degrees, \
check_posterize, check_prob, check_random_adjust_sharpness, check_random_affine, check_random_auto_contrast, \
check_random_color_adjust, check_random_crop, check_random_erasing, check_random_perspective, \
check_random_resize_crop, check_random_rotation, check_random_select_subpolicy_op, check_random_solarize, \
@ -194,6 +194,38 @@ class AdjustGamma(ImageTensorOperation, PyTensorOperation):
return util.adjust_gamma(img, self.gamma, self.gain)
class AdjustSharpness(ImageTensorOperation):
r"""
Adjust sharpness of input image. Input image is expected to be in [H, W, C] or [H, W] format.
Args:
sharpness_factor (float): How much to adjust the sharpness, should be a
non negative number. 0 gives a blurred image, 1 gives the
original image while 2 increases the Sharpness by a factor of 2.
Raises:
TypeError: If `sharpness_factor` is not of type float.
ValueError: If `sharpness_factor` is less than 0.
RuntimeError: If given tensor shape is not <H, W, C> or <H, W>.
Supported Platforms:
``CPU``
Examples:
>>> transforms_list = [vision.Decode(), vision.AdjustSharpness(sharpness_factor=2.0)]
>>> image_folder_dataset = image_folder_dataset.map(operations=transforms_list,
... input_columns=["image"])
"""
@check_adjust_sharpness
def __init__(self, sharpness_factor):
super().__init__()
self.sharpness_factor = sharpness_factor
self.implementation = Implementation.C
def parse(self):
return cde.AdjustSharpnessOperation(self.sharpness_factor)
class AutoAugment(ImageTensorOperation):
"""
Apply AutoAugment data augmentation method based on

View File

@ -1024,6 +1024,19 @@ def check_adjust_gamma(method):
return new_method
def check_adjust_sharpness(method):
"""Wrapper method to check the parameters of AdjustSharpness ops (Python and C++)."""
@wraps(method)
def new_method(self, *args, **kwargs):
[sharpness_factor], _ = parse_user_args(method, *args, **kwargs)
type_check(sharpness_factor, (float, int), "sharpness_factor")
check_value(sharpness_factor, (0, FLOAT_MAX_INTEGER))
return method(self, *args, **kwargs)
return new_method
def check_auto_contrast(method):
"""Wrapper method to check the parameters of AutoContrast ops (Python and C++)."""

View File

@ -2372,3 +2372,55 @@ TEST_F(MindDataTestPipeline, TestTrivialAugmentWideInvalidFillValue) {
std::shared_ptr<Iterator> iter = ds->CreateIterator();
EXPECT_EQ(iter, nullptr);
}
/// Feature: AdjustSharpness op
/// Description: Test AdjustSharpness pipeline
/// Expectation: Create an ImageFolder dataset then do auto AjustSharpness on it
TEST_F(MindDataTestPipeline, TestAdjustSharpness) {
MS_LOG(INFO) << "Doing MindDataTestPipeline-TestAdjustSharpness.";
std::string MindDataPath = "data/dataset";
std::string folder_path = MindDataPath + "/testImageNetData/train/";
std::shared_ptr<Dataset> ds = ImageFolder(folder_path, true, std::make_shared<RandomSampler>(false, 2));
EXPECT_NE(ds, nullptr);
auto adjustsharpness_op = vision::AdjustSharpness(2.0);
ds = ds->Map({adjustsharpness_op});
EXPECT_NE(ds, nullptr);
std::shared_ptr<Iterator> iter = ds->CreateIterator();
EXPECT_NE(iter, nullptr);
std::unordered_map<std::string, mindspore::MSTensor> row;
ASSERT_OK(iter->GetNextRow(&row));
uint64_t i = 0;
while (row.size() != 0) {
i++;
auto image = row["image"];
iter->GetNextRow(&row);
}
EXPECT_EQ(i, 2);
iter->Stop();
}
/// Feature: AdjustSharpness op
/// Description: Test parameter check
/// Expectation: Error logs are as expected
TEST_F(MindDataTestPipeline, TestAdjustSharpnessParamCheck) {
MS_LOG(INFO) << "Doing MindDataTestPipeline-TestAdjustSharpnessParamCheck.";
std::string MindDataPath = "data/dataset";
std::string folder_path = MindDataPath + "/testImageNetData/train/";
std::shared_ptr<Dataset> ds = ImageFolder(folder_path, true, std::make_shared<RandomSampler>(false, 2));
EXPECT_NE(ds, nullptr);
// Case 1: Negative sharpness_factor
// Create objects for the tensor ops
auto adjustsharpness_op = vision::AdjustSharpness(-1);
auto ds1 = ds->Map({adjustsharpness_op});
EXPECT_NE(ds1, nullptr);
// Create an iterator over the result of the above dataset
std::shared_ptr<Iterator> iter1 = ds1->CreateIterator();
// Expect failure: invalid value of AdjustSharpness
EXPECT_EQ(iter1, nullptr);
}

View File

@ -2851,3 +2851,20 @@ TEST_F(MindDataTestExecute, TestAdjustBrightness) {
Status rc = transform(image, &image);
EXPECT_EQ(rc, Status::OK());
}
/// Feature: AdjustSharpness
/// Description: Test executing Decode then AdjustSharpness op with eager mode
/// Expectation: The data is processed successfully
TEST_F(MindDataTestExecute, TestAdjustSharpnessEager) {
MS_LOG(INFO) << "Doing MindDataTestExecute-TestAdjustSharpnessEager.";
// Read images
auto image = ReadFileToTensor("data/dataset/apple.jpg");
// Transform params
auto decode = vision::Decode();
auto adjust_sharpness_op = vision::AdjustSharpness(1.0);
auto transform = Execute({decode, adjust_sharpness_op});
Status rc = transform(image, &image);
EXPECT_EQ(rc, Status::OK());
}

View File

@ -0,0 +1,157 @@
# Copyright 2022 Huawei Technologies Co., Ltd
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# ==============================================================================
"""
Testing AdjustSharpness op in DE
"""
import numpy as np
from numpy.testing import assert_allclose
import PIL
from PIL import Image, ImageEnhance
import mindspore.dataset as ds
import mindspore.dataset.transforms.transforms
import mindspore.dataset.vision as vision
from mindspore import log as logger
DATA_DIR = "../data/dataset/testImageNetData/train/"
MNIST_DATA_DIR = "../data/dataset/testMnistData"
DATA_DIR_2 = ["../data/dataset/test_tf_file_3_images/train-0000-of-0001.data"]
SCHEMA_DIR = "../data/dataset/test_tf_file_3_images/datasetSchema.json"
IMAGE_FILE = "../data/dataset/apple.jpg"
def generate_numpy_random_rgb(shape):
"""
Only generate floating points that are fractions like n / 256, since they
are RGB pixels. Some low-precision floating point types in this test can't
handle arbitrary precision floating points well.
"""
return np.random.randint(0, 256, shape) / 255.
def test_adjust_sharpness_eager():
"""
Feature: AdjustSharpness op
Description: Test eager support for AdjustSharpness C implementation
Expectation: Output is the same as expected output
"""
# Eager 3-channel
rgb_flat = generate_numpy_random_rgb((64, 3)).astype(np.uint8)
img_in = rgb_flat.reshape((8, 8, 3))
img_pil = Image.fromarray(img_in)
adjustsharpness_op = vision.AdjustSharpness(0.0)
img_out = adjustsharpness_op(img_in)
pil_out = ImageEnhance.Sharpness(img_pil).enhance(0)
pil_out = np.array(pil_out)
assert_allclose(pil_out.flatten(),
img_out.flatten(),
rtol=1e-5,
atol=0)
img_in2 = PIL.Image.open("../data/dataset/apple.jpg").convert("RGB")
adjustsharpness_op2 = vision.AdjustSharpness(1.0)
img_out2 = adjustsharpness_op2(img_in2)
img_out2 = np.array(img_out2)
pil_out2 = ImageEnhance.Sharpness(img_in2).enhance(1)
pil_out2 = np.array(pil_out2)
assert_allclose(pil_out2.flatten(),
img_out2.flatten(),
rtol=1e-5,
atol=0)
def test_adjust_sharpness_invalid_sharpnessfactor_param():
"""
Feature: AdjustSharpness op
Description: Test AdjustSharpness Cpp implementation with invalid ignore parameter
Expectation: Correct error is raised as expected
"""
logger.info("Test AdjustSharpness C implementation with invalid ignore parameter")
try:
data_set = ds.ImageFolderDataset(dataset_dir=DATA_DIR, shuffle=False)
data_set = data_set.map(
operations=[vision.Decode(), vision.Resize((224, 224)), lambda img: np.array(img[:, :, 0])],
input_columns=["image"])
# invalid alpha
data_set = data_set.map(operations=vision.AdjustSharpness(sharpness_factor=-10.0),
input_columns="image")
except ValueError as error:
logger.info("Got an exception in AdjustSharpness: {}".format(str(error)))
assert "Input is not within the required interval of " in str(error)
try:
data_set = ds.ImageFolderDataset(dataset_dir=DATA_DIR, shuffle=False)
data_set = data_set.map(
operations=[vision.Decode(), vision.Resize((224, 224)), lambda img: np.array(img[:, :, 0])],
input_columns=["image"])
# invalid alpha
data_set = data_set.map(operations=vision.AdjustSharpness(sharpness_factor=[1.0, 2.0]),
input_columns="image")
except TypeError as error:
logger.info("Got an exception in AdjustSharpness: {}".format(str(error)))
assert "is not of type [<class 'float'>, <class 'int'>], but got" in str(error)
def test_adjust_sharpness_pipeline():
"""
Feature: AdjustSharpness op
Description: Test AdjustSharpness Cpp implementation Pipeline
Expectation: Output is the same as expected output
"""
# First dataset
transforms1 = [vision.Decode(), vision.Resize([64, 64])]
transforms1 = mindspore.dataset.transforms.transforms.Compose(
transforms1)
ds1 = ds.TFRecordDataset(DATA_DIR_2,
SCHEMA_DIR,
columns_list=["image"],
shuffle=False)
ds1 = ds1.map(operations=transforms1, input_columns=["image"])
# Second dataset
transforms2 = [
vision.Decode(),
vision.Resize([64, 64]),
vision.AdjustSharpness(1.0)
]
transform2 = mindspore.dataset.transforms.transforms.Compose(
transforms2)
ds2 = ds.TFRecordDataset(DATA_DIR_2,
SCHEMA_DIR,
columns_list=["image"],
shuffle=False)
ds2 = ds2.map(operations=transform2, input_columns=["image"])
num_iter = 0
for data1, data2 in zip(ds1.create_dict_iterator(num_epochs=1),
ds2.create_dict_iterator(num_epochs=1)):
num_iter += 1
ori_img = data1["image"].asnumpy()
cvt_img = data2["image"].asnumpy()
assert_allclose(ori_img.flatten(),
cvt_img.flatten(),
rtol=1e-5,
atol=0)
assert ori_img.shape == cvt_img.shape
if __name__ == "__main__":
test_adjust_sharpness_eager()
test_adjust_sharpness_invalid_sharpnessfactor_param()
test_adjust_sharpness_pipeline()