Skip to content

Instantly share code, notes, and snippets.

@pachacamac
Created December 11, 2014 12:08
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save pachacamac/ca8d4ff22a177f90edb8 to your computer and use it in GitHub Desktop.
Save pachacamac/ca8d4ff22a177f90edb8 to your computer and use it in GitHub Desktop.
3d scanner code v1
begin
require 'oily_png'
rescue LoadError
STDERR.puts 'Warning: Gem oily_png not found. Using chunky_png instead. This will be slow!'
require 'chunky_png'
end
def load_image(file)
ChunkyPNG::Image.from_file(file)
rescue ChunkyPNG::SignatureMismatch
`convert '#{file}' '#{file}.png'`
img = ChunkyPNG::Image.from_file("#{file}.png").tap{File.delete "#{file}.png"}
end
def find_laser(img, opts={})
threshold = opts[:threshold] || 127
channel = opts[:channel] || :r
out_img = ChunkyPNG::Image.new(img.width, img.height, ChunkyPNG::Color::BLACK)
out_raw = []
img.height.times.each do |y|
max_intensity, max_intensity_pos = 0, 0
img.width.times.each do |x|
intensity = ChunkyPNG::Color.send(channel, img[x,y])
if intensity > max_intensity
max_intensity = intensity
max_intensity_pos = x
end
end
if max_intensity >= threshold
out_img[max_intensity_pos, y] = ChunkyPNG::Color::WHITE
out_raw << [max_intensity_pos, y]
end
end
[out_img, out_raw]
end
x_range = (230..330) #rough estimation
y_range = (254..473) #rough estimation
normal_x = (x_range.min + x_range.max) / 2 #rough estimation
px_per_frame = 3 #rough estimation replace with encoder-band later maybe
laser_threshold = 127
laser_color_channel = :r
pcf = File.open('point_cloud.xyz', 'w')
depth_map = ChunkyPNG::Image.new(500, 500, ChunkyPNG::Color.rgb(127,127,127))
Dir['ginger_frames/*.jpg'].sort.each_with_index do |file, idx|
puts file
img = load_image(file).crop(x_range.min, y_range.min, x_range.max - x_range.min, y_range.max - y_range.min)
laser_img, laser_raw = find_laser(img, threshold: laser_threshold, channel: laser_color_channel)
laser_raw.each do |x,y|
xyz = [idx * px_per_frame, y, normal_x - x].map{|e| e.round(2)}
_z = 127 + [[xyz[2].to_i / 2, -127].max, 128].min
depth_map[xyz[0],xyz[1]] = ChunkyPNG::Color.rgb(_z,_z,_z)
pcf.puts xyz.join(' ')
end
end
depth_map.save('depth_map.png')
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment