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

Merge branch 'master' into documentation

This commit is contained in:
ser1zw 2012-08-21 01:08:56 +09:00
commit 1c11610b14
12 changed files with 187 additions and 14 deletions

View file

@ -0,0 +1,16 @@
require 'opencv'
require 'benchmark'
include OpenCV
data = File.join(File.dirname(__FILE__), 'matching_to_many_images')
query = IplImage.load File.join(data, 'query.png'), CV_LOAD_IMAGE_GRAYSCALE
image_files = ['1.png', '2.png', '3.png'].map{|f| File.join(data, 'train', f)}
images = image_files.map{|f| IplImage.load f, CV_LOAD_IMAGE_GRAYSCALE}
matchs = query.match_descriptors(images)
match_index, count = matchs.max_by {|image_index, count| count}
puts "max match: #{image_files[match_index]}"

Binary file not shown.

After

Width:  |  Height:  |  Size: 119 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 116 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 112 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 118 KiB

View file

@ -0,0 +1,3 @@
1.png
2.png
3.png

View file

@ -33,8 +33,7 @@ rb_class()
VALUE
rb_allocate(VALUE klass)
{
CvChain *ptr;
return Data_Make_Struct(klass, CvChain, 0, 0, ptr);
return Data_Wrap_Struct(klass, mark_root_object, unregister_object, NULL);
}
/*
@ -58,11 +57,15 @@ rb_initialize(int argc, VALUE *argv, VALUE self)
storage = rb_cvCreateMemStorage(0);
try {
DATA_PTR(self) = (CvChain*)cvCreateSeq(CV_SEQ_ELTYPE_CODE, sizeof(CvChain),
sizeof(char), storage);
sizeof(int), storage);
}
catch (cv::Exception& e) {
raise_cverror(e);
}
CvSeq* self_ptr = CVSEQ(self);
cCvSeq::register_elem_class(self_ptr, rb_cFixnum);
register_root_object(self_ptr, storage_value);
return self;
}
@ -108,7 +111,7 @@ rb_codes(VALUE self)
cvStartReadChainPoints(chain, &reader);
for (int i = 0; i < total; ++i) {
CV_READ_SEQ_ELEM(reader.code, (*((CvSeqReader*)&(reader))));
rb_ary_store(ary, i, CHR2FIX(reader.code));
rb_ary_store(ary, i, INT2FIX(reader.code));
}
}
catch (cv::Exception& e) {
@ -184,7 +187,7 @@ new_object()
VALUE storage = cCvMemStorage::new_object();
CvSeq *seq = NULL;
try {
seq = cvCreateSeq(CV_SEQ_CHAIN_CONTOUR, sizeof(CvChain), sizeof(char), CVMEMSTORAGE(storage));
seq = cvCreateSeq(CV_SEQ_CHAIN_CONTOUR, sizeof(CvChain), sizeof(int), CVMEMSTORAGE(storage));
}
catch (cv::Exception& e) {
raise_cverror(e);

View file

@ -37,8 +37,7 @@ rb_class()
VALUE
rb_allocate(VALUE klass)
{
CvContour *ptr;
return Data_Make_Struct(klass, CvContour, mark_root_object, unregister_object, ptr);
return Data_Wrap_Struct(klass, mark_root_object, unregister_object, NULL);
}
/*
@ -59,15 +58,15 @@ rb_initialize(int argc, VALUE *argv, VALUE self)
else
storage = CHECK_CVMEMSTORAGE(storage);
CvContour* contour = (CvContour*)DATA_PTR(self);
try {
contour = (CvContour*)cvCreateSeq(CV_SEQ_ELTYPE_POINT, sizeof(CvContour),
DATA_PTR(self) = (CvContour*)cvCreateSeq(CV_SEQ_ELTYPE_POINT, sizeof(CvContour),
sizeof(CvPoint), CVMEMSTORAGE(storage));
}
catch (cv::Exception& e) {
raise_cverror(e);
}
register_root_object((CvSeq*)contour, storage);
cCvSeq::register_elem_class(CVSEQ(self), cCvPoint::rb_class());
register_root_object(CVSEQ(self), storage);
return self;
}

View file

@ -366,6 +366,7 @@ void define_ruby_class()
rb_define_method(rb_klass, "equalize_hist", RUBY_METHOD_FUNC(rb_equalize_hist), 0);
rb_define_method(rb_klass, "match_template", RUBY_METHOD_FUNC(rb_match_template), -1);
rb_define_method(rb_klass, "match_shapes", RUBY_METHOD_FUNC(rb_match_shapes), -1);
rb_define_method(rb_klass, "match_descriptors", RUBY_METHOD_FUNC(rb_match_descriptors), -1);
rb_define_method(rb_klass, "mean_shift", RUBY_METHOD_FUNC(rb_mean_shift), 2);
rb_define_method(rb_klass, "cam_shift", RUBY_METHOD_FUNC(rb_cam_shift), 2);
@ -5097,6 +5098,7 @@ rb_moments(int argc, VALUE *argv, VALUE self)
*
* Finds lines in binary image using a Hough transform.
* * method
* * The Hough transform variant, one of the following:
* * - CV_HOUGH_STANDARD - classical or standard Hough transform.
* * - CV_HOUGH_PROBABILISTIC - probabilistic Hough transform (more efficient in case if picture contains a few long linear segments).
@ -5105,11 +5107,13 @@ rb_moments(int argc, VALUE *argv, VALUE self)
* * theta - Angle resolution measured in radians.
* * threshold - Threshold parameter. A line is returned by the function if the corresponding accumulator value is greater than threshold.
* * param1
* * The first method-dependent parameter:
* * For the classical Hough transform it is not used (0).
* * For the probabilistic Hough transform it is the minimum line length.
* * For the multi-scale Hough transform it is the divisor for the distance resolution . (The coarse distance resolution will be rho and the accurate resolution will be (rho / param1)).
* * param2
* * The second method-dependent parameter:
* * For the classical Hough transform it is not used (0).
* * For the probabilistic Hough transform it is the maximum gap between line segments lying on the same line to treat them as a single line segment (i.e. to join them).
@ -5325,6 +5329,93 @@ rb_match_shapes(int argc, VALUE *argv, VALUE self)
return rb_float_new(result);
}
/**
* Port from OpenCV sample: matching_to_many_images.cpp
* call-seq:
* match_descriptors(<i>images[, detector_type="SURF"][, descriptor_type="SURF"][, matcher_type="FlannBased"]</i>) -> Hash
*
* Matching descriptors detected on one image to descriptors detected in image array.
* Returns a Hash contains match count of each image index.
* For example, a Hash {0 => 5, 2 => 10} means the images[0] has 5 key points matched, images[2] has 10 key points matched,
* and all of other images in the images array have no key point matched.
* Hence images[2] is the best match in general.
*
* <i>images</i> is an array of CvMat objects.
* <i>detector_type</i> is a string, default is "SURF", options: "SURF", "FAST", "SIFT", "STAR"
* <i>descriptor_type</i> is a string, default is "SURF", options: "SURF", "SIFT", "BRIEF"
* <i>matcher_type</i> is a string, default is "FlannBased", options: "FlannBased", "BruteForce"
*/
VALUE
rb_match_descriptors(int argc, VALUE *argv, VALUE self)
{
VALUE images, detector_type, descriptor_type, matcher_type;
rb_scan_args(argc, argv, "13", &images, &detector_type, &descriptor_type, &matcher_type);
if (RARRAY_LEN(images) == 0) {
return rb_hash_new();
}
if (NIL_P(detector_type)) {
detector_type = rb_str_new2("SURF");
}
if (NIL_P(descriptor_type)) {
descriptor_type = rb_str_new2("SURF");
}
if (NIL_P(matcher_type)) {
matcher_type = rb_str_new2("FlannBased");
}
cv::Mat queryImage = CVMAT(self);
std::vector<cv::Mat> trainImages;
for(int i=0; i < RARRAY_LEN(images); i++) {
trainImages.push_back(CVMAT_WITH_CHECK(RARRAY_PTR(images)[i]));
}
cv::Ptr<cv::FeatureDetector> featureDetector = cv::FeatureDetector::create(RSTRING_PTR(detector_type));
if (featureDetector.empty()) {
rb_raise(rb_eArgError, "Could not create feature detector by given detector type: %s", RSTRING_PTR(detector_type));
}
cv::Ptr<cv::DescriptorExtractor> descriptorExtractor = cv::DescriptorExtractor::create(RSTRING_PTR(descriptor_type));
if (descriptorExtractor.empty()) {
rb_raise(rb_eArgError, "Could not create descriptor extractor by given descriptor type: %s", RSTRING_PTR(descriptor_type));
}
cv::Ptr<cv::DescriptorMatcher> descriptorMatcher;
try {
descriptorMatcher = cv::DescriptorMatcher::create(RSTRING_PTR(matcher_type));
}
catch(cv::Exception& e) {
rb_raise(rb_eArgError, "Could not create descriptor matcher by given matcher type: %s", RSTRING_PTR(matcher_type));
}
std::vector<cv::KeyPoint> queryKeypoints;
std::vector<std::vector<cv::KeyPoint> > trainKeypoints;
featureDetector->detect(queryImage, queryKeypoints);
featureDetector->detect(trainImages, trainKeypoints);
cv::Mat queryDescriptors;
std::vector<cv::Mat> trainDescriptors;
descriptorExtractor->compute(queryImage, queryKeypoints, queryDescriptors);
descriptorExtractor->compute(trainImages, trainKeypoints, trainDescriptors);
std::vector<cv::DMatch> matches;
descriptorMatcher->add(trainDescriptors);
descriptorMatcher->train();
descriptorMatcher->match(queryDescriptors, matches);
VALUE _matches = rb_hash_new();
for (size_t i=0; i<matches.size(); i++) {
VALUE match = INT2FIX(matches[i].imgIdx);
VALUE count = rb_hash_aref(_matches, match);
if (NIL_P(count)) {
count = INT2FIX(1);
} else {
count = INT2FIX(FIX2INT(count) + 1);
}
rb_hash_aset(_matches, match, count);
}
return _matches;
}
/*
* call-seq:
* mean_shift(window, criteria) -> comp

View file

@ -220,6 +220,8 @@ VALUE rb_equalize_hist(VALUE self);
/* Matching*/
VALUE rb_match_template(int argc, VALUE *argv, VALUE self);
VALUE rb_match_shapes(int argc, VALUE *argv, VALUE self);
VALUE rb_match_descriptors(int argc, VALUE *argv, VALUE self);
/* Object Tracking */
VALUE rb_mean_shift(VALUE self, VALUE window, VALUE criteria);
VALUE rb_cam_shift(VALUE self, VALUE window, VALUE criteria);

