Reputation: 2281
I want to implement the gradient gaussian blur effect. By gradient, I mean the same effect as Photoshop. Take the following image as an example:
(source: photokaboom.com)
The blurriness of the image reduces as the y coordinate increases (take the top-left point as origin).
I know how to use kernel and FFT to implement normal guassian blur, but I don't know how to change the degree on blurriness with the change of y coordinate. I've tried to split the image into different lines (in the direction of y-axis) and apply different kernel to these blocks, but the effect is quite annoying in the joint part of these lines.
I've also tried the calculate the result pixel one by one, and fill the kernel on the run, the effect is quite good, but the algorithm is simply too slow!!
So I wonder how to implement a fast gradient gaussian blur algorithm?
Big thanks!
Upvotes: 1
Views: 2026
Reputation: 4525
The blur is 2D operation and it is hard to handle row-wise with different degree of blur in each row. Before considering Gaussian blur I recommend to explore a box blur solution that is visually hardly distinguishable from the Gaussian one.
A way to go is to use an Integral image. Creating it yourself is a good exercise and it is really simple: the size of the integral image is the same as your original image. The content is a sum of all pixel intensities above and to the left of a current pixel (we talk about each rgb channel separately). A simple iterative way to build an Integral image is to use this formula:
I(x,y)= Gray(x, y) + I(x-1, y) + I(x, y-1) - I(x-1, y-1)
A tip: you can do it even quicker if you first calculate a temporal array where each element just sums intensities to the left of it in the same row.
The beauty of integral images is that they allow to calculate the sum in a window of arbitrary size in constant time. In fact, this just require 4 operations: for a window at x1, y1, x2, y2 and integral image I(x, y)
sum(x1, y1, x2, y2) = I(x2, y2)+I(x1, y1)-I(x1, y2)-I(x2, y1)
Thus you can implement a fast blur box filter (you won’t see the difference between box and Gaussian filter effects visually)
Iblur(x, y, sz) = I(x+sz, y+sz)+I(x, y)-I(x+sz, y)-I(x, y+sz)/[sz*sz]
All you need to do now is to apply your fast blur operation to all your pixels varying sz as a function of y. It will take only 4*w*h operations; building your integral image is also O(h*w) so you actually can do it in the linear time. Do it for each channel separately and combine them in a new rgb.
Finally, integral image calculation is the basis for Haar box filters (instead of wavelets or Gabors) for fast detection of faces or objects, tracking, etc. Their speed is what allows finding faces in real-time nowadays so they are worth studying.
Upvotes: 2