vkit.mechanism.distortion.geometric.grid_rendering.interface
1# Copyright 2022 vkit-x Administrator. All Rights Reserved. 2# 3# This project (vkit-x/vkit) is dual-licensed under commercial and SSPL licenses. 4# 5# The commercial license gives you the full rights to create and distribute software 6# on your own terms without any SSPL license obligations. For more information, 7# please see the "LICENSE_COMMERCIAL.txt" file. 8# 9# This project is also available under Server Side Public License (SSPL). 10# The SSPL licensing is ideal for use cases such as open source projects with 11# SSPL distribution, student/academic purposes, hobby projects, internal research 12# projects without external distribution, or other projects where all SSPL 13# obligations can be met. For more information, please see the "LICENSE_SSPL.txt" file. 14from typing import ( 15 Generic, 16 Type, 17 TypeVar, 18 Tuple, 19 Optional, 20) 21 22import numpy as np 23from numpy.random import Generator as RandomGenerator 24 25from vkit.element import ( 26 Image, 27 Point, 28 Mask, 29 ScoreMap, 30) 31from ...interface import ( 32 DistortionConfig, 33 DistortionState, 34 Distortion, 35) 36from .type import ImageGrid 37from .point_projector import PointProjector 38from .grid_creator import create_dst_image_grid_and_shift_amounts_and_resize_ratios 39from .grid_blender import ( 40 blend_src_to_dst_image, 41 blend_src_to_dst_score_map, 42 blend_src_to_dst_mask, 43) 44 45_T_CONFIG = TypeVar('_T_CONFIG', bound=DistortionConfig) 46 47 48class DistortionStateImageGridBased(DistortionState[_T_CONFIG]): 49 50 @property 51 def shift_amount_y(self): 52 return self._shift_amount_y 53 54 @shift_amount_y.setter 55 def shift_amount_y(self, val: float): 56 self._shift_amount_y = val 57 58 @property 59 def shift_amount_x(self): 60 return self._shift_amount_x 61 62 @shift_amount_x.setter 63 def shift_amount_x(self, val: float): 64 self._shift_amount_x = val 65 66 @property 67 def resize_ratio_y(self): 68 return self._resize_ratio_y 69 70 @resize_ratio_y.setter 71 def resize_ratio_y(self, val: float): 72 self._resize_ratio_y = val 73 74 @property 75 def resize_ratio_x(self): 76 return self._resize_ratio_x 77 78 @resize_ratio_x.setter 79 def resize_ratio_x(self, val: float): 80 self._resize_ratio_x = val 81 82 @property 83 def src_image_grid(self): 84 return self._src_image_grid 85 86 @src_image_grid.setter 87 def src_image_grid(self, val: ImageGrid): 88 self._src_image_grid = val 89 90 @property 91 def dst_image_grid(self): 92 return self._dst_image_grid 93 94 @dst_image_grid.setter 95 def dst_image_grid(self, val: ImageGrid): 96 self._dst_image_grid = val 97 98 def initialize_image_grid_based( 99 self, 100 src_image_grid: ImageGrid, 101 point_projector: PointProjector, 102 resize_as_src: bool = False, 103 ): 104 self.src_image_grid = src_image_grid 105 106 ( 107 self.dst_image_grid, 108 (self.shift_amount_y, self.shift_amount_x), 109 (self.resize_ratio_y, self.resize_ratio_x), 110 ) = create_dst_image_grid_and_shift_amounts_and_resize_ratios( 111 self.src_image_grid, 112 point_projector, 113 resize_as_src=resize_as_src, 114 ) 115 116 def shift_and_resize_point(self, point: Point): 117 return Point.create( 118 y=(point.smooth_y - self.shift_amount_y) * self.resize_ratio_y, 119 x=(point.smooth_x - self.shift_amount_x) * self.resize_ratio_x, 120 ) 121 122 @property 123 def result_shape(self): 124 return (self.dst_image_grid.image_height, self.dst_image_grid.image_width) 125 126 127_T_STATE = TypeVar('_T_STATE', bound=DistortionStateImageGridBased) 128 129 130class FuncImageGridBased(Generic[_T_CONFIG, _T_STATE]): 131 132 @classmethod 133 def func_image( 134 cls, 135 config: _T_CONFIG, 136 state: Optional[_T_STATE], 137 image: Image, 138 rng: Optional[RandomGenerator], 139 ): 140 assert state 141 return blend_src_to_dst_image( 142 image, 143 state.src_image_grid, 144 state.dst_image_grid, 145 ) 146 147 @classmethod 148 def func_score_map( 149 cls, 150 config: _T_CONFIG, 151 state: Optional[_T_STATE], 152 score_map: ScoreMap, 153 rng: Optional[RandomGenerator], 154 ): 155 assert state 156 return blend_src_to_dst_score_map( 157 score_map, 158 state.src_image_grid, 159 state.dst_image_grid, 160 ) 161 162 @classmethod 163 def func_mask( 164 cls, 165 config: _T_CONFIG, 166 state: Optional[_T_STATE], 167 mask: Mask, 168 rng: Optional[RandomGenerator], 169 ): 170 assert state 171 return blend_src_to_dst_mask( 172 mask, 173 state.src_image_grid, 174 state.dst_image_grid, 175 ) 176 177 @classmethod 178 def func_active_mask( 179 cls, 180 config: _T_CONFIG, 181 state: Optional[_T_STATE], 182 shape: Tuple[int, int], 183 rng: Optional[RandomGenerator], 184 ): 185 assert state 186 border_polygon = state.dst_image_grid.generate_border_polygon() 187 active_mask = Mask.from_shape(( 188 state.dst_image_grid.image_height, 189 state.dst_image_grid.image_width, 190 )) 191 border_polygon.fill_mask(active_mask) 192 return active_mask 193 194 @classmethod 195 def func_point( 196 cls, 197 config: _T_CONFIG, 198 state: Optional[_T_STATE], 199 shape: Tuple[int, int], 200 point: Point, 201 rng: Optional[RandomGenerator], 202 ): 203 assert state 204 src_image_grid = state.src_image_grid 205 dst_image_grid = state.dst_image_grid 206 207 assert src_image_grid.grid_size 208 polygon_row = point.y // src_image_grid.grid_size 209 polygon_col = point.x // src_image_grid.grid_size 210 211 trans_mat = src_image_grid.get_trans_mat(polygon_row, polygon_col, dst_image_grid) 212 dst_tx, dst_ty, dst_t = np.matmul(trans_mat, (point.smooth_x, point.smooth_y, 1.0)) 213 return Point.create( 214 y=float(dst_ty / dst_t), 215 x=float(dst_tx / dst_t), 216 ) 217 218 219class DistortionImageGridBased(Distortion[_T_CONFIG, _T_STATE]): 220 221 def __init__( 222 self, 223 config_cls: Type[_T_CONFIG], 224 state_cls: Type[_T_STATE], 225 ): 226 func_cls = FuncImageGridBased[_T_CONFIG, _T_STATE] 227 super().__init__( 228 config_cls=config_cls, 229 state_cls=state_cls, 230 func_image=func_cls.func_image, 231 func_mask=func_cls.func_mask, 232 func_score_map=func_cls.func_score_map, 233 func_active_mask=func_cls.func_active_mask, 234 func_point=func_cls.func_point, 235 )
49class DistortionStateImageGridBased(DistortionState[_T_CONFIG]): 50 51 @property 52 def shift_amount_y(self): 53 return self._shift_amount_y 54 55 @shift_amount_y.setter 56 def shift_amount_y(self, val: float): 57 self._shift_amount_y = val 58 59 @property 60 def shift_amount_x(self): 61 return self._shift_amount_x 62 63 @shift_amount_x.setter 64 def shift_amount_x(self, val: float): 65 self._shift_amount_x = val 66 67 @property 68 def resize_ratio_y(self): 69 return self._resize_ratio_y 70 71 @resize_ratio_y.setter 72 def resize_ratio_y(self, val: float): 73 self._resize_ratio_y = val 74 75 @property 76 def resize_ratio_x(self): 77 return self._resize_ratio_x 78 79 @resize_ratio_x.setter 80 def resize_ratio_x(self, val: float): 81 self._resize_ratio_x = val 82 83 @property 84 def src_image_grid(self): 85 return self._src_image_grid 86 87 @src_image_grid.setter 88 def src_image_grid(self, val: ImageGrid): 89 self._src_image_grid = val 90 91 @property 92 def dst_image_grid(self): 93 return self._dst_image_grid 94 95 @dst_image_grid.setter 96 def dst_image_grid(self, val: ImageGrid): 97 self._dst_image_grid = val 98 99 def initialize_image_grid_based( 100 self, 101 src_image_grid: ImageGrid, 102 point_projector: PointProjector, 103 resize_as_src: bool = False, 104 ): 105 self.src_image_grid = src_image_grid 106 107 ( 108 self.dst_image_grid, 109 (self.shift_amount_y, self.shift_amount_x), 110 (self.resize_ratio_y, self.resize_ratio_x), 111 ) = create_dst_image_grid_and_shift_amounts_and_resize_ratios( 112 self.src_image_grid, 113 point_projector, 114 resize_as_src=resize_as_src, 115 ) 116 117 def shift_and_resize_point(self, point: Point): 118 return Point.create( 119 y=(point.smooth_y - self.shift_amount_y) * self.resize_ratio_y, 120 x=(point.smooth_x - self.shift_amount_x) * self.resize_ratio_x, 121 ) 122 123 @property 124 def result_shape(self): 125 return (self.dst_image_grid.image_height, self.dst_image_grid.image_width)
Abstract base class for generic types.
A generic type is typically declared by inheriting from this class parameterized with one or more type variables. For example, a generic mapping type might be defined as::
class Mapping(Generic[KT, VT]): def __getitem__(self, key: KT) -> VT: ... # Etc.
This class can then be used as follows::
def lookup_name(mapping: Mapping[KT, VT], key: KT, default: VT) -> VT: try: return mapping[key] except KeyError: return default
99 def initialize_image_grid_based( 100 self, 101 src_image_grid: ImageGrid, 102 point_projector: PointProjector, 103 resize_as_src: bool = False, 104 ): 105 self.src_image_grid = src_image_grid 106 107 ( 108 self.dst_image_grid, 109 (self.shift_amount_y, self.shift_amount_x), 110 (self.resize_ratio_y, self.resize_ratio_x), 111 ) = create_dst_image_grid_and_shift_amounts_and_resize_ratios( 112 self.src_image_grid, 113 point_projector, 114 resize_as_src=resize_as_src, 115 )
Inherited Members
131class FuncImageGridBased(Generic[_T_CONFIG, _T_STATE]): 132 133 @classmethod 134 def func_image( 135 cls, 136 config: _T_CONFIG, 137 state: Optional[_T_STATE], 138 image: Image, 139 rng: Optional[RandomGenerator], 140 ): 141 assert state 142 return blend_src_to_dst_image( 143 image, 144 state.src_image_grid, 145 state.dst_image_grid, 146 ) 147 148 @classmethod 149 def func_score_map( 150 cls, 151 config: _T_CONFIG, 152 state: Optional[_T_STATE], 153 score_map: ScoreMap, 154 rng: Optional[RandomGenerator], 155 ): 156 assert state 157 return blend_src_to_dst_score_map( 158 score_map, 159 state.src_image_grid, 160 state.dst_image_grid, 161 ) 162 163 @classmethod 164 def func_mask( 165 cls, 166 config: _T_CONFIG, 167 state: Optional[_T_STATE], 168 mask: Mask, 169 rng: Optional[RandomGenerator], 170 ): 171 assert state 172 return blend_src_to_dst_mask( 173 mask, 174 state.src_image_grid, 175 state.dst_image_grid, 176 ) 177 178 @classmethod 179 def func_active_mask( 180 cls, 181 config: _T_CONFIG, 182 state: Optional[_T_STATE], 183 shape: Tuple[int, int], 184 rng: Optional[RandomGenerator], 185 ): 186 assert state 187 border_polygon = state.dst_image_grid.generate_border_polygon() 188 active_mask = Mask.from_shape(( 189 state.dst_image_grid.image_height, 190 state.dst_image_grid.image_width, 191 )) 192 border_polygon.fill_mask(active_mask) 193 return active_mask 194 195 @classmethod 196 def func_point( 197 cls, 198 config: _T_CONFIG, 199 state: Optional[_T_STATE], 200 shape: Tuple[int, int], 201 point: Point, 202 rng: Optional[RandomGenerator], 203 ): 204 assert state 205 src_image_grid = state.src_image_grid 206 dst_image_grid = state.dst_image_grid 207 208 assert src_image_grid.grid_size 209 polygon_row = point.y // src_image_grid.grid_size 210 polygon_col = point.x // src_image_grid.grid_size 211 212 trans_mat = src_image_grid.get_trans_mat(polygon_row, polygon_col, dst_image_grid) 213 dst_tx, dst_ty, dst_t = np.matmul(trans_mat, (point.smooth_x, point.smooth_y, 1.0)) 214 return Point.create( 215 y=float(dst_ty / dst_t), 216 x=float(dst_tx / dst_t), 217 )
Abstract base class for generic types.
A generic type is typically declared by inheriting from this class parameterized with one or more type variables. For example, a generic mapping type might be defined as::
class Mapping(Generic[KT, VT]): def __getitem__(self, key: KT) -> VT: ... # Etc.
This class can then be used as follows::
def lookup_name(mapping: Mapping[KT, VT], key: KT, default: VT) -> VT: try: return mapping[key] except KeyError: return default
148 @classmethod 149 def func_score_map( 150 cls, 151 config: _T_CONFIG, 152 state: Optional[_T_STATE], 153 score_map: ScoreMap, 154 rng: Optional[RandomGenerator], 155 ): 156 assert state 157 return blend_src_to_dst_score_map( 158 score_map, 159 state.src_image_grid, 160 state.dst_image_grid, 161 )
178 @classmethod 179 def func_active_mask( 180 cls, 181 config: _T_CONFIG, 182 state: Optional[_T_STATE], 183 shape: Tuple[int, int], 184 rng: Optional[RandomGenerator], 185 ): 186 assert state 187 border_polygon = state.dst_image_grid.generate_border_polygon() 188 active_mask = Mask.from_shape(( 189 state.dst_image_grid.image_height, 190 state.dst_image_grid.image_width, 191 )) 192 border_polygon.fill_mask(active_mask) 193 return active_mask
195 @classmethod 196 def func_point( 197 cls, 198 config: _T_CONFIG, 199 state: Optional[_T_STATE], 200 shape: Tuple[int, int], 201 point: Point, 202 rng: Optional[RandomGenerator], 203 ): 204 assert state 205 src_image_grid = state.src_image_grid 206 dst_image_grid = state.dst_image_grid 207 208 assert src_image_grid.grid_size 209 polygon_row = point.y // src_image_grid.grid_size 210 polygon_col = point.x // src_image_grid.grid_size 211 212 trans_mat = src_image_grid.get_trans_mat(polygon_row, polygon_col, dst_image_grid) 213 dst_tx, dst_ty, dst_t = np.matmul(trans_mat, (point.smooth_x, point.smooth_y, 1.0)) 214 return Point.create( 215 y=float(dst_ty / dst_t), 216 x=float(dst_tx / dst_t), 217 )
220class DistortionImageGridBased(Distortion[_T_CONFIG, _T_STATE]): 221 222 def __init__( 223 self, 224 config_cls: Type[_T_CONFIG], 225 state_cls: Type[_T_STATE], 226 ): 227 func_cls = FuncImageGridBased[_T_CONFIG, _T_STATE] 228 super().__init__( 229 config_cls=config_cls, 230 state_cls=state_cls, 231 func_image=func_cls.func_image, 232 func_mask=func_cls.func_mask, 233 func_score_map=func_cls.func_score_map, 234 func_active_mask=func_cls.func_active_mask, 235 func_point=func_cls.func_point, 236 )
Abstract base class for generic types.
A generic type is typically declared by inheriting from this class parameterized with one or more type variables. For example, a generic mapping type might be defined as::
class Mapping(Generic[KT, VT]): def __getitem__(self, key: KT) -> VT: ... # Etc.
This class can then be used as follows::
def lookup_name(mapping: Mapping[KT, VT], key: KT, default: VT) -> VT: try: return mapping[key] except KeyError: return default
222 def __init__( 223 self, 224 config_cls: Type[_T_CONFIG], 225 state_cls: Type[_T_STATE], 226 ): 227 func_cls = FuncImageGridBased[_T_CONFIG, _T_STATE] 228 super().__init__( 229 config_cls=config_cls, 230 state_cls=state_cls, 231 func_image=func_cls.func_image, 232 func_mask=func_cls.func_mask, 233 func_score_map=func_cls.func_score_map, 234 func_active_mask=func_cls.func_active_mask, 235 func_point=func_cls.func_point, 236 )
Inherited Members
- vkit.mechanism.distortion.interface.Distortion
- prepare_config_and_rng
- get_shape_from_shapable_or_shape
- prepare_internals
- generate_config_and_state
- generate_config
- generate_state
- distort_image_based_on_internals
- distort_image
- distort_score_map_based_on_internals
- distort_score_map
- distort_mask_based_on_internals
- distort_mask
- get_active_mask_based_on_internals
- get_active_mask
- distort_point_based_on_internals
- distort_point
- distort_points_based_on_internals
- distort_points
- distort_polygon_based_on_internals
- distort_polygon
- distort_polygons_based_on_internals
- distort_polygons
- get_shape
- clip_result_elements
- distort