Last active
May 3, 2020 11:36
-
-
Save tuzz/62229fc253cacba2b7c1a0321b9afbaa to your computer and use it in GitHub Desktop.
Generate the weights/offsets for an efficient two-pass Gaussian blur filter of different sizes.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env ruby | |
# Generate the weights/ offsets for an efficient two-pass Gaussian blur filter of different sizes. | |
# Based on: http://rastergrid.com/blog/2010/09/efficient-gaussian-blur-with-linear-sampling/ | |
# | |
# Usage: ./gaussian [epsilon] | |
require "bigdecimal/util" | |
EPSILON = Float(ARGV[0] || 0.05) | |
@cache = {} | |
def row(n) | |
@cache[n] ||= (n == 0 ? [1] : [1, *row(n - 1).each_cons(2).map(&:sum), 1]) | |
end | |
last_size = 0 | |
1_000_000.times do |row_number| | |
next if row_number.odd? | |
row = row(row_number) | |
sum = row.sum | |
peak = row[row.size / 2].to_d / sum | |
# Remove weights that make negligible difference to the output image. | |
row = row.reject { |n| n.to_d / sum < peak * EPSILON } | |
sum = row.sum | |
# If we've already seen a row of this size, skip those that are more truncated. | |
next if row.size == last_size | |
last_size = row.size | |
midpoint = row.size / 2 | |
next if midpoint.odd? | |
weights_d = row.map { |n| n.to_d / sum }[midpoint..] | |
offsets_d = (0..midpoint).map(&:to_d) | |
break if weights_d[0] == 0 # Precision limit reached | |
weights_l = weights_d[1..].each_slice(2).map(&:sum) | |
offsets_l = offsets_d[1..].each_slice(2).map do |t1, t2| | |
numerator = offsets_d[t1] * weights_d[t1] + offsets_d[t2] * weights_d[t2] | |
denominator = weights_d[t1] + weights_d[t2] | |
numerator / denominator | |
end | |
weights_l.unshift(weights_d.first) | |
offsets_l.unshift(0.0) | |
puts "offsets_l: #{offsets_l.map(&:to_f).inspect}" | |
puts "weights_l: #{weights_l.map(&:to_f).inspect}" | |
puts "texture reads per pixel: #{weights_d.size}" | |
puts "effective kernel size: #{row.size}" | |
puts "pascal's triangle row: #{row_number}" | |
puts | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment