Merge pull request #1209 from nghiaho12:master

This commit is contained in:
Roman Donchenko 2013-10-01 17:07:39 +04:00 committed by OpenCV Buildbot
commit 8717281e0e
5 changed files with 788 additions and 1 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

View File

@ -716,3 +716,32 @@ See below a sample output of the function where each image pixel is tested again
.. [Suzuki85] Suzuki, S. and Abe, K., *Topological Structural Analysis of Digitized Binary Images by Border Following*. CVGIP 30 1, pp 32-46 (1985)
.. [TehChin89] Teh, C.H. and Chin, R.T., *On the Detection of Dominant Points on Digital Curve*. PAMI 11 8, pp 859-872 (1989)
rotatedRectangleIntersection
-------------------------------
Finds out if there is any intersection between two rotated rectangles. If there is then the vertices of the interesecting region are returned as well.
.. ocv:function:: int rotatedRectangleIntersection( const RotatedRect& rect1, const RotatedRect& rect2, OutputArray intersectingRegion )
.. ocv:pyfunction:: cv2.rotatedRectangleIntersection( rect1, rect2 ) -> retval, intersectingRegion
:param rect1: First rectangle
:param rect2: Second rectangle
:param intersectingRegion: The output array of the verticies of the intersecting region. It returns at most 8 vertices. Stored as ``std::vector<cv::Point2f>`` or ``cv::Mat`` as Mx1 of type CV_32FC2.
:param pointCount: The number of vertices.
The following values are returned by the function:
* INTERSECT_NONE=0 - No intersection
* INTERSECT_PARTIAL=1 - There is a partial intersection
* INTERSECT_FULL=2 - One of the rectangle is fully enclosed in the other
Below are some examples of intersection configurations. The hatched pattern indicates the intersecting region and the red vertices are returned by the function.
.. image:: pics/intersection.png

View File

