Skip to content
This repository was archived by the owner on Mar 19, 2023. It is now read-only.

Commit 87201c2

Browse files
authored
Merge pull request #224 from robmarkcole/ISSUE221
Issue221
2 parents 22fc7c8 + c1c9e86 commit 87201c2

2 files changed

Lines changed: 29 additions & 13 deletions

File tree

README.md

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,9 @@ image_processing:
2929
# custom_model: mask
3030
# confidence: 80
3131
save_file_folder: /config/snapshots/
32+
save_file_format: png
3233
save_timestamped_file: True
33-
always_save_latest_jpg: True
34+
always_save_latest_file: True
3435
scale: 0.75
3536
# roi_x_min: 0.35
3637
roi_x_max: 0.8
@@ -54,8 +55,9 @@ Configuration variables:
5455
- **custom_model**: (Optional) The name of a custom model if you are using one. Don't forget to add the targets from the custom model below
5556
- **confidence**: (Optional) The confidence (in %) above which detected targets are counted in the sensor state. Default value: 80
5657
- **save_file_folder**: (Optional) The folder to save processed images to. Note that folder path should be added to [whitelist_external_dirs](https://www.home-assistant.io/docs/configuration/basic/)
58+
- **save_file_format**: (Optional, default `jpg`, alternatively `png`) The file format to save images as. `png` generally results in easier to read annotations.
5759
- **save_timestamped_file**: (Optional, default `False`, requires `save_file_folder` to be configured) Save the processed image with the time of detection in the filename.
58-
- **always_save_latest_jpg**: (Optional, default `False`, requires `save_file_folder` to be configured) Always save the last processed image, even if there were no detections.
60+
- **always_save_latest_file**: (Optional, default `False`, requires `save_file_folder` to be configured) Always save the last processed image, even if there were no detections.
5961
- **scale**: (optional, default 1.0), range 0.1-1.0, applies a scaling factor to the images that are saved. This reduces the disk space used by saved images, and is especially beneficial when using high resolution cameras.
6062
- **show_boxes**: (optional, default `True`), if `False` bounding boxes are not shown on saved images
6163
- **roi_x_min**: (optional, default 0), range 0-1, must be less than roi_x_max

custom_components/deepstack_object/image_processing.py

Lines changed: 25 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -69,9 +69,10 @@
6969
CONF_TARGET = "target"
7070
CONF_TARGETS = "targets"
7171
CONF_TIMEOUT = "timeout"
72+
CONF_SAVE_FILE_FORMAT = "save_file_format"
7273
CONF_SAVE_FILE_FOLDER = "save_file_folder"
7374
CONF_SAVE_TIMESTAMPTED_FILE = "save_timestamped_file"
74-
CONF_ALWAYS_SAVE_LATEST_JPG = "always_save_latest_jpg"
75+
CONF_ALWAYS_SAVE_LATEST_FILE = "always_save_latest_file"
7576
CONF_SHOW_BOXES = "show_boxes"
7677
CONF_ROI_Y_MIN = "roi_y_min"
7778
CONF_ROI_X_MIN = "roi_x_min"
@@ -102,6 +103,8 @@
102103
OBJECT = "object"
103104
SAVED_FILE = "saved_file"
104105
MIN_CONFIDENCE = 0.1
106+
JPG = "jpg"
107+
PNG = "png"
105108

106109
# rgb(red, green, blue)
107110
RED = (255, 0, 0) # For objects within the ROI
@@ -134,8 +137,9 @@
134137
vol.Coerce(float, vol.Range(min=0.1, max=1))
135138
),
136139
vol.Optional(CONF_SAVE_FILE_FOLDER): cv.isdir,
140+
vol.Optional(CONF_SAVE_FILE_FORMAT, default=JPG): vol.In([JPG, PNG]),
137141
vol.Optional(CONF_SAVE_TIMESTAMPTED_FILE, default=False): cv.boolean,
138-
vol.Optional(CONF_ALWAYS_SAVE_LATEST_JPG, default=False): cv.boolean,
142+
vol.Optional(CONF_ALWAYS_SAVE_LATEST_FILE, default=False): cv.boolean,
139143
vol.Optional(CONF_SHOW_BOXES, default=True): cv.boolean,
140144
}
141145
)
@@ -233,8 +237,9 @@ def setup_platform(hass, config, add_devices, discovery_info=None):
233237
scale=config[CONF_SCALE],
234238
show_boxes=config[CONF_SHOW_BOXES],
235239
save_file_folder=save_file_folder,
240+
save_file_format=config[CONF_SAVE_FILE_FORMAT],
236241
save_timestamped_file=config.get(CONF_SAVE_TIMESTAMPTED_FILE),
237-
always_save_latest_jpg=config.get(CONF_ALWAYS_SAVE_LATEST_JPG),
242+
always_save_latest_file=config.get(CONF_ALWAYS_SAVE_LATEST_FILE),
238243
camera_entity=camera.get(CONF_ENTITY_ID),
239244
name=camera.get(CONF_NAME),
240245
)
@@ -261,8 +266,9 @@ def __init__(
261266
scale,
262267
show_boxes,
263268
save_file_folder,
269+
save_file_format,
264270
save_timestamped_file,
265-
always_save_latest_jpg,
271+
always_save_latest_file,
266272
camera_entity,
267273
name=None,
268274
):
@@ -296,6 +302,7 @@ def __init__(
296302
self._state = None
297303
self._objects = [] # The parsed raw data
298304
self._targets_found = []
305+
self._last_detection = None
299306

300307
self._roi_dict = {
301308
"y_min": roi_y_min,
@@ -305,12 +312,13 @@ def __init__(
305312
}
306313
self._scale = scale
307314
self._show_boxes = show_boxes
308-
self._last_detection = None
309315
self._image_width = None
310316
self._image_height = None
311317
self._save_file_folder = save_file_folder
318+
self._save_file_format = save_file_format
319+
self._always_save_latest_file = always_save_latest_file
312320
self._save_timestamped_file = save_timestamped_file
313-
self._always_save_latest_jpg = always_save_latest_jpg
321+
self._always_save_latest_file = always_save_latest_file
314322
self._image = None
315323

316324
def process_image(self, image):
@@ -377,7 +385,7 @@ def process_image(self, image):
377385
self._summary = dict(Counter(targets_found)) # e.g. {'car':2, 'person':1}
378386

379387
if self._save_file_folder:
380-
if self._state > 0 or self._always_save_latest_jpg:
388+
if self._state > 0 or self._always_save_latest_file:
381389
saved_image_path = self.save_image(
382390
self._targets_found, self._save_file_folder,
383391
)
@@ -405,6 +413,11 @@ def name(self):
405413
"""Return the name of the sensor."""
406414
return self._name
407415

416+
@property
417+
def unit_of_measurement(self):
418+
"""Return the unit of measurement."""
419+
return "targets"
420+
408421
@property
409422
def should_poll(self):
410423
"""Return the polling state."""
@@ -428,8 +441,9 @@ def device_state_attributes(self) -> Dict:
428441
]
429442
if self._save_file_folder:
430443
attr[CONF_SAVE_FILE_FOLDER] = str(self._save_file_folder)
444+
attr[CONF_SAVE_FILE_FORMAT] = self._save_file_format
431445
attr[CONF_SAVE_TIMESTAMPTED_FILE] = self._save_timestamped_file
432-
attr[CONF_ALWAYS_SAVE_LATEST_JPG] = self._always_save_latest_jpg
446+
attr[CONF_ALWAYS_SAVE_LATEST_FILE] = self._always_save_latest_file
433447
return attr
434448

435449
def save_image(self, targets, directory) -> str:
@@ -477,14 +491,14 @@ def save_image(self, targets, directory) -> str:
477491

478492
# Save images, returning the path of saved image as str
479493
latest_save_path = (
480-
directory / f"{get_valid_filename(self._name).lower()}_latest.jpg"
494+
directory / f"{get_valid_filename(self._name).lower()}_latest.{self._save_file_format}"
481495
)
482-
_LOGGER.info("Deepstack saved file %s", latest_save_path)
483496
img.save(latest_save_path)
497+
_LOGGER.info("Deepstack saved file %s", latest_save_path)
484498
saved_image_path = latest_save_path
485499

486500
if self._save_timestamped_file:
487-
timestamp_save_path = directory / f"{self._name}_{self._last_detection}.jpg"
501+
timestamp_save_path = directory / f"{self._name}_{self._last_detection}.{self._save_file_format}"
488502
img.save(timestamp_save_path)
489503
_LOGGER.info("Deepstack saved file %s", timestamp_save_path)
490504
saved_image_path = timestamp_save_path

0 commit comments

Comments
 (0)