From 613a17355de653d52d6f8d82339d3f3520375964 Mon Sep 17 00:00:00 2001 From: Rohit Girdhar Date: Fri, 14 Feb 2014 09:37:39 +0530 Subject: [PATCH 1/6] rotRect using points --- modules/core/include/opencv2/core/types.hpp | 26 +++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/modules/core/include/opencv2/core/types.hpp b/modules/core/include/opencv2/core/types.hpp index e2b49749e..bfc63816c 100644 --- a/modules/core/include/opencv2/core/types.hpp +++ b/modules/core/include/opencv2/core/types.hpp @@ -392,6 +392,7 @@ public: //! various constructors RotatedRect(); RotatedRect(const Point2f& center, const Size2f& size, float angle); + RotatedRect(const std::vector& points); //! returns 4 vertices of the rectangle void points(Point2f pts[]) const; @@ -1547,6 +1548,31 @@ inline RotatedRect::RotatedRect(const Point2f& _center, const Size2f& _size, float _angle) : center(_center), size(_size), angle(_angle) {} +inline +RotatedRect::RotatedRect(const std::vector& _points) +{ + CV_Assert( _points.size() == 3 ); + Point2f _center = 0.5f * (_points[0] + _points[2]); + Vec2f vecs[2]; + vecs[0] = Vec2f(_points[0] - _points[1]); + vecs[1] = Vec2f(_points[1] - _points[2]); + // check that given sides are perpendicular + CV_Assert( abs(vecs[0].dot(vecs[1])) <= 0.001 ); + + // wd_i stores which vector (0,1) or (1,2) will make the width + // One of them will definitely have slope within -1 to 1 + int wd_i = 0; + if( vecs[1][0] != 0 && fabs(vecs[1][1] / vecs[1][0]) <= 1.0f ) wd_i = 1; + int ht_i = (wd_i + 1) % 2; + + float _angle = atan(vecs[wd_i][1] / vecs[wd_i][0]) * 180.0f / (float) CV_PI; + float _width = norm(vecs[wd_i]); + float _height = norm(vecs[ht_i]); + + center = _center; + size = Size2f(_width, _height); + angle = _angle; +} ///////////////////////////////// Range ///////////////////////////////// From a879e1fcd69490f2a93cc88665810e72e6ca677d Mon Sep 17 00:00:00 2001 From: Rohit Girdhar Date: Mon, 17 Feb 2014 19:00:36 +0530 Subject: [PATCH 2/6] fixed warnings --- modules/core/include/opencv2/core/types.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/core/include/opencv2/core/types.hpp b/modules/core/include/opencv2/core/types.hpp index bfc63816c..2a1070303 100644 --- a/modules/core/include/opencv2/core/types.hpp +++ b/modules/core/include/opencv2/core/types.hpp @@ -1566,8 +1566,8 @@ RotatedRect::RotatedRect(const std::vector& _points) int ht_i = (wd_i + 1) % 2; float _angle = atan(vecs[wd_i][1] / vecs[wd_i][0]) * 180.0f / (float) CV_PI; - float _width = norm(vecs[wd_i]); - float _height = norm(vecs[ht_i]); + float _width = (float) norm(vecs[wd_i]); + float _height = (float) norm(vecs[ht_i]); center = _center; size = Size2f(_width, _height); From b939b4ae3b76b97b7041b5c37e40e3b34ffd086f Mon Sep 17 00:00:00 2001 From: Rohit Girdhar Date: Wed, 19 Feb 2014 20:58:40 +0530 Subject: [PATCH 3/6] removed inline, changed interface --- modules/core/include/opencv2/core/types.hpp | 27 +-------------------- modules/core/src/matrix.cpp | 24 ++++++++++++++++++ 2 files changed, 25 insertions(+), 26 deletions(-) diff --git a/modules/core/include/opencv2/core/types.hpp b/modules/core/include/opencv2/core/types.hpp index 2a1070303..0b09c6fb0 100644 --- a/modules/core/include/opencv2/core/types.hpp +++ b/modules/core/include/opencv2/core/types.hpp @@ -392,7 +392,7 @@ public: //! various constructors RotatedRect(); RotatedRect(const Point2f& center, const Size2f& size, float angle); - RotatedRect(const std::vector& points); + RotatedRect(const Point2f& point1, const Point2f& point2, const Point2f& point3); //! returns 4 vertices of the rectangle void points(Point2f pts[]) const; @@ -1548,31 +1548,6 @@ inline RotatedRect::RotatedRect(const Point2f& _center, const Size2f& _size, float _angle) : center(_center), size(_size), angle(_angle) {} -inline -RotatedRect::RotatedRect(const std::vector& _points) -{ - CV_Assert( _points.size() == 3 ); - Point2f _center = 0.5f * (_points[0] + _points[2]); - Vec2f vecs[2]; - vecs[0] = Vec2f(_points[0] - _points[1]); - vecs[1] = Vec2f(_points[1] - _points[2]); - // check that given sides are perpendicular - CV_Assert( abs(vecs[0].dot(vecs[1])) <= 0.001 ); - - // wd_i stores which vector (0,1) or (1,2) will make the width - // One of them will definitely have slope within -1 to 1 - int wd_i = 0; - if( vecs[1][0] != 0 && fabs(vecs[1][1] / vecs[1][0]) <= 1.0f ) wd_i = 1; - int ht_i = (wd_i + 1) % 2; - - float _angle = atan(vecs[wd_i][1] / vecs[wd_i][0]) * 180.0f / (float) CV_PI; - float _width = (float) norm(vecs[wd_i]); - float _height = (float) norm(vecs[ht_i]); - - center = _center; - size = Size2f(_width, _height); - angle = _angle; -} ///////////////////////////////// Range ///////////////////////////////// diff --git a/modules/core/src/matrix.cpp b/modules/core/src/matrix.cpp index e89799973..02ca1c969 100644 --- a/modules/core/src/matrix.cpp +++ b/modules/core/src/matrix.cpp @@ -5204,6 +5204,30 @@ void normalize( const SparseMat& src, SparseMat& dst, double a, int norm_type ) ////////////////////// RotatedRect ////////////////////// +RotatedRect::RotatedRect(const Point2f& _point1, const Point2f& _point2, const Point2f& _point3) +{ + Point2f _center = 0.5f * (_point1 + _point3); + Vec2f vecs[2]; + vecs[0] = Vec2f(_point1 - _point2); + vecs[1] = Vec2f(_point2 - _point3); + // check that given sides are perpendicular + CV_Assert( abs(vecs[0].dot(vecs[1])) <= 0.001 ); + + // wd_i stores which vector (0,1) or (1,2) will make the width + // One of them will definitely have slope within -1 to 1 + int wd_i = 0; + if( vecs[1][0] != 0 && abs(vecs[1][1] / vecs[1][0]) <= 1.0f ) wd_i = 1; + int ht_i = (wd_i + 1) % 2; + + float _angle = atan(vecs[wd_i][1] / vecs[wd_i][0]) * 180.0f / (float) CV_PI; + float _width = (float) norm(vecs[wd_i]); + float _height = (float) norm(vecs[ht_i]); + + center = _center; + size = Size2f(_width, _height); + angle = _angle; +} + void RotatedRect::points(Point2f pt[]) const { double _angle = angle*CV_PI/180.; From ea7b1bb3d2418ffa34a155ce7b80239ef6a02a5d Mon Sep 17 00:00:00 2001 From: Rohit Girdhar Date: Thu, 20 Feb 2014 17:51:48 +0530 Subject: [PATCH 4/6] added test, doc --- modules/core/doc/basic_structures.rst | 5 +++++ modules/core/src/matrix.cpp | 2 +- modules/core/test/test_io.cpp | 1 + 3 files changed, 7 insertions(+), 1 deletion(-) diff --git a/modules/core/doc/basic_structures.rst b/modules/core/doc/basic_structures.rst index 886a886df..280c317ae 100644 --- a/modules/core/doc/basic_structures.rst +++ b/modules/core/doc/basic_structures.rst @@ -316,6 +316,7 @@ RotatedRect RotatedRect(); RotatedRect(const Point2f& center, const Size2f& size, float angle); RotatedRect(const CvBox2D& box); + RotatedRect(const Point2f& point1, const Point2f& point2, const Point2f& point3); //! returns 4 vertices of the rectangle void points(Point2f pts[]) const; @@ -338,7 +339,11 @@ The class represents rotated (i.e. not up-right) rectangles on a plane. Each rec :param size: Width and height of the rectangle. :param angle: The rotation angle in a clockwise direction. When the angle is 0, 90, 180, 270 etc., the rectangle becomes an up-right rectangle. :param box: The rotated rectangle parameters as the obsolete CvBox2D structure. + .. ocv:function:: RotatedRect::RotatedRect(const Point2f& point1, const Point2f& point2, const Point2f& point3) + :param point1: + :param point2: + :param point3: Any 3 end points of the RotatedRect. They must be given in order (either clockwise or anticlockwise). .. ocv:function:: void RotatedRect::points( Point2f pts[] ) const .. ocv:function:: Rect RotatedRect::boundingRect() const diff --git a/modules/core/src/matrix.cpp b/modules/core/src/matrix.cpp index 02ca1c969..7f1dfe690 100644 --- a/modules/core/src/matrix.cpp +++ b/modules/core/src/matrix.cpp @@ -5216,7 +5216,7 @@ RotatedRect::RotatedRect(const Point2f& _point1, const Point2f& _point2, const P // wd_i stores which vector (0,1) or (1,2) will make the width // One of them will definitely have slope within -1 to 1 int wd_i = 0; - if( vecs[1][0] != 0 && abs(vecs[1][1] / vecs[1][0]) <= 1.0f ) wd_i = 1; + if( abs(vecs[1][1]) < abs(vecs[1][0]) ) wd_i = 1; int ht_i = (wd_i + 1) % 2; float _angle = atan(vecs[wd_i][1] / vecs[wd_i][0]) * 180.0f / (float) CV_PI; diff --git a/modules/core/test/test_io.cpp b/modules/core/test/test_io.cpp index 23c0aad62..71c739154 100644 --- a/modules/core/test/test_io.cpp +++ b/modules/core/test/test_io.cpp @@ -403,6 +403,7 @@ protected: Size s1(6, 7), os1; Complex c1(9, 10), oc1; Rect r1(11, 12, 13, 14), or1; + RotatedRect rr1(Point2f(0,0), Point2f(100,100), Point2f(50, 150)); Vec v1(15, 16, 17, 18, 19), ov1; Scalar sc1(20.0, 21.1, 22.2, 23.3), osc1; Range g1(7, 8), og1; From 347a3dc520358738c1b42654de2e37651c2174d8 Mon Sep 17 00:00:00 2001 From: Rohit Girdhar Date: Fri, 21 Feb 2014 03:00:03 +0530 Subject: [PATCH 5/6] added randomized test --- modules/core/src/matrix.cpp | 2 +- modules/core/test/test_io.cpp | 1 - modules/core/test/test_rotatedrect.cpp | 107 +++++++++++++++++++++++++ 3 files changed, 108 insertions(+), 2 deletions(-) create mode 100644 modules/core/test/test_rotatedrect.cpp diff --git a/modules/core/src/matrix.cpp b/modules/core/src/matrix.cpp index 7f1dfe690..d52c2a709 100644 --- a/modules/core/src/matrix.cpp +++ b/modules/core/src/matrix.cpp @@ -5211,7 +5211,7 @@ RotatedRect::RotatedRect(const Point2f& _point1, const Point2f& _point2, const P vecs[0] = Vec2f(_point1 - _point2); vecs[1] = Vec2f(_point2 - _point3); // check that given sides are perpendicular - CV_Assert( abs(vecs[0].dot(vecs[1])) <= 0.001 ); + CV_Assert( abs(vecs[0].dot(vecs[1])) <= FLT_EPSILON ); // wd_i stores which vector (0,1) or (1,2) will make the width // One of them will definitely have slope within -1 to 1 diff --git a/modules/core/test/test_io.cpp b/modules/core/test/test_io.cpp index 71c739154..23c0aad62 100644 --- a/modules/core/test/test_io.cpp +++ b/modules/core/test/test_io.cpp @@ -403,7 +403,6 @@ protected: Size s1(6, 7), os1; Complex c1(9, 10), oc1; Rect r1(11, 12, 13, 14), or1; - RotatedRect rr1(Point2f(0,0), Point2f(100,100), Point2f(50, 150)); Vec v1(15, 16, 17, 18, 19), ov1; Scalar sc1(20.0, 21.1, 22.2, 23.3), osc1; Range g1(7, 8), og1; diff --git a/modules/core/test/test_rotatedrect.cpp b/modules/core/test/test_rotatedrect.cpp new file mode 100644 index 000000000..a163f30d1 --- /dev/null +++ b/modules/core/test/test_rotatedrect.cpp @@ -0,0 +1,107 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// Intel License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000, Intel Corporation, all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * The name of Intel Corporation may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// This software is provided by the copyright holders and contributors "as is" and +// any express or implied warranties, including, but not limited to, the implied +// warranties of merchantability and fitness for a particular purpose are disclaimed. +// In no event shall the Intel Corporation or contributors be liable for any direct, +// indirect, incidental, special, exemplary, or consequential damages +// (including, but not limited to, procurement of substitute goods or services; +// loss of use, data, or profits; or business interruption) however caused +// and on any theory of liability, whether in contract, strict liability, +// or tort (including negligence or otherwise) arising in any way out of +// the use of this software, even if advised of the possibility of such damage. +// +//M*/ + +#include "test_precomp.hpp" + +using namespace cv; +using namespace std; + +class Core_RotatedRectConstructorTest : public cvtest::BaseTest +{ +public: + Core_RotatedRectConstructorTest(); +protected: + int prepare_test_case( int ); + void run_func(); + int validate_test_results( int ); + const static int MAX_COORD_VAL = 1000; + Point2f a, b, c; + RotatedRect rec; +}; + +Core_RotatedRectConstructorTest::Core_RotatedRectConstructorTest() +{ + test_case_count = 100; +} + +int Core_RotatedRectConstructorTest::prepare_test_case( int test_case_idx ) +{ + cvtest::BaseTest::prepare_test_case( test_case_idx ); + RNG& rng = ts->get_rng(); + a = Point2f( (float) (cvtest::randInt(rng) % MAX_COORD_VAL), (float) (cvtest::randInt(rng) % MAX_COORD_VAL) ); + b = Point2f( (float) (cvtest::randInt(rng) % MAX_COORD_VAL) , (float) (cvtest::randInt(rng) % MAX_COORD_VAL) ); + // to ensure a != b + while( norm(a - b) == 0 ) { + b = Point2f( (float) (cvtest::randInt(rng) % MAX_COORD_VAL) , (float) (cvtest::randInt(rng) % MAX_COORD_VAL) ); + } + Vec2f along(a - b); + Vec2f perp = Vec2f(-along[1], along[0]); + float d = (float) (cvtest::randInt(rng) % MAX_COORD_VAL) + 1.0f; // c can't be same as b, so d must be > 0 + c = Point2f( b.x + d * perp[0], b.y + d * perp[1] ); + return 1; +} + +void Core_RotatedRectConstructorTest::run_func() +{ + rec = RotatedRect(a, b, c); +} + +int Core_RotatedRectConstructorTest::validate_test_results( int ) +{ + int code = cvtest::TS::OK; + Point2f vertices[4]; + rec.points(vertices); + + int count_match = 0; + for( int i = 0; i < 4; i++ ) + { + if( norm(vertices[i] - a) <= 0.1 ) count_match++; + else if( norm(vertices[i] - b) <= 0.1 ) count_match++; + else if( norm(vertices[i] - c) <= 0.1 ) count_match++; + } + if( count_match == 3 ) + return code; + ts->printf( cvtest::TS::LOG, "RotatedRect end points don't match those supplied in constructor"); + ts->set_failed_test_info( cvtest::TS::FAIL_INVALID_OUTPUT ); + return code; +} + +TEST(Core_RotatedRect, three_point_constructor) { Core_RotatedRectConstructorTest test; test.safe_run(); } From fd4461d54389e9674b97c64a445baa7ed3e95980 Mon Sep 17 00:00:00 2001 From: Rohit Girdhar Date: Sat, 22 Feb 2014 00:26:10 +0530 Subject: [PATCH 6/6] addressed issues --- modules/core/src/matrix.cpp | 2 +- modules/core/test/test_rotatedrect.cpp | 30 +++++++++++++------------- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/modules/core/src/matrix.cpp b/modules/core/src/matrix.cpp index d52c2a709..e80a70874 100644 --- a/modules/core/src/matrix.cpp +++ b/modules/core/src/matrix.cpp @@ -5211,7 +5211,7 @@ RotatedRect::RotatedRect(const Point2f& _point1, const Point2f& _point2, const P vecs[0] = Vec2f(_point1 - _point2); vecs[1] = Vec2f(_point2 - _point3); // check that given sides are perpendicular - CV_Assert( abs(vecs[0].dot(vecs[1])) <= FLT_EPSILON ); + CV_Assert( abs(vecs[0].dot(vecs[1])) / (norm(vecs[0]) * norm(vecs[1])) <= FLT_EPSILON ); // wd_i stores which vector (0,1) or (1,2) will make the width // One of them will definitely have slope within -1 to 1 diff --git a/modules/core/test/test_rotatedrect.cpp b/modules/core/test/test_rotatedrect.cpp index a163f30d1..c600ef1dd 100644 --- a/modules/core/test/test_rotatedrect.cpp +++ b/modules/core/test/test_rotatedrect.cpp @@ -52,7 +52,7 @@ protected: int prepare_test_case( int ); void run_func(); int validate_test_results( int ); - const static int MAX_COORD_VAL = 1000; + float MAX_COORD_VAL; Point2f a, b, c; RotatedRect rec; }; @@ -60,22 +60,24 @@ protected: Core_RotatedRectConstructorTest::Core_RotatedRectConstructorTest() { test_case_count = 100; + MAX_COORD_VAL = 1000.0f; } int Core_RotatedRectConstructorTest::prepare_test_case( int test_case_idx ) { cvtest::BaseTest::prepare_test_case( test_case_idx ); RNG& rng = ts->get_rng(); - a = Point2f( (float) (cvtest::randInt(rng) % MAX_COORD_VAL), (float) (cvtest::randInt(rng) % MAX_COORD_VAL) ); - b = Point2f( (float) (cvtest::randInt(rng) % MAX_COORD_VAL) , (float) (cvtest::randInt(rng) % MAX_COORD_VAL) ); - // to ensure a != b - while( norm(a - b) == 0 ) { - b = Point2f( (float) (cvtest::randInt(rng) % MAX_COORD_VAL) , (float) (cvtest::randInt(rng) % MAX_COORD_VAL) ); + a = Point2f( rng.uniform(-MAX_COORD_VAL, MAX_COORD_VAL), rng.uniform(-MAX_COORD_VAL, MAX_COORD_VAL) ); + do + { + b = Point2f( rng.uniform(-MAX_COORD_VAL, MAX_COORD_VAL), rng.uniform(-MAX_COORD_VAL, MAX_COORD_VAL) ); } + while( norm(a - b) <= FLT_EPSILON ); Vec2f along(a - b); Vec2f perp = Vec2f(-along[1], along[0]); - float d = (float) (cvtest::randInt(rng) % MAX_COORD_VAL) + 1.0f; // c can't be same as b, so d must be > 0 - c = Point2f( b.x + d * perp[0], b.y + d * perp[1] ); + double d = (double) rng.uniform(1.0f, 5.0f); + if( cvtest::randInt(rng) % 2 == 0 ) d = -d; + c = Point2f( (float) ((double) b.x + d * perp[0]), (float) ((double) b.y + d * perp[1]) ); return 1; } @@ -86,22 +88,20 @@ void Core_RotatedRectConstructorTest::run_func() int Core_RotatedRectConstructorTest::validate_test_results( int ) { - int code = cvtest::TS::OK; Point2f vertices[4]; rec.points(vertices); - int count_match = 0; for( int i = 0; i < 4; i++ ) { - if( norm(vertices[i] - a) <= 0.1 ) count_match++; - else if( norm(vertices[i] - b) <= 0.1 ) count_match++; - else if( norm(vertices[i] - c) <= 0.1 ) count_match++; + if( norm(vertices[i] - a) <= 0.001 ) count_match++; + else if( norm(vertices[i] - b) <= 0.001 ) count_match++; + else if( norm(vertices[i] - c) <= 0.001 ) count_match++; } if( count_match == 3 ) - return code; + return cvtest::TS::OK; ts->printf( cvtest::TS::LOG, "RotatedRect end points don't match those supplied in constructor"); ts->set_failed_test_info( cvtest::TS::FAIL_INVALID_OUTPUT ); - return code; + return cvtest::TS::OK; } TEST(Core_RotatedRect, three_point_constructor) { Core_RotatedRectConstructorTest test; test.safe_run(); }