mirror of
https://github.com/opencv/opencv.git
synced 2025-06-07 01:13:28 +08:00
Merge pull request #20533 from AleksandrPanov:minAreaRect_fix_rotatingCalipers
This commit is contained in:
commit
266a868ba9
@ -88,6 +88,32 @@ enum { CALIPERS_MAXHEIGHT=0, CALIPERS_MINAREARECT=1, CALIPERS_MAXDIST=2 };
|
||||
// Notes:
|
||||
//F*/
|
||||
|
||||
static void rotate90CCW(const cv::Point2f& in, cv::Point2f &out)
|
||||
{
|
||||
out.x = -in.y;
|
||||
out.y = in.x;
|
||||
}
|
||||
|
||||
static void rotate90CW(const cv::Point2f& in, cv::Point2f &out)
|
||||
{
|
||||
out.x = in.y;
|
||||
out.y = -in.x;
|
||||
}
|
||||
|
||||
static void rotate180(const cv::Point2f& in, cv::Point2f &out)
|
||||
{
|
||||
out.x = -in.x;
|
||||
out.y = -in.y;
|
||||
}
|
||||
|
||||
/* return true if first vector is to the right (clockwise) of the second */
|
||||
static bool firstVecIsRight(const cv::Point2f& vec1, const cv::Point2f &vec2)
|
||||
{
|
||||
cv::Point2f tmp;
|
||||
rotate90CW(vec1, tmp);
|
||||
return tmp.x * vec2.x + tmp.y * vec2.y < 0;
|
||||
}
|
||||
|
||||
/* we will use usual cartesian coordinates */
|
||||
static void rotatingCalipers( const Point2f* points, int n, int mode, float* out )
|
||||
{
|
||||
@ -100,6 +126,7 @@ static void rotatingCalipers( const Point2f* points, int n, int mode, float* out
|
||||
Point2f* vect = (Point2f*)(inv_vect_length + n);
|
||||
int left = 0, bottom = 0, right = 0, top = 0;
|
||||
int seq[4] = { -1, -1, -1, -1 };
|
||||
Point2f rot_vect[4];
|
||||
|
||||
/* rotating calipers sides will always have coordinates
|
||||
(a,b) (-b,a) (-a,-b) (b, -a)
|
||||
@ -179,32 +206,18 @@ static void rotatingCalipers( const Point2f* points, int n, int mode, float* out
|
||||
/* all of edges will be checked while rotating calipers by 90 degrees */
|
||||
for( k = 0; k < n; k++ )
|
||||
{
|
||||
/* sinus of minimal angle */
|
||||
/*float sinus;*/
|
||||
|
||||
/* compute cosine of angle between calipers side and polygon edge */
|
||||
/* dp - dot product */
|
||||
float dp[4] = {
|
||||
+base_a * vect[seq[0]].x + base_b * vect[seq[0]].y,
|
||||
-base_b * vect[seq[1]].x + base_a * vect[seq[1]].y,
|
||||
-base_a * vect[seq[2]].x - base_b * vect[seq[2]].y,
|
||||
+base_b * vect[seq[3]].x - base_a * vect[seq[3]].y,
|
||||
};
|
||||
|
||||
float maxcos = dp[0] * inv_vect_length[seq[0]];
|
||||
|
||||
/* number of calipers edges, that has minimal angle with edge */
|
||||
int main_element = 0;
|
||||
|
||||
/* choose minimal angle */
|
||||
for ( i = 1; i < 4; ++i )
|
||||
/* choose minimum angle between calipers side and polygon edge by dot product sign */
|
||||
rot_vect[0] = vect[seq[0]];
|
||||
rotate90CW(vect[seq[1]], rot_vect[1]);
|
||||
rotate180(vect[seq[2]], rot_vect[2]);
|
||||
rotate90CCW(vect[seq[3]], rot_vect[3]);
|
||||
for (i = 1; i < 4; i++)
|
||||
{
|
||||
float cosalpha = dp[i] * inv_vect_length[seq[i]];
|
||||
if (cosalpha > maxcos)
|
||||
{
|
||||
if (firstVecIsRight(rot_vect[i], rot_vect[main_element]))
|
||||
main_element = i;
|
||||
maxcos = cosalpha;
|
||||
}
|
||||
}
|
||||
|
||||
/*rotate calipers*/
|
||||
|
@ -2384,5 +2384,78 @@ TEST(Imgproc_minAreaRect, reproducer_18157)
|
||||
EXPECT_TRUE(checkMinAreaRect(rr, contour)) << rr.center << " " << rr.size << " " << rr.angle;
|
||||
}
|
||||
|
||||
TEST(Imgproc_minAreaRect, reproducer_19769_lightweight)
|
||||
{
|
||||
const int N = 23;
|
||||
float pts_[N][2] = {
|
||||
{1325, 732}, {1248, 808}, {582, 1510}, {586, 1524},
|
||||
{595, 1541}, {599, 1547}, {789, 1745}, {829, 1786},
|
||||
{997, 1958}, {1116, 2074}, {1207, 2066}, {1216, 2058},
|
||||
{1231, 2044}, {1265, 2011}, {2036, 1254}, {2100, 1191},
|
||||
{2169, 1123}, {2315, 979}, {2395, 900}, {2438, 787},
|
||||
{2434, 782}, {2416, 762}, {2266, 610}
|
||||
};
|
||||
Mat contour(N, 1, CV_32FC2, (void*)pts_);
|
||||
|
||||
RotatedRect rr = cv::minAreaRect(contour);
|
||||
|
||||
EXPECT_TRUE(checkMinAreaRect(rr, contour)) << rr.center << " " << rr.size << " " << rr.angle;
|
||||
}
|
||||
|
||||
TEST(Imgproc_minAreaRect, reproducer_19769)
|
||||
{
|
||||
const int N = 169;
|
||||
float pts_[N][2] = {
|
||||
{1854, 227}, {1850, 228}, {1847, 229}, {1835, 235},
|
||||
{1832, 237}, {1829, 239}, {1825, 242}, {1818, 248},
|
||||
{1807, 258}, {1759, 306}, {1712, 351}, {1708, 356},
|
||||
{1658, 404}, {1655, 408}, {1602, 459}, {1599, 463},
|
||||
{1542, 518}, {1477, 582}, {1402, 656}, {1325, 732},
|
||||
{1248, 808}, {1161, 894}, {1157, 898}, {1155, 900},
|
||||
{1068, 986}, {1060, 995}, {1058, 997}, {957, 1097},
|
||||
{956, 1097}, {814, 1238}, {810, 1242}, {805, 1248},
|
||||
{610, 1442}, {603, 1450}, {599, 1455}, {596, 1459},
|
||||
{594, 1462}, {592, 1465}, {590, 1470}, {588, 1472},
|
||||
{586, 1476}, {586, 1478}, {584, 1481}, {583, 1485},
|
||||
{582, 1490}, {582, 1510}, {583, 1515}, {584, 1518},
|
||||
{585, 1521}, {586, 1524}, {593, 1538}, {595, 1541},
|
||||
{597, 1544}, {599, 1547}, {603, 1552}, {609, 1559},
|
||||
{623, 1574}, {645, 1597}, {677, 1630}, {713, 1667},
|
||||
{753, 1707}, {789, 1744}, {789, 1745}, {829, 1786},
|
||||
{871, 1828}, {909, 1867}, {909, 1868}, {950, 1910},
|
||||
{953, 1912}, {997, 1958}, {1047, 2009}, {1094, 2056},
|
||||
{1105, 2066}, {1110, 2070}, {1113, 2072}, {1116, 2074},
|
||||
{1119, 2076}, {1122, 2077}, {1124, 2079}, {1130, 2082},
|
||||
{1133, 2083}, {1136, 2084}, {1139, 2085}, {1142, 2086},
|
||||
{1148, 2087}, {1166, 2087}, {1170, 2086}, {1174, 2085},
|
||||
{1177, 2084}, {1180, 2083}, {1188, 2079}, {1190, 2077},
|
||||
{1193, 2076}, {1196, 2074}, {1199, 2072}, {1202, 2070},
|
||||
{1207, 2066}, {1216, 2058}, {1231, 2044}, {1265, 2011},
|
||||
{1314, 1962}, {1360, 1917}, {1361, 1917}, {1408, 1871},
|
||||
{1457, 1822}, {1508, 1773}, {1512, 1768}, {1560, 1722},
|
||||
{1617, 1665}, {1671, 1613}, {1730, 1554}, {1784, 1502},
|
||||
{1786, 1500}, {1787, 1498}, {1846, 1440}, {1850, 1437},
|
||||
{1908, 1380}, {1974, 1314}, {2034, 1256}, {2036, 1254},
|
||||
{2100, 1191}, {2169, 1123}, {2242, 1051}, {2315, 979},
|
||||
{2395, 900}, {2426, 869}, {2435, 859}, {2438, 855},
|
||||
{2440, 852}, {2442, 849}, {2443, 846}, {2445, 844},
|
||||
{2446, 842}, {2446, 840}, {2448, 837}, {2449, 834},
|
||||
{2450, 829}, {2450, 814}, {2449, 809}, {2448, 806},
|
||||
{2447, 803}, {2442, 793}, {2440, 790}, {2438, 787},
|
||||
{2434, 782}, {2428, 775}, {2416, 762}, {2411, 758},
|
||||
{2342, 688}, {2340, 686}, {2338, 684}, {2266, 610},
|
||||
{2260, 605}, {2170, 513}, {2075, 417}, {2073, 415},
|
||||
{2069, 412}, {1955, 297}, {1955, 296}, {1913, 254},
|
||||
{1904, 246}, {1897, 240}, {1894, 238}, {1891, 236},
|
||||
{1888, 234}, {1880, 230}, {1877, 229}, {1874, 228},
|
||||
{1870, 227}
|
||||
};
|
||||
Mat contour(N, 1, CV_32FC2, (void*)pts_);
|
||||
|
||||
RotatedRect rr = cv::minAreaRect(contour);
|
||||
|
||||
EXPECT_TRUE(checkMinAreaRect(rr, contour)) << rr.center << " " << rr.size << " " << rr.angle;
|
||||
}
|
||||
|
||||
}} // namespace
|
||||
/* End of file. */
|
||||
|
Loading…
Reference in New Issue
Block a user