Гірничодобувні підприємства — другий за смертністю сектор після будівництва. У підземних шахтах ризик фатальних інцидентів у 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%. Зв'яжіться з нами для безкоштовного аудиту вашого об'єкта. Замовте демо-доступ до системи.







