1
0
Fork 0
mirror of https://github.com/ruby-opencv/ruby-opencv synced 2023-03-27 23:22:12 -04:00
ruby-opencv/examples/match_kdtree.rb

88 lines
2.3 KiB
Ruby
Executable file

#!/usr/bin/env ruby
# -*- mode: ruby; coding: utf-8-unix -*-
# A sample of matching SURF feature points using kd-tree
# See http://tech.groups.yahoo.com/group/OpenCV/message/62318
require 'opencv'
include OpenCV
USE_EXTENDED_DESCRIPTOR = true
THRESHOLD = 1500
DESCRIPTOR_SIZE = USE_EXTENDED_DESCRIPTOR ? 128 : 64
img1 = CvMat.load('lenna.jpg', CV_LOAD_IMAGE_GRAYSCALE)
img2 = CvMat.load('lenna-rotated.jpg', CV_LOAD_IMAGE_GRAYSCALE)
puts 'Extracting features from img1 using SURF...'
param = CvSURFParams.new(THRESHOLD, USE_EXTENDED_DESCRIPTOR)
kp1, desc1 = img1.extract_surf(param)
puts "found #{kp1.size} keypoints from img1"
puts 'Extracting features from img2 using SURF...'
kp2, desc2 = img2.extract_surf(param)
puts "found #{kp2.size} keypoints from img2"
puts 'Matching keypoints...'
desc1mat = CvMat.new(kp1.size, DESCRIPTOR_SIZE, :cv32f, 1)
desc2mat = CvMat.new(kp2.size, DESCRIPTOR_SIZE, :cv32f, 1)
desc1.each_with_index { |desc, i|
desc.each_with_index { |d, j|
desc1mat[i, j] = CvScalar.new(d)
}
}
desc2.each_with_index { |desc, i|
desc.each_with_index { |d, j|
desc2mat[i, j] = CvScalar.new(d)
}
}
feature_tree = CvFeatureTree.new(desc1mat)
results, distances = feature_tree.find_features(desc2mat, 1, 250)
reverse_lookup = []
reverse_lookup_dist = []
kp1.size.times { |i|
reverse_lookup << -1
reverse_lookup_dist << Float::MAX
}
match_count = 0
kp2.size.times { |j|
i = results[j][0].to_i
d = distances[j][0]
if (d < reverse_lookup_dist[i])
match_count += 1 if reverse_lookup_dist[i] == Float::MAX
reverse_lookup[i] = j
reverse_lookup_dist[i] = d
end
}
puts "found #{match_count} putative correspondences"
points1 = []
points2 = []
kp2.size.times { |j|
i = results[j][0].to_i
if (j == reverse_lookup[i])
points1 << kp1[i].pt
points2 << kp2[j].pt
end
}
width = img1.cols + img2.cols
height = (img1.rows > img2.rows) ? img1.rows : img2.rows
correspond = IplImage.new(width, height, :cv8u, 1);
correspond.set_roi(CvRect.new(0, 0, img1.cols, img1.rows))
img1.copy(correspond)
correspond.set_roi(CvRect.new(img1.cols, 0, img1.cols + img2.cols, img2.rows))
img2.copy(correspond)
correspond.reset_roi
points1.zip(points2) { |pt1, pt2|
pt2.x += img1.cols
correspond.line!(pt1, pt2, :color => CvColor::White)
}
GUI::Window.new('Object Correspond').show correspond
GUI::wait_key