File size: 3,436 Bytes
2ebce2f d456ca5 2ebce2f d456ca5 2ebce2f d456ca5 2ebce2f d456ca5 2ebce2f 9eebbbf d456ca5 2ebce2f 387ddd5 2ebce2f 9eebbbf 2ebce2f bd636c2 2ebce2f d456ca5 2ebce2f d456ca5 2ebce2f 0e66bfe 2ebce2f d456ca5 2ebce2f | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 | import cv2
import numpy as np
import pandas as pd
from pathlib import Path
from src.config_loader import load_config
from src.ocr_utils_demo import ocr_title, ocr_sensors
def process_single_image(img: np.ndarray, color_ranges: dict):
"""
Обрабатывает одно изображение:
- вытаскивает титул;
- находит и оцифровывает сенсоры;
- возвращает структуру с результатом.
"""
# ---------- 1. Оцифровка титула ----------
h, w = img.shape[:2]
title_roi = img[:45, :int(w / 2.4)]
title_text = ocr_title(title_roi)
# ---------- 2. Оцифровка сенсоров ----------
hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
mask = None
for (lo, hi) in color_ranges.values():
lo_np = np.array(lo, dtype=np.uint8)
hi_np = np.array(hi, dtype=np.uint8)
cur = cv2.inRange(hsv, lo_np, hi_np)
mask = cur if mask is None else cv2.bitwise_or(mask, cur)
contours, _ = cv2.findContours(mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
rois, positions = [], []
for cnt in contours:
x, y, ww, hh = cv2.boundingRect(cnt)
if ww < 90 or hh < 17:
continue
if hh / ww > 1.5:
continue
hh_clamped = min(hh, 17)
roi = img[y:y + hh_clamped, x:x + ww]
rois.append(roi)
positions.append((x, y, ww, hh))
# ---------- 3. OCR сенсоров ----------
sensors = []
if rois:
ocr_results = ocr_sensors(rois)
for (x, y, ww, hh), result in zip(positions, ocr_results):
sensors.append({
"text": result["text"],
"score": result["score"],
"x": x,
"y": y,
"w": ww,
"h": hh
})
return title_text, sensors
# ---------------------------------------------------------
# Основной pipeline → Excel
# ---------------------------------------------------------
def process_image_to_excel(cfg: dict):
input_dir = Path(cfg["paths"]["input"])
output_dir = Path(cfg["paths"]["output"])
excel_name = cfg["export"]["excel_filename"]
output_dir.mkdir(parents=True, exist_ok=True)
excel_path = output_dir / excel_name
color_ranges = cfg["colors"]
results = []
for img_path in input_dir.glob("*.png"):
name = img_path.name
img = cv2.imread(str(img_path))
if img is None:
print(f"Не могу прочитать файл {name}")
continue
title_text, sensors = process_single_image(img, color_ranges)
for sen in sensors:
results.append({
"filename": name,
"title": title_text,
"sensor_name": sen["text"],
"score": sen["score"]
})
if not results:
print("⚠ Нет данных для записи.")
return
df = pd.DataFrame(results)
df.to_excel(excel_path, index=False, engine="openpyxl")
print(f"✅ Готово! Excel сохранён: {excel_path.resolve()}")
# ---------------------------------------------------------
# Запуск
# ---------------------------------------------------------
if __name__ == "__main__":
cfg = load_config("configs/config.yaml")
process_image_to_excel(cfg)
|