diff --git a/.coveragerc b/.coveragerc index aff0979ca1d..792cf9ddfe0 100644 --- a/.coveragerc +++ b/.coveragerc @@ -926,7 +926,6 @@ omit = homeassistant/components/onvif/sensor.py homeassistant/components/onvif/util.py homeassistant/components/open_meteo/weather.py - homeassistant/components/opencv/* homeassistant/components/openevse/sensor.py homeassistant/components/openexchangerates/__init__.py homeassistant/components/openexchangerates/coordinator.py diff --git a/homeassistant/components/opencv/__init__.py b/homeassistant/components/opencv/__init__.py deleted file mode 100644 index 0e4a755b2b9..00000000000 --- a/homeassistant/components/opencv/__init__.py +++ /dev/null @@ -1 +0,0 @@ -"""The opencv component.""" diff --git a/homeassistant/components/opencv/image_processing.py b/homeassistant/components/opencv/image_processing.py deleted file mode 100644 index e3dbe10a1a0..00000000000 --- a/homeassistant/components/opencv/image_processing.py +++ /dev/null @@ -1,196 +0,0 @@ -"""Support for OpenCV classification on images.""" - -from __future__ import annotations - -from datetime import timedelta -import logging - -import numpy as np -import requests -import voluptuous as vol - -from homeassistant.components.image_processing import ( - PLATFORM_SCHEMA, - ImageProcessingEntity, -) -from homeassistant.const import CONF_ENTITY_ID, CONF_NAME, CONF_SOURCE -from homeassistant.core import HomeAssistant, split_entity_id -import homeassistant.helpers.config_validation as cv -from homeassistant.helpers.entity_platform import AddEntitiesCallback -from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType - -try: - # Verify that the OpenCV python package is pre-installed - import cv2 - - CV2_IMPORTED = True -except ImportError: - CV2_IMPORTED = False - - -_LOGGER = logging.getLogger(__name__) - -ATTR_MATCHES = "matches" -ATTR_TOTAL_MATCHES = "total_matches" - -CASCADE_URL = ( - "https://raw.githubusercontent.com/opencv/opencv/master/data/" - "lbpcascades/lbpcascade_frontalface.xml" -) - -CONF_CLASSIFIER = "classifier" -CONF_FILE = "file" -CONF_MIN_SIZE = "min_size" -CONF_NEIGHBORS = "neighbors" -CONF_SCALE = "scale" - -DEFAULT_CLASSIFIER_PATH = "lbp_frontalface.xml" -DEFAULT_MIN_SIZE = (30, 30) -DEFAULT_NEIGHBORS = 4 -DEFAULT_SCALE = 1.1 -DEFAULT_TIMEOUT = 10 - -SCAN_INTERVAL = timedelta(seconds=2) - -PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend( - { - vol.Optional(CONF_CLASSIFIER): { - cv.string: vol.Any( - cv.isfile, - vol.Schema( - { - vol.Required(CONF_FILE): cv.isfile, - vol.Optional(CONF_SCALE, DEFAULT_SCALE): float, - vol.Optional( - CONF_NEIGHBORS, DEFAULT_NEIGHBORS - ): cv.positive_int, - vol.Optional(CONF_MIN_SIZE, DEFAULT_MIN_SIZE): vol.Schema( - vol.All(vol.Coerce(tuple), vol.ExactSequence([int, int])) - ), - } - ), - ) - } - } -) - - -def _create_processor_from_config(hass, camera_entity, config): - """Create an OpenCV processor from configuration.""" - classifier_config = config.get(CONF_CLASSIFIER) - name = f"{config[CONF_NAME]} {split_entity_id(camera_entity)[1].replace('_', ' ')}" - - processor = OpenCVImageProcessor(hass, camera_entity, name, classifier_config) - - return processor - - -def _get_default_classifier(dest_path): - """Download the default OpenCV classifier.""" - _LOGGER.info("Downloading default classifier") - req = requests.get(CASCADE_URL, stream=True, timeout=10) - with open(dest_path, "wb") as fil: - for chunk in req.iter_content(chunk_size=1024): - if chunk: # filter out keep-alive new chunks - fil.write(chunk) - - -def setup_platform( - hass: HomeAssistant, - config: ConfigType, - add_entities: AddEntitiesCallback, - discovery_info: DiscoveryInfoType | None = None, -) -> None: - """Set up the OpenCV image processing platform.""" - if not CV2_IMPORTED: - _LOGGER.error( - "No OpenCV library found! Install or compile for your system " - "following instructions here: https://opencv.org/?s=releases" - ) - return - - if CONF_CLASSIFIER not in config: - dest_path = hass.config.path(DEFAULT_CLASSIFIER_PATH) - _get_default_classifier(dest_path) - config[CONF_CLASSIFIER] = {"Face": dest_path} - - add_entities( - OpenCVImageProcessor( - hass, - camera[CONF_ENTITY_ID], - camera.get(CONF_NAME), - config[CONF_CLASSIFIER], - ) - for camera in config[CONF_SOURCE] - ) - - -class OpenCVImageProcessor(ImageProcessingEntity): - """Representation of an OpenCV image processor.""" - - def __init__(self, hass, camera_entity, name, classifiers): - """Initialize the OpenCV entity.""" - self.hass = hass - self._camera_entity = camera_entity - if name: - self._name = name - else: - self._name = f"OpenCV {split_entity_id(camera_entity)[1]}" - self._classifiers = classifiers - self._matches = {} - self._total_matches = 0 - self._last_image = None - - @property - def camera_entity(self): - """Return camera entity id from process pictures.""" - return self._camera_entity - - @property - def name(self): - """Return the name of the image processor.""" - return self._name - - @property - def state(self): - """Return the state of the entity.""" - return self._total_matches - - @property - def extra_state_attributes(self): - """Return device specific state attributes.""" - return {ATTR_MATCHES: self._matches, ATTR_TOTAL_MATCHES: self._total_matches} - - def process_image(self, image): - """Process the image.""" - cv_image = cv2.imdecode(np.asarray(bytearray(image)), cv2.IMREAD_UNCHANGED) - - matches = {} - total_matches = 0 - - for name, classifier in self._classifiers.items(): - scale = DEFAULT_SCALE - neighbors = DEFAULT_NEIGHBORS - min_size = DEFAULT_MIN_SIZE - if isinstance(classifier, dict): - path = classifier[CONF_FILE] - scale = classifier.get(CONF_SCALE, scale) - neighbors = classifier.get(CONF_NEIGHBORS, neighbors) - min_size = classifier.get(CONF_MIN_SIZE, min_size) - else: - path = classifier - - cascade = cv2.CascadeClassifier(path) - - detections = cascade.detectMultiScale( - cv_image, scaleFactor=scale, minNeighbors=neighbors, minSize=min_size - ) - regions = [] - for x, y, w, h in detections: - regions.append((int(x), int(y), int(w), int(h))) - total_matches += 1 - - matches[name] = regions - - self._matches = matches - self._total_matches = total_matches diff --git a/homeassistant/components/opencv/manifest.json b/homeassistant/components/opencv/manifest.json deleted file mode 100644 index 3c484385934..00000000000 --- a/homeassistant/components/opencv/manifest.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "domain": "opencv", - "name": "OpenCV", - "codeowners": [], - "documentation": "https://www.home-assistant.io/integrations/opencv", - "iot_class": "local_push", - "requirements": ["numpy==1.26.0", "opencv-python-headless==4.6.0.66"] -} diff --git a/homeassistant/generated/integrations.json b/homeassistant/generated/integrations.json index 7ed8c4accd1..1de015ac780 100644 --- a/homeassistant/generated/integrations.json +++ b/homeassistant/generated/integrations.json @@ -4183,12 +4183,6 @@ "config_flow": false, "iot_class": "cloud_push" }, - "opencv": { - "name": "OpenCV", - "integration_type": "hub", - "config_flow": false, - "iot_class": "local_push" - }, "openerz": { "name": "Open ERZ", "integration_type": "hub", diff --git a/requirements_all.txt b/requirements_all.txt index 635c0deb245..6ce453c11b4 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -1407,7 +1407,6 @@ numato-gpio==0.12.0 # homeassistant.components.compensation # homeassistant.components.iqvia -# homeassistant.components.opencv # homeassistant.components.stream # homeassistant.components.tensorflow # homeassistant.components.trend @@ -1449,9 +1448,6 @@ open-meteo==0.3.1 # homeassistant.components.openai_conversation openai==1.3.8 -# homeassistant.components.opencv -# opencv-python-headless==4.6.0.66 - # homeassistant.components.openerz openerz-api==0.3.0 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index eef277af206..8832c9b8d88 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -1125,7 +1125,6 @@ numato-gpio==0.12.0 # homeassistant.components.compensation # homeassistant.components.iqvia -# homeassistant.components.opencv # homeassistant.components.stream # homeassistant.components.tensorflow # homeassistant.components.trend diff --git a/script/gen_requirements_all.py b/script/gen_requirements_all.py index 8cf8f33c542..4cab1f167c7 100755 --- a/script/gen_requirements_all.py +++ b/script/gen_requirements_all.py @@ -29,7 +29,6 @@ COMMENT_REQUIREMENTS = ( "decora-wifi", "evdev", "face-recognition", - "opencv-python-headless", "pybluez", "pycocotools", "pycups",