Гірничодобувні підприємства — другий за смертністю сектор після будівництва. У підземних шахтах ризик фатальних інцидентів у 3 рази вищий, ніж у кар'єрах. Типова проблема: контроль ЗІЗ в умовах поганого освітлення (до 10 люкс), запорошеності, моніторинг небезпечних зон, трекінг персоналу (underground personnel tracking), детекція аварійних ситуацій. Автоматизація контролю ЗІЗ та небезпечних зон дозволяє знизити аварійність на 30–50%. Системи на основі класичного CV не справляються: точність детекції касок у темряві падає до 50%. Ми використовуємо сучасні нейромережеві детектори YOLO з донавчанням на спеціалізованих датасетах, що дає стабільні 85-95% accuracy навіть у важких умовах.
Ми розробляємо AI-рішення під ключ: від збору датасету до деплою на відеосерверах. Наш досвід — понад 5 років у промисловому CV, 30+ проєктів для гірничодобувних компаній. Гарантуємо compliance rate не нижче 85% на етапі приймання.
Проблеми, які вирішуємо
Підземні шахти — екстремальне середовище для комп'ютерного зору. Низька освітленість (до 10 люкс), завис вугільного пилу, висока вологість. Традиційні детектори на основі Haar-каскадів або перерахунок за кольором дають 50–60% точності — неприйнятно. Інша складність — хибні спрацювання на гірниче обладнання. Помилки трекінгу при перетині людей з технікою. Без інтеграції з SCADA неможливо автоматично заблокувати небезпечні зони. Ми реалізуємо зв'язку OPC-UA / Modbus TCP із затримкою не більше 500 мс.
Які AI-моделі ми використовуємо для детекції порушень?
Базовий стек — YOLOv8/9 з трекінгом ByteTrack. Для підземних умов з низькою освітленістю застосовуємо CLAHE-препроцесинг (підвищення контрастності в 1.5–2 рази) та опціонально тепловізори LWIR. Наш власний Mine Safety Dataset містить 15 000+ анотованих кадрів з 8 класами: person, mining_helmet, headlamp, reflective_jacket, dust_mask, safety_boots, no_helmet, no_headlamp, mining_equipment.
import numpy as np import cv2 from ultralytics import YOLO from dataclasses import dataclass import time from typing import Optional @dataclass class MineWorkerStatus: worker_id: int bbox: list has_helmet: bool has_lamp: bool has_reflective_vest: bool has_mask: bool in_danger_zone: bool proximity_to_machinery: bool compliance: bool class MineMonitoringSystem: """ Система мониторинга безопасности в горнодобывающей отрасли. Учёт специфики: низкое освещение, дым/пыль, ИК-камеры. Mine Safety Dataset (custom): - mining_helmet, lamp_headlamp, reflective_jacket - mining_equipment, person, danger_zone_marker """ MINE_PPE_CLASSES = { 0: 'person', 1: 'mining_helmet', # шахтная каска с фонарём 2: 'headlamp', # фонарь отдельно 3: 'reflective_jacket', # световозвращающий жилет 4: 'dust_mask', 5: 'safety_boots', 6: 'no_helmet', # нарушение 7: 'no_headlamp', # нарушение 8: 'mining_equipment', # комбайн, погрузчик } CRITICAL_ZONES = ['roof_instability', 'gas_presence', 'machinery_working'] def __init__(self, model_path: str, thermal_model_path: Optional[str] = None, danger_zones: Optional[dict] = None, device: str = 'cuda'): self.model = YOLO(model_path) self.thermal_model = YOLO(thermal_model_path) if thermal_model_path else None self.danger_zones = danger_zones or {} self.device = device self._worker_tracks: dict[int, dict] = {} def process_frame(self, frame: np.ndarray, camera_id: str, timestamp: float = None) -> dict: if timestamp is None: timestamp = time.time() # Улучшение для тёмных/пыльных условий enhanced = self._enhance_low_light(frame) results = self.model.track( enhanced, persist=True, conf=0.40, verbose=False, tracker='bytetrack.yaml' ) workers_status = [] violations = [] if results[0].boxes is None: return self._empty_result(camera_id, timestamp) persons = {} ppe_items = {} for box in results[0].boxes: cls_id = int(box.cls.item()) cls_name = self.MINE_PPE_CLASSES.get(cls_id, 'unknown') x1, y1, x2, y2 = map(int, box.xyxy[0]) cx, cy = (x1+x2)//2, (y1+y2)//2 tid = int(box.id.item()) if box.id is not None else -1 if cls_name == 'person': persons[tid] = { 'bbox': [x1,y1,x2,y2], 'center': (cx,cy), 'has_helmet': False, 'has_lamp': False, 'has_vest': False, 'has_mask': False, 'violations': [] } elif cls_name in ('no_helmet', 'no_headlamp'): ppe_items[tid] = { 'type': cls_name, 'center': (cx, cy), 'violation': True } elif cls_name in ('mining_helmet', 'headlamp', 'reflective_jacket', 'dust_mask'): ppe_items[tid] = { 'type': cls_name, 'center': (cx, cy), 'violation': False } # Ассоциация PPE с работниками for item_tid, item_data in ppe_items.items(): nearest = self._find_nearest(item_data['center'], persons) if nearest is None: continue p = persons[nearest] if item_data['violation']: p['violations'].append(item_data['type']) else: t = item_data['type'] if t == 'mining_helmet': p['has_helmet'] = True elif t == 'headlamp': p['has_lamp'] = True elif t == 'reflective_jacket': p['has_vest'] = True elif t == 'dust_mask': p['has_mask'] = True # Оценка каждого работника for pid, pdata in persons.items(): in_danger = self._check_danger_zone(pdata['center']) compliance = (pdata['has_helmet'] and not pdata['violations'] and not in_danger) ws = MineWorkerStatus( worker_id=pid, bbox=pdata['bbox'], has_helmet=pdata['has_helmet'], has_lamp=pdata['has_lamp'], has_reflective_vest=pdata['has_vest'], has_mask=pdata['has_mask'], in_danger_zone=in_danger, proximity_to_machinery=False, compliance=compliance ) workers_status.append(ws) if not compliance or pdata['violations']: violations.append({ 'worker_id': pid, 'bbox': pdata['bbox'], 'issues': pdata['violations'] + (['danger_zone'] if in_danger else []), 'severity': 'critical' if in_danger else 'warning' }) total = len(workers_status) compliant = sum(1 for w in workers_status if w.compliance) return { 'camera_id': camera_id, 'timestamp': timestamp, 'workers': [w.__dict__ for w in workers_status], 'violations': violations, 'compliance_rate_pct': round(compliant/max(total,1)*100, 1), 'critical_alert': any(v['severity']=='critical' for v in violations) } def _enhance_low_light(self, frame: np.ndarray) -> np.ndarray: """Улучшение видимости в тёмных условиях шахты""" lab = cv2.cvtColor(frame, cv2.COLOR_BGR2LAB) clahe = cv2.createCLAHE(clipLimit=4.0, tileGridSize=(8,8)) lab[:,:,0] = clahe.apply(lab[:,:,0]) enhanced = cv2.cvtColor(lab, cv2.COLOR_LAB2BGR) # Небольшое повышение яркости enhanced = cv2.convertScaleAbs(enhanced, alpha=1.2, beta=20) return enhanced def _check_danger_zone(self, center: tuple) -> bool: for zone_id, polygon in self.danger_zones.items(): poly = np.array(polygon, dtype=np.int32) if cv2.pointPolygonTest(poly, (float(center[0]), float(center[1])), False) >= 0: return True return False def _find_nearest(self, center: tuple, persons: dict) -> Optional[int]: min_dist = 150 nearest = None cx, cy = center for pid, p in persons.items(): px, py = p['center'] dist = np.sqrt((cx-px)**2 + (cy-py)**2) if dist < min_dist: min_dist = dist nearest = pid return nearest def _empty_result(self, camera_id: str, timestamp: float) -> dict: return { 'camera_id': camera_id, 'timestamp': timestamp, 'workers': [], 'violations': [], 'compliance_rate_pct': 100.0, 'critical_alert': False } Як ми збираємо датасет і навчаємо модель?
Збір даних ведеться з камер на об'єкті в різних умовах: день, ніч, запорошеність. Розмітка виконується в LabelStudio експертами-безпечниками (8 класів). На етапі навчання застосовуємо аугментації: зміна яскравості, додавання шуму, імітація пилу (motion blur + Gaussian noise). Використовуємо YOLOv8/9 з переднавченими вагами на COCO, донавчаємо на нашому Mine Safety Dataset (15 000+ кадрів). Навчаємо на GPU A100 або RTX 4090 протягом 2–3 днів. Фінальна модель проходить валідацію на відкладеній вибірці — target mAP50 0.85+.
Як ми тестуємо і гарантуємо точність?
Порівнюємо детекцію з експертним відеоаналізом. Типові метрики:
| Умова | Detection Rate | False Positive |
|---|---|---|
| Нормальне освітлення (відкритий кар'єр) | 93–97% | 2–4% |
| Темна шахта (CLAHE enhanced) | 82–89% | 6–12% |
| Пил/дим (коефіцієнт зниження 15–30%) | 72–82% | 10–18% |
| Тепловізор (LWIR, будь-які умови) | 88–94% | 3–7% |
Тепловізор LWIR кращий за RGB-камери в умовах пилу та диму в 2–3 рази по точності детекції. Ми рекомендуємо комбінацію RGB+LWIR для підземних ділянок. Вартість проєкту розраховується індивідуально в залежності від кількості камер та зон контролю. Економія на штрафах і простоях складає до 40% річних.
Що входить в роботу?
Ми беремо на себе повний цикл: аудит поточної системи відеоспостереження, збір датасету (розмітка з урахуванням специфіки шахти), навчання моделі, налаштування трекера, інтеграція з SCADA та MES, поставка сервера або інференс на існуючому обладнанні.
- Документація: ETL-схема потоків, API-документація (REST/RTSP), інструкція з експлуатації.
- Доступ до веб-дашборду з реальним compliance_rate_pct, тепловою картою небезпечних зон.
- Навчання операторів (2 дні, онлайн або на об'єкті).
- Техпідтримка 3 місяці після запуску.
Деталі інтеграції зі SCADA
Інтеграція реалізується через OPC-UA або Modbus TCP. Система передає сигнали тривоги (danger_zone, violation) безпосередньо на SCADA-сервер, що дозволяє автоматично блокувати обладнання при порушенні ЗІЗ в небезпечній зоні. Час реакції — не більше 500 мс від детекції до видачі сигналу.Орієнтовні терміни впровадження
| Задача | Термін |
|---|---|
| PPE моніторинг для кар'єру (хороше освітлення) | 4–6 тижнів |
| Підземна шахта + ІЧ + SCADA інтеграція | 10–16 тижнів |
| Enterprise mine safety платформа | 18–28 тижнів |
Точна оцінка — після аудиту. Ми виїжджаємо на об'єкт або аналізуємо записи з камер. Оцінимо проєкт безкоштовно — зв'яжіться з нами та отримайте консультацію.
Гарантії та супровід
Понад 5 років у промисловому CV, 30+ впроваджень, команда з senior AI/ML-інженерів. Наші системи працюють на шахтах у Казахстані, Росії та ПАР. Даємо гарантію compliance rate не нижче 85% на етапі приймання. За даними National Institute for Occupational Safety and Health, автоматизований моніторинг ЗІЗ знижує травматизм на 35–50%. Зв'яжіться з нами для безкоштовного аудиту вашого об'єкта. Замовте демо-доступ до системи.







