Home »
Articles
Bicubic Interpolation vs. AI Super-Resolution: How Upscaling Works
Last updated : October 18, 2026
Call resize() on a small image in Python, make it four times bigger, and it comes out soft. Every time. I remember being a bit annoyed by that as a student, because the online image upscaler I'd tried on the same photo gave back something way crisper, and I couldn't work out what it knew that my one line of code didn't. The short answer is that interpolation only spreads the old pixels apart, and a neural network predicts new detail. The longer answer is easier to see than to read, so below there's code for both, ready to paste into a notebook.
What Interpolation Actually Does
Make an image 2× bigger and you've got four times the pixels, which means 3 out of every 4 of them are blank and need to be filled with something. How you fill them? That's what interpolation means, nothing fancier.
The laziest option is nearest-neighbour. Copy the closest old pixel, done, hard edges stay hard and you get chunky stair steps for free. Bilinear mixes the 4 closest pixels. Bicubic reaches out to 16 of them (a 4×4 patch) and fits a smooth curve, and since that looks decent on most photos it's what editors use unless you tell them otherwise. Lanczos looks even further out with a windowed sinc; it's a touch crisper than bicubic, but now and then you'll spot ringing, faint halos right beside a strong edge.
All four share one problem though. They average, and you can't average your way to information that was never there.
Trying the Classic Methods with Pillow
Pillow lets you compare them in a few lines (pip install pillow first):
Now open the four PNGs and zoom into hair, grass or a bit of text. Nearest is pure Minecraft. Bilinear is blurry. Bicubic and Lanczos are nicer, sure, but still soft, and you'll notice it straight away. (On Pillow versions older than 9.1 the constants are Image.NEAREST, Image.BICUBIC and so on.)
How AI Super-Resolution Is Different
There's no fixed formula in a super-resolution model. It learned from piles of image pairs, a sharp photo as the answer and a shrunk, blurred or badly compressed copy of the same photo as the question. Do that enough times and the network starts to know things like "a fuzzy diagonal like this is usually a clean edge" or "this grey smear on a head is probably hair", and it redraws them that way.
So the two methods are basically answering different questions. Bicubic wants the average of the neighbours. The network is asking which sharp picture could have turned into this blurry mess. Turns out, for real photos, that question has a much better answer. It's also exactly why AI output now and then shows you detail that looks fine and simply wasn't there.
Running a Pre-Trained Model with OpenCV
You don't have to train a thing, by the way. Install the contrib build of OpenCV and you get dnn_superres, which knows how to load EDSR, ESPCN, FSRCNN and LapSRN models people already trained.
Then you need the weights. I used EDSR_x4.pb here; OpenCV's dnn_superres docs point to the GitHub repos where each one lives. Put it in the same folder as the script:
Heads up, EDSR is big and slow on a CPU once images get large. For quick experiments I'd swap in ESPCN_x4.pb with setModel("espcn", 4), way faster, slightly less sharp.
Measuring the Difference (and Why the Numbers Can Fool You)
Want a number? Start with a sharp photo, shrink it, blow it back up both ways and see which one lands closer to where you started. People usually use PSNR for that (peak signal-to-noise ratio, measured in dB) and OpenCV can compute it for you:
On ordinary photos EDSR usually wins by a couple of decibels, which is a real gap. Here's what most tutorials leave out, though. PSNR likes being close on average, and a slightly blurry guess is often pretty close on average! That's how GAN models like ESRGAN, whose textures look far more real to a person, can end up with a lower PSNR than smoother networks. Papers add perceptual scores such as LPIPS for exactly this reason. Look at the pictures, don't just trust the number.
When to Use Which Approach
I still use bicubic a lot. It's instant, it gives the same output every run and it never makes anything up, which is what you want for thumbnails, UI assets, scientific images, or any pipeline where surprise detail would be a bug.
For stuff people will actually look at, an old family photo, a tiny product shot that has to go to print, a compressed image you need inside a design, super-resolution is the better tool. Keep a human looking at text, faces and anything that might end up as evidence, that's all.
My rule of thumb: a machine judges the output or it must be reproducible, go classic. People judge it, try super-resolution and compare.
Final Thoughts
Interpolation averages what's already there, so the image gets bigger without really getting sharper. A super-resolution network has seen millions of examples of sharp images and guesses the missing detail from that. Run the snippets above on one of your own photos and put the results next to each other, and honestly, you probably won't want plain bicubic for photos again.