Cross-correlation slides a kernel over an image without flipping. Convolution flips the kernel 180° first. For symmetric kernels they are identical; for asymmetric kernels the outputs differ — and PyTorch conv2d actually performs cross-correlation.
Cross-correlation computes the dot product between a kernel K and each local patch of an image f. The kernel slides over the image in its original orientation: (f ⋆ K)[i,j] = Σ_{m,n} f[i+m, j+n] · K[m,n]. This is the direct matching operation — it finds how well the kernel pattern matches the local image region at each position.
Cross-correlation is the foundation of template matching: given a template (the kernel), the output is high wherever the image content resembles that template. It is also what CNNs compute — when you call torch.nn.Conv2d, PyTorch performs cross-correlation, not true mathematical convolution, even though the operation is called "convolution".
Convolution flips the kernel 180° (both horizontally and vertically) before computing the dot product: (f * K)[i,j] = Σ_{m,n} f[i+m, j+n] · K[−m,−n]. Equivalently, the flipped kernel K' = K[−m,−n] is used in a cross-correlation. For 2D, flipping 180° is the same as rotating by 180°.
True convolution is defined this way to satisfy the commutativity property: f * K = K * f. Cross-correlation does not commute. Convolution also preserves the impulse response property: convolving a signal with a delta function returns the signal unchanged. These mathematical properties make convolution the correct operation for linear time-invariant (LTI) signal processing theory.
For symmetric kernels (Gaussian, box, Laplacian) the flip makes no difference — the output is identical for correlation and convolution. The distinction only matters for asymmetric kernels like Sobel operators or the Prewitt gradient filter.
An asymmetric kernel produces different results under correlation vs. convolution. Consider the Sobel-x kernel: [[−1,0,1],[−2,0,2],[−1,0,1]]. Under correlation, it detects left-to-right edges (positive response on the right side of an edge). Under convolution (flipped kernel), it detects right-to-left edges. The sign of the gradient response flips.
Gaussian blur, box filter, Laplacian: K = K flipped. Correlation and convolution give identical results. The distinction is irrelevant in practice for these filters.
Sobel, Prewitt, motion blur: K ≠ K flipped. The gradient direction or motion direction flips between correlation and convolution. Always check the convention used by the library.
PyTorch, TensorFlow, and most deep learning frameworks name their layer Conv2d but implement cross-correlation. This is a well-known naming inconsistency. Because the weights are learned, the network can absorb the flip into the learned weights — a "flipped" weight matrix learned by correlation is equivalent to an "unflipped" weight learned by convolution. The mathematical distinction has no practical consequence in gradient-based learning.
Understanding the distinction matters when you need to port a filter defined in signal processing literature (which uses true convolution) to a deep learning framework (which uses correlation). The kernel must be pre-flipped to produce the same numerical output.
Say the answer out loud before revealing — recalling is what makes it stick. Next: Edge Detection with Sobel and Canny →
What is the difference between cross-correlation and convolution?
Why is convolution defined with a flip when cross-correlation seems more intuitive?
Does PyTorch's Conv2d perform true convolution or cross-correlation?
Give an example where correlation and convolution produce different results.