Свёртка на чистом PHP: четыре цикла находят границы на картинке
Свёрточные сети кажутся чёрным ящиком, пока не напишешь свёртку руками. Автор восьмой части серии для PHP-разработчиков берёт картинку 5×5, ядро 3×3 и четыре вложенных цикла. Фильтр скользит по пикселям, перемножает значения с весами и складывает: на тёмной зоне получается 0, на границе 570.
AI-обработка оригинала Habr AI; редакция Hamidun News
Большинство разработчиков слышали про свёрточные нейросети, но мало кто понимает, что происходит внутри слоя. Восьмая часть серии «AI для PHP-разработчиков» снимает этот туман: автор реализует свёртку на чистом PHP 8.1+, без библиотек и готовых ML-алгоритмов.
Как компьютер видит картинку
Для машины изображение это матрица чисел. В чёрно-белом варианте каждый пиксель принимает значение от 0 (чёрный) до 255 (белый). В примере берётся картинка 5×5: три левых столбца со значением 10 и два правых со значением 200. Между третьим и четвёртым столбцами проходит вертикальная граница, её и нужно найти.
Для этого используется ядро свёртки (kernel), небольшая матрица весов 3×3. Слева стоят -1, в центре 0, справа 1. Ядро сравнивает яркость левой и правой частей участка: если они похожи, слагаемые гасят друг друга, если различаются, результат большой по модулю.
Как это работает в коде
Функция convolve() принимает входную матрицу и ядро. Размер результата считается просто: ширина входа минус ширина ядра плюс один, то же для высоты. Для 5×5 и 3×3 получается карта признаков 3×3. Два внешних цикла двигают окно по изображению, два внутренних перемножают пиксели с весами и копят сумму.
В реализации stride равен 1, padding равен 0, ядро не переворачивается. Строго говоря, это cross-correlation, а не математическая свёртка, но в глубоком обучении её принято называть свёрткой. Значения результата не обрезаются до диапазона 0–255: карта признаков может содержать отрицательные числа и значения выше 255.
На выходе получается матрица, где первая колонка состоит из нулей, а две другие равны 570. Для однородной тёмной области фильтр не видит перепада, и результат нулевой. Когда окно захватывает и тёмные, и светлые пиксели, каждая строка даёт 190, а три строки в сумме дают 570.
Почему два отклика на одну границу
Два значения 570 не означают две границы. Окно шириной 3 пикселя при сдвиге на единицу дважды захватывает переход от тёмного к светлому, поэтому отклик держится в двух соседних позициях. Это нормальное поведение ядра, а не баг.
Дальше в статье автор меняет веса и ищет горизонтальные границы, показывая, что смена фильтра меняет то, на что реагирует слой.
Что с этим делать
Практический вывод скромный, но честный. Для продакшена такой код не годится: четыре вложенных цикла на PHP будут медленными на реальных изображениях, а для серьёзной работы нужны оптимизированные библиотеки или вызов внешних моделей. Зато если вы работаете с компьютерным зрением через API или расширения, понимание свёртки помогает читать документацию, отлаживать неожиданные результаты и понимать, что именно учит сеть: в CNN веса ядер не задаются вручную, а подбираются в обучении.
Статья полезна как учебный материал для PHP-команд, которые хотят разобраться в основе CNN без перехода на Python.
- 23 окт. 2026 г.Парадокс ИИ-разработки: почему на чистом листе скорость растёт на 55%, а в зрелом коде падает на 19%
- 3 июл. 2026 г.Нейросеть для прогноза ВВП на C++ без TensorFlow: работает на Arduino за 400 рублей
- 9 окт. 2026 г.SLVR на Qwen2.5-VL-7B прибавил 14,2 пункта на BLINK Relation без текстового CoT
- 22 окт. 2026 г.AgentVQA проверил 22 VLM на агентных задачах: лучшая набрала лишь 58,5%
Вопросы и ответы по материалу
Что известно по теме: как компьютер видит картинку?
Для машины изображение это матрица чисел. В чёрно-белом варианте каждый пиксель принимает значение от 0 (чёрный) до 255 (белый). В примере берётся картинка 5×5: три левых столбца со значением 10 и два правых со значением 200. Между третьим и четвёртым столбцами проходит вертикальная граница, её и нужно найти. Для этого используется ядро свёртки (kernel), небольшая матрица весов 3×3. Слева стоят -1, в центре 0, справа 1.
Что известно по теме: как это работает в коде?
Функция convolve() принимает входную матрицу и ядро. Размер результата считается просто: ширина входа минус ширина ядра плюс один, то же для высоты. Для 5×5 и 3×3 получается карта признаков 3×3. Два внешних цикла двигают окно по изображению, два внутренних перемножают пиксели с весами и копят сумму. В реализации stride равен 1, padding равен 0, ядро не переворачивается. Строго говоря, это cross-correlation, а не математическая свёртка, но в глубоком обучении её принято называть свёрткой.
Что известно по теме: почему два отклика на одну границу?
Два значения 570 не означают две границы. Окно шириной 3 пикселя при сдвиге на единицу дважды захватывает переход от тёмного к светлому, поэтому отклик держится в двух соседних позициях. Это нормальное поведение ядра, а не баг. Дальше в статье автор меняет веса и ищет горизонтальные границы, показывая, что смена фильтра меняет то, на что реагирует слой.
Протестируйте новые LLM и мультимодальные модели в одном окне
Платформа Nomad AI (nomadnet.ai) даёт прямой доступ к Claude Opus 5.5, GPT-6, Gemini 3.1, DeepSeek и автономным агентам без VPN, зарубежных карт и зоопарка подписок.
Главное из мира ИИ — раз в неделю
7 ключевых событий недели, отобранных вручную. Без шума, репостов и пресс-релизов.
Готово! Проверьте почту — мы отправили подтверждение.