Skip to content

Instantly share code, notes, and snippets.

@pnlybubbles
Last active January 3, 2016 08:19
Show Gist options
  • Save pnlybubbles/8435425 to your computer and use it in GitHub Desktop.
Save pnlybubbles/8435425 to your computer and use it in GitHub Desktop.
適当に書いた画像変換プログラム。なにが起きてるかよくわからない。むちゃくちゃ遅い。
# encoding: utf-8
# require "pp"
# require "pry"
require "RMagick"
include Magick
module ImageAnalize
class MagickItem
attr_reader :img
def initialize(img_magick)
@img = img_magick
end
def to_dict_array
img_da = []
@img.each_pixel do |p, x, y|
img_da[y] ||= []
img_da[y][x] = p
end
return DictArrayItem.new(img_da)
end
end
class DictArrayItem
def initialize(img_da)
@img = img_da
end
def to_hsla
return DictArrayItem.new(@img.map { |y_p| y_p.map { |p| p.to_hsla } })
end
def to_diff
img_delta = []
th = []
@img.each_with_index do |y_p, y|
th[y] = Thread.new do
y_p.each_with_index do |p, x|
p_here = p
p_prev = around_pixel(x, y, -1, 0)
p_next = around_pixel(x, y, 1, 0)
p_above = around_pixel(x, y, 0, -1)
p_below = around_pixel(x, y, 0, 1)
p_above_prev = around_pixel(x, y, -1, -1)
p_below_next = around_pixel(x, y, 1, 1)
p_above_next = around_pixel(x, y, 1, -1)
p_below_prev = around_pixel(x, y, -1, 1)
p_delta_horizontal = diff(p_prev, p_next, 1)
p_delta_vertical = diff(p_above, p_below, 1)
p_delta_topleft_bottomright = diff(p_above_prev, p_below_next, Math.sqrt(2))
p_delta_topright_bottomleft = diff(p_above_next, p_below_prev, Math.sqrt(2))
p_delta = balance(p_delta_horizontal, p_delta_vertical, p_delta_topleft_bottomright, p_delta_topright_bottomleft)
img_delta[y] ||= []
img_delta[y][x] = p_delta
end
end
end
th.each { |thj| thj.join }
return DictArrayItem.new(img_delta)
end
def calibrate(*max_calibrate)
max_value = @img.map { |x_a| x_a.transpose.map { |a| a.max } }.transpose.map { |a| a.max }
calibrate_img = @img.map do |y_p|
y_p.map do |p|
(0...max_calibrate.length).to_a.map do |i|
max_calibrate[i] * (1 - p[i] / max_value[i])
end
end
end
return DictArrayItem.new(calibrate_img)
end
def set_all(*p_all)
return DictArrayItem.new(@img.map { |y_p| y_p.map { |p| p.zip(p_all).map { |v| v[1] || v[0] } } })
end
def to_magick
img_new = Magick::Image.new(@img[0].length, @img.length)
@img.each_with_index do |y_p, y|
y_p.each_with_index do |p, x|
pixel = Magick::Pixel.from_hsla(*p)
img_new.pixel_color(x, y, pixel)
end
end
return MagickItem.new(img_new)
end
private
def diff(p1, p2, d)
return p1.zip(p2).map { |a| (a[0] - a[1]).abs / d }
end
def balance(*p)
return p[0].zip(*p[1..-1]).map { |a| a.inject(0) { |r, v| r += v } / p.length }
end
def around_pixel(x, y, rx, ry)
if (x + rx > 0 && x + rx < @img[0].length - 1) && (y + ry > 0 && y + ry < @img.length - 1)
return @img[y + ry][x + rx]
else
return @img[y][x]
end
end
end
end
# -- ui --
img_file = ARGV[0]
start_time = Time.now.instance_eval { '%s.%03d' % [strftime('%Y%m%d%H%M%S'), (usec / 1000.0).round] }.to_f
puts "start : #{start_time}"
puts "load file : #{File.expand_path(img_file)}"
img_src = Magick::ImageList.new(img_file)
puts "size : #{img_src.columns} x #{img_src.rows}"
img_analize = ImageAnalize::MagickItem.new(img_src)
img_result = img_analize.to_dict_array.to_hsla.to_diff.calibrate(*[255.0, 255.0, 255.0, 1.0]).set_all(*[0, 0, nil, 1.0]).to_magick.img
img_new_name = img_file.gsub(/\.png/, "_delta_#{Time.now.strftime('%y-%m-%d_%H.%M.%S')}.png")
img_result.write(img_new_name)
puts "generate file : #{File.expand_path(img_new_name)}"
finish_time = Time.now.instance_eval { '%s.%03d' % [strftime('%Y%m%d%H%M%S'), (usec / 1000.0).round] }.to_f
puts "finish : #{finish_time}"
puts "elapsed time : #{finish_time - start_time}"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment