mirror of
https://github.com/ruby-opencv/ruby-opencv
synced 2023-03-27 23:22:12 -04:00
tested and fixed PointSet
This commit is contained in:
parent
67845bc4cc
commit
f8685c49c8
5 changed files with 219 additions and 48 deletions
|
@ -12,7 +12,7 @@
|
|||
|
||||
#include "opencv.h"
|
||||
|
||||
#define __NAMESPACE_BEGIN_CVMEMSTORAGE namespace cCvMemStorage{
|
||||
#define __NAMESPACE_BEGIN_CVMEMSTORAGE namespace cCvMemStorage {
|
||||
#define __NAMESPACE_END_CVMEMSTORAGE }
|
||||
|
||||
__NAMESPACE_BEGIN_OPENCV
|
||||
|
|
|
@ -147,7 +147,7 @@ rb_initialize(int argc, VALUE *argv, VALUE self)
|
|||
else
|
||||
storage = rb_cvCreateMemStorage(0);
|
||||
|
||||
if(!rb_obj_is_kind_of(klass, rb_cClass))
|
||||
if (!rb_obj_is_kind_of(klass, rb_cClass))
|
||||
raise_typeerror(klass, rb_cClass);
|
||||
|
||||
int type = 0, size = 0;
|
||||
|
@ -404,7 +404,7 @@ rb_pop(VALUE self)
|
|||
if (seq->total == 0)
|
||||
return Qnil;
|
||||
|
||||
VALUE object;
|
||||
VALUE object = Qnil;
|
||||
VALUE klass = seqblock_class(seq);
|
||||
try {
|
||||
if (klass == rb_cFixnum) {
|
||||
|
|
|
@ -36,13 +36,13 @@ define_ruby_module()
|
|||
VALUE opencv = rb_module_opencv();
|
||||
module = rb_define_module_under(opencv, "PointSet");
|
||||
rb_define_method(module, "contour_area", RUBY_METHOD_FUNC(rb_contour_area), -1);
|
||||
rb_define_method(module, "fit_ellipse", RUBY_METHOD_FUNC(rb_fit_ellipse), 0);
|
||||
rb_define_method(module, "fit_ellipse2", RUBY_METHOD_FUNC(rb_fit_ellipse2), 0);
|
||||
|
||||
rb_define_method(module, "convex_hull", RUBY_METHOD_FUNC(rb_convex_hull), -1);
|
||||
rb_define_method(module, "convex_hull2", RUBY_METHOD_FUNC(rb_convex_hull2), -1);
|
||||
rb_define_method(module, "check_contour_convexity", RUBY_METHOD_FUNC(rb_check_contour_convexity), 0);
|
||||
rb_define_alias(module, "convexity?", "check_contour_convexity");
|
||||
rb_define_method(module, "convexity_defects", RUBY_METHOD_FUNC(rb_convexity_defects), -1);
|
||||
rb_define_method(module, "min_area_rect", RUBY_METHOD_FUNC(rb_min_area_rect), 0);
|
||||
rb_define_method(module, "convexity_defects", RUBY_METHOD_FUNC(rb_convexity_defects), 1);
|
||||
rb_define_method(module, "min_area_rect2", RUBY_METHOD_FUNC(rb_min_area_rect2), 0);
|
||||
rb_define_method(module, "min_enclosing_circle", RUBY_METHOD_FUNC(rb_min_enclosing_circle), 0);
|
||||
}
|
||||
|
||||
|
@ -71,39 +71,59 @@ rb_contour_area(int argc, VALUE *argv, VALUE self)
|
|||
{
|
||||
VALUE slice;
|
||||
rb_scan_args(argc, argv, "01", &slice);
|
||||
return rb_float_new(cvContourArea(CVARR(self), NIL_P(slice) ? CV_WHOLE_SEQ : VALUE_TO_CVSLICE(slice)));
|
||||
double area = 0;
|
||||
try {
|
||||
area = cvContourArea(CVARR(self), NIL_P(slice) ? CV_WHOLE_SEQ : VALUE_TO_CVSLICE(slice));
|
||||
}
|
||||
catch (cv::Exception& e) {
|
||||
raise_cverror(e);
|
||||
}
|
||||
return rb_float_new(area);
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* fit_ellipse -> cvbox2d
|
||||
* fit_ellipse2 -> cvbox2d
|
||||
*
|
||||
* Return fits ellipse to set of 2D points.
|
||||
*/
|
||||
VALUE
|
||||
rb_fit_ellipse(VALUE self)
|
||||
rb_fit_ellipse2(VALUE self)
|
||||
{
|
||||
return cCvBox2D::new_object(cvFitEllipse2(CVARR(self)));
|
||||
CvBox2D box;
|
||||
try {
|
||||
box = cvFitEllipse2(CVARR(self));
|
||||
}
|
||||
catch (cv::Exception& e) {
|
||||
raise_cverror(e);
|
||||
}
|
||||
return cCvBox2D::new_object(box);
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* convex_hull(<i>[reverse = fasle]</i>) -> cvcontour
|
||||
* convex_hull2(<i>[orientation_clockwise = true]</i>) -> cvcontour
|
||||
*
|
||||
* Finds convex hull of 2D point set using Sklansky's algorithm.
|
||||
*
|
||||
* <i>reverse</i> is desired orientation of convex hull.
|
||||
* If reverse is false mean clockwise, otherwise counter clockwise.
|
||||
* <i>orientation_clockwise</i>: Desired orientation of convex hull (true: clockwise, false: counter clockwise).
|
||||
*/
|
||||
VALUE
|
||||
rb_convex_hull(int argc, VALUE *argv, VALUE self)
|
||||
rb_convex_hull2(int argc, VALUE *argv, VALUE self)
|
||||
{
|
||||
VALUE reverse, storage;
|
||||
rb_scan_args(argc, argv, "01", &reverse);
|
||||
storage = cCvMemStorage::new_object();
|
||||
CvSeq *hull = cvConvexHull2(CVSEQ(self), CVMEMSTORAGE(storage), TRUE_OR_FALSE(reverse, 0) ? CV_COUNTER_CLOCKWISE : CV_CLOCKWISE, 1);
|
||||
if(CV_IS_SEQ_HOLE(CVSEQ(self)))
|
||||
hull->flags |= CV_SEQ_FLAG_HOLE;
|
||||
VALUE clockwise, return_points;
|
||||
rb_scan_args(argc, argv, "02", &clockwise, &return_points);
|
||||
VALUE storage = cCvMemStorage::new_object();
|
||||
CvSeq *hull = NULL;
|
||||
int return_pts = TRUE_OR_FALSE(return_points, 1);
|
||||
try {
|
||||
hull = cvConvexHull2(CVSEQ(self), CVMEMSTORAGE(storage),
|
||||
TRUE_OR_FALSE(clockwise, 1) ? CV_CLOCKWISE : CV_COUNTER_CLOCKWISE,
|
||||
return_pts);
|
||||
}
|
||||
catch (cv::Exception& e) {
|
||||
raise_cverror(e);
|
||||
}
|
||||
return cCvSeq::new_sequence(cCvContour::rb_class(), hull, cCvPoint::rb_class(), storage);
|
||||
}
|
||||
|
||||
|
@ -116,38 +136,59 @@ rb_convex_hull(int argc, VALUE *argv, VALUE self)
|
|||
VALUE
|
||||
rb_check_contour_convexity(VALUE self)
|
||||
{
|
||||
return cvCheckContourConvexity(CVARR(self)) ? Qtrue : Qfalse;
|
||||
int convexity = 0;
|
||||
try {
|
||||
convexity = cvCheckContourConvexity(CVARR(self));
|
||||
}
|
||||
catch (cv::Exception& e) {
|
||||
raise_cverror(e);
|
||||
}
|
||||
return convexity ? Qtrue : Qfalse;
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* convexity_defects(<i>[reverse = false]</i>) -> cvseq(include CvConvexityDefect)
|
||||
* convexity_defects(<i>hull</i>) -> cvseq(include CvConvexityDefect)
|
||||
*
|
||||
* Finds convexity defects of contour.
|
||||
*/
|
||||
VALUE
|
||||
rb_convexity_defects(int argc, VALUE *argv, VALUE self)
|
||||
rb_convexity_defects(VALUE self, VALUE hull)
|
||||
{
|
||||
VALUE reverse, storage;
|
||||
rb_scan_args(argc, argv, "01", &reverse);
|
||||
storage = cCvMemStorage::new_object();
|
||||
CvSeq *hull, *convex;
|
||||
hull = cvConvexHull2(CVSEQ(self), CVMEMSTORAGE(storage), TRUE_OR_FALSE(reverse, 0) ? CV_COUNTER_CLOCKWISE : CV_CLOCKWISE, 0);
|
||||
convex = cvConvexityDefects(CVSEQ(self), hull, CVMEMSTORAGE(storage));
|
||||
return cCvSeq::new_sequence(cCvSeq::rb_class(), convex, cCvConvexityDefect::rb_class(), storage);
|
||||
CvSeq *defects = NULL;
|
||||
CvSeq *hull_seq = CVSEQ_WITH_CHECK(hull);
|
||||
CvMemStorage *stg = hull_seq->storage;
|
||||
try {
|
||||
defects = cvConvexityDefects(CVSEQ(self), hull_seq, stg);
|
||||
}
|
||||
catch (cv::Exception& e) {
|
||||
raise_cverror(e);
|
||||
}
|
||||
// FIXME: This storage is shared with the argument "hull".
|
||||
// This causes a severe problem that when "hull"'s memory is collected by GC, "defects"'s storage is
|
||||
// also collected.
|
||||
VALUE storage = Data_Wrap_Struct(cCvMemStorage::rb_class(), 0, cCvMemStorage::cvmemstorage_free, stg);
|
||||
return cCvSeq::new_sequence(cCvSeq::rb_class(), defects, cCvConvexityDefect::rb_class(), storage);
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* min_area_rect -> cvbox2d
|
||||
* min_area_rect2 -> cvbox2d
|
||||
*
|
||||
* Finds circumscribed rectangle of minimal area for given 2D point set.
|
||||
*/
|
||||
VALUE
|
||||
rb_min_area_rect(VALUE self)
|
||||
rb_min_area_rect2(VALUE self)
|
||||
{
|
||||
VALUE storage = cCvMemStorage::new_object();
|
||||
return cCvBox2D::new_object(cvMinAreaRect2(CVARR(self), CVMEMSTORAGE(storage)));
|
||||
CvBox2D rect;
|
||||
try {
|
||||
rect = cvMinAreaRect2(CVARR(self), CVMEMSTORAGE(storage));
|
||||
}
|
||||
catch (cv::Exception& e) {
|
||||
raise_cverror(e);
|
||||
}
|
||||
return cCvBox2D::new_object(rect);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -160,8 +201,15 @@ VALUE
|
|||
rb_min_enclosing_circle(VALUE self)
|
||||
{
|
||||
VALUE circle = cCvCircle32f::rb_allocate(cCvCircle32f::rb_class());
|
||||
cvMinEnclosingCircle(CVARR(self), &CVCIRCLE32F(circle)->center, &CVCIRCLE32F(circle)->radius);
|
||||
return circle;
|
||||
int success = 0;
|
||||
try {
|
||||
success = cvMinEnclosingCircle(CVARR(self), &CVCIRCLE32F(circle)->center,
|
||||
&CVCIRCLE32F(circle)->radius);
|
||||
}
|
||||
catch (cv::Exception& e) {
|
||||
raise_cverror(e);
|
||||
}
|
||||
return success ? circle : Qnil;
|
||||
}
|
||||
|
||||
VALUE
|
||||
|
@ -217,29 +265,33 @@ VALUE_TO_POINT_SET(VALUE object)
|
|||
VALUE tmp, storage;
|
||||
int length;
|
||||
CvPoint2D32f p32;
|
||||
if(rb_obj_is_kind_of(object, cCvSeq::rb_class())){
|
||||
if (rb_obj_is_kind_of(object, cCvSeq::rb_class())) {
|
||||
seq = CVSEQ(object);
|
||||
if(CV_IS_SEQ_POINT_SET(seq)){
|
||||
if (CV_IS_SEQ_POINT_SET(seq)) {
|
||||
return seq;
|
||||
}else{
|
||||
}
|
||||
else {
|
||||
rb_raise(rb_eTypeError, "sequence is not contain %s or %s.", rb_class2name(cCvPoint::rb_class()), rb_class2name(cCvPoint2D32f::rb_class()));
|
||||
}
|
||||
}else if(rb_obj_is_kind_of(object, cCvMat::rb_class())){
|
||||
}
|
||||
else if (rb_obj_is_kind_of(object, cCvMat::rb_class())) {
|
||||
/* to do */
|
||||
rb_raise(rb_eNotImpError, "CvMat to CvSeq conversion not implemented.");
|
||||
}else if(rb_obj_is_kind_of(object, rb_cArray)){
|
||||
}
|
||||
else if (rb_obj_is_kind_of(object, rb_cArray)) {
|
||||
//pointset = cCvSeq::new_sequence(cCvSeq::rb_class(), )
|
||||
length = RARRAY_LEN(object);
|
||||
storage = cCvMemStorage::new_object();
|
||||
seq = cvCreateSeq(CV_SEQ_POINT_SET, sizeof(CvSeq), sizeof(CvPoint), CVMEMSTORAGE(storage));
|
||||
for(int i = 0; i < RARRAY_LEN(object); i++){
|
||||
for (int i = 0; i < RARRAY_LEN(object); i++) {
|
||||
p32.x = NUM2DBL(rb_funcall(rb_ary_entry(object, i), rb_intern("x"), 0));
|
||||
p32.y = NUM2DBL(rb_funcall(rb_ary_entry(object, i), rb_intern("y"), 0));
|
||||
cvSeqPush(seq, &p32);
|
||||
}
|
||||
tmp = cCvSeq::new_sequence(cCvSeq::rb_class(), seq, cCvPoint2D32f::rb_class(), storage);
|
||||
return seq;
|
||||
}else{
|
||||
}
|
||||
else {
|
||||
rb_raise(rb_eTypeError, "Can't convert CvSeq(PointSet).");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
#ifndef RUBY_OPENCV_POINTSET_H
|
||||
#define RUBY_OPENCV_POINTSET_H
|
||||
|
||||
#define __NAMESPACE_BEGIN_POINT_SET namespace mPointSet{
|
||||
#define __NAMESPACE_BEGIN_POINT_SET namespace mPointSet {
|
||||
#define __NAMESPACE_END_POINT_SET }
|
||||
|
||||
#include"opencv.h"
|
||||
|
@ -22,12 +22,12 @@ VALUE rb_module();
|
|||
|
||||
void define_ruby_module();
|
||||
VALUE rb_contour_area(int argc, VALUE *argv, VALUE self);
|
||||
VALUE rb_fit_ellipse(VALUE self);
|
||||
VALUE rb_fit_ellipse2(VALUE self);
|
||||
VALUE rb_convex_hull2(int argc, VALUE *argv, VALUE self);
|
||||
VALUE rb_fit_line(int argc, VALUE *argv, VALUE self);
|
||||
VALUE rb_convex_hull(int argc, VALUE *argv, VALUE self);
|
||||
VALUE rb_check_contour_convexity(VALUE self);
|
||||
VALUE rb_convexity_defects(int argc, VALUE *argv, VALUE self);
|
||||
VALUE rb_min_area_rect(VALUE self);
|
||||
VALUE rb_convexity_defects(VALUE self, VALUE hull);
|
||||
VALUE rb_min_area_rect2(VALUE self);
|
||||
VALUE rb_min_enclosing_circle(VALUE self);
|
||||
VALUE rb_calc_pgh(VALUE self);
|
||||
|
||||
|
|
119
test/test_pointset.rb
Executable file
119
test/test_pointset.rb
Executable file
|
@ -0,0 +1,119 @@
|
|||
#!/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 OpenCV::Pointset
|
||||
class TestPointset < OpenCVTestCase
|
||||
def setup
|
||||
mat0 = create_cvmat(128, 128, :cv8u, 1) { |j, i|
|
||||
(j - 64) ** 2 + (i - 64) ** 2 <= (32 ** 2) ? CvColor::White : CvColor::Black
|
||||
}
|
||||
@contour1 = mat0.find_contours
|
||||
@contour2 = CvContour.new
|
||||
end
|
||||
|
||||
def test_contour_area
|
||||
assert_equal(3118, @contour1.contour_area.to_i)
|
||||
|
||||
s = CvSlice.new(0, @contour1.size / 2)
|
||||
assert_equal(1527, @contour1.contour_area(s).to_i)
|
||||
|
||||
assert_raise(TypeError) {
|
||||
@contour1.contour_area(DUMMY_OBJ)
|
||||
}
|
||||
assert_raise(CvStsBadArg) {
|
||||
@contour2.contour_area
|
||||
}
|
||||
end
|
||||
|
||||
def test_fit_ellipse2
|
||||
box = @contour1.fit_ellipse2
|
||||
|
||||
center = box.center
|
||||
assert_equal(64, center.x.to_i)
|
||||
assert_equal(64, center.y.to_i)
|
||||
|
||||
size = box.size
|
||||
assert_in_delta(63.116, size.width, 0.001)
|
||||
assert_in_delta(63.116, size.height, 0.001)
|
||||
assert_in_delta(180, box.angle, 0.001)
|
||||
|
||||
assert_raise(CvStsBadSize) {
|
||||
@contour2.fit_ellipse2
|
||||
}
|
||||
end
|
||||
|
||||
def test_convex_hull2
|
||||
[@contour1.convex_hull2, @contour1.convex_hull2(true)].each { |hull|
|
||||
assert_equal(36, hull.size)
|
||||
assert_equal(CvContour, hull.class)
|
||||
assert_equal(CvPoint, hull[0].class)
|
||||
assert_equal(32, hull[0].x)
|
||||
assert_equal(64, hull[0].y)
|
||||
}
|
||||
|
||||
hull = @contour1.convex_hull2(false)
|
||||
assert_equal(36, hull.size)
|
||||
assert_equal(CvContour, hull.class)
|
||||
assert_equal(CvPoint, hull[0].class)
|
||||
assert_equal(96, hull[0].x)
|
||||
assert_equal(64, hull[0].y)
|
||||
|
||||
@contour1.convex_hull2(DUMMY_OBJ)
|
||||
end
|
||||
|
||||
def test_check_contour_convexity
|
||||
assert_false(@contour1.check_contour_convexity)
|
||||
end
|
||||
|
||||
def test_convexity_defects
|
||||
flunk('FIXME: Currently PointSet#convexity_defects does not work well.')
|
||||
hull = @contour1.convex_hull2(true, false)
|
||||
defects = @contour1.convexity_defects(hull)
|
||||
puts defects.class
|
||||
puts defects[0].start.to_a.join(', ')
|
||||
assert_equal(CvSeq, defects.class)
|
||||
assert_equal(CvConvexityDefect, defects[0].class)
|
||||
end
|
||||
|
||||
def test_min_area_rect2
|
||||
box = @contour1.min_area_rect2
|
||||
|
||||
assert_equal(CvBox2D, box.class)
|
||||
center = box.center
|
||||
assert_equal(64, center.x.to_i)
|
||||
assert_equal(64, center.y.to_i)
|
||||
|
||||
size = box.size
|
||||
assert_in_delta(63.356, size.width, 0.001)
|
||||
assert_in_delta(63.356, size.height, 0.001)
|
||||
assert_in_delta(-8.130, box.angle, 0.001)
|
||||
|
||||
flunk('FIXME: Currently PointSet#min_area_rect2 causes segmentation fault when "self" is invalid.')
|
||||
assert_raise(CvStsBadSize) {
|
||||
@contour2.min_area_rect2
|
||||
}
|
||||
end
|
||||
|
||||
def test_min_enclosing_circle
|
||||
circle = @contour1.min_enclosing_circle
|
||||
assert_equal(CvCircle32f, circle.class)
|
||||
center = circle.center
|
||||
assert_equal(64, center.x.to_i)
|
||||
assert_equal(64, center.y.to_i)
|
||||
assert_in_delta(32.959, circle.radius, 0.001)
|
||||
|
||||
assert_raise(CvStsBadSize) {
|
||||
@contour2.min_enclosing_circle
|
||||
}
|
||||
end
|
||||
|
||||
def test_calc_pgh
|
||||
flunk('FIXME: PointSet#calc_pgh is not implemented yet.')
|
||||
end
|
||||
end
|
||||
|
Loading…
Add table
Add a link
Reference in a new issue