valetudo-map-parser 0.1.9b8__py3-none-any.whl → 0.1.9b10__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- valetudo_map_parser/config/types.py +0 -1
- valetudo_map_parser/config/utils.py +175 -103
- valetudo_map_parser/hypfer_draw.py +4 -5
- valetudo_map_parser/hypfer_handler.py +3 -18
- valetudo_map_parser/map_data.py +14 -14
- valetudo_map_parser/rand25_handler.py +11 -26
- {valetudo_map_parser-0.1.9b8.dist-info → valetudo_map_parser-0.1.9b10.dist-info}/METADATA +1 -1
- valetudo_map_parser-0.1.9b10.dist-info/RECORD +20 -0
- valetudo_map_parser-0.1.9b8.dist-info/RECORD +0 -20
- {valetudo_map_parser-0.1.9b8.dist-info → valetudo_map_parser-0.1.9b10.dist-info}/LICENSE +0 -0
- {valetudo_map_parser-0.1.9b8.dist-info → valetudo_map_parser-0.1.9b10.dist-info}/NOTICE.txt +0 -0
- {valetudo_map_parser-0.1.9b8.dist-info → valetudo_map_parser-0.1.9b10.dist-info}/WHEEL +0 -0
@@ -1,16 +1,43 @@
|
|
1
1
|
"""Utility code for the valetudo map parser."""
|
2
2
|
|
3
|
+
from dataclasses import dataclass
|
4
|
+
from functools import partial
|
3
5
|
import hashlib
|
4
6
|
import json
|
5
7
|
from logging import getLogger
|
6
8
|
|
7
|
-
from PIL import ImageOps
|
9
|
+
from PIL import ImageOps, Image
|
8
10
|
|
9
11
|
from .types import ChargerPosition, ImageSize, NumpyArray, RobotPosition
|
12
|
+
from .shared import CameraShared
|
10
13
|
|
11
14
|
_LOGGER = getLogger(__name__)
|
12
15
|
|
13
16
|
|
17
|
+
@dataclass
|
18
|
+
class ResizeParams:
|
19
|
+
"""Resize the image to the given dimensions and aspect ratio."""
|
20
|
+
|
21
|
+
pil_img: Image # PIL image object
|
22
|
+
width: int
|
23
|
+
height: int
|
24
|
+
aspect_ratio: str = None
|
25
|
+
crop_size: list = None
|
26
|
+
is_rand: bool = False
|
27
|
+
offset_func: callable = None # Function reference for offset calculation
|
28
|
+
|
29
|
+
|
30
|
+
@dataclass
|
31
|
+
class OffsetParams:
|
32
|
+
"""Map parameters."""
|
33
|
+
|
34
|
+
wsf: int
|
35
|
+
hsf: int
|
36
|
+
width: int
|
37
|
+
height: int
|
38
|
+
rand256: bool = False
|
39
|
+
|
40
|
+
|
14
41
|
class BaseHandler:
|
15
42
|
"""Avoid Code duplication"""
|
16
43
|
|
@@ -30,8 +57,16 @@ class BaseHandler:
|
|
30
57
|
self.crop_img_size = [0, 0]
|
31
58
|
self.offset_x = 0
|
32
59
|
self.offset_y = 0
|
33
|
-
self.shared =
|
60
|
+
self.shared = CameraShared(self.file_name)
|
34
61
|
self.crop_area = [0, 0, 0, 0]
|
62
|
+
self.zooming = False
|
63
|
+
self.async_resize_image = partial(
|
64
|
+
async_resize_image,
|
65
|
+
width=self.shared.image_ref_width,
|
66
|
+
height=self.shared.image_ref_height,
|
67
|
+
crop_size=self.crop_img_size,
|
68
|
+
offset_func=self.async_map_coordinates_offset,
|
69
|
+
)
|
35
70
|
|
36
71
|
def get_frame_number(self) -> int:
|
37
72
|
"""Return the frame number of the image."""
|
@@ -53,88 +88,18 @@ class BaseHandler:
|
|
53
88
|
"""Return the JSON ID from the image."""
|
54
89
|
return self.json_id
|
55
90
|
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
if width / height > new_aspect_ratio:
|
66
|
-
new_width = int(pil_img.height * new_aspect_ratio)
|
67
|
-
new_height = pil_img.height
|
68
|
-
else:
|
69
|
-
new_width = pil_img.width
|
70
|
-
new_height = int(pil_img.width / new_aspect_ratio)
|
71
|
-
_LOGGER.debug(
|
72
|
-
"%s: Image Aspect Ratio: %s, %s",
|
73
|
-
self.file_name,
|
74
|
-
str(wsf),
|
75
|
-
str(hsf),
|
76
|
-
)
|
77
|
-
(
|
78
|
-
self.crop_img_size[0],
|
79
|
-
self.crop_img_size[1],
|
80
|
-
) = await self.async_map_coordinates_offset(
|
81
|
-
wsf, hsf, new_width, new_height, is_rand
|
82
|
-
)
|
83
|
-
return ImageOps.pad(pil_img, (new_width, new_height))
|
84
|
-
return ImageOps.pad(pil_img, (width, height))
|
85
|
-
|
86
|
-
async def async_map_coordinates_offset(
|
87
|
-
self, wsf: int, hsf: int, width: int, height: int, rand256: bool = False
|
88
|
-
) -> tuple[int, int]:
|
89
|
-
"""
|
90
|
-
Offset the coordinates to the map.
|
91
|
-
"""
|
92
|
-
|
93
|
-
if wsf == 1 and hsf == 1:
|
94
|
-
self.set_image_offset_ratio_1_1(width, height, rand256)
|
95
|
-
elif wsf == 2 and hsf == 1:
|
96
|
-
self.set_image_offset_ratio_2_1(width, height, rand256)
|
97
|
-
elif wsf == 3 and hsf == 2:
|
98
|
-
self.set_image_offset_ratio_3_2(width, height, rand256)
|
99
|
-
elif wsf == 5 and hsf == 4:
|
100
|
-
self.set_image_offset_ratio_5_4(width, height, rand256)
|
101
|
-
elif wsf == 9 and hsf == 16:
|
102
|
-
self.set_image_offset_ratio_9_16(width, height, rand256)
|
103
|
-
elif wsf == 16 and hsf == 9:
|
104
|
-
self.set_image_offset_ratio_16_9(width, height, rand256)
|
105
|
-
return width, height
|
106
|
-
|
107
|
-
@staticmethod
|
108
|
-
async def calculate_array_hash(layers: dict, active: list[int] = None) -> str:
|
109
|
-
"""Calculate the hash of the image based on layers and active zones."""
|
110
|
-
if layers and active:
|
111
|
-
data_to_hash = {
|
112
|
-
"layers": len(layers["wall"][0]),
|
113
|
-
"active_segments": tuple(active),
|
114
|
-
}
|
115
|
-
data_json = json.dumps(data_to_hash, sort_keys=True)
|
116
|
-
return hashlib.sha256(data_json.encode()).hexdigest()
|
117
|
-
return None
|
118
|
-
|
119
|
-
@staticmethod
|
120
|
-
async def async_copy_array(original_array: NumpyArray) -> NumpyArray:
|
121
|
-
"""Copy the array."""
|
122
|
-
return NumpyArray.copy(original_array)
|
123
|
-
|
124
|
-
def get_map_points(self) -> dict:
|
125
|
-
"""Return the map points."""
|
126
|
-
return [
|
127
|
-
{"x": 0, "y": 0}, # Top-left corner 0
|
128
|
-
{"x": self.crop_img_size[0], "y": 0}, # Top-right corner 1
|
129
|
-
{
|
130
|
-
"x": self.crop_img_size[0],
|
131
|
-
"y": self.crop_img_size[1],
|
132
|
-
}, # Bottom-right corner 2
|
133
|
-
{"x": 0, "y": self.crop_img_size[1]}, # Bottom-left corner (optional) 3
|
134
|
-
]
|
91
|
+
def check_zoom_and_aspect_ratio(self) -> bool:
|
92
|
+
"""Check if the image is zoomed and has an aspect ratio."""
|
93
|
+
return (
|
94
|
+
self.shared.image_auto_zoom
|
95
|
+
and self.shared.vacuum_state == "cleaning"
|
96
|
+
and self.zooming
|
97
|
+
and self.shared.image_zoom_lock_ratio
|
98
|
+
or self.shared.image_aspect_ratio != "None"
|
99
|
+
)
|
135
100
|
|
136
|
-
def
|
137
|
-
|
101
|
+
def _set_image_offset_ratio_1_1(
|
102
|
+
self, width: int, height: int, rand256: bool = False
|
138
103
|
) -> None:
|
139
104
|
"""Set the image offset ratio to 1:1."""
|
140
105
|
|
@@ -160,8 +125,8 @@ class BaseHandler:
|
|
160
125
|
self.offset_y,
|
161
126
|
)
|
162
127
|
|
163
|
-
def
|
164
|
-
|
128
|
+
def _set_image_offset_ratio_2_1(
|
129
|
+
self, width: int, height: int, rand256: bool = False
|
165
130
|
) -> None:
|
166
131
|
"""Set the image offset ratio to 2:1."""
|
167
132
|
|
@@ -188,8 +153,8 @@ class BaseHandler:
|
|
188
153
|
self.offset_y,
|
189
154
|
)
|
190
155
|
|
191
|
-
def
|
192
|
-
|
156
|
+
def _set_image_offset_ratio_3_2(
|
157
|
+
self, width: int, height: int, rand256: bool = False
|
193
158
|
) -> None:
|
194
159
|
"""Set the image offset ratio to 3:2."""
|
195
160
|
|
@@ -199,13 +164,11 @@ class BaseHandler:
|
|
199
164
|
if rotation in [0, 180]:
|
200
165
|
self.offset_y = width - self.crop_img_size[0]
|
201
166
|
self.offset_x = ((height - self.crop_img_size[1]) // 2) - (
|
202
|
-
|
167
|
+
self.crop_img_size[1] // 10
|
203
168
|
)
|
204
169
|
elif rotation in [90, 270]:
|
205
170
|
self.offset_y = (self.crop_img_size[0] - width) // 2
|
206
|
-
self.offset_x = (self.crop_img_size[1] - height) + (
|
207
|
-
(height // 10) // 2
|
208
|
-
)
|
171
|
+
self.offset_x = (self.crop_img_size[1] - height) + ((height // 10) // 2)
|
209
172
|
else:
|
210
173
|
if rotation in [0, 180]:
|
211
174
|
self.offset_x = (width - self.crop_img_size[0]) // 2
|
@@ -221,8 +184,8 @@ class BaseHandler:
|
|
221
184
|
self.offset_y,
|
222
185
|
)
|
223
186
|
|
224
|
-
def
|
225
|
-
|
187
|
+
def _set_image_offset_ratio_5_4(
|
188
|
+
self, width: int, height: int, rand256: bool = False
|
226
189
|
) -> None:
|
227
190
|
"""Set the image offset ratio to 5:4."""
|
228
191
|
|
@@ -230,16 +193,14 @@ class BaseHandler:
|
|
230
193
|
if not rand256:
|
231
194
|
if rotation in [0, 180]:
|
232
195
|
self.offset_x = ((width - self.crop_img_size[0]) // 2) - (
|
233
|
-
|
196
|
+
self.crop_img_size[0] // 2
|
234
197
|
)
|
235
198
|
self.offset_y = (self.crop_img_size[1] - height) - (
|
236
|
-
|
199
|
+
self.crop_img_size[1] // 2
|
237
200
|
)
|
238
201
|
elif rotation in [90, 270]:
|
239
202
|
self.offset_y = ((self.crop_img_size[0] - width) // 2) - 10
|
240
|
-
self.offset_x = (self.crop_img_size[1] - height) + (
|
241
|
-
height // 10
|
242
|
-
)
|
203
|
+
self.offset_x = (self.crop_img_size[1] - height) + (height // 10)
|
243
204
|
else:
|
244
205
|
if rotation in [0, 180]:
|
245
206
|
self.offset_y = (width - self.crop_img_size[0]) // 2
|
@@ -255,8 +216,8 @@ class BaseHandler:
|
|
255
216
|
self.offset_y,
|
256
217
|
)
|
257
218
|
|
258
|
-
def
|
259
|
-
|
219
|
+
def _set_image_offset_ratio_9_16(
|
220
|
+
self, width: int, height: int, rand256: bool = False
|
260
221
|
) -> None:
|
261
222
|
"""Set the image offset ratio to 9:16."""
|
262
223
|
|
@@ -283,8 +244,8 @@ class BaseHandler:
|
|
283
244
|
self.offset_y,
|
284
245
|
)
|
285
246
|
|
286
|
-
def
|
287
|
-
|
247
|
+
def _set_image_offset_ratio_16_9(
|
248
|
+
self, width: int, height: int, rand256: bool = False
|
288
249
|
) -> None:
|
289
250
|
"""Set the image offset ratio to 16:9."""
|
290
251
|
|
@@ -311,6 +272,71 @@ class BaseHandler:
|
|
311
272
|
self.offset_y,
|
312
273
|
)
|
313
274
|
|
275
|
+
async def async_map_coordinates_offset(
|
276
|
+
self, params: OffsetParams
|
277
|
+
) -> tuple[int, int]:
|
278
|
+
"""
|
279
|
+
Offset the coordinates to the map.
|
280
|
+
"""
|
281
|
+
if params.wsf == 1 and params.hsf == 1:
|
282
|
+
self._set_image_offset_ratio_1_1(
|
283
|
+
params.width, params.height, params.rand256
|
284
|
+
)
|
285
|
+
elif params.wsf == 2 and params.hsf == 1:
|
286
|
+
self._set_image_offset_ratio_2_1(
|
287
|
+
params.width, params.height, params.rand256
|
288
|
+
)
|
289
|
+
elif params.wsf == 3 and params.hsf == 2:
|
290
|
+
self._set_image_offset_ratio_3_2(
|
291
|
+
params.width, params.height, params.rand256
|
292
|
+
)
|
293
|
+
elif params.wsf == 5 and params.hsf == 4:
|
294
|
+
self._set_image_offset_ratio_5_4(
|
295
|
+
params.width, params.height, params.rand256
|
296
|
+
)
|
297
|
+
elif params.wsf == 9 and params.hsf == 16:
|
298
|
+
self._set_image_offset_ratio_9_16(
|
299
|
+
params.width, params.height, params.rand256
|
300
|
+
)
|
301
|
+
elif params.wsf == 16 and params.hsf == 9:
|
302
|
+
self._set_image_offset_ratio_16_9(
|
303
|
+
params.width, params.height, params.rand256
|
304
|
+
)
|
305
|
+
return params.width, params.height
|
306
|
+
|
307
|
+
@staticmethod
|
308
|
+
async def calculate_array_hash(
|
309
|
+
layers: dict, active: list[int] = None
|
310
|
+
) -> str or None:
|
311
|
+
"""Calculate the hash of the image based on layers and active zones."""
|
312
|
+
if layers and active:
|
313
|
+
data_to_hash = {
|
314
|
+
"layers": len(layers["wall"][0]),
|
315
|
+
"active_segments": tuple(active),
|
316
|
+
}
|
317
|
+
data_json = json.dumps(data_to_hash, sort_keys=True)
|
318
|
+
return hashlib.sha256(data_json.encode()).hexdigest()
|
319
|
+
return None
|
320
|
+
|
321
|
+
@staticmethod
|
322
|
+
async def async_copy_array(original_array: NumpyArray) -> NumpyArray:
|
323
|
+
"""Copy the array."""
|
324
|
+
return NumpyArray.copy(original_array)
|
325
|
+
|
326
|
+
def get_map_points(
|
327
|
+
self,
|
328
|
+
) -> list[dict[str, int] | dict[str, int] | dict[str, int] | dict[str, int]]:
|
329
|
+
"""Return the map points."""
|
330
|
+
return [
|
331
|
+
{"x": 0, "y": 0}, # Top-left corner 0
|
332
|
+
{"x": self.crop_img_size[0], "y": 0}, # Top-right corner 1
|
333
|
+
{
|
334
|
+
"x": self.crop_img_size[0],
|
335
|
+
"y": self.crop_img_size[1],
|
336
|
+
}, # Bottom-right corner 2
|
337
|
+
{"x": 0, "y": self.crop_img_size[1]}, # Bottom-left corner (optional) 3
|
338
|
+
]
|
339
|
+
|
314
340
|
def get_vacuum_points(self, rotation_angle: int) -> list[dict[str, int]]:
|
315
341
|
"""Calculate the calibration points based on the rotation angle."""
|
316
342
|
|
@@ -446,4 +472,50 @@ class BaseHandler:
|
|
446
472
|
id_count += 1
|
447
473
|
if id_count > 1:
|
448
474
|
_LOGGER.debug("%s: Point Properties updated.", self.file_name)
|
449
|
-
return point_properties
|
475
|
+
return point_properties
|
476
|
+
|
477
|
+
@staticmethod
|
478
|
+
def get_corners(
|
479
|
+
x_max: int, x_min: int, y_max: int, y_min: int
|
480
|
+
) -> list[tuple[int, int]]:
|
481
|
+
"""Return the corners of the image."""
|
482
|
+
return [
|
483
|
+
(x_min, y_min),
|
484
|
+
(x_max, y_min),
|
485
|
+
(x_max, y_max),
|
486
|
+
(x_min, y_max),
|
487
|
+
]
|
488
|
+
|
489
|
+
|
490
|
+
async def async_resize_image(params: ResizeParams):
|
491
|
+
"""Resize the image to the given dimensions and aspect ratio."""
|
492
|
+
if params.aspect_ratio:
|
493
|
+
wsf, hsf = [int(x) for x in params.aspect_ratio.split(",")]
|
494
|
+
if wsf == 0 or hsf == 0:
|
495
|
+
return params.pil_img
|
496
|
+
new_aspect_ratio = wsf / hsf
|
497
|
+
if params.width / params.height > new_aspect_ratio:
|
498
|
+
new_width = int(params.pil_img.height * new_aspect_ratio)
|
499
|
+
new_height = params.pil_img.height
|
500
|
+
else:
|
501
|
+
new_width = params.pil_img.width
|
502
|
+
new_height = int(params.pil_img.width / new_aspect_ratio)
|
503
|
+
|
504
|
+
_LOGGER.debug(
|
505
|
+
"Image Aspect Ratio: %s, %s",
|
506
|
+
str(wsf),
|
507
|
+
str(hsf),
|
508
|
+
)
|
509
|
+
|
510
|
+
if params.crop_size is not None:
|
511
|
+
params.crop_size[0], params.crop_size[1] = await params.offset_func(
|
512
|
+
wsf=wsf,
|
513
|
+
hsf=hsf,
|
514
|
+
width=new_width,
|
515
|
+
height=new_height,
|
516
|
+
rand256=params.is_rand,
|
517
|
+
)
|
518
|
+
|
519
|
+
return ImageOps.pad(params.pil_img, (new_width, new_height))
|
520
|
+
|
521
|
+
return ImageOps.pad(params.pil_img, (params.width, params.height))
|
@@ -262,9 +262,9 @@ class ImageDraw:
|
|
262
262
|
for path in path_pixels:
|
263
263
|
# Get the points from the current path and extend multiple paths.
|
264
264
|
points = path.get("points", [])
|
265
|
-
|
265
|
+
sublist = self.img_h.data.sublist(points, 2)
|
266
266
|
self.img_h.shared.map_new_path = self.img_h.data.sublist_join(
|
267
|
-
|
267
|
+
sublist, 2
|
268
268
|
)
|
269
269
|
np_array = await self.img_h.draw.lines(
|
270
270
|
np_array, self.img_h.shared.map_new_path, 5, color_move
|
@@ -276,9 +276,8 @@ class ImageDraw:
|
|
276
276
|
try:
|
277
277
|
entity_dict = self.img_h.data.find_points_entities(m_json)
|
278
278
|
except (ValueError, KeyError):
|
279
|
-
|
280
|
-
|
281
|
-
_LOGGER.info("%s: Got the points in the json.", self.file_name)
|
279
|
+
return None
|
280
|
+
_LOGGER.info("%s: Got the points in the json.", self.file_name)
|
282
281
|
return entity_dict
|
283
282
|
|
284
283
|
async def async_get_robot_in_room(
|
@@ -40,8 +40,6 @@ class HypferMapImageHandler(BaseHandler):
|
|
40
40
|
self.img_hash = None # hash of the image calculated to check differences.
|
41
41
|
self.img_base_layer = None # numpy array store the map base layer.
|
42
42
|
self.active_zones = None # vacuum active zones.
|
43
|
-
self.frame_number = 0 # frame number of the image.
|
44
|
-
self.zooming = False # zooming the image.
|
45
43
|
self.svg_wait = False # SVG image creation wait.
|
46
44
|
self.trim_down = 0 # memory stored trims calculated once.
|
47
45
|
self.trim_left = 0 # memory stored trims calculated once.
|
@@ -78,12 +76,7 @@ class HypferMapImageHandler(BaseHandler):
|
|
78
76
|
x_max,
|
79
77
|
y_max,
|
80
78
|
) = await self.data.async_get_rooms_coordinates(pixels, pixel_size)
|
81
|
-
corners =
|
82
|
-
(x_min, y_min),
|
83
|
-
(x_max, y_min),
|
84
|
-
(x_max, y_max),
|
85
|
-
(x_min, y_max),
|
86
|
-
]
|
79
|
+
corners = self.get_corners(x_max, x_min, y_max, y_min)
|
87
80
|
room_id = str(segment_id)
|
88
81
|
self.rooms_pos.append(
|
89
82
|
{
|
@@ -253,17 +246,9 @@ class HypferMapImageHandler(BaseHandler):
|
|
253
246
|
pil_img = Image.fromarray(img_np_array, mode="RGBA")
|
254
247
|
del img_np_array
|
255
248
|
# reduce the image size if the zoomed image is bigger then the original.
|
256
|
-
if (
|
257
|
-
self.shared.image_auto_zoom
|
258
|
-
and self.shared.vacuum_state == "cleaning"
|
259
|
-
and self.zooming
|
260
|
-
and self.shared.image_zoom_lock_ratio
|
261
|
-
or self.shared.image_aspect_ratio != "None"
|
262
|
-
):
|
263
|
-
width = self.shared.image_ref_width
|
264
|
-
height = self.shared.image_ref_height
|
249
|
+
if self.check_zoom_and_aspect_ratio():
|
265
250
|
resized_image = await self.async_resize_image(
|
266
|
-
pil_img,
|
251
|
+
pil_img, self.shared.image_aspect_ratio
|
267
252
|
)
|
268
253
|
return resized_image
|
269
254
|
_LOGGER.debug("%s: Frame Completed.", self.file_name)
|
valetudo_map_parser/map_data.py
CHANGED
@@ -239,7 +239,7 @@ class RandImageData:
|
|
239
239
|
return compressed_pixels
|
240
240
|
|
241
241
|
@staticmethod
|
242
|
-
def
|
242
|
+
def _calculate_max_x_y(coord_array):
|
243
243
|
"""Calculate the max and min x and y coordinates."""
|
244
244
|
max_x = -float("inf")
|
245
245
|
max_y = -float("inf")
|
@@ -334,18 +334,18 @@ class RandImageData:
|
|
334
334
|
def get_rrm_currently_cleaned_zones(json_data: JsonType) -> dict:
|
335
335
|
"""Get the currently cleaned zones from the json."""
|
336
336
|
re_zones = json_data.get("currently_cleaned_zones", [])
|
337
|
-
formatted_zones = RandImageData.
|
337
|
+
formatted_zones = RandImageData._rrm_valetudo_format_zone(re_zones)
|
338
338
|
return formatted_zones
|
339
339
|
|
340
340
|
@staticmethod
|
341
341
|
def get_rrm_forbidden_zones(json_data: JsonType) -> dict:
|
342
342
|
"""Get the forbidden zones from the json."""
|
343
343
|
re_zones = json_data.get("forbidden_zones", [])
|
344
|
-
formatted_zones = RandImageData.
|
344
|
+
formatted_zones = RandImageData._rrm_valetudo_format_zone(re_zones)
|
345
345
|
return formatted_zones
|
346
346
|
|
347
347
|
@staticmethod
|
348
|
-
def
|
348
|
+
def _rrm_valetudo_format_zone(coordinates: list) -> any:
|
349
349
|
"""Format the zones from RRM to Valetudo."""
|
350
350
|
formatted_zones = []
|
351
351
|
for zone_data in coordinates:
|
@@ -387,7 +387,7 @@ class RandImageData:
|
|
387
387
|
return formatted_zones
|
388
388
|
|
389
389
|
@staticmethod
|
390
|
-
def
|
390
|
+
def _rrm_valetudo_lines(coordinates: list) -> list:
|
391
391
|
"""Format the lines from RRM to Valetudo."""
|
392
392
|
formatted_lines = []
|
393
393
|
for lines in coordinates:
|
@@ -402,7 +402,7 @@ class RandImageData:
|
|
402
402
|
tmp_data = json_data.get("virtual_walls", [])
|
403
403
|
except KeyError:
|
404
404
|
return None
|
405
|
-
virtual_walls = RandImageData.
|
405
|
+
virtual_walls = RandImageData._rrm_valetudo_lines(tmp_data)
|
406
406
|
return virtual_walls
|
407
407
|
|
408
408
|
@staticmethod
|
@@ -495,11 +495,11 @@ class RandImageData:
|
|
495
495
|
return None
|
496
496
|
return seg_ids
|
497
497
|
|
498
|
-
@staticmethod
|
499
|
-
def convert_negative_angle(angle: int) -> int:
|
500
|
-
|
501
|
-
|
502
|
-
|
503
|
-
|
504
|
-
|
505
|
-
|
498
|
+
# @staticmethod
|
499
|
+
# def convert_negative_angle(angle: int) -> int:
|
500
|
+
# """Convert negative angle to positive."""
|
501
|
+
# angle_c = angle % 360 # Ensure angle is within 0-359
|
502
|
+
# if angle_c < 0:
|
503
|
+
# angle_c += 360 # Convert negative angle to positive
|
504
|
+
# angle = angle_c + 180 # add offset
|
505
|
+
# return angle
|
@@ -55,14 +55,13 @@ class ReImageHandler(BaseHandler):
|
|
55
55
|
self.trim_left = None # Trim left
|
56
56
|
self.trim_right = None # Trim right
|
57
57
|
self.trim_up = None # Trim up
|
58
|
-
self.zooming = False # Zooming flag
|
59
58
|
self.file_name = self.shared.file_name # File name
|
60
59
|
self.offset_top = self.shared.offset_top # offset top
|
61
60
|
self.offset_bottom = self.shared.offset_down # offset bottom
|
62
61
|
self.offset_left = self.shared.offset_left # offset left
|
63
62
|
self.offset_right = self.shared.offset_right # offset right
|
64
63
|
self.imd = ImageDraw(self) # Image Draw
|
65
|
-
self.
|
64
|
+
self.crop = AutoCrop(self)
|
66
65
|
|
67
66
|
async def extract_room_properties(
|
68
67
|
self, json_data: JsonType, destinations: JsonType
|
@@ -96,12 +95,7 @@ class ReImageHandler(BaseHandler):
|
|
96
95
|
x_max = self.outlines[id_x][1][0]
|
97
96
|
y_min = self.outlines[id_x][0][1]
|
98
97
|
y_max = self.outlines[id_x][1][1]
|
99
|
-
corners =
|
100
|
-
(x_min, y_min),
|
101
|
-
(x_max, y_min),
|
102
|
-
(x_max, y_max),
|
103
|
-
(x_min, y_max),
|
104
|
-
]
|
98
|
+
corners = self.get_corners(x_max, x_min, y_max, y_min)
|
105
99
|
# rand256 vacuums accept int(room_id) or str(name)
|
106
100
|
# the card will soon support int(room_id) but the camera will send name
|
107
101
|
# this avoids the manual change of the values in the card.
|
@@ -251,30 +245,21 @@ class ReImageHandler(BaseHandler):
|
|
251
245
|
img_np_array = await self.imd.async_draw_robot_on_map(
|
252
246
|
img_np_array, robot_position, robot_position_angle, colors["robot"]
|
253
247
|
)
|
254
|
-
img_np_array = await self.
|
248
|
+
img_np_array = await self.crop.async_auto_trim_and_zoom_image(
|
255
249
|
img_np_array,
|
256
|
-
colors["background"],
|
257
|
-
int(self.shared.margins),
|
258
|
-
int(self.shared.image_rotate),
|
259
|
-
self.zooming,
|
250
|
+
detect_colour=colors["background"],
|
251
|
+
margin_size=int(self.shared.margins),
|
252
|
+
rotate=int(self.shared.image_rotate),
|
253
|
+
zoom=self.zooming,
|
260
254
|
rand256=True,
|
261
255
|
)
|
262
256
|
return img_np_array
|
263
257
|
|
264
258
|
async def _finalize_image(self, pil_img):
|
265
|
-
if (
|
266
|
-
self.
|
267
|
-
|
268
|
-
|
269
|
-
and self.shared.image_zoom_lock_ratio
|
270
|
-
or self.shared.image_aspect_ratio != "None"
|
271
|
-
):
|
272
|
-
width = self.shared.image_ref_width
|
273
|
-
height = self.shared.image_ref_height
|
274
|
-
if self.shared.image_aspect_ratio != "None":
|
275
|
-
pil_img = await self.async_resize_image(
|
276
|
-
pil_img, width, height, self.shared.image_aspect_ratio, True
|
277
|
-
)
|
259
|
+
if self.check_zoom_and_aspect_ratio():
|
260
|
+
pil_img = await self.async_resize_image(
|
261
|
+
pil_img, self.shared.image_aspect_ratio, True
|
262
|
+
)
|
278
263
|
_LOGGER.debug("%s: Frame Completed.", self.file_name)
|
279
264
|
return pil_img
|
280
265
|
|
@@ -0,0 +1,20 @@
|
|
1
|
+
valetudo_map_parser/__init__.py,sha256=pWRSVGM2OtPKTzdpPTEgLrNYjZ9P2duwaDLI_KN-iLY,809
|
2
|
+
valetudo_map_parser/config/__init__.py,sha256=DQ9plV3ZF_K25Dp5ZQHPDoG-40dQoJNdNi-dfNeR3Zc,48
|
3
|
+
valetudo_map_parser/config/auto_crop.py,sha256=z97Yqoe96ZiWmgaKTFv7sODb9UD6doRduTeQXMYWXVA,11018
|
4
|
+
valetudo_map_parser/config/colors.py,sha256=0sTI_x0ZMchSDPTsEivdTXDn58nEbyE4REXIp0IpWdg,6514
|
5
|
+
valetudo_map_parser/config/drawable.py,sha256=hsrEJCMVOrjs5sJfr26SeqJD0VNlYWwxcVkkHeaxx7U,20356
|
6
|
+
valetudo_map_parser/config/rand25_parser.py,sha256=fehyF18hRWRWbXbojocQCIaIch21Lbh1wtl2XdKRSl0,16447
|
7
|
+
valetudo_map_parser/config/shared.py,sha256=LQV5K8tbVhEKUkby9ssjEmh_T4Ai-Euzsbag_HWYVRc,9448
|
8
|
+
valetudo_map_parser/config/types.py,sha256=sdjqhcxpRSxNFLVHIyCg-RDL9JIjtQHoR2C2WpocWBc,16107
|
9
|
+
valetudo_map_parser/config/utils.py,sha256=mCmTRxiy5REBPvm3S8_b3nCce4pFAjRyCUnAvz3omLw,18536
|
10
|
+
valetudo_map_parser/hypfer_draw.py,sha256=s58ak9IBYLjJyoddfDC99PfQ12HTjkSfJYXqCi4vZKs,14931
|
11
|
+
valetudo_map_parser/hypfer_handler.py,sha256=lA9rC4gO0cNas4ValRikw4X6Uc0sqo2-Roj7EQi1MBA,13471
|
12
|
+
valetudo_map_parser/map_data.py,sha256=6FbQfgxFB6E4kcOWokReJOVSekVaE1kStyhTQhAhiOg,19469
|
13
|
+
valetudo_map_parser/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
14
|
+
valetudo_map_parser/rand25_handler.py,sha256=u3N-_qjpYQM3WO4cnhqHIPa7TMquJ9XYqhoUYFKoc8I,15276
|
15
|
+
valetudo_map_parser/reimg_draw.py,sha256=dtdbYKKxmQnbOaHBHayWEF07OdSnTKo2CPSOW0qpgH0,12506
|
16
|
+
valetudo_map_parser-0.1.9b10.dist-info/LICENSE,sha256=Lh-qBbuRV0-jiCIBhfV7NgdwFxQFOXH3BKOzK865hRs,10480
|
17
|
+
valetudo_map_parser-0.1.9b10.dist-info/METADATA,sha256=ha_vys80z9E1XW1dDtgbHMigATO4vb2w-7gDRqJ1_mM,1029
|
18
|
+
valetudo_map_parser-0.1.9b10.dist-info/NOTICE.txt,sha256=5lTOuWiU9aiEnJ2go8sc7lTJ7ntMBx0g0GFnNrswCY4,2533
|
19
|
+
valetudo_map_parser-0.1.9b10.dist-info/WHEEL,sha256=IYZQI976HJqqOpQU6PHkJ8fb3tMNBFjg-Cn-pwAbaFM,88
|
20
|
+
valetudo_map_parser-0.1.9b10.dist-info/RECORD,,
|
@@ -1,20 +0,0 @@
|
|
1
|
-
valetudo_map_parser/__init__.py,sha256=pWRSVGM2OtPKTzdpPTEgLrNYjZ9P2duwaDLI_KN-iLY,809
|
2
|
-
valetudo_map_parser/config/__init__.py,sha256=DQ9plV3ZF_K25Dp5ZQHPDoG-40dQoJNdNi-dfNeR3Zc,48
|
3
|
-
valetudo_map_parser/config/auto_crop.py,sha256=z97Yqoe96ZiWmgaKTFv7sODb9UD6doRduTeQXMYWXVA,11018
|
4
|
-
valetudo_map_parser/config/colors.py,sha256=0sTI_x0ZMchSDPTsEivdTXDn58nEbyE4REXIp0IpWdg,6514
|
5
|
-
valetudo_map_parser/config/drawable.py,sha256=hsrEJCMVOrjs5sJfr26SeqJD0VNlYWwxcVkkHeaxx7U,20356
|
6
|
-
valetudo_map_parser/config/rand25_parser.py,sha256=fehyF18hRWRWbXbojocQCIaIch21Lbh1wtl2XdKRSl0,16447
|
7
|
-
valetudo_map_parser/config/shared.py,sha256=LQV5K8tbVhEKUkby9ssjEmh_T4Ai-Euzsbag_HWYVRc,9448
|
8
|
-
valetudo_map_parser/config/types.py,sha256=-8F1WwCH5hKSih83-WPjYbGdQyKmNqkDmSKvlyz6qPg,16163
|
9
|
-
valetudo_map_parser/config/utils.py,sha256=V_GmVL10hLaGWRltv8FvxEEohRfswWDmmnp6HA0vsn8,16627
|
10
|
-
valetudo_map_parser/hypfer_draw.py,sha256=46bYtbcaZHDYDtOie4byM3Z8CcXw-vl7uQfwN7KdZOk,14958
|
11
|
-
valetudo_map_parser/hypfer_handler.py,sha256=hBYy6trd1hmFkyOPJmm1T-y4byi-xGqS8yN_Xwhl0E0,14073
|
12
|
-
valetudo_map_parser/map_data.py,sha256=qm1Zlfex0JrfhQsAKUOzsceZL0X92oAyGJ5Wvsq6YhA,19447
|
13
|
-
valetudo_map_parser/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
14
|
-
valetudo_map_parser/rand25_handler.py,sha256=vph1BCO0g77kTi18y6sqqJfyJfT5033l9CoxJIDO1Ak,15827
|
15
|
-
valetudo_map_parser/reimg_draw.py,sha256=dtdbYKKxmQnbOaHBHayWEF07OdSnTKo2CPSOW0qpgH0,12506
|
16
|
-
valetudo_map_parser-0.1.9b8.dist-info/LICENSE,sha256=Lh-qBbuRV0-jiCIBhfV7NgdwFxQFOXH3BKOzK865hRs,10480
|
17
|
-
valetudo_map_parser-0.1.9b8.dist-info/METADATA,sha256=uoqN0vHYxk79Tfy0Sq4D9aiHjbjwm2gzqUxQbxD3WPU,1028
|
18
|
-
valetudo_map_parser-0.1.9b8.dist-info/NOTICE.txt,sha256=5lTOuWiU9aiEnJ2go8sc7lTJ7ntMBx0g0GFnNrswCY4,2533
|
19
|
-
valetudo_map_parser-0.1.9b8.dist-info/WHEEL,sha256=IYZQI976HJqqOpQU6PHkJ8fb3tMNBFjg-Cn-pwAbaFM,88
|
20
|
-
valetudo_map_parser-0.1.9b8.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|