View file

@ -22,6 +22,8 @@ VALUE rb_class();
void define_ruby_class();
VALUE seqblock_class(void *ptr);
void register_elem_class(CvSeq *seq, VALUE klass);
void unregister_elem_class(void *ptr);
VALUE rb_allocate(VALUE klass);

57
test/test_cvmat_matching.rb Executable file
View file

@ -0,0 +1,57 @@
#!/usr/bin/env ruby
# -*- mode: ruby; coding: utf-8-unix -*-
require 'test/unit'
require 'opencv'
require File.expand_path(File.dirname(__FILE__)) + '/helper'
include OpenCV
# Tests for matching functions of OpenCV::CvMat
class TestCvMat_matching < OpenCVTestCase
def setup
@query = read_test_image('query.png')
@images = ['1.png', '2.png', '3.png'].map{|f| read_test_image('train', f)}
end
def data_dir
File.join(File.dirname(__FILE__), '..', 'examples', 'matching_to_many_images')
end
def read_test_image(*path)
IplImage.load File.join(data_dir, *path), CV_LOAD_IMAGE_GRAYSCALE
end
def test_match_descriptors
matchs = @query.match_descriptors(@images)
match_index, count = matchs.max_by {|image_index, count| count}
assert_equal 2, match_index
end
def test_match_descriptors_with_empty_image_array
assert_equal({}, @query.match_descriptors([]))
end
def test_match_descriptors_with_wrong_detector_type_argument
assert_raise ArgumentError do
@query.match_descriptors(@images, "Wrong")
end
end
def test_match_descriptors_with_wrong_descriptor_type_argument
assert_raise ArgumentError do
@query.match_descriptors(@images, "SURF", "wrong")
end
end
def test_match_descriptors_with_wrong_matcher_type_argument
assert_raise ArgumentError do
@query.match_descriptors(@images, "SURF", "SURF", "wrong")
end
end
def test_match_descriptors_with_invalid_image_array
assert_raise TypeError do
@query.match_descriptors([DUMMY_OBJ, DUMMY_OBJ])
end
end
end