Hi,
I am glad Albumentations was useful in FakeSTormer. The RandomDownScale used during SBI source generation is now covered by the built-in Downscale, including the same nearest-neighbor downscale, linear upscale, and discrete 2×/4× choices.
The current RandomDownScale contains the complete operation:
class RandomDownScale(ImageOnlyTransform):
def __init__(self,
always_apply: bool = False,
p: float = 0.5,
ratio_list: list = [2,4]):
self.ratio_list = ratio_list
super().__init__(p=p, always_apply=always_apply)
def apply(self, img: np.ndarray, ratio: int, **params):
return self.randomdownscale(img, ratio, **params)
def get_params(self):
ratio = self.ratio_list[np.random.randint(len(self.ratio_list))]
return {"ratio": ratio}
def randomdownscale(self, img, ratio, **kwargs):
keep_ratio = True
keep_input_shape = True
H, W, C = img.shape
# r = np.random.uniform(2, 4)
img_ds = cv2.resize(img, (int(W/ratio), int(H/ratio)), interpolation=cv2.INTER_NEAREST)
if keep_input_shape:
img_ds = cv2.resize(img_ds, (W,H), interpolation=cv2.INTER_LINEAR)
return img_ds
def get_transform_init_args_names(self):
return ("ratio_list",)
Both the image and video builders place it beside Sharpen with equal weight:
A.OneOf([
RandomDownScale(p=1),
A.Sharpen(alpha=(0.2, 0.5), lightness=(0.5, 1.0), p=1),
],p=1),
The video path stores the first frame's replay and applies it to later frames:
if data_type == 'video':
if index == 0:
transform = get_source_transforms(data_type=data_type)
data = transform(image=source.astype(np.uint8))
source = data['image']
replay_params = data['replay']
param_store_ins.add_parameters('s_replay_params', replay_params)
else:
replay_params = param_store_ins.get_parameters('s_replay_params')
data = alb.ReplayCompose.replay(replay_params, image=source.astype(np.uint8))
source = data['image']
The existing distribution has three outcomes: 2× downscale with probability 1/4, 4× downscale with probability 1/4, and sharpening with probability 1/2. OneOf uses each child's p as its selection weight, so the exact discrete distribution can stay flat and explicit:
def source_quality_transform():
return A.OneOf([
A.Downscale(scale_range=(0.5, 0.5), interpolation_pair={"downscale": cv2.INTER_NEAREST, "upscale": cv2.INTER_LINEAR}, p=0.25),
A.Downscale(scale_range=(0.25, 0.25), interpolation_pair={"downscale": cv2.INTER_NEAREST, "upscale": cv2.INTER_LINEAR}, p=0.25),
A.Sharpen(alpha_range=(0.2, 0.5), lightness_range=(0.5, 1.0), p=0.5),
], p=1)
Then both repeated quality blocks become the same small call, and the custom class can be removed:
@@ -241,4 +241 @@
- A.OneOf([
- RandomDownScale(p=1),
- A.Sharpen(alpha=(0.2, 0.5), lightness=(0.5, 1.0), p=1),
- ],p=1),
+ source_quality_transform(),
@@ -254,4 +251 @@
- A.OneOf([
- RandomDownScale(p=1),
- A.Sharpen(alpha=(0.2, 0.5), lightness=(0.5, 1.0), p=1),
- ],p=1),
+ source_quality_transform(),
The existing transform(image=...) and ReplayCompose.replay(..., image=...) calls remain unchanged. The replacement also keeps the configured range of Sharpen while using its current 2.3.5 argument names.
I tested the published albumentationsx==2.3.5 wheel and matching tag with RGB uint8 arrays shaped 224×224, 317×317, 319×257, and 768×512. For both fixed scale factors, the old OpenCV code and Downscale matched element-for-element and preserved shape and dtype. A 128-seed ReplayCompose check exercised all three branches and reproduced every result exactly.
The 1/4, 1/4, 1/2 probabilities follow directly from the old two equal choices and the new OneOf weights; they do not depend on that seed check. The random-number stream will change after migration, so saved training runs should not be expected to produce the same sampled sequence.
The recommended environment and Dockerfile pin albumentations==1.1.0, so I did not open a dependency-change PR.
A complete 2.3.5 migration also needs the removed always_apply arguments, the old DualTransform import path, and the *_limit/quality_lower/quality_upper arguments elsewhere in geo_transform.py to be updated and tested through image and video training.
If you want to try the maintained package, the Python import remains import albumentations as A:
pip uninstall albumentations
pip install -U albumentationsx
The packages use different licenses: albumentations==1.1.0 is MIT, while albumentationsx==2.3.5 is AGPL-3.0-only. The license guide explains the terms. Albumentations, LLC also offers commercial licenses with alternative terms.
If you have feedback, complaints, or proposals for AlbumentationsX, please open an issue. I read the tracker every day.
If this note is useful, a star or sponsorship would mean a lot.
Hi,
I am glad Albumentations was useful in FakeSTormer. The
RandomDownScaleused during SBI source generation is now covered by the built-in Downscale, including the same nearest-neighbor downscale, linear upscale, and discrete 2×/4× choices.The current
RandomDownScalecontains the complete operation:Both the image and video builders place it beside
Sharpenwith equal weight:The video path stores the first frame's replay and applies it to later frames:
The existing distribution has three outcomes: 2× downscale with probability
1/4, 4× downscale with probability1/4, and sharpening with probability1/2.OneOfuses each child'spas its selection weight, so the exact discrete distribution can stay flat and explicit:Then both repeated quality blocks become the same small call, and the custom class can be removed:
The existing
transform(image=...)andReplayCompose.replay(..., image=...)calls remain unchanged. The replacement also keeps the configured range of Sharpen while using its current 2.3.5 argument names.I tested the published
albumentationsx==2.3.5wheel and matching tag with RGBuint8arrays shaped224×224,317×317,319×257, and768×512. For both fixed scale factors, the old OpenCV code and Downscale matched element-for-element and preserved shape and dtype. A 128-seedReplayComposecheck exercised all three branches and reproduced every result exactly.The
1/4,1/4,1/2probabilities follow directly from the old two equal choices and the newOneOfweights; they do not depend on that seed check. The random-number stream will change after migration, so saved training runs should not be expected to produce the same sampled sequence.The recommended environment and Dockerfile pin
albumentations==1.1.0, so I did not open a dependency-change PR.A complete 2.3.5 migration also needs the removed
always_applyarguments, the oldDualTransformimport path, and the*_limit/quality_lower/quality_upperarguments elsewhere ingeo_transform.pyto be updated and tested through image and video training.If you want to try the maintained package, the Python import remains
import albumentations as A:The packages use different licenses:
albumentations==1.1.0is MIT, whilealbumentationsx==2.3.5isAGPL-3.0-only. The license guide explains the terms. Albumentations, LLC also offers commercial licenses with alternative terms.If you have feedback, complaints, or proposals for AlbumentationsX, please open an issue. I read the tracker every day.
If this note is useful, a star or sponsorship would mean a lot.