111 слов | 1 минута
YOLOv8 + Bitrix: интеграция через Python-микросервис
Напрямую запускать нейросети из PHP через exec() неэффективно: загрузка модели занимает 1–3 секунды на каждый запрос.
Оптимальная архитектура:
- Python-скрипт с FastAPI загружает модель один раз при старте и ждёт запросы.
- PHP отправляет изображение на локальный порт и мгновенно получает JSON.
Bitrix (PHP) → HTTP POST → Python FastAPI (порт 5000) → YOLOv8 → JSON
Настройка Python-сервиса
Установка зависимостей
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)
cards = []
for r in results:
for box in r.boxes:
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
Для production используйте systemd или supervisor для фонового запуска.
Интеграция в PHP (Битрикс)
use Bitrix\Main\Web\HttpClient;
use Bitrix\Main\Web\Json;
function recognizeCards($filePath)
{
$httpClient = new HttpClient();
$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";
$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) {
return false;
}
}
return false;
}
Пример вызова
$imagePath = $_SERVER["DOCUMENT_ROOT"] . "/upload/image.jpg";
$cards = recognizeCards($imagePath);
if ($cards) {
foreach ($cards as $card) {
echo "Объект: <b>" . $card['card'] . "</b> ";
echo "(Точность: " . round($card['confidence'] * 100) . "%)<br>";
}
}
Преимущества архитектуры
| Параметр | Значение |
|---|---|
| Скорость | Модель загружается один раз, обработка запроса — доли секунды |
| Изоляция | Ошибка в Python-скрипте не влияет на PHP-процесс Битрикса |
| Масштабируемость | При высокой нагрузке Python-сервис можно вынести на отдельный GPU-сервер |
| Обновление модели | Замена model.onnx/.pt без изменений на стороне PHP |