Convolution in Pure PHP: Four Loops Find Edges in an Image
Convolutional networks seem like a black box until you write a convolution by hand. The author of part eight of the series for PHP developers takes a 5×5 image, a 3×3 kernel and four nested loops. The filter slides across the pixels, multiplies values by weights and sums them up: a dark area yields 0, while the edge yields 570.
AI-processed from Habr AI; edited by Hamidun News
Most developers have heard of convolutional neural networks, but few understand what happens inside the layer. Part eight of the series "AI for PHP Developers" clears away that fog: the author implements convolution in pure PHP 8.1+, with no libraries or ready-made ML algorithms.
How a Computer Sees an Image
For a machine, an image is a matrix of numbers. In grayscale, each pixel takes a value from 0 (black) to 255 (white). The example uses a 5×5 image: the three left columns have the value 10 and the two right columns have the value 200. A vertical edge runs between the third and fourth columns, and that is what needs to be found.
For this, a convolution kernel is used, a small 3×3 matrix of weights. The left column holds -1, the center 0, the right 1. The kernel compares the brightness of the left and right parts of a patch: if they are similar, the terms cancel each other out; if they differ, the result is large in absolute value.
How It Works in Code
The convolve() function takes an input matrix and a kernel. The size of the result is simple to compute: input width minus kernel width plus one, and the same for height. For 5×5 and 3×3, this gives a 3×3 feature map. The two outer loops move the window across the image, and the two inner loops multiply pixels by weights and accumulate the sum.
In this implementation, stride is 1, padding is 0, and the kernel is not flipped. Strictly speaking, this is cross-correlation rather than mathematical convolution, but in deep learning it is conventionally called convolution. The result values are not clipped to the 0–255 range: a feature map can contain negative numbers and values above 255.
The output is a matrix whose first column consists of zeros, while the other two equal 570. For a uniform dark region, the filter sees no change, and the result is zero. When the window covers both dark and light pixels, each row yields 190, and the three rows sum to 570.
Why Two Responses for One Edge
Two values of 570 do not mean two edges. A window 3 pixels wide, shifted by one, captures the dark-to-light transition twice, so the response persists in two adjacent positions. This is normal kernel behavior, not a bug.
Later in the article, the author changes the weights and searches for horizontal edges, showing that changing the filter changes what the layer responds to.
What to Do With This
The practical takeaway is modest but honest. This code is not suitable for production: four nested loops in PHP will be slow on real images, and serious work requires optimized libraries or calls to external models. However, if you work with computer vision through APIs or extensions, understanding convolution helps you read documentation, debug unexpected results and understand what exactly the network learns: in a CNN, kernel weights are not set by hand but are tuned during training.
The article is useful as learning material for PHP teams who want to understand the basis of CNNs without switching to Python.
- Oct 23, 2026The AI development paradox: why greenfield coding speeds up 55% while mature codebases slow down 19%
- Jul 3, 2026A GDP forecasting neural network in C++ with no TensorFlow: it runs on a 400-ruble Arduino
- Oct 9, 2026SLVR Adds 14.2 Points on BLINK Relation to Qwen2.5-VL-7B Without Text CoT
- Oct 22, 2026AgentVQA Tests 22 VLMs on Agentic Tasks: The Best Scores Just 58.5%
Key Questions Answered
How a Computer Sees an Image?
For a machine, an image is a matrix of numbers. In grayscale, each pixel takes a value from 0 (black) to 255 (white). The example uses a 5×5 image: the three left columns have the value 10 and the two right columns have the value 200. A vertical edge runs between the third and fourth columns, and that is what needs to be found. For this, a convolution kernel is used, a small 3×3 matrix of weights. The left column holds -1, the center 0, the right 1.
How It Works in Code?
The convolve() function takes an input matrix and a kernel. The size of the result is simple to compute: input width minus kernel width plus one, and the same for height. For 5×5 and 3×3, this gives a 3×3 feature map. The two outer loops move the window across the image, and the two inner loops multiply pixels by weights and accumulate the sum. In this implementation, stride is 1, padding is 0, and the kernel is not flipped.
Why Two Responses for One Edge?
Two values of 570 do not mean two edges. A window 3 pixels wide, shifted by one, captures the dark-to-light transition twice, so the response persists in two adjacent positions. This is normal kernel behavior, not a bug. Later in the article, the author changes the weights and searches for horizontal edges, showing that changing the filter changes what the layer responds to.
Test Frontier LLMs & Autonomous Agents in One Workspace
Run Claude Opus 5.5, GPT-6, Gemini 3.1, and DeepSeek side-by-side in Nomad AI (nomadnet.ai) — unified model routing, deep research, and multimodal workflows under one subscription.
The AI world, distilled — once a week
Seven stories that actually mattered, hand-picked. No noise, no reposts, no press releases.
Done! Check your inbox for a confirmation.