diff --git a/common/README.md b/common/README.md
index 39166944fc5e9abe06731bc79252cece3f807c26..c46c8443f363cd645477e268b2316d68a2bf28d1 100644
--- a/common/README.md
+++ b/common/README.md
@@ -68,13 +68,13 @@ You have 2 options to download the videos:
 1. First, go on the [google sheet](https://docs.google.com/spreadsheets/d/1kIrMOjcKJ8hslZoVMx1D0H7QYj9nQLFvzUAQ1U4Le-I/edit#gid=0), and choose a video that nobody already did, and put your name in the 2nd column
 2. Download the video, in **720p**
 3. Rename it using the video id on twitch, and place it in [../dataset/twitch/videos](../dataset/twitch/videos)
-5. Launch the python script [./research_common/scripts/extract_robots_views_from_video.py](research_common/scripts/extract_robots_views_from_video.py), with the video id as parameter (In Pycharm, `Run` > `Edit Configurations...`, then in parameters enter the id). You can put multiple video ids by separating them with spaces.
+5. Launch the python script [./research/common/scripts/extract_robots_views_from_video.py](research/common/scripts/extract_robots_views_from_video.py), with the video id as parameter (In Pycharm, `Run` > `Edit Configurations...`, then in parameters enter the id). You can put multiple video ids by separating them with spaces.
 
 The frames will appear in the [../dataset/twitch/robots-views](../dataset/twitch/robots-views) folder.
 
 #### Aerial dataset
 
-Once you have the robots views in the [../dataset/twitch/robots-views](../dataset/twitch/robots-views) folder, run the python script [./research_common/scripts/move_aerial_views.py](research_common/scripts/move_aerial_views.py). It will put the aerial views in the [../dataset/twitch/aerial-views](../dataset/twitch/aerial-views) directory.
+Once you have the robots views in the [../dataset/twitch/robots-views](../dataset/twitch/robots-views) folder, run the python script [./research/common/scripts/move_aerial_views.py](research/common/scripts/move_aerial_views.py). It will put the aerial views in the [../dataset/twitch/aerial-views](../dataset/twitch/aerial-views) directory.
 
 
 
diff --git a/common/research_common/__init__.py b/common/research/common/__init__.py
similarity index 100%
rename from common/research_common/__init__.py
rename to common/research/common/__init__.py
diff --git a/common/research_common/constants.py b/common/research/common/constants.py
similarity index 92%
rename from common/research_common/constants.py
rename to common/research/common/constants.py
index 969bbb4490d9729c8c7cad53f3361654f64b5ab2..8d90b8acd48eaf627b2bbc55086b0a23996335b4 100644
--- a/common/research_common/constants.py
+++ b/common/research/common/constants.py
@@ -6,7 +6,7 @@ DSET_DIR: Path = PROJECT_DIR / "dataset"
 
 TWITCH_DSET_DIR: Path = DSET_DIR / "twitch"
 DJI_ROCO_DSET_DIR: Path = DSET_DIR / "dji_roco"
-DJI_ROCO_ZOOMED_DSET_DIR: Path = DSET_DIR / "dji_roco_zoomed_v1"
+DJI_ROCO_ZOOMED_DSET_DIR: Path = DSET_DIR / "dji_roco_zoomed_v2"
 TENSORFLOW_RECORDS_DIR: Path = DSET_DIR / "tf_records"
 TWITCH_ROBOTS_VIEWS_DIR: Path = TWITCH_DSET_DIR / "robots-views"
 TWITCH_DSET_ROBOTS_VIEWS_DIR: Path = TWITCH_DSET_DIR / "final-robots-views"
diff --git a/common/research_common/image_pipeline_evaluation/__init__.py b/common/research/common/dataset/__init__.py
similarity index 100%
rename from common/research_common/image_pipeline_evaluation/__init__.py
rename to common/research/common/dataset/__init__.py
diff --git a/common/research_common/dataset/directory_roco_dataset.py b/common/research/common/dataset/directory_roco_dataset.py
similarity index 91%
rename from common/research_common/dataset/directory_roco_dataset.py
rename to common/research/common/dataset/directory_roco_dataset.py
index ba35e9c8cffff7f3390a79fa34c43680e2f7e0c5..adf694d018fea20ead15ad2d0298bf9efc20b6df 100644
--- a/common/research_common/dataset/directory_roco_dataset.py
+++ b/common/research/common/dataset/directory_roco_dataset.py
@@ -1,7 +1,7 @@
 from pathlib import Path
 from typing import Iterable
 
-from research_common.dataset.roco_dataset import ROCODataset
+from research.common.dataset.roco_dataset import ROCODataset
 
 
 class DirectoryROCODataset(ROCODataset):
diff --git a/common/tests/unittests/__init__.py b/common/research/common/dataset/dji/__init__.py
similarity index 100%
rename from common/tests/unittests/__init__.py
rename to common/research/common/dataset/dji/__init__.py
diff --git a/common/research_common/dataset/dji/dji_roco_datasets.py b/common/research/common/dataset/dji/dji_roco_datasets.py
similarity index 78%
rename from common/research_common/dataset/dji/dji_roco_datasets.py
rename to common/research/common/dataset/dji/dji_roco_datasets.py
index 43ade1a796cc97978615dc25c24c093d777ef990..b85ef3f746d0dfaf877e137f035eaabb3720f2c8 100644
--- a/common/research_common/dataset/dji/dji_roco_datasets.py
+++ b/common/research/common/dataset/dji/dji_roco_datasets.py
@@ -1,7 +1,7 @@
 from enum import Enum
 
-from research_common.constants import DJI_ROCO_DSET_DIR
-from research_common.dataset.directory_roco_dataset import DirectoryROCODataset
+from research.common.constants import DJI_ROCO_DSET_DIR
+from research.common.dataset.directory_roco_dataset import DirectoryROCODataset
 
 
 class DJIROCODataset(DirectoryROCODataset, Enum):
diff --git a/common/research_common/dataset/dji/dji_roco_zoomed_datasets.py b/common/research/common/dataset/dji/dji_roco_zoomed_datasets.py
similarity index 67%
rename from common/research_common/dataset/dji/dji_roco_zoomed_datasets.py
rename to common/research/common/dataset/dji/dji_roco_zoomed_datasets.py
index ab2e2c6d5abc48674569d159cf6d7c8aa80dbef1..550eb602304f24768531816ae9737f3de1cef9e9 100644
--- a/common/research_common/dataset/dji/dji_roco_zoomed_datasets.py
+++ b/common/research/common/dataset/dji/dji_roco_zoomed_datasets.py
@@ -1,13 +1,13 @@
 from enum import Enum, auto
 
 from polystar.common.utils.str_utils import camel2snake
-from research_common.constants import DJI_ROCO_ZOOMED_DSET_DIR
-from research_common.dataset.directory_roco_dataset import DirectoryROCODataset
+from research.common.constants import DJI_ROCO_ZOOMED_DSET_DIR
+from research.common.dataset.directory_roco_dataset import DirectoryROCODataset
 
 
 class DJIROCOZoomedDataset(DirectoryROCODataset, Enum):
     def __init__(self, _):
-        super().__init__(DJI_ROCO_ZOOMED_DSET_DIR / camel2snake(self.name), f"{self.name}ZoomedV1")
+        super().__init__(DJI_ROCO_ZOOMED_DSET_DIR / camel2snake(self.name), f"{self.name}ZoomedV2")
 
     CentralChina = auto()
     NorthChina = auto()
diff --git a/common/tests/unittests/object_validators/__init__.py b/common/research/common/dataset/improvement/__init__.py
similarity index 100%
rename from common/tests/unittests/object_validators/__init__.py
rename to common/research/common/dataset/improvement/__init__.py
diff --git a/common/research_common/dataset/improvement/zoom.py b/common/research/common/dataset/improvement/zoom.py
similarity index 98%
rename from common/research_common/dataset/improvement/zoom.py
rename to common/research/common/dataset/improvement/zoom.py
index c975a5896b59475b0abe69eb2a20067956414bf4..0cdf21670607ddb86818315860afc05527bf84fd 100644
--- a/common/research_common/dataset/improvement/zoom.py
+++ b/common/research/common/dataset/improvement/zoom.py
@@ -7,7 +7,7 @@ from polystar.common.models.box import Box
 from polystar.common.models.image_annotation import ImageAnnotation
 from polystar.common.target_pipeline.objects_validators.in_box_validator import InBoxValidator
 from polystar.common.view.plt_results_viewer import PltResultViewer
-from research_common.dataset.dji.dji_roco_datasets import DJIROCODataset
+from research.common.dataset.dji.dji_roco_datasets import DJIROCODataset
 
 
 def crop_image_annotation(image_annotation: ImageAnnotation, box: Box, min_coverage: float) -> ImageAnnotation:
diff --git a/drone-at-base/polystar/drone_at_base/__init__.py b/common/research/common/dataset/perturbations/__init__.py
similarity index 100%
rename from drone-at-base/polystar/drone_at_base/__init__.py
rename to common/research/common/dataset/perturbations/__init__.py
diff --git a/robots-at-runes/research/dataset/perturbations/examples/.gitignore b/common/research/common/dataset/perturbations/examples/.gitignore
similarity index 100%
rename from robots-at-runes/research/dataset/perturbations/examples/.gitignore
rename to common/research/common/dataset/perturbations/examples/.gitignore
diff --git a/robots-at-runes/research/dataset/perturbations/examples/test.png b/common/research/common/dataset/perturbations/examples/test.png
similarity index 100%
rename from robots-at-runes/research/dataset/perturbations/examples/test.png
rename to common/research/common/dataset/perturbations/examples/test.png
diff --git a/robots-at-robots/research/dataset/__init__.py b/common/research/common/dataset/perturbations/image_modifiers/__init__.py
similarity index 100%
rename from robots-at-robots/research/dataset/__init__.py
rename to common/research/common/dataset/perturbations/image_modifiers/__init__.py
diff --git a/common/research/common/dataset/perturbations/image_modifiers/brightness.py b/common/research/common/dataset/perturbations/image_modifiers/brightness.py
new file mode 100644
index 0000000000000000000000000000000000000000..ac9c863fd055dfee96a6a97229fc21835c158fc0
--- /dev/null
+++ b/common/research/common/dataset/perturbations/image_modifiers/brightness.py
@@ -0,0 +1,22 @@
+from dataclasses import dataclass
+
+import numpy as np
+
+from polystar.common.models.image import Image
+from research.common.dataset.perturbations.image_modifiers.image_modifier_abc import ImageModifierABC
+
+
+@dataclass
+class BrightnessModifier(ImageModifierABC):
+    max_offset: float = 10.0
+
+    def modify(self, image: Image, intensity: float) -> Image:
+        offset = self.max_offset * intensity
+        perturbed_image = np.clip((image.astype(np.uint16) + offset), 0, 255).astype(np.uint8)
+        return perturbed_image
+
+
+if __name__ == "__main__":
+    from research.common.dataset.perturbations.utils import simple_modifier_demo
+
+    simple_modifier_demo(BrightnessModifier())
diff --git a/common/research/common/dataset/perturbations/image_modifiers/contrast.py b/common/research/common/dataset/perturbations/image_modifiers/contrast.py
new file mode 100644
index 0000000000000000000000000000000000000000..f920d074c9ccc568b055620d631b5d9e1166c208
--- /dev/null
+++ b/common/research/common/dataset/perturbations/image_modifiers/contrast.py
@@ -0,0 +1,23 @@
+from dataclasses import dataclass
+
+import numpy as np
+
+from polystar.common.models.image import Image
+from research.common.dataset.perturbations.image_modifiers.image_modifier_abc import ImageModifierABC
+
+
+@dataclass
+class ContrastModifier(ImageModifierABC):
+    min_coef: float = 0.8
+    max_coef: float = 1.5
+
+    def modify(self, image: Image, intensity: float) -> Image:
+        coef = self.min_coef + (self.max_coef - self.min_coef) * intensity
+        perturbed_image = np.clip((image.astype(np.uint16) * coef), 0, 255).astype(np.uint8)
+        return perturbed_image
+
+
+if __name__ == "__main__":
+    from research.common.dataset.perturbations.utils import simple_modifier_demo
+
+    simple_modifier_demo(ContrastModifier())
diff --git a/common/research/common/dataset/perturbations/image_modifiers/gaussian_blur.py b/common/research/common/dataset/perturbations/image_modifiers/gaussian_blur.py
new file mode 100644
index 0000000000000000000000000000000000000000..58dd943672323d2c0da3744d6a826fa983aea5cc
--- /dev/null
+++ b/common/research/common/dataset/perturbations/image_modifiers/gaussian_blur.py
@@ -0,0 +1,29 @@
+from dataclasses import dataclass
+
+import cv2
+
+from polystar.common.models.image import Image
+from research.common.dataset.perturbations.image_modifiers.image_modifier_abc import ImageModifierABC
+
+
+@dataclass
+class GaussianBlurrer(ImageModifierABC):
+    max_factor: float = 0.015
+
+    def modify(self, image: Image, intensity: float) -> Image:
+        blur_factor = intensity * self.max_factor
+        width, height, *_ = image.shape
+
+        x, y = _to_odd_number(width * blur_factor), _to_odd_number(height * blur_factor)
+        image = cv2.GaussianBlur(image, (x, y), cv2.BORDER_DEFAULT)
+        return image
+
+
+def _to_odd_number(number):
+    return int(number // 2 * 2) - 1
+
+
+if __name__ == "__main__":
+    from research.common.dataset.perturbations.utils import simple_modifier_demo
+
+    simple_modifier_demo(GaussianBlurrer())
diff --git a/common/research/common/dataset/perturbations/image_modifiers/gaussian_noise.py b/common/research/common/dataset/perturbations/image_modifiers/gaussian_noise.py
new file mode 100644
index 0000000000000000000000000000000000000000..d84897a9d7d12044ed224cf0d0ee339a27853161
--- /dev/null
+++ b/common/research/common/dataset/perturbations/image_modifiers/gaussian_noise.py
@@ -0,0 +1,25 @@
+from dataclasses import dataclass
+
+import numpy as np
+
+from polystar.common.models.image import Image
+from research.common.dataset.perturbations.image_modifiers.image_modifier_abc import ImageModifierABC
+
+
+@dataclass
+class GaussianNoiser(ImageModifierABC):
+    max_variance: float = 300.0
+
+    def modify(self, image: Image, intensity: float) -> Image:
+        variance = self.max_variance * intensity
+        sigma = variance ** 0.5
+        row, column, ch = image.shape
+        gaussian = np.random.normal(0, sigma, (row, column, ch))
+        perturbed_image = np.clip((image.astype(np.uint16) + gaussian), 0, 255).astype(np.uint8)
+        return perturbed_image
+
+
+if __name__ == "__main__":
+    from research.common.dataset.perturbations.utils import simple_modifier_demo
+
+    simple_modifier_demo(GaussianNoiser())
diff --git a/common/research/common/dataset/perturbations/image_modifiers/horizontal_blur.py b/common/research/common/dataset/perturbations/image_modifiers/horizontal_blur.py
new file mode 100644
index 0000000000000000000000000000000000000000..b40b697f81e1be0fb0f5aa03aab9d0086a668211
--- /dev/null
+++ b/common/research/common/dataset/perturbations/image_modifiers/horizontal_blur.py
@@ -0,0 +1,40 @@
+from dataclasses import dataclass
+
+import cv2
+import numpy as np
+
+from polystar.common.models.image import Image
+from research.common.dataset.perturbations.image_modifiers.image_modifier_abc import ImageModifierABC
+
+
+@dataclass
+class HorizontalBlurrer(ImageModifierABC):
+    max_kernel_size: int = 11
+
+    def modify(self, image: Image, intensity: float) -> Image:
+        kernel = self._make_zero_kernel(intensity)
+        self._fill_middle_row_with_ones(kernel)
+        self._normalize_kernel(kernel)
+        return self._apply_kernel(image, kernel)
+
+    def _make_zero_kernel(self, intensity: float) -> np.ndarray:
+        kernel_size = int(self.max_kernel_size * intensity) + 1
+        return np.zeros((kernel_size, kernel_size))
+
+    @staticmethod
+    def _fill_middle_row_with_ones(kernel: np.ndarray):
+        kernel[len(kernel) // 2, :] = 1
+
+    @staticmethod
+    def _normalize_kernel(kernel: np.ndarray):
+        kernel /= len(kernel)
+
+    @staticmethod
+    def _apply_kernel(image: Image, kernel: np.ndarray) -> Image:
+        return cv2.filter2D(image, -1, kernel)
+
+
+if __name__ == "__main__":
+    from research.common.dataset.perturbations.utils import simple_modifier_demo
+
+    simple_modifier_demo(HorizontalBlurrer())
diff --git a/common/research/common/dataset/perturbations/image_modifiers/image_modifier_abc.py b/common/research/common/dataset/perturbations/image_modifiers/image_modifier_abc.py
new file mode 100644
index 0000000000000000000000000000000000000000..6a13fc0fcabc96dde6441a02c37c21072217b93d
--- /dev/null
+++ b/common/research/common/dataset/perturbations/image_modifiers/image_modifier_abc.py
@@ -0,0 +1,9 @@
+from abc import ABC, abstractmethod
+
+from polystar.common.models.image import Image
+
+
+class ImageModifierABC(ABC):
+    @abstractmethod
+    def modify(self, image: Image, intensity: float) -> Image:
+        pass
diff --git a/common/research/common/dataset/perturbations/image_modifiers/saturation.py b/common/research/common/dataset/perturbations/image_modifiers/saturation.py
new file mode 100644
index 0000000000000000000000000000000000000000..e97318b4bf4a4d93838e5977ac84022f534c9f3b
--- /dev/null
+++ b/common/research/common/dataset/perturbations/image_modifiers/saturation.py
@@ -0,0 +1,27 @@
+from dataclasses import dataclass
+
+import cv2
+import numpy as np
+
+from polystar.common.models.image import Image
+from research.common.dataset.perturbations.image_modifiers.image_modifier_abc import ImageModifierABC
+
+
+@dataclass
+class SaturationModifier(ImageModifierABC):
+    max_saturation: float = 0.6
+
+    def modify(self, image: Image, intensity: float) -> Image:
+        saturation_factor = 1 + self.max_saturation * intensity
+        image_hsv = cv2.cvtColor(image, cv2.COLOR_RGB2HSV)
+        (h, s, v) = cv2.split(image_hsv)
+        new_s = np.clip((s.astype(np.uint16) * saturation_factor), 0, 255).astype(np.uint8)
+        new_image_hsv = cv2.merge([h, new_s, v])
+        image_rgb = cv2.cvtColor(new_image_hsv, cv2.COLOR_HSV2RGB).astype(np.uint8)
+        return image_rgb
+
+
+if __name__ == "__main__":
+    from research.common.dataset.perturbations.utils import simple_modifier_demo
+
+    simple_modifier_demo(SaturationModifier())
diff --git a/common/research/common/dataset/perturbations/perturbator.py b/common/research/common/dataset/perturbations/perturbator.py
new file mode 100644
index 0000000000000000000000000000000000000000..986aa8a91fa6b80575f7ca3b9d48159b544e9cbe
--- /dev/null
+++ b/common/research/common/dataset/perturbations/perturbator.py
@@ -0,0 +1,56 @@
+from dataclasses import dataclass
+from pathlib import Path
+from random import shuffle
+from typing import List
+
+import cv2
+import matplotlib.pyplot as plt
+import numpy as np
+
+from polystar.common.models.image import Image
+from research.common.dataset.perturbations.image_modifiers.brightness import BrightnessModifier
+from research.common.dataset.perturbations.image_modifiers.contrast import ContrastModifier
+from research.common.dataset.perturbations.image_modifiers.gaussian_blur import GaussianBlurrer
+from research.common.dataset.perturbations.image_modifiers.gaussian_noise import GaussianNoiser
+from research.common.dataset.perturbations.image_modifiers.horizontal_blur import HorizontalBlurrer
+from research.common.dataset.perturbations.image_modifiers.image_modifier_abc import ImageModifierABC
+from research.common.dataset.perturbations.image_modifiers.saturation import SaturationModifier
+
+
+@dataclass
+class ImagePerturbator:
+    modifiers: List[ImageModifierABC]
+    min_intensity: float = 1.0
+
+    def perturbate(self, image: Image) -> Image:
+        shuffle(self.modifiers)
+        intensities = self._generate_intensities()
+        for modifier, intensity in zip(self.modifiers, intensities):
+            image = modifier.modify(image, intensity)
+        return image
+
+    def _generate_intensities(self) -> List[float]:
+        total_intensity = np.random.random() * (1.0 - self.min_intensity) + self.min_intensity
+        intensities = np.random.random(len(self.modifiers))
+        return intensities / intensities.sum() * total_intensity
+
+
+if __name__ == "__main__":
+    EXAMPLE_DIR = Path(__file__).parent / "examples"
+    rune_img = Image.from_path(EXAMPLE_DIR / "test.png")
+    perturbator = ImagePerturbator(
+        [
+            ContrastModifier(),
+            GaussianBlurrer(),
+            GaussianNoiser(),
+            HorizontalBlurrer(),
+            SaturationModifier(),
+            BrightnessModifier(),
+        ]
+    )
+    rune_perturbed = perturbator.perturbate(rune_img)
+    cv2.imwrite(str(EXAMPLE_DIR / "res_full_pipeline.png"), cv2.cvtColor(rune_perturbed, cv2.COLOR_RGB2BGR))
+    plt.axis("off")
+    plt.tight_layout()
+    plt.imshow(rune_perturbed)
+    plt.show()
diff --git a/robots-at-runes/research/dataset/perturbations/utils.py b/common/research/common/dataset/perturbations/utils.py
similarity index 60%
rename from robots-at-runes/research/dataset/perturbations/utils.py
rename to common/research/common/dataset/perturbations/utils.py
index 4982c6a9a204a420d6668c8b9132c690b3a55adc..551bc65023efc8983c09ec78dbdbbeb598a7dce7 100644
--- a/robots-at-runes/research/dataset/perturbations/utils.py
+++ b/common/research/common/dataset/perturbations/utils.py
@@ -1,4 +1,3 @@
-from collections import Callable
 from pathlib import Path
 
 import cv2
@@ -6,16 +5,15 @@ import matplotlib.pyplot as plt
 import numpy as np
 
 from polystar.common.models.image import Image
+from research.common.dataset.perturbations.image_modifiers.image_modifier_abc import ImageModifierABC
 
 EXAMPLE_DIR = Path(__file__).parent / "examples"
 
 
-def simple_perturbator_test(perturbator_function: Callable):
+def simple_modifier_demo(modifier: ImageModifierABC):
     rune_img = Image.from_path(EXAMPLE_DIR / "test.png")
-    rune_perturbed = perturbator_function(rune_img, 1)
-    cv2.imwrite(
-        str(EXAMPLE_DIR / f"res_{perturbator_function.__name__}.png"), cv2.cvtColor(rune_perturbed, cv2.COLOR_RGB2BGR)
-    )
+    rune_perturbed = modifier.modify(rune_img, 1)
+    cv2.imwrite(str(EXAMPLE_DIR / f"res_{modifier}.png"), cv2.cvtColor(rune_perturbed, cv2.COLOR_RGB2BGR))
     side_by_side_display = np.hstack((rune_img, rune_perturbed))
     h, w, _ = rune_img.shape
     plt.figure(figsize=(12, 6 * h / w))
diff --git a/common/research_common/dataset/roco_dataset.py b/common/research/common/dataset/roco_dataset.py
similarity index 100%
rename from common/research_common/dataset/roco_dataset.py
rename to common/research/common/dataset/roco_dataset.py
diff --git a/common/research_common/dataset/roco_dataset_descriptor.py b/common/research/common/dataset/roco_dataset_descriptor.py
similarity index 90%
rename from common/research_common/dataset/roco_dataset_descriptor.py
rename to common/research/common/dataset/roco_dataset_descriptor.py
index 7f95b783d3f4542efe6493ecd45d7b56377c12ee..1fb8c289bf02f81ab6dd34260d556eaf41dd40e4 100644
--- a/common/research_common/dataset/roco_dataset_descriptor.py
+++ b/common/research/common/dataset/roco_dataset_descriptor.py
@@ -7,10 +7,10 @@ from pandas import DataFrame
 
 from polystar.common.models.object import Armor, ObjectType
 from polystar.common.utils.markdown import MarkdownFile
-from research_common.dataset.dji.dji_roco_datasets import DJIROCODataset
-from research_common.dataset.dji.dji_roco_zoomed_datasets import DJIROCOZoomedDataset
-from research_common.dataset.roco_dataset import ROCODataset
-from research_common.dataset.twitch.twitch_roco_datasets import TwitchROCODataset
+from research.common.dataset.dji.dji_roco_datasets import DJIROCODataset
+from research.common.dataset.dji.dji_roco_zoomed_datasets import DJIROCOZoomedDataset
+from research.common.dataset.roco_dataset import ROCODataset
+from research.common.dataset.twitch.twitch_roco_datasets import TwitchROCODataset
 
 
 @dataclass
diff --git a/common/research_common/dataset/split.py b/common/research/common/dataset/split.py
similarity index 82%
rename from common/research_common/dataset/split.py
rename to common/research/common/dataset/split.py
index cf7b4026b6d7b61b948c9755831f514b7b5dc856..eeecc6fb8ec49e88347933b40d5e5fb5744a9665 100644
--- a/common/research_common/dataset/split.py
+++ b/common/research/common/dataset/split.py
@@ -1,7 +1,7 @@
 from enum import Enum
 from pathlib import Path
 
-from research_common.dataset.directory_roco_dataset import DirectoryROCODataset
+from research.common.dataset.directory_roco_dataset import DirectoryROCODataset
 
 
 class Split(Enum):
diff --git a/common/research_common/dataset/split_dataset.py b/common/research/common/dataset/split_dataset.py
similarity index 86%
rename from common/research_common/dataset/split_dataset.py
rename to common/research/common/dataset/split_dataset.py
index e2956b5102f31c3183187e24f33fbd1097814302..7ee242b7d88a1d55d44f6bd6ecfb066b0c46abef 100644
--- a/common/research_common/dataset/split_dataset.py
+++ b/common/research/common/dataset/split_dataset.py
@@ -1,9 +1,9 @@
 from pathlib import Path
 from typing import Iterable, List
 
-from research_common.dataset.directory_roco_dataset import DirectoryROCODataset
-from research_common.dataset.dji.dji_roco_datasets import DJIROCODataset
-from research_common.dataset.split import Split
+from research.common.dataset.directory_roco_dataset import DirectoryROCODataset
+from research.common.dataset.dji.dji_roco_datasets import DJIROCODataset
+from research.common.dataset.split import Split
 
 
 class SplitDataset(DirectoryROCODataset):
diff --git a/common/research_common/dataset/tensorflow_record.py b/common/research/common/dataset/tensorflow_record.py
similarity index 96%
rename from common/research_common/dataset/tensorflow_record.py
rename to common/research/common/dataset/tensorflow_record.py
index 93a0f5140f085f7b3a893d436e3de12f82abe966..7e835380b534ec17c2230b17d30fb2110c1652d5 100644
--- a/common/research_common/dataset/tensorflow_record.py
+++ b/common/research/common/dataset/tensorflow_record.py
@@ -8,8 +8,8 @@ from tqdm import tqdm
 
 from polystar.common.models.image_annotation import ImageAnnotation
 from polystar.common.models.label_map import label_map
-from research_common.constants import TENSORFLOW_RECORDS_DIR
-from research_common.dataset.roco_dataset import ROCODataset
+from research.common.constants import TENSORFLOW_RECORDS_DIR
+from research.common.dataset.roco_dataset import ROCODataset
 
 
 class TensorflowRecordFactory:
diff --git a/robots-at-runes/research/dataset/__init__.py b/common/research/common/dataset/twitch/__init__.py
similarity index 100%
rename from robots-at-runes/research/dataset/__init__.py
rename to common/research/common/dataset/twitch/__init__.py
diff --git a/common/research_common/dataset/twitch/aerial_view_detector.py b/common/research/common/dataset/twitch/aerial_view_detector.py
similarity index 82%
rename from common/research_common/dataset/twitch/aerial_view_detector.py
rename to common/research/common/dataset/twitch/aerial_view_detector.py
index 17ce4d75c18c42655ae9cf8fbeef7013c912db96..501b3ff583b2b861e08af11563e05312823b06c5 100644
--- a/common/research_common/dataset/twitch/aerial_view_detector.py
+++ b/common/research/common/dataset/twitch/aerial_view_detector.py
@@ -2,8 +2,8 @@ from pathlib import Path
 
 from skimage import io
 
-from research_common.constants import TWITCH_DSET_DIR
-from research_common.dataset.twitch.mask_detector import MaskDetector
+from research.common.constants import TWITCH_DSET_DIR
+from research.common.dataset.twitch.mask_detector import MaskDetector
 
 aerial_view_detector = MaskDetector(
     Path(__file__).parent / "mask_aerial.jpg",
diff --git a/common/research_common/dataset/twitch/mask_aerial.jpg b/common/research/common/dataset/twitch/mask_aerial.jpg
similarity index 100%
rename from common/research_common/dataset/twitch/mask_aerial.jpg
rename to common/research/common/dataset/twitch/mask_aerial.jpg
diff --git a/common/research_common/dataset/twitch/mask_detector.py b/common/research/common/dataset/twitch/mask_detector.py
similarity index 100%
rename from common/research_common/dataset/twitch/mask_detector.py
rename to common/research/common/dataset/twitch/mask_detector.py
diff --git a/common/research_common/dataset/twitch/mask_robot_view.jpg b/common/research/common/dataset/twitch/mask_robot_view.jpg
similarity index 100%
rename from common/research_common/dataset/twitch/mask_robot_view.jpg
rename to common/research/common/dataset/twitch/mask_robot_view.jpg
diff --git a/common/research_common/dataset/twitch/robots_views_extractor.py b/common/research/common/dataset/twitch/robots_views_extractor.py
similarity index 93%
rename from common/research_common/dataset/twitch/robots_views_extractor.py
rename to common/research/common/dataset/twitch/robots_views_extractor.py
index c14759bc74ab4250992d3d5f5a6e204c1dedeacc..7ddc5473d2ff0e15871ab590c229969b8c94fdc1 100644
--- a/common/research_common/dataset/twitch/robots_views_extractor.py
+++ b/common/research/common/dataset/twitch/robots_views_extractor.py
@@ -4,8 +4,8 @@ import numpy as np
 from tqdm import tqdm
 
 from polystar.common.frame_generators.fps_video_frame_generator import FPSVideoFrameGenerator
-from research_common.constants import TWITCH_DSET_DIR, TWITCH_ROBOTS_VIEWS_DIR
-from research_common.dataset.twitch.mask_detector import is_image_from_robot_view
+from research.common.constants import TWITCH_DSET_DIR, TWITCH_ROBOTS_VIEWS_DIR
+from research.common.dataset.twitch.mask_detector import is_image_from_robot_view
 
 
 class RobotsViewExtractor:
diff --git a/common/research_common/dataset/twitch/twitch_roco_datasets.py b/common/research/common/dataset/twitch/twitch_roco_datasets.py
similarity index 84%
rename from common/research_common/dataset/twitch/twitch_roco_datasets.py
rename to common/research/common/dataset/twitch/twitch_roco_datasets.py
index ff4ffa26332a5b5af91aa05eb8f51ff14096b6cc..f6c1ac68a91af0535c5bea329fcdd5b64e9002f1 100644
--- a/common/research_common/dataset/twitch/twitch_roco_datasets.py
+++ b/common/research/common/dataset/twitch/twitch_roco_datasets.py
@@ -2,7 +2,7 @@
 >>> TwitchROCODataset.TWITCH_470149568.dataset_name
 'T470149568'
 
->>> from research_common.constants import DSET_DIR
+>>> from research import DSET_DIR
 >>> TwitchROCODataset.TWITCH_470149568.dataset_path.relative_to(DSET_DIR)
 PosixPath('twitch/v1/470149568')
 
@@ -12,8 +12,8 @@ PosixPath('twitch/v1/470149568')
 
 from enum import Enum, auto
 
-from research_common.constants import TWITCH_DSET_DIR
-from research_common.dataset.directory_roco_dataset import DirectoryROCODataset
+from research.common.constants import TWITCH_DSET_DIR
+from research.common.dataset.directory_roco_dataset import DirectoryROCODataset
 
 
 class TwitchROCODataset(DirectoryROCODataset, Enum):
diff --git a/common/research_common/dataset/union_dataset.py b/common/research/common/dataset/union_dataset.py
similarity index 87%
rename from common/research_common/dataset/union_dataset.py
rename to common/research/common/dataset/union_dataset.py
index a580bb0c9897322780d63a6fe63d66da1bbe0d14..80560c5478d2b8d450c4b560fd1f976fd5243772 100644
--- a/common/research_common/dataset/union_dataset.py
+++ b/common/research/common/dataset/union_dataset.py
@@ -1,4 +1,4 @@
-from research_common.dataset.roco_dataset import ROCODataset
+from research.common.dataset.roco_dataset import ROCODataset
 
 
 class UnionDataset(ROCODataset):
diff --git a/robots-at-runes/research/dataset/blend/__init__.py b/common/research/common/image_pipeline_evaluation/__init__.py
similarity index 100%
rename from robots-at-runes/research/dataset/blend/__init__.py
rename to common/research/common/image_pipeline_evaluation/__init__.py
diff --git a/common/research_common/image_pipeline_evaluation/image_dataset_generator.py b/common/research/common/image_pipeline_evaluation/image_dataset_generator.py
similarity index 88%
rename from common/research_common/image_pipeline_evaluation/image_dataset_generator.py
rename to common/research/common/image_pipeline_evaluation/image_dataset_generator.py
index c2848779ea75666d70dde2931dffa9ed096dce8b..862b0492325578aa2391ed6afc85d098066d5aee 100644
--- a/common/research_common/image_pipeline_evaluation/image_dataset_generator.py
+++ b/common/research/common/image_pipeline_evaluation/image_dataset_generator.py
@@ -1,9 +1,9 @@
 from abc import abstractmethod
 from pathlib import Path
-from typing import TypeVar, Generic, Tuple, List, Iterable
+from typing import Generic, Iterable, List, Tuple, TypeVar
 
 from polystar.common.models.image import Image
-from research_common.dataset.directory_roco_dataset import DirectoryROCODataset
+from research.common.dataset.directory_roco_dataset import DirectoryROCODataset
 
 T = TypeVar("T")
 
diff --git a/common/research_common/image_pipeline_evaluation/image_pipeline_evaluation_reporter.py b/common/research/common/image_pipeline_evaluation/image_pipeline_evaluation_reporter.py
similarity index 92%
rename from common/research_common/image_pipeline_evaluation/image_pipeline_evaluation_reporter.py
rename to common/research/common/image_pipeline_evaluation/image_pipeline_evaluation_reporter.py
index ad5edc1a72cc65201994ff697c6efa4b8c50bdde..47cacc236e7d46677e2debd7e63151ce4907508d 100644
--- a/common/research_common/image_pipeline_evaluation/image_pipeline_evaluation_reporter.py
+++ b/common/research/common/image_pipeline_evaluation/image_pipeline_evaluation_reporter.py
@@ -11,13 +11,11 @@ from polystar.common.image_pipeline.image_pipeline import ImagePipeline
 from polystar.common.utils.dataframe import format_df_column, format_df_row, format_df_rows
 from polystar.common.utils.markdown import MarkdownFile
 from polystar.common.utils.time import create_time_id
-from research_common.constants import DSET_DIR, EVALUATION_DIR
-from research_common.dataset.roco_dataset import ROCODataset
-from research_common.image_pipeline_evaluation.image_pipeline_evaluator import (
-    ClassificationResults,
-    ImagePipelineEvaluator,
-    SetClassificationResults,
-)
+from research.common.constants import DSET_DIR, EVALUATION_DIR
+from research.common.dataset.roco_dataset import ROCODataset
+from research.common.image_pipeline_evaluation.image_pipeline_evaluator import (ClassificationResults,
+                                                                                ImagePipelineEvaluator,
+                                                                                SetClassificationResults)
 
 
 @dataclass
diff --git a/common/research_common/image_pipeline_evaluation/image_pipeline_evaluator.py b/common/research/common/image_pipeline_evaluation/image_pipeline_evaluator.py
similarity index 96%
rename from common/research_common/image_pipeline_evaluation/image_pipeline_evaluator.py
rename to common/research/common/image_pipeline_evaluation/image_pipeline_evaluator.py
index ba6e4e994481362f7a28bee3bbddf2f0d77d9e52..e47782ef0c2d180d154ffd8e3ab90b1b359d7d86 100644
--- a/common/research_common/image_pipeline_evaluation/image_pipeline_evaluator.py
+++ b/common/research/common/image_pipeline_evaluation/image_pipeline_evaluator.py
@@ -9,8 +9,8 @@ from sklearn.metrics import classification_report, confusion_matrix
 from memoized_property import memoized_property
 from polystar.common.image_pipeline.image_pipeline import ImagePipeline
 from polystar.common.models.image import Image
-from research_common.dataset.directory_roco_dataset import DirectoryROCODataset
-from research_common.image_pipeline_evaluation.image_dataset_generator import ImageDatasetGenerator
+from research.common.dataset.directory_roco_dataset import DirectoryROCODataset
+from research.common.image_pipeline_evaluation.image_dataset_generator import ImageDatasetGenerator
 
 
 @dataclass
diff --git a/robots-at-runes/research/dataset/blend/labeled_image_modifiers/__init__.py b/common/research/common/scripts/__init__.py
similarity index 100%
rename from robots-at-runes/research/dataset/blend/labeled_image_modifiers/__init__.py
rename to common/research/common/scripts/__init__.py
diff --git a/common/research_common/scripts/construct_dataset_from_manual_annotation.py b/common/research/common/scripts/construct_dataset_from_manual_annotation.py
similarity index 100%
rename from common/research_common/scripts/construct_dataset_from_manual_annotation.py
rename to common/research/common/scripts/construct_dataset_from_manual_annotation.py
diff --git a/common/research_common/scripts/construct_twith_datasets_from_manual_annotation.py b/common/research/common/scripts/construct_twith_datasets_from_manual_annotation.py
similarity index 87%
rename from common/research_common/scripts/construct_twith_datasets_from_manual_annotation.py
rename to common/research/common/scripts/construct_twith_datasets_from_manual_annotation.py
index 3989bba47072f03992f2b9d29b6a059c95423082..2306f80d42513b2e4c63829b6915a3d9df081cb7 100644
--- a/common/research_common/scripts/construct_twith_datasets_from_manual_annotation.py
+++ b/common/research/common/scripts/construct_twith_datasets_from_manual_annotation.py
@@ -1,11 +1,11 @@
 from os import remove
-from shutil import copy, move, rmtree, make_archive
+from shutil import copy, make_archive, move, rmtree
 
-from research_common.constants import TWITCH_DSET_DIR, TWITCH_ROBOTS_VIEWS_DIR, TWITCH_DSET_ROBOTS_VIEWS_DIR
-from research_common.dataset.directory_roco_dataset import DirectoryROCODataset
-from research_common.dataset.roco_dataset_descriptor import make_markdown_dataset_report
-from research_common.scripts.construct_dataset_from_manual_annotation import construct_dataset_from_manual_annotations
-from research_common.scripts.correct_annotations import AnnotationFileCorrector
+from research.common.constants import TWITCH_DSET_DIR, TWITCH_DSET_ROBOTS_VIEWS_DIR, TWITCH_ROBOTS_VIEWS_DIR
+from research.common.dataset.directory_roco_dataset import DirectoryROCODataset
+from research.common.dataset.roco_dataset_descriptor import make_markdown_dataset_report
+from research.common.scripts.construct_dataset_from_manual_annotation import construct_dataset_from_manual_annotations
+from research.common.scripts.correct_annotations import AnnotationFileCorrector
 
 
 def _construct_mixed_twitch_dset():
diff --git a/common/research_common/scripts/correct_annotations.py b/common/research/common/scripts/correct_annotations.py
similarity index 100%
rename from common/research_common/scripts/correct_annotations.py
rename to common/research/common/scripts/correct_annotations.py
diff --git a/common/research_common/scripts/create_tensorflow_records.py b/common/research/common/scripts/create_tensorflow_records.py
similarity index 70%
rename from common/research_common/scripts/create_tensorflow_records.py
rename to common/research/common/scripts/create_tensorflow_records.py
index f7ea87b6ca5295b55a337aa819c22aecb124087a..9ca8456ae221659545d270e34a418205bcb4c305 100644
--- a/common/research_common/scripts/create_tensorflow_records.py
+++ b/common/research/common/scripts/create_tensorflow_records.py
@@ -1,10 +1,10 @@
 from itertools import chain
 
-from research_common.dataset.dji.dji_roco_datasets import DJIROCODataset
-from research_common.dataset.dji.dji_roco_zoomed_datasets import DJIROCOZoomedDataset
-from research_common.dataset.tensorflow_record import TensorflowRecordFactory
-from research_common.dataset.twitch.twitch_roco_datasets import TwitchROCODataset
-from research_common.dataset.union_dataset import UnionDataset
+from research.common.dataset.dji.dji_roco_datasets import DJIROCODataset
+from research.common.dataset.dji.dji_roco_zoomed_datasets import DJIROCOZoomedDataset
+from research.common.dataset.tensorflow_record import TensorflowRecordFactory
+from research.common.dataset.twitch.twitch_roco_datasets import TwitchROCODataset
+from research.common.dataset.union_dataset import UnionDataset
 
 
 def create_one_record_per_roco_dset():
@@ -12,9 +12,7 @@ def create_one_record_per_roco_dset():
         TensorflowRecordFactory.from_dataset(roco_set)
 
 
-if __name__ == "__main__":
-    # create_one_record_per_roco_dset()
-
+def create_twitch_records():
     TensorflowRecordFactory.from_dataset(
         UnionDataset(
             TwitchROCODataset.TWITCH_470149568,
@@ -24,21 +22,31 @@ if __name__ == "__main__":
             TwitchROCODataset.TWITCH_470152730,
         )
     )
-
     TensorflowRecordFactory.from_dataset(
         UnionDataset(
             TwitchROCODataset.TWITCH_470152838, TwitchROCODataset.TWITCH_470153081, TwitchROCODataset.TWITCH_470158483,
         )
     )
 
+
+def create_dji_records():
     TensorflowRecordFactory.from_dataset(
         UnionDataset(DJIROCODataset.CentralChina, DJIROCODataset.NorthChina, DJIROCODataset.SouthChina)
     )
     TensorflowRecordFactory.from_dataset(DJIROCODataset.Final)
 
+
+def create_dji_zoomed_records():
     TensorflowRecordFactory.from_dataset(
         UnionDataset(
             DJIROCOZoomedDataset.CentralChina, DJIROCOZoomedDataset.NorthChina, DJIROCOZoomedDataset.SouthChina
         )
     )
     TensorflowRecordFactory.from_dataset(DJIROCOZoomedDataset.Final)
+
+
+if __name__ == "__main__":
+    create_one_record_per_roco_dset()
+    create_twitch_records()
+    create_dji_records()
+    create_dji_zoomed_records()
diff --git a/common/research_common/scripts/extract_robots_views_from_video.py b/common/research/common/scripts/extract_robots_views_from_video.py
similarity index 69%
rename from common/research_common/scripts/extract_robots_views_from_video.py
rename to common/research/common/scripts/extract_robots_views_from_video.py
index ac41ab6d63dba1fc9438a4090e8f8baa8cd1435d..55f149699d17cf776fc741e023bf489a9397483a 100644
--- a/common/research_common/scripts/extract_robots_views_from_video.py
+++ b/common/research/common/scripts/extract_robots_views_from_video.py
@@ -1,6 +1,6 @@
 import sys
 
-from research_common.dataset.twitch.robots_views_extractor import RobotsViewExtractor
+from research.common.dataset.twitch.robots_views_extractor import RobotsViewExtractor
 
 if __name__ == "__main__":
     for _video_name in sys.argv[1:]:
diff --git a/common/research/common/scripts/improve_roco_by_zooming.py b/common/research/common/scripts/improve_roco_by_zooming.py
new file mode 100644
index 0000000000000000000000000000000000000000..9550fa94f4eb301b011d78b1f3f1985819c5200d
--- /dev/null
+++ b/common/research/common/scripts/improve_roco_by_zooming.py
@@ -0,0 +1,40 @@
+from tqdm import tqdm
+
+from research.common.dataset.dji.dji_roco_datasets import DJIROCODataset
+from research.common.dataset.dji.dji_roco_zoomed_datasets import DJIROCOZoomedDataset
+from research.common.dataset.improvement.zoom import Zoomer
+from research.common.dataset.perturbations.image_modifiers.brightness import BrightnessModifier
+from research.common.dataset.perturbations.image_modifiers.contrast import ContrastModifier
+from research.common.dataset.perturbations.image_modifiers.saturation import SaturationModifier
+from research.common.dataset.perturbations.perturbator import ImagePerturbator
+
+
+def improve_dji_roco_dataset_by_zooming_and_perturbating(
+    dset: DJIROCODataset, zoomer: Zoomer, perturbator: ImagePerturbator
+):
+    zoomed_dset: DJIROCOZoomedDataset = DJIROCOZoomedDataset[dset.name]
+    zoomed_dset.dataset_path.mkdir(parents=True)
+
+    for img in tqdm(dset.image_annotations, desc=f"Processing {dset}", unit="image", total=len(dset)):
+        for i, zoomed_image in enumerate(zoomer.zoom(img), 1):
+            zoomed_image._image = perturbator.perturbate(zoomed_image.image)
+            zoomed_image.save_to_dir(zoomed_dset.dataset_path, f"{img.image_path.stem}_zoom_{i}")
+
+
+def improve_all_dji_datasets_by_zooming_and_perturbating(zoomer: Zoomer, perturbator: ImagePerturbator):
+    for _dset in DJIROCODataset:
+        improve_dji_roco_dataset_by_zooming_and_perturbating(zoomer=zoomer, dset=_dset, perturbator=perturbator)
+
+
+if __name__ == "__main__":
+    improve_all_dji_datasets_by_zooming_and_perturbating(
+        Zoomer(w=854, h=480, max_overlap=0.15, min_coverage=0.5),
+        ImagePerturbator(
+            [
+                ContrastModifier(min_coef=0.7, max_coef=1.5),
+                BrightnessModifier(max_offset=10.0),
+                SaturationModifier(max_saturation=0.6),
+            ],
+            min_intensity=0.5,
+        ),
+    )
diff --git a/common/research_common/scripts/make_twitch_chunks_to_annotate.py b/common/research/common/scripts/make_twitch_chunks_to_annotate.py
similarity index 94%
rename from common/research_common/scripts/make_twitch_chunks_to_annotate.py
rename to common/research/common/scripts/make_twitch_chunks_to_annotate.py
index 159a36ceba6fcc0238f8a0ef5792732f4662433c..136ab64fdafa3cdcedd7fe3f31d45b9817b87a8e 100644
--- a/common/research_common/scripts/make_twitch_chunks_to_annotate.py
+++ b/common/research/common/scripts/make_twitch_chunks_to_annotate.py
@@ -4,7 +4,7 @@ from itertools import count
 from pathlib import Path
 from typing import Iterator
 
-from research_common.constants import TWITCH_ROBOTS_VIEWS_DIR
+from research.common.constants import TWITCH_ROBOTS_VIEWS_DIR
 
 
 @dataclass
@@ -21,7 +21,6 @@ class DatasetChunker:
                 self._make_next_chunk(chunk_number, image_paths_iterator)
         except StopIteration:
             self._zip_chunk(self._get_chunk_dir(self._get_number_existing_chunks() + 1))
-            pass
 
     def _make_next_chunk(self, chunk_number: int, image_paths_iterator: Iterator[Path]):
         chunk_dir = self._get_chunk_dir(chunk_number)
diff --git a/common/research_common/scripts/move_aerial_views.py b/common/research/common/scripts/move_aerial_views.py
similarity index 81%
rename from common/research_common/scripts/move_aerial_views.py
rename to common/research/common/scripts/move_aerial_views.py
index dc66f371b9084c1999f3bea405652204ffdec6f9..7950840762214088a841593f9a94405f208e22b4 100644
--- a/common/research_common/scripts/move_aerial_views.py
+++ b/common/research/common/scripts/move_aerial_views.py
@@ -3,8 +3,8 @@ from shutil import move
 from skimage import io
 from tqdm import tqdm
 
-from research_common.constants import TWITCH_DSET_DIR, TWITCH_ROBOTS_VIEWS_DIR
-from research_common.dataset.twitch.aerial_view_detector import aerial_view_detector
+from research.common.constants import TWITCH_DSET_DIR, TWITCH_ROBOTS_VIEWS_DIR
+from research.common.dataset.twitch.aerial_view_detector import aerial_view_detector
 
 AERIAL_VIEWS_DIR = TWITCH_DSET_DIR / "aerial-views"
 
diff --git a/common/research_common/scripts/train_val_test_split.py b/common/research/common/scripts/train_val_test_split.py
similarity index 88%
rename from common/research_common/scripts/train_val_test_split.py
rename to common/research/common/scripts/train_val_test_split.py
index 1d98a83bde1542aec5b8f20cc45b61be9a6fe17f..4da68d5d439af29661aa64bb443b29f342bde7ac 100644
--- a/common/research_common/scripts/train_val_test_split.py
+++ b/common/research/common/scripts/train_val_test_split.py
@@ -3,9 +3,9 @@ from typing import Iterable
 
 from sklearn.model_selection import train_test_split
 
-from research_common.dataset.directory_roco_dataset import DirectoryROCODataset
-from research_common.dataset.dji.dji_roco_datasets import DJIROCODataset
-from research_common.dataset.split import Split
+from research.common.dataset.directory_roco_dataset import DirectoryROCODataset
+from research.common.dataset.dji.dji_roco_datasets import DJIROCODataset
+from research.common.dataset.split import Split
 
 
 def _check_for_previous_split(dataset: DirectoryROCODataset):
diff --git a/common/research_common/scripts/visualize_dataset.py b/common/research/common/scripts/visualize_dataset.py
similarity index 67%
rename from common/research_common/scripts/visualize_dataset.py
rename to common/research/common/scripts/visualize_dataset.py
index f74696ed6e122331e571626490c320deecc74be0..13254ff04717c3a57dbe41829158f082912b303c 100644
--- a/common/research_common/scripts/visualize_dataset.py
+++ b/common/research/common/scripts/visualize_dataset.py
@@ -1,6 +1,6 @@
 from polystar.common.view.plt_results_viewer import PltResultViewer
-from research_common.dataset.dji.dji_roco_zoomed_datasets import DJIROCOZoomedDataset
-from research_common.dataset.roco_dataset import ROCODataset
+from research.common.dataset.dji.dji_roco_zoomed_datasets import DJIROCOZoomedDataset
+from research.common.dataset.roco_dataset import ROCODataset
 
 
 def visualize_dataset(dataset: ROCODataset, n_images: int):
@@ -14,4 +14,4 @@ def visualize_dataset(dataset: ROCODataset, n_images: int):
 
 
 if __name__ == "__main__":
-    visualize_dataset(DJIROCOZoomedDataset.CentralChina, 10)
+    visualize_dataset(DJIROCOZoomedDataset.CentralChina, 20)
diff --git a/common/research_common/scripts/improve_roco_by_zooming.py b/common/research_common/scripts/improve_roco_by_zooming.py
deleted file mode 100644
index 182697bd7f5d324932676ae4bbe91500615689ec..0000000000000000000000000000000000000000
--- a/common/research_common/scripts/improve_roco_by_zooming.py
+++ /dev/null
@@ -1,23 +0,0 @@
-from tqdm import tqdm
-
-from research_common.dataset.dji.dji_roco_datasets import DJIROCODataset
-from research_common.dataset.dji.dji_roco_zoomed_datasets import DJIROCOZoomedDataset
-from research_common.dataset.improvement.zoom import Zoomer
-
-
-def improve_dji_roco_dataset_by_zooming(dset: DJIROCODataset, zoomer: Zoomer):
-    zoomed_dset: DJIROCOZoomedDataset = DJIROCOZoomedDataset[dset.name]
-    zoomed_dset.dataset_path.mkdir(parents=True, exist_ok=True)
-
-    for img in tqdm(dset.image_annotations, desc=f"Processing {dset}", unit="image", total=len(dset)):
-        for i, zoomed_image in enumerate(zoomer.zoom(img), 1):
-            zoomed_image.save_to_dir(zoomed_dset.dataset_path, f"{img.image_path.stem}_zoom_{i}")
-
-
-def improve_all_dji_datasets_by_zooming(zoomer: Zoomer):
-    for _dset in DJIROCODataset:
-        improve_dji_roco_dataset_by_zooming(zoomer=zoomer, dset=_dset)
-
-
-if __name__ == "__main__":
-    improve_all_dji_datasets_by_zooming(Zoomer(854, 480, 0.15, 0.5))
diff --git a/robots-at-runes/research/dataset/perturbations/__init__.py b/common/tests/common/unittests/__init__.py
similarity index 100%
rename from robots-at-runes/research/dataset/perturbations/__init__.py
rename to common/tests/common/unittests/__init__.py
diff --git a/robots-at-runes/research/dataset/perturbations/perturbator_functions/__init__.py b/common/tests/common/unittests/object_validators/__init__.py
similarity index 100%
rename from robots-at-runes/research/dataset/perturbations/perturbator_functions/__init__.py
rename to common/tests/common/unittests/object_validators/__init__.py
diff --git a/common/tests/unittests/object_validators/test_in_box_validator.py b/common/tests/common/unittests/object_validators/test_in_box_validator.py
similarity index 100%
rename from common/tests/unittests/object_validators/test_in_box_validator.py
rename to common/tests/common/unittests/object_validators/test_in_box_validator.py
diff --git a/dataset/dji_roco_zoomed_v1/.gitignore b/dataset/dji_roco_zoomed_v2/.gitignore
similarity index 100%
rename from dataset/dji_roco_zoomed_v1/.gitignore
rename to dataset/dji_roco_zoomed_v2/.gitignore
diff --git a/drone-at-base/Readme.md b/drone-at-base/Readme.md
deleted file mode 100644
index eaab14ed2e29a3e755f914890528338dafa13988..0000000000000000000000000000000000000000
--- a/drone-at-base/Readme.md
+++ /dev/null
@@ -1,6 +0,0 @@
-
-# Drone@Base
-
-## Goal
-
-The goal of this project is to detect the base, from the drone, to be able to assist the pilot into shooting it.
diff --git a/drone-at-base/config/settings.toml b/drone-at-base/config/settings.toml
deleted file mode 100644
index bbefeb544733c90046f74ea7b2382c7c0d7bc7cc..0000000000000000000000000000000000000000
--- a/drone-at-base/config/settings.toml
+++ /dev/null
@@ -1,5 +0,0 @@
-[default]
-
-[development]
-
-[production]
diff --git a/drone-at-base/polystar/drone_at_base/globals.py b/drone-at-base/polystar/drone_at_base/globals.py
deleted file mode 100644
index 47f6b6e023c9c117cbdc4303427ead05e7e614d0..0000000000000000000000000000000000000000
--- a/drone-at-base/polystar/drone_at_base/globals.py
+++ /dev/null
@@ -1,5 +0,0 @@
-from polystar.common.settings import make_settings
-
-PROJECT_NAME = "drone-at-base"
-
-settings = make_settings(PROJECT_NAME)
diff --git a/robots-at-robots/research/constants.py b/robots-at-robots/research/constants.py
deleted file mode 100644
index 8b137891791fe96927ad78e64b0aad7bded08bdc..0000000000000000000000000000000000000000
--- a/robots-at-robots/research/constants.py
+++ /dev/null
@@ -1 +0,0 @@
-
diff --git a/robots-at-robots/research/robots_at_robots/__init__.py b/robots-at-robots/research/robots_at_robots/__init__.py
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/robots-at-robots/research/robots_at_robots/armor_color/__init__.py b/robots-at-robots/research/robots_at_robots/armor_color/__init__.py
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/robots-at-robots/research/armor_color/armor_color_pipeline_reporter_factory.py b/robots-at-robots/research/robots_at_robots/armor_color/armor_color_pipeline_reporter_factory.py
similarity index 69%
rename from robots-at-robots/research/armor_color/armor_color_pipeline_reporter_factory.py
rename to robots-at-robots/research/robots_at_robots/armor_color/armor_color_pipeline_reporter_factory.py
index d6fa16ec204c720a71e977e95492457d2e9624d1..86e417131a39f8cd6b1d5b8491e0987714f068ec 100644
--- a/robots-at-robots/research/armor_color/armor_color_pipeline_reporter_factory.py
+++ b/robots-at-robots/research/robots_at_robots/armor_color/armor_color_pipeline_reporter_factory.py
@@ -1,9 +1,9 @@
 from typing import List
 
-from research.dataset.armor_color_dataset_factory import ArmorColorDatasetGenerator
-from research_common.dataset.directory_roco_dataset import DirectoryROCODataset
-from research_common.image_pipeline_evaluation.image_pipeline_evaluation_reporter import ImagePipelineEvaluationReporter
-from research_common.image_pipeline_evaluation.image_pipeline_evaluator import ImagePipelineEvaluator
+from research.common.dataset.directory_roco_dataset import DirectoryROCODataset
+from research.common.image_pipeline_evaluation.image_pipeline_evaluation_reporter import ImagePipelineEvaluationReporter
+from research.common.image_pipeline_evaluation.image_pipeline_evaluator import ImagePipelineEvaluator
+from research.robots_at_robots.dataset.armor_color_dataset_factory import ArmorColorDatasetGenerator
 
 
 class ArmorColorPipelineReporterFactory:
diff --git a/robots-at-robots/research/armor_color/baseline_experiments.py b/robots-at-robots/research/robots_at_robots/armor_color/baseline_experiments.py
similarity index 85%
rename from robots-at-robots/research/armor_color/baseline_experiments.py
rename to robots-at-robots/research/robots_at_robots/armor_color/baseline_experiments.py
index fbad510085f6e2fbdcdcbe98d07e2743a364b4c9..9ef9a9391e91067326c6f2a06b762b94b956e718 100644
--- a/robots-at-robots/research/armor_color/baseline_experiments.py
+++ b/robots-at-robots/research/robots_at_robots/armor_color/baseline_experiments.py
@@ -4,8 +4,9 @@ from polystar.common.image_pipeline.classifier_image_pipeline import ClassifierI
 from polystar.common.image_pipeline.image_featurizer.mean_rgb_channels_featurizer import MeanChannelsFeaturizer
 from polystar.common.image_pipeline.models.random_model import RandomModel
 from polystar.common.image_pipeline.models.red_blue_channels_comparison_model import RedBlueComparisonModel
-from research.armor_color.armor_color_pipeline_reporter_factory import ArmorColorPipelineReporterFactory
-from research_common.dataset.twitch.twitch_roco_datasets import TwitchROCODataset
+from research.common.dataset.twitch.twitch_roco_datasets import TwitchROCODataset
+from research.robots_at_robots.armor_color.armor_color_pipeline_reporter_factory import \
+    ArmorColorPipelineReporterFactory
 
 if __name__ == "__main__":
     logging.getLogger().setLevel("INFO")
diff --git a/robots-at-robots/research/robots_at_robots/armor_digit/__init__.py b/robots-at-robots/research/robots_at_robots/armor_digit/__init__.py
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/robots-at-robots/research/armor_digit/armor_digit_pipeline_reporter_factory.py b/robots-at-robots/research/robots_at_robots/armor_digit/armor_digit_pipeline_reporter_factory.py
similarity index 72%
rename from robots-at-robots/research/armor_digit/armor_digit_pipeline_reporter_factory.py
rename to robots-at-robots/research/robots_at_robots/armor_digit/armor_digit_pipeline_reporter_factory.py
index 5546f27d39414036d1d7290564acb9a26c03f9b4..7d54e8d8bcef4b3d2cde2b23b44295e65ce86ba8 100644
--- a/robots-at-robots/research/armor_digit/armor_digit_pipeline_reporter_factory.py
+++ b/robots-at-robots/research/robots_at_robots/armor_digit/armor_digit_pipeline_reporter_factory.py
@@ -1,9 +1,9 @@
 from typing import Iterable, List
 
-from research.dataset.armor_digit_dataset_factory import ArmorDigitDatasetGenerator
-from research_common.dataset.directory_roco_dataset import DirectoryROCODataset
-from research_common.image_pipeline_evaluation.image_pipeline_evaluation_reporter import ImagePipelineEvaluationReporter
-from research_common.image_pipeline_evaluation.image_pipeline_evaluator import ImagePipelineEvaluator
+from research.common.dataset.directory_roco_dataset import DirectoryROCODataset
+from research.common.image_pipeline_evaluation.image_pipeline_evaluation_reporter import ImagePipelineEvaluationReporter
+from research.common.image_pipeline_evaluation.image_pipeline_evaluator import ImagePipelineEvaluator
+from research.robots_at_robots.dataset.armor_digit_dataset_factory import ArmorDigitDatasetGenerator
 
 
 class ArmorDigitPipelineReporterFactory:
diff --git a/robots-at-robots/research/armor_digit/baseline_experiments.py b/robots-at-robots/research/robots_at_robots/armor_digit/baseline_experiments.py
similarity index 77%
rename from robots-at-robots/research/armor_digit/baseline_experiments.py
rename to robots-at-robots/research/robots_at_robots/armor_digit/baseline_experiments.py
index a85cb3af904405599b5e0918d9a398f816985c2a..8dd1dcf51940ef845b079364091d00a32f3ead72 100644
--- a/robots-at-robots/research/armor_digit/baseline_experiments.py
+++ b/robots-at-robots/research/robots_at_robots/armor_digit/baseline_experiments.py
@@ -2,8 +2,9 @@ import logging
 
 from polystar.common.image_pipeline.classifier_image_pipeline import ClassifierImagePipeline
 from polystar.common.image_pipeline.models.random_model import RandomModel
-from research.armor_digit.armor_digit_pipeline_reporter_factory import ArmorDigitPipelineReporterFactory
-from research_common.dataset.twitch.twitch_roco_datasets import TwitchROCODataset
+from research.common.dataset.twitch.twitch_roco_datasets import TwitchROCODataset
+from research.robots_at_robots.armor_digit.armor_digit_pipeline_reporter_factory import \
+    ArmorDigitPipelineReporterFactory
 
 if __name__ == "__main__":
     logging.getLogger().setLevel("INFO")
diff --git a/drone-at-base/research/constants.py b/robots-at-robots/research/robots_at_robots/constants.py
similarity index 100%
rename from drone-at-base/research/constants.py
rename to robots-at-robots/research/robots_at_robots/constants.py
diff --git a/robots-at-robots/research/robots_at_robots/dataset/__init__.py b/robots-at-robots/research/robots_at_robots/dataset/__init__.py
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/robots-at-robots/research/dataset/armor_color_dataset_factory.py b/robots-at-robots/research/robots_at_robots/dataset/armor_color_dataset_factory.py
similarity index 73%
rename from robots-at-robots/research/dataset/armor_color_dataset_factory.py
rename to robots-at-robots/research/robots_at_robots/dataset/armor_color_dataset_factory.py
index c601fa168777f24dc93832706e6470836c7821b6..441dfdb67f80a93dd223438a1f65d651b574b214 100644
--- a/robots-at-robots/research/dataset/armor_color_dataset_factory.py
+++ b/robots-at-robots/research/robots_at_robots/dataset/armor_color_dataset_factory.py
@@ -1,7 +1,7 @@
 from pathlib import Path
 
 from polystar.common.models.object import Armor
-from research.dataset.armor_image_dataset_factory import ArmorImageDatasetGenerator
+from research.robots_at_robots.dataset.armor_image_dataset_factory import ArmorImageDatasetGenerator
 
 
 class ArmorColorDatasetGenerator(ArmorImageDatasetGenerator[str]):
diff --git a/robots-at-robots/research/dataset/armor_dataset_factory.py b/robots-at-robots/research/robots_at_robots/dataset/armor_dataset_factory.py
similarity index 85%
rename from robots-at-robots/research/dataset/armor_dataset_factory.py
rename to robots-at-robots/research/robots_at_robots/dataset/armor_dataset_factory.py
index 03a176a426c850a984a13c490ff76144b50517e7..a5138d440e3bea1bfcdd7665dc600047dc719624 100644
--- a/robots-at-robots/research/dataset/armor_dataset_factory.py
+++ b/robots-at-robots/research/robots_at_robots/dataset/armor_dataset_factory.py
@@ -1,14 +1,14 @@
 from pathlib import Path
-from typing import List, Iterable, Tuple
+from typing import Iterable, List, Tuple
 
 import matplotlib.pyplot as plt
 
 from polystar.common.models.image import Image
 from polystar.common.models.image_annotation import ImageAnnotation
-from polystar.common.models.object import ObjectType, Armor
+from polystar.common.models.object import Armor, ObjectType
 from polystar.common.target_pipeline.objects_validators.type_object_validator import TypeObjectValidator
-from research_common.dataset.dji.dji_roco_datasets import DJIROCODataset
-from research_common.dataset.roco_dataset import ROCODataset
+from research.common.dataset.dji.dji_roco_datasets import DJIROCODataset
+from research.common.dataset.roco_dataset import ROCODataset
 
 
 class ArmorDatasetFactory:
diff --git a/robots-at-robots/research/dataset/armor_digit_dataset_factory.py b/robots-at-robots/research/robots_at_robots/dataset/armor_digit_dataset_factory.py
similarity index 85%
rename from robots-at-robots/research/dataset/armor_digit_dataset_factory.py
rename to robots-at-robots/research/robots_at_robots/dataset/armor_digit_dataset_factory.py
index 70be5507e55477413850c5103be4b85ed8e13f55..7117bf15d88b6ff3e9952321447323fc6b281864 100644
--- a/robots-at-robots/research/dataset/armor_digit_dataset_factory.py
+++ b/robots-at-robots/research/robots_at_robots/dataset/armor_digit_dataset_factory.py
@@ -2,7 +2,7 @@ from pathlib import Path
 from typing import Set
 
 from polystar.common.models.object import Armor
-from research.dataset.armor_image_dataset_factory import ArmorImageDatasetGenerator
+from research.robots_at_robots.dataset.armor_image_dataset_factory import ArmorImageDatasetGenerator
 
 
 class ArmorDigitDatasetGenerator(ArmorImageDatasetGenerator[int]):
diff --git a/robots-at-robots/research/dataset/armor_image_dataset_factory.py b/robots-at-robots/research/robots_at_robots/dataset/armor_image_dataset_factory.py
similarity index 88%
rename from robots-at-robots/research/dataset/armor_image_dataset_factory.py
rename to robots-at-robots/research/robots_at_robots/dataset/armor_image_dataset_factory.py
index dfdf35b8ec6ea55e0cffc1c6f9458a69e7190109..33291bf0306eb04c78dd99f8f5d40a1f5a789f2f 100644
--- a/robots-at-robots/research/dataset/armor_image_dataset_factory.py
+++ b/robots-at-robots/research/robots_at_robots/dataset/armor_image_dataset_factory.py
@@ -1,16 +1,16 @@
 import json
 from abc import abstractmethod
 from pathlib import Path
-from typing import TypeVar, Tuple, Iterable
+from typing import Iterable, Tuple, TypeVar
 
 import cv2
 
 from polystar.common.models.image import Image
 from polystar.common.models.object import Armor
 from polystar.common.utils.time import create_time_id
-from research.dataset.armor_dataset_factory import ArmorDatasetFactory
-from research_common.dataset.directory_roco_dataset import DirectoryROCODataset
-from research_common.image_pipeline_evaluation.image_dataset_generator import ImageDatasetGenerator
+from research.common.dataset.directory_roco_dataset import DirectoryROCODataset
+from research.common.image_pipeline_evaluation.image_dataset_generator import ImageDatasetGenerator
+from research.robots_at_robots.dataset.armor_dataset_factory import ArmorDatasetFactory
 
 T = TypeVar("T")
 
diff --git a/robots-at-robots/research/demos/demo_infer.py b/robots-at-robots/research/robots_at_robots/demos/demo_infer.py
similarity index 82%
rename from robots-at-robots/research/demos/demo_infer.py
rename to robots-at-robots/research/robots_at_robots/demos/demo_infer.py
index d3604ccb35bfa1c4a1509f6ededd3bf77486ca42..1151453045a4c9f3b9c7635b6d298f88bb0e07be 100644
--- a/robots-at-robots/research/demos/demo_infer.py
+++ b/robots-at-robots/research/robots_at_robots/demos/demo_infer.py
@@ -4,10 +4,10 @@ from polystar.common.target_pipeline.objects_validators.confidence_object_valida
 from polystar.common.utils.tensorflow import patch_tf_v2
 from polystar.common.view.plt_results_viewer import PltResultViewer
 from polystar.robots_at_robots.dependency_injection import make_injector
-from research.demos.utils import load_tf_model
-from research_common.dataset.dji.dji_roco_datasets import DJIROCODataset
-from research_common.dataset.split import Split
-from research_common.dataset.split_dataset import SplitDataset
+from research.common.dataset.dji.dji_roco_datasets import DJIROCODataset
+from research.common.dataset.split import Split
+from research.common.dataset.split_dataset import SplitDataset
+from research.robots_at_robots.demos.utils import load_tf_model
 
 if __name__ == "__main__":
     patch_tf_v2()
diff --git a/robots-at-robots/research/demos/demo_pipeline.py b/robots-at-robots/research/robots_at_robots/demos/demo_pipeline.py
similarity index 91%
rename from robots-at-robots/research/demos/demo_pipeline.py
rename to robots-at-robots/research/robots_at_robots/demos/demo_pipeline.py
index ae48d4cddc7ae958e5f363cf402a574636aac2d1..0ca742b89cde8ee9a1d8158e4dce96bd4362c41e 100644
--- a/robots-at-robots/research/demos/demo_pipeline.py
+++ b/robots-at-robots/research/robots_at_robots/demos/demo_pipeline.py
@@ -18,11 +18,11 @@ from polystar.common.target_pipeline.target_pipeline import NoTargetFoundExcepti
 from polystar.common.utils.tensorflow import patch_tf_v2
 from polystar.common.view.plt_results_viewer import PltResultViewer
 from polystar.robots_at_robots.dependency_injection import make_injector
-from research.demos.utils import load_tf_model
-from research_common.dataset.dji.dji_roco_datasets import DJIROCODataset
-from research_common.dataset.split import Split
-from research_common.dataset.split_dataset import SplitDataset
-from research_common.dataset.twitch.twitch_roco_datasets import TwitchROCODataset
+from research.common.dataset.dji.dji_roco_datasets import DJIROCODataset
+from research.common.dataset.split import Split
+from research.common.dataset.split_dataset import SplitDataset
+from research.common.dataset.twitch.twitch_roco_datasets import TwitchROCODataset
+from research.robots_at_robots.demos.utils import load_tf_model
 
 if __name__ == "__main__":
     patch_tf_v2()
diff --git a/robots-at-robots/research/demos/demo_pipeline_camera.py b/robots-at-robots/research/robots_at_robots/demos/demo_pipeline_camera.py
similarity index 100%
rename from robots-at-robots/research/demos/demo_pipeline_camera.py
rename to robots-at-robots/research/robots_at_robots/demos/demo_pipeline_camera.py
diff --git a/robots-at-robots/research/demos/utils.py b/robots-at-robots/research/robots_at_robots/demos/utils.py
similarity index 100%
rename from robots-at-robots/research/demos/utils.py
rename to robots-at-robots/research/robots_at_robots/demos/utils.py
diff --git a/robots-at-runes/research/dataset/perturbations/perturbator.py b/robots-at-runes/research/dataset/perturbations/perturbator.py
deleted file mode 100644
index bccf8e2255db6829523c5bfd79cdd9689392d860..0000000000000000000000000000000000000000
--- a/robots-at-runes/research/dataset/perturbations/perturbator.py
+++ /dev/null
@@ -1,42 +0,0 @@
-from dataclasses import dataclass
-from pathlib import Path
-from random import shuffle
-from typing import Callable, List
-
-import cv2
-import matplotlib.pyplot as plt
-import numpy as np
-
-from polystar.common.models.image import Image
-from research.dataset.perturbations.perturbator_functions.contrast import contrast
-from research.dataset.perturbations.perturbator_functions.gaussian_blur import gaussian_blur
-from research.dataset.perturbations.perturbator_functions.gaussian_noise import gaussian_noise
-from research.dataset.perturbations.perturbator_functions.horizontal_blur import horizontal_blur
-
-
-@dataclass
-class ImagePerturbator:
-    perturbator_functions: List[Callable[[Image, float], Image]]
-
-    def perturbate(self, image: Image) -> Image:
-        shuffle(self.perturbator_functions)
-        intensities = self._generate_intensities()
-        for perturbator_function, intensity in zip(self.perturbator_functions, intensities):
-            image = perturbator_function(image, intensity)
-        return image
-
-    def _generate_intensities(self) -> List[float]:
-        intensities = np.random.random(len(self.perturbator_functions))
-        return intensities / intensities.sum()
-
-
-if __name__ == "__main__":
-    EXAMPLE_DIR = Path(__file__).parent / "examples"
-    rune_img = Image.from_path(EXAMPLE_DIR / "test.png")
-    perturbator = ImagePerturbator([contrast, gaussian_blur, gaussian_noise, horizontal_blur])
-    rune_perturbed = perturbator.perturbate(rune_img)
-    cv2.imwrite(str(EXAMPLE_DIR / "res_full_pipeline.png"), cv2.cvtColor(rune_perturbed, cv2.COLOR_RGB2BGR))
-    plt.axis("off")
-    plt.tight_layout()
-    plt.imshow(rune_perturbed)
-    plt.show()
diff --git a/robots-at-runes/research/dataset/perturbations/perturbator_functions/brightness.py b/robots-at-runes/research/dataset/perturbations/perturbator_functions/brightness.py
deleted file mode 100644
index ba69c2dcbe1ee4f5934deb1afc3a0b3ab4c659cc..0000000000000000000000000000000000000000
--- a/robots-at-runes/research/dataset/perturbations/perturbator_functions/brightness.py
+++ /dev/null
@@ -1,16 +0,0 @@
-import numpy as np
-
-from polystar.common.models.image import Image
-
-
-def brightness(image: Image, intensity: float) -> Image:
-    MAX_BETA = 10
-    beta = MAX_BETA * intensity
-    perturbed_image = np.clip((image.astype(np.uint16) + beta), 0, 255).astype(np.uint8)
-    return perturbed_image
-
-
-if __name__ == "__main__":
-    from research.dataset.perturbations.utils import simple_perturbator_test
-
-    simple_perturbator_test(brightness)
diff --git a/robots-at-runes/research/dataset/perturbations/perturbator_functions/contrast.py b/robots-at-runes/research/dataset/perturbations/perturbator_functions/contrast.py
deleted file mode 100644
index 0398a24b55ef82298596b8a7a007ae6cfd309646..0000000000000000000000000000000000000000
--- a/robots-at-runes/research/dataset/perturbations/perturbator_functions/contrast.py
+++ /dev/null
@@ -1,17 +0,0 @@
-import numpy as np
-
-from polystar.common.models.image import Image
-
-
-def contrast(image: Image, intensity: float) -> Image:
-    ALPHA_FACTOR = 0.7
-    MIN_ALPHA = 0.8
-    alpha = MIN_ALPHA + ALPHA_FACTOR * intensity
-    perturbed_image = np.clip((image.astype(np.uint16) * alpha), 0, 255).astype(np.uint8)
-    return perturbed_image
-
-
-if __name__ == "__main__":
-    from research.dataset.perturbations.utils import simple_perturbator_test
-
-    simple_perturbator_test(contrast)
diff --git a/robots-at-runes/research/dataset/perturbations/perturbator_functions/gaussian_blur.py b/robots-at-runes/research/dataset/perturbations/perturbator_functions/gaussian_blur.py
deleted file mode 100644
index eb1e46a9ffeac96fd546bf65bf3a4d246dc30cb4..0000000000000000000000000000000000000000
--- a/robots-at-runes/research/dataset/perturbations/perturbator_functions/gaussian_blur.py
+++ /dev/null
@@ -1,24 +0,0 @@
-import cv2
-
-from polystar.common.models.image import Image
-
-
-def to_odd_number(number):
-    return int(number // 2 * 2) - 1
-
-
-def gaussian_blur(image: Image, intensity: float) -> Image:
-    MAX_FACTOR = 0.015
-    blur_factor = intensity * MAX_FACTOR
-    width = image.shape[0]
-    height = image.shape[1]
-
-    x, y = to_odd_number(width * blur_factor), to_odd_number(height * blur_factor)
-    image = cv2.GaussianBlur(image, (x, y), cv2.BORDER_DEFAULT)
-    return image
-
-
-if __name__ == "__main__":
-    from research.dataset.perturbations.utils import simple_perturbator_test
-
-    simple_perturbator_test(gaussian_blur)
diff --git a/robots-at-runes/research/dataset/perturbations/perturbator_functions/gaussian_noise.py b/robots-at-runes/research/dataset/perturbations/perturbator_functions/gaussian_noise.py
deleted file mode 100644
index 2a287ccd4a083ac556a5e9706967348fd04ebc77..0000000000000000000000000000000000000000
--- a/robots-at-runes/research/dataset/perturbations/perturbator_functions/gaussian_noise.py
+++ /dev/null
@@ -1,20 +0,0 @@
-import numpy as np
-
-from polystar.common.models.image import Image
-
-
-def gaussian_noise(image: Image, intensity: float) -> Image:
-    MAX_VARIANCE = 300
-    mean = 0
-    variance = MAX_VARIANCE * intensity
-    sigma = variance ** 0.5
-    row, column, ch = image.shape
-    gaussian = np.random.normal(mean, sigma, (row, column, ch))
-    perturbed_image = np.clip((image.astype(np.uint16) + gaussian), 0, 255).astype(np.uint8)
-    return perturbed_image
-
-
-if __name__ == "__main__":
-    from research.dataset.perturbations.utils import simple_perturbator_test
-
-    simple_perturbator_test(gaussian_noise)
diff --git a/robots-at-runes/research/dataset/perturbations/perturbator_functions/horizontal_blur.py b/robots-at-runes/research/dataset/perturbations/perturbator_functions/horizontal_blur.py
deleted file mode 100644
index c62d32f3eee057f354168217a96ce707c241441e..0000000000000000000000000000000000000000
--- a/robots-at-runes/research/dataset/perturbations/perturbator_functions/horizontal_blur.py
+++ /dev/null
@@ -1,24 +0,0 @@
-import cv2
-import numpy as np
-
-from polystar.common.models.image import Image
-
-
-def horizontal_blur(image: Image, intensity: float) -> Image:
-    MAX_KERNEL_SIZE = 11
-    kernel_size = int(MAX_KERNEL_SIZE * intensity) + 1
-    # Fill kernel with zeros
-    kernel_horizontal = np.zeros((kernel_size, kernel_size))
-    # Fill middle row with ones
-    kernel_horizontal[int(abs(kernel_size - 1) / 2), :] = np.ones(kernel_size)
-
-    # Normalize
-    kernel_horizontal /= kernel_size
-
-    return cv2.filter2D(image, -1, kernel_horizontal)
-
-
-if __name__ == "__main__":
-    from research.dataset.perturbations.utils import simple_perturbator_test
-
-    simple_perturbator_test(horizontal_blur)
diff --git a/robots-at-runes/research/dataset/perturbations/perturbator_functions/saturation.py b/robots-at-runes/research/dataset/perturbations/perturbator_functions/saturation.py
deleted file mode 100644
index 188b78a7998574f1f556dbc48eb67f7071f619c5..0000000000000000000000000000000000000000
--- a/robots-at-runes/research/dataset/perturbations/perturbator_functions/saturation.py
+++ /dev/null
@@ -1,21 +0,0 @@
-import numpy as np
-import cv2
-
-from polystar.common.models.image import Image
-
-
-def saturation(image: Image, intensity: float) -> Image:
-    MAX_SATURATION = 0.6
-    saturation_factor = 1 + MAX_SATURATION * intensity
-    image_hsv = cv2.cvtColor(image, cv2.COLOR_RGB2HSV)
-    (h, s, v) = cv2.split(image_hsv)
-    new_s = np.clip((s.astype(np.uint16) * saturation_factor), 0, 255).astype(np.uint8)
-    new_image_hsv = cv2.merge([h, new_s, v])
-    image_rgb = cv2.cvtColor(new_image_hsv, cv2.COLOR_HSV2RGB).astype(np.uint8)
-    return image_rgb
-
-
-if __name__ == "__main__":
-    from research.dataset.perturbations.utils import simple_perturbator_test
-
-    simple_perturbator_test(saturation)
diff --git a/robots-at-runes/research/robots_at_runes/__init__.py b/robots-at-runes/research/robots_at_runes/__init__.py
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/robots-at-runes/research/constants.py b/robots-at-runes/research/robots_at_runes/constants.py
similarity index 72%
rename from robots-at-runes/research/constants.py
rename to robots-at-runes/research/robots_at_runes/constants.py
index 8379bc8539c9a7fd786739991c4ebeb313dd1744..17ddaf2c02ed8f9123aa4661fdf8fcf7d2adfd60 100644
--- a/robots-at-runes/research/constants.py
+++ b/robots-at-runes/research/robots_at_runes/constants.py
@@ -1,6 +1,6 @@
 from pathlib import Path
 
-from research_common.constants import DSET_DIR
+from research.common.constants import DSET_DIR
 
 RUNES_DATASET_DIR: Path = DSET_DIR / "runes"
 
diff --git a/robots-at-runes/research/robots_at_runes/dataset/__init__.py b/robots-at-runes/research/robots_at_runes/dataset/__init__.py
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/robots-at-runes/research/robots_at_runes/dataset/blend/__init__.py b/robots-at-runes/research/robots_at_runes/dataset/blend/__init__.py
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/robots-at-runes/research/dataset/blend/examples/.gitignore b/robots-at-runes/research/robots_at_runes/dataset/blend/examples/.gitignore
similarity index 100%
rename from robots-at-runes/research/dataset/blend/examples/.gitignore
rename to robots-at-runes/research/robots_at_runes/dataset/blend/examples/.gitignore
diff --git a/robots-at-runes/research/dataset/blend/examples/back1.jpg b/robots-at-runes/research/robots_at_runes/dataset/blend/examples/back1.jpg
similarity index 100%
rename from robots-at-runes/research/dataset/blend/examples/back1.jpg
rename to robots-at-runes/research/robots_at_runes/dataset/blend/examples/back1.jpg
diff --git a/robots-at-runes/research/dataset/blend/examples/logo.png b/robots-at-runes/research/robots_at_runes/dataset/blend/examples/logo.png
similarity index 100%
rename from robots-at-runes/research/dataset/blend/examples/logo.png
rename to robots-at-runes/research/robots_at_runes/dataset/blend/examples/logo.png
diff --git a/robots-at-runes/research/dataset/blend/examples/logo.xml b/robots-at-runes/research/robots_at_runes/dataset/blend/examples/logo.xml
similarity index 100%
rename from robots-at-runes/research/dataset/blend/examples/logo.xml
rename to robots-at-runes/research/robots_at_runes/dataset/blend/examples/logo.xml
diff --git a/robots-at-runes/research/dataset/blend/image_blender.py b/robots-at-runes/research/robots_at_runes/dataset/blend/image_blender.py
similarity index 88%
rename from robots-at-runes/research/dataset/blend/image_blender.py
rename to robots-at-runes/research/robots_at_runes/dataset/blend/image_blender.py
index c19202e3d159e3298ede9df9695cf388a5f20c7f..976aba5d9e9ebf178655cc3f69b3a3184f554fc0 100644
--- a/robots-at-runes/research/dataset/blend/image_blender.py
+++ b/robots-at-runes/research/robots_at_runes/dataset/blend/image_blender.py
@@ -6,8 +6,9 @@ import cv2
 import numpy as np
 
 from polystar.common.models.image import Image
-from research.dataset.blend.labeled_image_modifiers.labeled_image_modifier_abc import LabeledImageModifierABC
-from research.dataset.labeled_image import LabeledImage, PointOfInterest
+from research.robots_at_runes.dataset.blend.labeled_image_modifiers.labeled_image_modifier_abc import \
+    LabeledImageModifierABC
+from research.robots_at_runes.dataset.labeled_image import LabeledImage, PointOfInterest
 
 
 @dataclass
@@ -69,8 +70,8 @@ if __name__ == "__main__":
 
     import matplotlib.pyplot as plt
 
-    from research.dataset.blend.labeled_image_modifiers.labeled_image_rotator import LabeledImageRotator
-    from research.dataset.blend.labeled_image_modifiers.labeled_image_scaler import LabeledImageScaler
+    from research.robots_at_runes.dataset.blend.labeled_image_modifiers.labeled_image_rotator import LabeledImageRotator
+    from research.robots_at_runes.dataset.blend.labeled_image_modifiers.labeled_image_scaler import LabeledImageScaler
 
     EXAMPLES_DIR = Path(__file__).parent / "examples"
 
diff --git a/robots-at-runes/research/robots_at_runes/dataset/blend/labeled_image_modifiers/__init__.py b/robots-at-runes/research/robots_at_runes/dataset/blend/labeled_image_modifiers/__init__.py
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/robots-at-runes/research/dataset/blend/labeled_image_modifiers/labeled_image_modifier_abc.py b/robots-at-runes/research/robots_at_runes/dataset/blend/labeled_image_modifiers/labeled_image_modifier_abc.py
similarity index 94%
rename from robots-at-runes/research/dataset/blend/labeled_image_modifiers/labeled_image_modifier_abc.py
rename to robots-at-runes/research/robots_at_runes/dataset/blend/labeled_image_modifiers/labeled_image_modifier_abc.py
index e3ab2e7f4c7bd4bec333f24a3267e48b02b639c6..cf6f90b958abc9e2bdcaefb1a513addf4f2478e1 100644
--- a/robots-at-runes/research/dataset/blend/labeled_image_modifiers/labeled_image_modifier_abc.py
+++ b/robots-at-runes/research/robots_at_runes/dataset/blend/labeled_image_modifiers/labeled_image_modifier_abc.py
@@ -2,7 +2,7 @@ from abc import ABC, abstractmethod
 from random import random
 
 from polystar.common.models.image import Image
-from research.dataset.labeled_image import LabeledImage, PointOfInterest
+from research.robots_at_runes.dataset.labeled_image import LabeledImage, PointOfInterest
 
 
 class LabeledImageModifierABC(ABC):
diff --git a/robots-at-runes/research/dataset/blend/labeled_image_modifiers/labeled_image_rotator.py b/robots-at-runes/research/robots_at_runes/dataset/blend/labeled_image_modifiers/labeled_image_rotator.py
similarity index 85%
rename from robots-at-runes/research/dataset/blend/labeled_image_modifiers/labeled_image_rotator.py
rename to robots-at-runes/research/robots_at_runes/dataset/blend/labeled_image_modifiers/labeled_image_rotator.py
index 860972cbf0cc10519f982ef1a799c342bfc43361..6e241c20957c08f66f9d01de926d6b34824c070f 100644
--- a/robots-at-runes/research/dataset/blend/labeled_image_modifiers/labeled_image_rotator.py
+++ b/robots-at-runes/research/robots_at_runes/dataset/blend/labeled_image_modifiers/labeled_image_rotator.py
@@ -1,12 +1,12 @@
 from dataclasses import dataclass
 
-import cv2
 import numpy as np
-from imutils import rotate_bound
 
+from imutils import rotate_bound
 from polystar.common.models.image import Image
-from research.dataset.blend.labeled_image_modifiers.labeled_image_modifier_abc import LabeledImageModifierABC
-from research.dataset.labeled_image import PointOfInterest
+from research.robots_at_runes.dataset.blend.labeled_image_modifiers.labeled_image_modifier_abc import \
+    LabeledImageModifierABC
+from research.robots_at_runes.dataset.labeled_image import PointOfInterest
 
 
 @dataclass
diff --git a/robots-at-runes/research/dataset/blend/labeled_image_modifiers/labeled_image_scaler.py b/robots-at-runes/research/robots_at_runes/dataset/blend/labeled_image_modifiers/labeled_image_scaler.py
similarity index 80%
rename from robots-at-runes/research/dataset/blend/labeled_image_modifiers/labeled_image_scaler.py
rename to robots-at-runes/research/robots_at_runes/dataset/blend/labeled_image_modifiers/labeled_image_scaler.py
index b98e25f4fa1a32e4197984864fe887dd7690b024..a7dacd8e246e6e92c88c1b81495d3f965c82300b 100644
--- a/robots-at-runes/research/dataset/blend/labeled_image_modifiers/labeled_image_scaler.py
+++ b/robots-at-runes/research/robots_at_runes/dataset/blend/labeled_image_modifiers/labeled_image_scaler.py
@@ -3,8 +3,9 @@ from dataclasses import dataclass
 import cv2
 
 from polystar.common.models.image import Image
-from research.dataset.blend.labeled_image_modifiers.labeled_image_modifier_abc import LabeledImageModifierABC
-from research.dataset.labeled_image import LabeledImage, PointOfInterest
+from research.robots_at_runes.dataset.blend.labeled_image_modifiers.labeled_image_modifier_abc import \
+    LabeledImageModifierABC
+from research.robots_at_runes.dataset.labeled_image import PointOfInterest
 
 
 @dataclass
diff --git a/robots-at-runes/research/dataset/dataset_generator.py b/robots-at-runes/research/robots_at_runes/dataset/dataset_generator.py
similarity index 53%
rename from robots-at-runes/research/dataset/dataset_generator.py
rename to robots-at-runes/research/robots_at_runes/dataset/dataset_generator.py
index f63844793d2576fc5431fc3be5c5374a08614b7f..d5a871c2436e5fe02b9085769b9a765fce95104f 100644
--- a/robots-at-runes/research/dataset/dataset_generator.py
+++ b/robots-at-runes/research/robots_at_runes/dataset/dataset_generator.py
@@ -5,16 +5,18 @@ import cv2
 from tqdm import trange
 
 from polystar.common.models.image import load_images_in_directory
-from research.constants import RUNES_DATASET_DIR
-from research.dataset.blend.image_blender import ImageBlender
-from research.dataset.blend.labeled_image_modifiers.labeled_image_rotator import LabeledImageRotator
-from research.dataset.blend.labeled_image_modifiers.labeled_image_scaler import LabeledImageScaler
-from research.dataset.labeled_image import load_labeled_images_in_directory
-from research.dataset.perturbations.perturbator import ImagePerturbator
-from research.dataset.perturbations.perturbator_functions.contrast import contrast
-from research.dataset.perturbations.perturbator_functions.gaussian_blur import gaussian_blur
-from research.dataset.perturbations.perturbator_functions.gaussian_noise import gaussian_noise
-from research.dataset.perturbations.perturbator_functions.horizontal_blur import horizontal_blur
+from research.common.dataset.perturbations.image_modifiers.brightness import BrightnessModifier
+from research.common.dataset.perturbations.image_modifiers.contrast import ContrastModifier
+from research.common.dataset.perturbations.image_modifiers.gaussian_blur import GaussianBlurrer
+from research.common.dataset.perturbations.image_modifiers.gaussian_noise import GaussianNoiser
+from research.common.dataset.perturbations.image_modifiers.horizontal_blur import HorizontalBlurrer
+from research.common.dataset.perturbations.image_modifiers.saturation import SaturationModifier
+from research.common.dataset.perturbations.perturbator import ImagePerturbator
+from research.robots_at_runes.constants import RUNES_DATASET_DIR
+from research.robots_at_runes.dataset.blend.image_blender import ImageBlender
+from research.robots_at_runes.dataset.blend.labeled_image_modifiers.labeled_image_rotator import LabeledImageRotator
+from research.robots_at_runes.dataset.blend.labeled_image_modifiers.labeled_image_scaler import LabeledImageScaler
+from research.robots_at_runes.dataset.labeled_image import load_labeled_images_in_directory
 
 
 class DatasetGenerator:
@@ -50,7 +52,16 @@ if __name__ == "__main__":
         ImageBlender(
             background_size=(1_280, 720), object_modifiers=[LabeledImageScaler(1.5), LabeledImageRotator(180)]
         ),
-        ImagePerturbator([contrast, gaussian_blur, gaussian_noise, horizontal_blur]),
+        ImagePerturbator(
+            [
+                ContrastModifier(min_coef=0.7, max_coef=1.5),
+                GaussianBlurrer(max_factor=0.015),
+                GaussianNoiser(max_variance=300.0),
+                HorizontalBlurrer(max_kernel_size=11),
+                SaturationModifier(max_saturation=0.6),
+                BrightnessModifier(max_offset=10.0),
+            ]
+        ),
         RUNES_DATASET_DIR / "resources" / "objects",
         RUNES_DATASET_DIR / "resources" / "backgrounds",
     )
diff --git a/robots-at-runes/research/dataset/labeled_image.py b/robots-at-runes/research/robots_at_runes/dataset/labeled_image.py
similarity index 100%
rename from robots-at-runes/research/dataset/labeled_image.py
rename to robots-at-runes/research/robots_at_runes/dataset/labeled_image.py