Bart Wronski, a graphics programmer, writes about image processing, texture filtering, rendering and sometimes software engineering practice.
HN commenters link it for image deconvolution and bilinear filtering explanations, and discuss details of its blur kernels and the half-pixel offset.
The major dithering algorithm that's missing from this list is blue-noise dithering. This is very similar to "ordered dithering"; you can think of ordered dithering as either thresholding the pixel values with a different threshold value on each pixel, following a regular pattern, or as adding a different offset value to each pixel, following a regular pattern, and thresholding the result with a constant threshold. Blue-noise dithering replaces the regular pattern with a random pattern that's been high-pass filtered. This has all the advantages of ordered dithering, in particular avoiding "crawling" patterns during animation, but avoids the repetitive patterns and line artifacts it introduces.
https://nelari.us/post/quick_and_dirty_dithering/ is the best quick introduction to the technique that I've seen. There's a more comprehensive introduction at https://momentsingraphics.de/BlueNoise.html. https://bartwronski.com/2016/10/30/dithering-part-three-real-world-2d-quantization-dithering/ also demonstrates it, comparing it to other dithering algorithms.
Ulichney introduced blue noise to dithering in 01988 as a refinement of "white-noise dithering", also known as "random dithering", where you just add white noise before thresholding: https://cv.ulichney.com/papers/1988-blue-noise.pdf. Ulichney's paper is also a pretty comprehensive overview of dithering algorithms at the time, and he also makes some interesting observations about high-pass prefiltering ("sharpening", for…
Cool, interesting links to code -- thank you! I chased down Intel's paper the code linked to describing how it works on archive.org.
https://web.archive.org/web/20110317025924/https://software.intel.com/en-us/articles/iir-gaussian-blur-filter-implementation-using-intel-advanced-vector-extensions
It's not just about using SIMD instructions (they help), and laying out memory to optimize cache performance (which also helps), but most importantly that Gaussian blur is a "separable filter" that you can break up into a horizontal and vertical pass, each of which require a lot fewer memory references (on the order of just two times the number of pixels times the kernel size, instead of the number of pixels times the kernel size squared):
IIR Gaussian Blur Filter Implementation using Intel® Advanced Vector Extensions
>This white paper proposes an implementation for the Infinite Impulse Response (IIR) Gaussian blur filter [1] [2] [3] using Intel® Advanced Vector Extensions (Intel® AVX) instructions. [...]
>The IIR Gaussian blur filter applies equation (1) on each pixel through two sequential passes:
The horizontal pass: This pass processes the input image left-to-right (row-wise), then right-to-left. The output of the left-to-right pass is added to the right-to-left pass.
>The vertical pass: Usually, the vertical pass processes the output from the horizontal pass top-to-bottom (column-wise), and then bottom-to-top. Accessing the input column-wise leads to a lot of cache blocks…
As a toy example if you have pixels a,b,c and you blur to (a+b)/2,(b+c)/2, you can recover back c - a. You might be able to have a good estimate of the boundary condition ("a"), e.g. you can just use (a+b)/2 as an approximation for "a", so the recovered result might look fairly close.
You'll basically want to look up the area of deconvolution. You can interpret it in linear algebra terms as trying to invert an ill-conditioned matrix, or in signal processing terms as trying to multiply by the inverse of the PSF. In real-world cases the main challenge is doing so without blowing up any error that comes from quantization noise (or other types of noise).
See https://bartwronski.com/2022/05/26/removing-blur-from-images-deconvolution-and-using-optimized-simple-filters/ and https://yuzhikov.com/articles/BlurredImagesRestoration1.htm
Assasin's Creed mentions of Geometry Shaders being used - (March, 2014, GDC) - https://bartwronski.files.wordpress.com/2014/03/ac4_gdc.pdf
possibly many others.
EDIT: Here is much more updated version (4 versions actually with much more detailed images/video and more notes) - from the author's web-page - http://bartwronski.com/2014/05/09/digital-dragons-2014-slides/
oh, and if you are looking for some fun graphics failures :)
http://igetyourfail.blogspot.com/2009/02/behold-power-of-geometry-shaders.html
I've experimented with that. It only works if you pick you pick a form of ordered dithering, like a Bayer index or Interleaved Gradient Noise[0][1]. Which looks pretty terrible compared to error diffusion dithering approaches like Sierra3. And even if you use ordered dithering it only somewhat helps with compression.
[0]https://bartwronski.com/2016/10/30/dithering-part-three-real-world-2d-quantization-dithering/
[1] https://www.iryoku.com/next-generation-post-processing-in-call-of-duty-advanced-warfare
I meant about where this line comes from:
mask = masks[0][0]
Presumably 0 is the class ID? For someone new to ML or object detection, it might not be obvious why you take the first channel here.
Also recent related reading: https://bartwronski.com/2020/03/15/using-jax-numpy-and-optimization-techniques-to-improve-separable-image-filters/
HN Discussion: https://news.ycombinator.com/item?id=22590360&ref=hvper.com&utm_source=hvper.com&utm_medium=website