170 слов | 1 минута

Интеграция YOLOv8 с PHP (1C-Битрикс)

Напрямую запускать нейросети внутри PHP (через exec) неэффективно, так как загрузка модели в память занимает время (1–3 секунды на каждый запрос).

Оптимальное решение: Архитектура микросервиса.

  1. Python-скрипт висит в памяти, один раз загружает модель и ждет запросы.
  2. PHP отправляет картинку на локальный порт (например, 5000) и мгновенно получает JSON с координатами карт.

Настройка Python сервиса

Этот сервис будет работать на том же сервере, где установлен 1С-Битрикс.

Установка зависимостей

Выполните в консоли сервера:

pip install fastapi uvicorn ultralytics python-multipart

Создание сервиса

Создайте файл poker_api.py:

from fastapi import FastAPI, UploadFile, File
from ultralytics import YOLO
from PIL import Image
import io

app = FastAPI()

# Загружаем модель ОДИН раз при старте
# Укажите полный путь к файлу, если он не в той же папке
model = YOLO("yolov8m.pt") 

@app.post("/predict")
async def predict(file: UploadFile = File(...)):
    # Читаем картинку из памяти без сохранения на диск
    image_data = await file.read()
    image = Image.open(io.BytesIO(image_data))

    # Распознаем
    results = model(image)

    # Формируем JSON ответ
    cards = []
    for r in results:
        for box in r.boxes:
            # Получаем ID класса, имя и точность
            cls_id = int(box.cls[0])
            class_name = model.names[cls_id]
            conf = float(box.conf[0])

            cards.append({
                "card": class_name,
                "confidence": round(conf, 2),
                "box": box.xywh.tolist()[0] # координаты [x, y, w, h]
            })

    return {"result": cards}

Запуск сервиса

Запустите сервер (для тестов):

uvicorn poker_api:app --host 127.0.0.1 --port 5000

(Для продакшна рекомендуется использовать systemd или supervisor, чтобы скрипт работал в фоне).

Интеграция в PHP (Битрикс)

Используем стандартный класс Bitrix\Main\Web\HttpClient, чтобы не зависеть от сторонних библиотек.

Добавьте этот код в ваш класс, компонент или init.php:

use Bitrix\Main\Web\HttpClient;
use Bitrix\Main\Web\Json;

function recognizeCards($filePath) {
    $httpClient = new HttpClient();

    // Формируем multipart-запрос вручную (для отправки файла)
    $boundary = '--------------------------' . microtime(true);
    $httpClient->setHeader('Content-Type', 'multipart/form-data; boundary=' . $boundary);

    // Проверка существования файла
    if (!file_exists($filePath)) {
        return false;
    }

    $fileContent = file_get_contents($filePath);
    $filename = basename($filePath);

    // Тело запроса
    $body = "--" . $boundary . "\r\n";
    $body .= "Content-Disposition: form-data; name=\"file\"; filename=\"" . $filename . "\"\r\n";
    $body .= "Content-Type: image/jpeg\r\n\r\n";
    $body .= $fileContent . "\r\n";
    $body .= "--" . $boundary . "--\r\n";

    // Отправляем запрос локальному Python-сервису
    $response = $httpClient->post('http://127.0.0.1:5000/predict', $body);

    // Обработка ответа
    if ($httpClient->getStatus() == 200) {
        try {
            $data = Json::decode($response);
            return $data['result']; // Возвращаем массив карт
        } catch (\Exception $e) {
            // Логирование ошибки JSON
            return false;
        }
    }

    return false;
}

Пример использования

$imagePath = $_SERVER["DOCUMENT_ROOT"] . "/upload/poker_screen.jpg";
$cards = recognizeCards($imagePath);

if ($cards) {
    foreach ($cards as $card) {
        echo "Карта: <b>" . $card['card'] . "</b> ";
        echo "(Вероятность: " . ($card['confidence'] * 100) . "%)<br>";
    }
} else {
    echo "Не удалось распознать карты или ошибка сервиса.";
}

Преимущества подхода

  1. Скорость: Модель YOLOv8m (Medium) весит ~50 МБ. При использовании микросервиса она загружается в оперативную память один раз. Обработка запроса занимает доли секунды.
  2. Надежность: Ошибка в Python-скрипте не уронит PHP-процесс Битрикса.
  3. Масштабируемость: При высокой нагрузке Python-сервис можно вынести на отдельный сервер с GPU.