@ -462,7 +462,11 @@ enum { COLOR_BGR2BGRA = 0,
COLOR_COLORCVT_MAX = 139
};
//! types of intersection between rectangles
enum { INTERSECT_NONE = 0,
INTERSECT_PARTIAL = 1,
INTERSECT_FULL = 2
};
/*!
The Base Class for 1D or Row-wise Filters
@ -1486,6 +1490,9 @@ CV_EXPORTS_W void fitLine( InputArray points, OutputArray line, int distType,
//! checks if the point is inside the contour. Optionally computes the signed distance from the point to the contour boundary
CV_EXPORTS_W double pointPolygonTest( InputArray contour, Point2f pt, bool measureDist );
//! computes whether two rotated rectangles intersect and returns the vertices of the intersecting region
CV_EXPORTS_W int rotatedRectangleIntersection( const RotatedRect& rect1, const RotatedRect& rect2, OutputArray intersectingRegion );
CV_EXPORTS_W Ptr<CLAHE> createCLAHE(double clipLimit = 40.0, Size tileGridSize = Size(8, 8));
//! Ballard, D.H. (1981). Generalizing the Hough transform to detect arbitrary shapes. Pattern Recognition 13 (2): 111-122.

View File

@ -0,0 +1,252 @@
/*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.
//
//
// License Agreement
// For Open Source Computer Vision Library
//
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
// Copyright (C) 2008-2011, Willow Garage Inc., all rights reserved.
// Third party copyrights are property of their respective owners.
//
// @Authors
// Nghia Ho, nghiaho12@yahoo.com
//
// 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 OpenCV Foundation 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 OpenCV Foundation 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 "precomp.hpp"
namespace cv
{
int rotatedRectangleIntersection( const RotatedRect& rect1, const RotatedRect& rect2, OutputArray intersectingRegion )
{
const float samePointEps = 0.00001; // used to test if two points are the same
Point2f vec1[4], vec2[4];
Point2f pts1[4], pts2[4];
std::vector <Point2f> intersection;
rect1.points(pts1);
rect2.points(pts2);
int ret = INTERSECT_FULL;
// Specical case of rect1 == rect2
{
bool same = true;
for( int i = 0; i < 4; i++ )
{
if( fabs(pts1[i].x - pts2[i].x) > samePointEps || (fabs(pts1[i].y - pts2[i].y) > samePointEps) )
{
same = false;
break;
}
}
if(same)
{
intersection.resize(4);
for( int i = 0; i < 4; i++ )
{
intersection[i] = pts1[i];
}
Mat(intersection).copyTo(intersectingRegion);
return INTERSECT_FULL;
}
}
// Line vector
// A line from p1 to p2 is: p1 + (p2-p1)*t, t=[0,1]
for( int i = 0; i < 4; i++ )
{
vec1[i].x = pts1[(i+1)%4].x - pts1[i].x;
vec1[i].y = pts1[(i+1)%4].y - pts1[i].y;
vec2[i].x = pts2[(i+1)%4].x - pts2[i].x;
vec2[i].y = pts2[(i+1)%4].y - pts2[i].y;
}
// Line test - test all line combos for intersection
for( int i = 0; i < 4; i++ )
{
for( int j = 0; j < 4; j++ )
{
// Solve for 2x2 Ax=b
float x21 = pts2[j].x - pts1[i].x;
float y21 = pts2[j].y - pts1[i].y;
float vx1 = vec1[i].x;
float vy1 = vec1[i].y;
float vx2 = vec2[j].x;
float vy2 = vec2[j].y;
float det = vx2*vy1 - vx1*vy2;
float t1 = (vx2*y21 - vy2*x21) / det;
float t2 = (vx1*y21 - vy1*x21) / det;
// This takes care of parallel lines
if( cvIsInf(t1) || cvIsInf(t2) || cvIsNaN(t1) || cvIsNaN(t2) )
{
continue;
}
if( t1 >= 0.0f && t1 <= 1.0f && t2 >= 0.0f && t2 <= 1.0f )
{
float xi = pts1[i].x + vec1[i].x*t1;
float yi = pts1[i].y + vec1[i].y*t1;
intersection.push_back(Point2f(xi,yi));
}
}
}
if( !intersection.empty() )
{
ret = INTERSECT_PARTIAL;
}
// Check for vertices from rect1 inside recct2
for( int i = 0; i < 4; i++ )
{
// We do a sign test to see which side the point lies.
// If the point all lie on the same sign for all 4 sides of the rect,
// then there's an intersection
int posSign = 0;
int negSign = 0;
float x = pts1[i].x;
float y = pts1[i].y;
for( int j = 0; j < 4; j++ )
{
// line equation: Ax + By + C = 0
// see which side of the line this point is at
float A = -vec2[j].y;
float B = vec2[j].x;
float C = -(A*pts2[j].x + B*pts2[j].y);
float s = A*x+ B*y+ C;
if( s >= 0 )
{
posSign++;
}
else
{
negSign++;
}
}
if( posSign == 4 || negSign == 4 )
{
intersection.push_back(pts1[i]);
}
}
// Reverse the check - check for vertices from rect2 inside recct1
for( int i = 0; i < 4; i++ )
{
// We do a sign test to see which side the point lies.
// If the point all lie on the same sign for all 4 sides of the rect,
// then there's an intersection
int posSign = 0;
int negSign = 0;
float x = pts2[i].x;
float y = pts2[i].y;
for( int j = 0; j < 4; j++ )
{
// line equation: Ax + By + C = 0
// see which side of the line this point is at
float A = -vec1[j].y;
float B = vec1[j].x;
float C = -(A*pts1[j].x + B*pts1[j].y);
float s = A*x + B*y + C;
if( s >= 0 )
{
posSign++;
}
else
{
negSign++;
}
}
if( posSign == 4 || negSign == 4 )
{
intersection.push_back(pts2[i]);
}
}
// Get rid of dupes
for( int i = 0; i < (int)intersection.size()-1; i++ )
{
for( size_t j = i+1; j < intersection.size(); j++ )
{
float dx = intersection[i].x - intersection[j].x;
float dy = intersection[i].y - intersection[j].y;
double d2 = dx*dx + dy*dy; // can be a really small number, need double here
if( d2 < samePointEps*samePointEps )
{
// Found a dupe, remove it
std::swap(intersection[j], intersection.back());
intersection.pop_back();
i--; // restart check
}
}
}
if( intersection.empty() )
{
return INTERSECT_NONE ;
}
// If this check fails then it means we're getting dupes, increase samePointEps
CV_Assert( intersection.size() <= 8 );
Mat(intersection).copyTo(intersectingRegion);
return ret;
}
} // end namespace

View File

@ -0,0 +1,499 @@
/*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.
//
//
// License Agreement
// For Open Source Computer Vision Library
//
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
// Copyright (C) 2008-2011, Willow Garage Inc., all rights reserved.
// Third party copyrights are property of their respective owners.
//
// @Authors
// Nghia Ho, nghiaho12@yahoo.com
//
// 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 OpenCV Foundation 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 OpenCV Foundation 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;
#define ACCURACY 0.00001
class CV_RotatedRectangleIntersectionTest: public cvtest::ArrayTest
{
public:
protected:
void run (int);
private:
void test1();
void test2();
void test3();
void test4();
void test5();
void test6();
void test7();
void test8();
void test9();
};
void CV_RotatedRectangleIntersectionTest::run(int)
{
// See pics/intersection.png for the scenarios we are testing
// Test the following scenarios:
// 1 - no intersection
// 2 - partial intersection, rectangle translated
// 3 - partial intersection, rectangle rotated 45 degree on the corner, forms a triangle intersection
// 4 - full intersection, rectangles of same size directly on top of each other
// 5 - partial intersection, rectangle on top rotated 45 degrees
// 6 - partial intersection, rectangle on top of different size
// 7 - full intersection, rectangle fully enclosed in the other
// 8 - partial intersection, rectangle corner just touching. point contact
// 9 - partial intersetion. rectangle side by side, line contact
test1();
test2();
test3();
test4();
test5();
test6();
test7();
test8();
test9();
}
void CV_RotatedRectangleIntersectionTest::test1()
{
// no intersection
RotatedRect rect1, rect2;
rect1.center.x = 0;
rect1.center.y = 0;
rect1.size.width = 2;
rect1.size.height = 2;
rect1.angle = 12.0f;
rect2.center.x = 10;
rect2.center.y = 10;
rect2.size.width = 2;
rect2.size.height = 2;
rect2.angle = 34.0f;
vector<Point2f> vertices;
int ret = rotatedRectangleIntersection(rect1, rect2, vertices);
CV_Assert(ret == INTERSECT_NONE);
CV_Assert(vertices.empty());
}
void CV_RotatedRectangleIntersectionTest::test2()
{
// partial intersection, rectangles translated
RotatedRect rect1, rect2;
rect1.center.x = 0;
rect1.center.y = 0;
rect1.size.width = 2;
rect1.size.height = 2;
rect1.angle = 0;
rect2.center.x = 1;
rect2.center.y = 1;
rect2.size.width = 2;
rect2.size.height = 2;
rect2.angle = 0;
vector<Point2f> vertices;
int ret = rotatedRectangleIntersection(rect1, rect2, vertices);
CV_Assert(ret == INTERSECT_PARTIAL);
CV_Assert(vertices.size() == 4);
vector<Point2f> possibleVertices(4);
possibleVertices[0] = Point2f(0.0f, 0.0f);
possibleVertices[1] = Point2f(1.0f, 1.0f);
possibleVertices[2] = Point2f(0.0f, 1.0f);
possibleVertices[3] = Point2f(1.0f, 0.0f);
for( size_t i = 0; i < vertices.size(); i++ )
{
double bestR = DBL_MAX;
for( size_t j = 0; j < possibleVertices.size(); j++ )
{
double dx = vertices[i].x - possibleVertices[j].x;
double dy = vertices[i].y - possibleVertices[j].y;
double r = sqrt(dx*dx + dy*dy);
bestR = std::min(bestR, r);
}
CV_Assert(bestR < ACCURACY);
}
}
void CV_RotatedRectangleIntersectionTest::test3()
{
// partial intersection, rectangles rotated 45 degree on the corner, forms a triangle intersection
RotatedRect rect1, rect2;
rect1.center.x = 0;
rect1.center.y = 0;
rect1.size.width = 2;
rect1.size.height = 2;
rect1.angle = 0;
rect2.center.x = 1;
rect2.center.y = 1;
rect2.size.width = sqrt(2.0f);
rect2.size.height = 20;
rect2.angle = 45.0f;
vector<Point2f> vertices;
int ret = rotatedRectangleIntersection(rect1, rect2, vertices);
CV_Assert(ret == INTERSECT_PARTIAL);
CV_Assert(vertices.size() == 3);
vector<Point2f> possibleVertices(3);
possibleVertices[0] = Point2f(1.0f, 1.0f);
possibleVertices[1] = Point2f(0.0f, 1.0f);
possibleVertices[2] = Point2f(1.0f, 0.0f);
for( size_t i = 0; i < vertices.size(); i++ )
{
double bestR = DBL_MAX;
for( size_t j = 0; j < possibleVertices.size(); j++ )
{
double dx = vertices[i].x - possibleVertices[j].x;
double dy = vertices[i].y - possibleVertices[j].y;
double r = sqrt(dx*dx + dy*dy);
bestR = std::min(bestR, r);
}
CV_Assert(bestR < ACCURACY);
}
}
void CV_RotatedRectangleIntersectionTest::test4()
{
// full intersection, rectangles of same size directly on top of each other
RotatedRect rect1, rect2;
rect1.center.x = 0;
rect1.center.y = 0;
rect1.size.width = 2;
rect1.size.height = 2;
rect1.angle = 0;
rect2.center.x = 0;
rect2.center.y = 0;
rect2.size.width = 2;
rect2.size.height = 2;
rect2.angle = 0;
vector<Point2f> vertices;
int ret = rotatedRectangleIntersection(rect1, rect2, vertices);
CV_Assert(ret == INTERSECT_FULL);
CV_Assert(vertices.size() == 4);
vector<Point2f> possibleVertices(4);
possibleVertices[0] = Point2f(-1.0f, 1.0f);
possibleVertices[1] = Point2f(1.0f, -1.0f);
possibleVertices[2] = Point2f(-1.0f, -1.0f);
possibleVertices[3] = Point2f(1.0f, 1.0f);
for( size_t i = 0; i < vertices.size(); i++ )
{
double bestR = DBL_MAX;
for( size_t j = 0; j < possibleVertices.size(); j++ )
{
double dx = vertices[i].x - possibleVertices[j].x;
double dy = vertices[i].y - possibleVertices[j].y;
double r = sqrt(dx*dx + dy*dy);
bestR = std::min(bestR, r);
}
CV_Assert(bestR < ACCURACY);
}
}
void CV_RotatedRectangleIntersectionTest::test5()
{
// partial intersection, rectangle on top rotated 45 degrees
RotatedRect rect1, rect2;
rect1.center.x = 0;
rect1.center.y = 0;
rect1.size.width = 2;
rect1.size.height = 2;
rect1.angle = 0;
rect2.center.x = 0;
rect2.center.y = 0;
rect2.size.width = 2;
rect2.size.height = 2;
rect2.angle = 45.0f;
vector<Point2f> vertices;
int ret = rotatedRectangleIntersection(rect1, rect2, vertices);
CV_Assert(ret == INTERSECT_PARTIAL);
CV_Assert(vertices.size() == 8);
vector<Point2f> possibleVertices(8);
possibleVertices[0] = Point2f(-1.0f, -0.414214f);
possibleVertices[1] = Point2f(-1.0f, 0.414214f);
possibleVertices[2] = Point2f(-0.414214f, -1.0f);
possibleVertices[3] = Point2f(0.414214f, -1.0f);
possibleVertices[4] = Point2f(1.0f, -0.414214f);
possibleVertices[5] = Point2f(1.0f, 0.414214f);
possibleVertices[6] = Point2f(0.414214f, 1.0f);
possibleVertices[7] = Point2f(-0.414214f, 1.0f);
for( size_t i = 0; i < vertices.size(); i++ )
{
double bestR = DBL_MAX;
for( size_t j = 0; j < possibleVertices.size(); j++ )
{
double dx = vertices[i].x - possibleVertices[j].x;
double dy = vertices[i].y - possibleVertices[j].y;
double r = sqrt(dx*dx + dy*dy);
bestR = std::min(bestR, r);
}
CV_Assert(bestR < ACCURACY);
}
}
void CV_RotatedRectangleIntersectionTest::test6()
{
// 6 - partial intersection, rectangle on top of different size
RotatedRect rect1, rect2;
rect1.center.x = 0;
rect1.center.y = 0;
rect1.size.width = 2;
rect1.size.height = 2;
rect1.angle = 0;
rect2.center.x = 0;
rect2.center.y = 0;
rect2.size.width = 2;
rect2.size.height = 10;
rect2.angle = 0;
vector<Point2f> vertices;
int ret = rotatedRectangleIntersection(rect1, rect2, vertices);
CV_Assert(ret == INTERSECT_PARTIAL);
CV_Assert(vertices.size() == 4);
vector<Point2f> possibleVertices(4);
possibleVertices[0] = Point2f(1.0f, 1.0f);
possibleVertices[1] = Point2f(1.0f, -1.0f);
possibleVertices[2] = Point2f(-1.0f, -1.0f);
possibleVertices[3] = Point2f(-1.0f, 1.0f);
for( size_t i = 0; i < vertices.size(); i++ )
{
double bestR = DBL_MAX;
for( size_t j = 0; j < possibleVertices.size(); j++ )
{
double dx = vertices[i].x - possibleVertices[j].x;
double dy = vertices[i].y - possibleVertices[j].y;
double r = sqrt(dx*dx + dy*dy);
bestR = std::min(bestR, r);
}
CV_Assert(bestR < ACCURACY);
}
}
void CV_RotatedRectangleIntersectionTest::test7()
{
// full intersection, rectangle fully enclosed in the other
RotatedRect rect1, rect2;
rect1.center.x = 0;
rect1.center.y = 0;
rect1.size.width = 12.34;
rect1.size.height = 56.78;
rect1.angle = 0;
rect2.center.x = 0;
rect2.center.y = 0;
rect2.size.width = 2;
rect2.size.height = 2;
rect2.angle = 0;
vector<Point2f> vertices;
int ret = rotatedRectangleIntersection(rect1, rect2, vertices);
CV_Assert(ret == INTERSECT_FULL);
CV_Assert(vertices.size() == 4);
vector<Point2f> possibleVertices(4);
possibleVertices[0] = Point2f(1.0f, 1.0f);
possibleVertices[1] = Point2f(1.0f, -1.0f);
possibleVertices[2] = Point2f(-1.0f, -1.0f);
possibleVertices[3] = Point2f(-1.0f, 1.0f);
for( size_t i = 0; i < vertices.size(); i++ )
{
double bestR = DBL_MAX;
for( size_t j = 0; j < possibleVertices.size(); j++ )
{
double dx = vertices[i].x - possibleVertices[j].x;
double dy = vertices[i].y - possibleVertices[j].y;
double r = sqrt(dx*dx + dy*dy);
bestR = std::min(bestR, r);
}
CV_Assert(bestR < ACCURACY);
}
}
void CV_RotatedRectangleIntersectionTest::test8()
{
// full intersection, rectangle fully enclosed in the other
RotatedRect rect1, rect2;
rect1.center.x = 0;
rect1.center.y = 0;
rect1.size.width = 2;
rect1.size.height = 2;
rect1.angle = 0;
rect2.center.x = 2;
rect2.center.y = 2;
rect2.size.width = 2;
rect2.size.height = 2;
rect2.angle = 0;
vector<Point2f> vertices;
int ret = rotatedRectangleIntersection(rect1, rect2, vertices);
CV_Assert(ret == INTERSECT_PARTIAL);
CV_Assert(vertices.size() == 1);
double dx = vertices[0].x - 1;
double dy = vertices[0].y - 1;
double r = sqrt(dx*dx + dy*dy);
CV_Assert(r < ACCURACY);
}
void CV_RotatedRectangleIntersectionTest::test9()
{
// full intersection, rectangle fully enclosed in the other
RotatedRect rect1, rect2;
rect1.center.x = 0;
rect1.center.y = 0;
rect1.size.width = 2;
rect1.size.height = 2;
rect1.angle = 0;
rect2.center.x = 2;
rect2.center.y = 0;
rect2.size.width = 2;
rect2.size.height = 123.45;
rect2.angle = 0;
vector<Point2f> vertices;
int ret = rotatedRectangleIntersection(rect1, rect2, vertices);
CV_Assert(ret == INTERSECT_PARTIAL);
CV_Assert(vertices.size() == 2);
vector<Point2f> possibleVertices(2);
possibleVertices[0] = Point2f(1.0f, 1.0f);
possibleVertices[1] = Point2f(1.0f, -1.0f);
for( size_t i = 0; i < vertices.size(); i++ )
{
double bestR = DBL_MAX;
for( size_t j = 0; j < possibleVertices.size(); j++ )
{
double dx = vertices[i].x - possibleVertices[j].x;
double dy = vertices[i].y - possibleVertices[j].y;
double r = sqrt(dx*dx + dy*dy);
bestR = std::min(bestR, r);
}
CV_Assert(bestR < ACCURACY);
}
}
TEST (Imgproc_RotatedRectangleIntersection, accuracy) { CV_RotatedRectangleIntersectionTest test; test.safe_run(); }