РелизОткрытые веса · В работуHabr AI→ оригинал

Свёртка на чистом PHP: четыре цикла находят границы на картинке

Свёрточные сети кажутся чёрным ящиком, пока не напишешь свёртку руками. Автор восьмой части серии для PHP-разработчиков берёт картинку 5×5, ядро 3×3 и четыре вложенных цикла. Фильтр скользит по пикселям, перемножает значения с весами и складывает: на тёмной зоне получается 0, на границе 570.

AI-обработка оригинала Habr AI; редакция Hamidun News
Свёртка на чистом PHP: четыре цикла находят границы на картинке
Источник: Habr AI. Коллаж: Hamidun News.
Слушать статью
Паспорт материала и цифры
ПараметрДанные
ПервоисточникHabr AI ↗
Главный редактор
Свёртка в CNNчетыре цикла, умножение и сумма
Ключевой факт #2Ядро с весами -1, 0, 1 реагирует на вертикальную границу
Ключевой факт #3Одна граница даёт два отклика из-за размера окна

Большинство разработчиков слышали про свёрточные нейросети, но мало кто понимает, что происходит внутри слоя. Восьмая часть серии «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.

Сюжет

Вопросы и ответы по материалу

Что известно по теме: как компьютер видит картинку?

Для машины изображение это матрица чисел. В чёрно-белом варианте каждый пиксель принимает значение от 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 пикселя при сдвиге на единицу дважды захватывает переход от тёмного к светлому, поэтому отклик держится в двух соседних позициях. Это нормальное поведение ядра, а не баг. Дальше в статье автор меняет веса и ищет горизонтальные границы, показывая, что смена фильтра меняет то, на что реагирует слой.

ЖХ
Жемал Хамидун — CPO Alpina Digital, продакт-менеджер AlpinaGPT. Делает AI-продукты с 2019 года. Hamidun News — pet project, который вырос в production-агрегатор с 6000+ читателей.
✦ Единое AI-пространство · Nomad

Протестируйте новые LLM и мультимодальные модели в одном окне

Платформа Nomad AI (nomadnet.ai) даёт прямой доступ к Claude Opus 5.5, GPT-6, Gemini 3.1, DeepSeek и автономным агентам без VPN, зарубежных карт и зоопарка подписок.

Открыть Nomad AI →Автономный Nomad Agent
Что вы думаете?
Загружаем комментарии…